@@ -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,23 +33,41 @@ 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.
pub fn all() -> impl Iterator<Item = Self> {
unsafe {
- let mut display_count: u32 = 0;
- let result = CGGetActiveDisplayList(0, std::ptr::null_mut(), &mut display_count);
+ // We're assuming there aren't more than 32 displays connected to the system.
+ let mut displays = Vec::with_capacity(32);
+ let mut display_count = 0;
+ let result = CGGetActiveDisplayList(
+ displays.capacity() as u32,
+ displays.as_mut_ptr(),
+ &mut display_count,
+ );
if result == 0 {
- let mut displays = Vec::with_capacity(display_count as usize);
- CGGetActiveDisplayList(display_count, displays.as_mut_ptr(), &mut display_count);
displays.set_len(display_count as usize);
-
displays.into_iter().map(MacDisplay)
} else {
- panic!("Failed to get active display list");
+ panic!("Failed to get active display list. Result: {result}");
}
}
}
@@ -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;