From 71b0bc20cacb60af6da6b10be81e28dc9419b269 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Wed, 4 Dec 2024 16:32:51 +0100 Subject: [PATCH 1/3] Use wrapper type for CFUUID This no longer exposes `CGDisplayCreateUUIDFromDisplayID` and instead offers a new `CfUuid` type that can be created from a display ID and also cleans itself up on drop. Closes #4031 --- src/platform_impl/apple/appkit/ffi.rs | 20 ++++++++++++++++- src/platform_impl/apple/appkit/monitor.rs | 27 ++++++++++------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/platform_impl/apple/appkit/ffi.rs b/src/platform_impl/apple/appkit/ffi.rs index 92d4874e4b..8c1b0aaf41 100644 --- a/src/platform_impl/apple/appkit/ffi.rs +++ b/src/platform_impl/apple/appkit/ffi.rs @@ -67,7 +67,25 @@ pub type CGDisplayModeRef = *mut c_void; // https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/SystemFrameworks/SystemFrameworks.html#//apple_ref/doc/uid/TP40001067-CH210-BBCFFIEG #[link(name = "ApplicationServices", kind = "framework")] extern "C" { - pub fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef; + fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef; +} + +/// Convenice wrapper around `CFUUIDRef` which releases on drop. +#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] +pub(crate) struct CfUuid(pub(crate) CFUUIDRef); + +impl CfUuid { + pub fn from_display_id(value: CGDirectDisplayID) -> Self { + CfUuid(unsafe { CGDisplayCreateUUIDFromDisplayID(value) }) + } +} + +impl Drop for CfUuid { + fn drop(&mut self) { + unsafe { + core_foundation::base::CFRelease(self.0 as *const _); + } + } } #[link(name = "CoreGraphics", kind = "framework")] diff --git a/src/platform_impl/apple/appkit/monitor.rs b/src/platform_impl/apple/appkit/monitor.rs index 8917c36a07..f650245eda 100644 --- a/src/platform_impl/apple/appkit/monitor.rs +++ b/src/platform_impl/apple/appkit/monitor.rs @@ -133,15 +133,19 @@ impl VideoModeHandle { #[derive(Clone)] pub struct MonitorHandle(CGDirectDisplayID); +impl MonitorHandle { + /// Internal comparisons of [`MonitorHandle`]s are done first requesting a UUID for the handle. + fn uuid(&self) -> ffi::CfUuid { + ffi::CfUuid::from_display_id(self.0) + } +} + // `CGDirectDisplayID` changes on video mode change, so we cannot rely on that // for comparisons, but we can use `CGDisplayCreateUUIDFromDisplayID` to get an // unique identifier that persists even across system reboots impl PartialEq for MonitorHandle { fn eq(&self, other: &Self) -> bool { - unsafe { - ffi::CGDisplayCreateUUIDFromDisplayID(self.0) - == ffi::CGDisplayCreateUUIDFromDisplayID(other.0) - } + self.uuid() == other.uuid() } } @@ -155,18 +159,13 @@ impl PartialOrd for MonitorHandle { impl Ord for MonitorHandle { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - unsafe { - ffi::CGDisplayCreateUUIDFromDisplayID(self.0) - .cmp(&ffi::CGDisplayCreateUUIDFromDisplayID(other.0)) - } + self.uuid().cmp(&other.uuid()) } } impl std::hash::Hash for MonitorHandle { fn hash(&self, state: &mut H) { - unsafe { - ffi::CGDisplayCreateUUIDFromDisplayID(self.0).hash(state); - } + self.uuid().hash(state); } } @@ -287,12 +286,10 @@ impl MonitorHandle { } pub(crate) fn ns_screen(&self, mtm: MainThreadMarker) -> Option> { - let uuid = unsafe { ffi::CGDisplayCreateUUIDFromDisplayID(self.0) }; + let uuid = self.uuid(); NSScreen::screens(mtm).into_iter().find(|screen| { let other_native_id = get_display_id(screen); - let other_uuid = unsafe { - ffi::CGDisplayCreateUUIDFromDisplayID(other_native_id as CGDirectDisplayID) - }; + let other_uuid = ffi::CfUuid::from_display_id(other_native_id); uuid == other_uuid }) } From 4b5ee2b8f7f07b970099eea5f024d2855ee1c426 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Tue, 17 Dec 2024 13:38:32 +0100 Subject: [PATCH 2/3] MacOS: Use UUIDBytes for monitor comparisons etc. --- src/platform_impl/apple/appkit/ffi.rs | 20 +------------- src/platform_impl/apple/appkit/monitor.rs | 33 ++++++++++++++++++++--- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/platform_impl/apple/appkit/ffi.rs b/src/platform_impl/apple/appkit/ffi.rs index 8c1b0aaf41..92d4874e4b 100644 --- a/src/platform_impl/apple/appkit/ffi.rs +++ b/src/platform_impl/apple/appkit/ffi.rs @@ -67,25 +67,7 @@ pub type CGDisplayModeRef = *mut c_void; // https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/SystemFrameworks/SystemFrameworks.html#//apple_ref/doc/uid/TP40001067-CH210-BBCFFIEG #[link(name = "ApplicationServices", kind = "framework")] extern "C" { - fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef; -} - -/// Convenice wrapper around `CFUUIDRef` which releases on drop. -#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)] -pub(crate) struct CfUuid(pub(crate) CFUUIDRef); - -impl CfUuid { - pub fn from_display_id(value: CGDirectDisplayID) -> Self { - CfUuid(unsafe { CGDisplayCreateUUIDFromDisplayID(value) }) - } -} - -impl Drop for CfUuid { - fn drop(&mut self) { - unsafe { - core_foundation::base::CFRelease(self.0 as *const _); - } - } + pub fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef; } #[link(name = "CoreGraphics", kind = "framework")] diff --git a/src/platform_impl/apple/appkit/monitor.rs b/src/platform_impl/apple/appkit/monitor.rs index f650245eda..bbb25241af 100644 --- a/src/platform_impl/apple/appkit/monitor.rs +++ b/src/platform_impl/apple/appkit/monitor.rs @@ -7,6 +7,7 @@ use std::num::{NonZeroU16, NonZeroU32}; use core_foundation::array::{CFArrayGetCount, CFArrayGetValueAtIndex}; use core_foundation::base::{CFRelease, TCFType}; use core_foundation::string::CFString; +use core_foundation::uuid::{CFUUIDGetUUIDBytes, CFUUID}; use core_graphics::display::{ CGDirectDisplayID, CGDisplay, CGDisplayBounds, CGDisplayCopyDisplayMode, }; @@ -133,10 +134,34 @@ impl VideoModeHandle { #[derive(Clone)] pub struct MonitorHandle(CGDirectDisplayID); +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +struct MonitorUuid([u8; 16]); + impl MonitorHandle { /// Internal comparisons of [`MonitorHandle`]s are done first requesting a UUID for the handle. - fn uuid(&self) -> ffi::CfUuid { - ffi::CfUuid::from_display_id(self.0) + fn uuid(&self) -> MonitorUuid { + let cf_uuid = unsafe { + CFUUID::wrap_under_create_rule(ffi::CGDisplayCreateUUIDFromDisplayID(self.0)) + }; + let uuid = unsafe { CFUUIDGetUUIDBytes(cf_uuid.as_concrete_TypeRef()) }; + MonitorUuid([ + uuid.byte0, + uuid.byte1, + uuid.byte2, + uuid.byte3, + uuid.byte4, + uuid.byte5, + uuid.byte6, + uuid.byte7, + uuid.byte8, + uuid.byte9, + uuid.byte10, + uuid.byte11, + uuid.byte12, + uuid.byte13, + uuid.byte14, + uuid.byte15, + ]) } } @@ -289,8 +314,8 @@ impl MonitorHandle { let uuid = self.uuid(); NSScreen::screens(mtm).into_iter().find(|screen| { let other_native_id = get_display_id(screen); - let other_uuid = ffi::CfUuid::from_display_id(other_native_id); - uuid == other_uuid + let other = MonitorHandle::new(other_native_id); + uuid == other.uuid() }) } } From 3558bb7b1b4dbb3d10d55fa52cc88cbcee531c33 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Tue, 17 Dec 2024 14:52:55 +0100 Subject: [PATCH 3/3] Use type alias for MonitorUuid --- src/platform_impl/apple/appkit/monitor.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/apple/appkit/monitor.rs b/src/platform_impl/apple/appkit/monitor.rs index bbb25241af..67ba0b18c7 100644 --- a/src/platform_impl/apple/appkit/monitor.rs +++ b/src/platform_impl/apple/appkit/monitor.rs @@ -134,8 +134,7 @@ impl VideoModeHandle { #[derive(Clone)] pub struct MonitorHandle(CGDirectDisplayID); -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -struct MonitorUuid([u8; 16]); +type MonitorUuid = [u8; 16]; impl MonitorHandle { /// Internal comparisons of [`MonitorHandle`]s are done first requesting a UUID for the handle. @@ -144,7 +143,7 @@ impl MonitorHandle { CFUUID::wrap_under_create_rule(ffi::CGDisplayCreateUUIDFromDisplayID(self.0)) }; let uuid = unsafe { CFUUIDGetUUIDBytes(cf_uuid.as_concrete_TypeRef()) }; - MonitorUuid([ + MonitorUuid::from([ uuid.byte0, uuid.byte1, uuid.byte2,