Use NSScreen to fetch primary display

According to Chromium source, `NSScreen::screens` should always get us
one display.

We made this change because we ran into panics caused by the previous
`unwrap()` when `CGGetActiveDisplayList` might return an empty list.
This commit is contained in:
Thorsten Ball 2024-01-16 14:23:10 +01:00
parent 03bfe3ef80
commit f938bae0a2
2 changed files with 23 additions and 2 deletions

View file

@ -1,10 +1,16 @@
use crate::{point, size, Bounds, DisplayId, GlobalPixels, PlatformDisplay};
use anyhow::Result;
use cocoa::{
appkit::NSScreen,
base::{id, nil},
foundation::{NSDictionary, NSString},
};
use core_foundation::uuid::{CFUUIDGetUUIDBytes, CFUUIDRef};
use core_graphics::{
display::{CGDirectDisplayID, CGDisplayBounds, CGGetActiveDisplayList},
geometry::{CGPoint, CGRect, CGSize},
};
use objc::{msg_send, sel, sel_impl};
use std::any::Any;
use uuid::Uuid;
@ -27,7 +33,22 @@ impl MacDisplay {
/// Get the primary screen - the one with the menu bar, and whose bottom left
/// corner is at the origin of the AppKit coordinate system.
pub fn primary() -> Self {
Self::all().next().unwrap()
// Instead of iterating through all active systems displays via `all()` we use the first
// NSScreen and gets its CGDirectDisplayID, because we can't be sure that `CGGetActiveDisplayList`
// will always return a list of active displays (machine might be sleeping).
//
// The following is what Chromium does too:
//
// https://chromium.googlesource.com/chromium/src/+/66.0.3359.158/ui/display/mac/screen_mac.mm#56
unsafe {
let screens = NSScreen::screens(nil);
let screen = cocoa::foundation::NSArray::objectAtIndex(screens, 0);
let device_description = NSScreen::deviceDescription(screen);
let screen_number_key: id = NSString::alloc(nil).init_str("NSScreenNumber");
let screen_number = device_description.objectForKey_(screen_number_key);
let screen_number: CGDirectDisplayID = msg_send![screen_number, unsignedIntegerValue];
Self(screen_number)
}
}
/// Obtains an iterator over all currently active system displays.

View file

@ -484,7 +484,7 @@ impl MacWindow {
let display = options
.display_id
.and_then(|display_id| MacDisplay::all().find(|display| display.id() == display_id))
.and_then(MacDisplay::find_by_id)
.unwrap_or_else(MacDisplay::primary);
let mut target_screen = nil;