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 }) }