I came across this question on S.O. while searching for how to open a new NSWindow / NSView on a connected display.
I converted the obj-c code to Swift as well as I could, but I cannot get it to work. I have the method set up inside an IBAction and I linked the action to a button I placed in the ViewController's View titled "Show External Display."
What am I doing wrong? Is there a good resource that can help me for working with connected displays using Cocoa/AppKit? I've read the docs, but still can't seem to get this working.
import Cocoa
class ViewController: NSViewController {
var externalDisplay: NSScreen?
var fullScreenWindow: NSWindow?
var fullScreenView: NSView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
@IBAction func showExternalDisplayButtonClicked(sender: Any?) {
// Open a window on the external display if present
if NSScreen.screens.count > 1 {
externalDisplay = NSScreen.screens.last
let externalDisplayRect = externalDisplay!.frame
fullScreenWindow = NSWindow(contentRect: externalDisplayRect, styleMask: .borderless, backing: .buffered, defer: true, screen: externalDisplay)
fullScreenWindow!.level = .normal
fullScreenWindow!.isOpaque = false
fullScreenWindow!.hidesOnDeactivate = false
fullScreenWindow!.backgroundColor = .red
let viewRect = NSRect(x: 0, y: 0, width: externalDisplay!.frame.width, height: externalDisplay!.frame.height)
fullScreenView = NSView(frame: viewRect)
fullScreenWindow!.contentView = fullScreenView
fullScreenWindow!.makeKeyAndOrderFront(self)
}
}
}
As pointed out on another site, the problem was caused by me setting the styleMask as .borderless without .titled, which prevents the window from becoming key or main according to this.
Here's my updated code that works in Swift 5.5:
import Cocoa
class ViewController: NSViewController {
var externalDisplay: NSScreen?
var fullScreenWindow: NSWindow?
var fullScreenView: NSView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
@IBAction func showExternalDisplayButtonClicked(sender: Any?) {
// Open the external display window if one is present
if NSScreen.screens.count > 1 {
externalDisplay = NSScreen.screens.last
let mask: NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable, .borderless]
fullScreenWindow = NSWindow(contentRect: externalDisplay!.frame, styleMask: mask, backing: .buffered, defer: true, screen: externalDisplay)
fullScreenWindow!.level = .normal
fullScreenWindow!.isOpaque = false
fullScreenWindow!.hidesOnDeactivate = false
fullScreenWindow!.backgroundColor = .red
let viewRect = NSRect(x: 0, y: 0, width: externalDisplay!.frame.width, height: externalDisplay!.frame.height)
fullScreenView = NSView(frame: viewRect)
fullScreenWindow!.contentView = fullScreenView
fullScreenView?.window?.toggleFullScreen(self)
}
}
}