Reputation: 3121
I need to show a window on the external screen (e.g. monitor connected to the Macbook). But I don't know how to distinguish between internal MacBook screen and external one. Calling of NSScreen.screens()
returns list of all screens and in my case screen with index 0 is my connected external screen and screen with index 1 is my internal (built in) MacBook screen. But documentation says:
The screen at index 0 in the returned array corresponds to the primary screen of the user’s system.
So why is my connected screen marked as primary? Is external screen on all systems is marked as primary => can I suppose that on all systems with connected external screen is this screen on 0 position?
Also, OS X dock is visible only on my internal screen and I thought that dock is by default visible on the primary screen, but that is not true.
Is there a way to reliable determine the correct external screen?
Upvotes: 3
Views: 2209
Reputation: 66302
July 2022 Update: Updated the below code to remove the guard
statement since NSScreen.screens
no longer returns an optional.
To expand on werediver's answer, here's one implementation:
extension NSScreen {
class func externalScreens() -> [NSScreen] {
let description: NSDeviceDescriptionKey = NSDeviceDescriptionKey(rawValue: "NSScreenNumber")
return screens.filter {
guard let deviceID = $0.deviceDescription[description] as? NSNumber else { return false }
print(deviceID)
return CGDisplayIsBuiltin(deviceID.uint32Value) == 0
}
}
}
Usage is simple:
let externalScreens = NSScreen.externalScreens()
You might want to adjust the behavior in the guard
statements' else
blocks depending on your needs.
Upvotes: 6
Reputation: 4757
There is a note in the beginning of NSScreen Class Reference page:
NOTE
The NSScreen class is for getting information about the available displays only. If you need additional information or want to change the attributes relating to a display, you must use Quartz Services. For more information, see Quartz Display Services Reference.
From Quartz Display Services Reference we can learn that the main screen is not necessary the built-in one. From CGMainDisplayID() description:
The main display is the display with its screen location at (0,0) in the global display coordinate space. In a system without display mirroring, the display with the menu bar is typically the main display.
If mirroring is enabled and the menu bar appears on more than one display, this function provides a reliable way to find the main display.
In case of hardware mirroring, the drawable display becomes the main display. In case of software mirroring, the display with the highest resolution and deepest pixel depth typically becomes the main display.
So, if you can use Quartz Display Services directly, use CGDisplayIsBuiltin() function to determine whether the display is built-in or not.
Upvotes: 3