Skip to content

Commit

Permalink
Use wrapper type for CFUUID
Browse files Browse the repository at this point in the history
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 rust-windowing#4031
  • Loading branch information
killercup committed Dec 4, 2024
1 parent 171d53c commit 87d8a93
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 16 deletions.
20 changes: 19 additions & 1 deletion src/platform_impl/apple/appkit/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down
27 changes: 12 additions & 15 deletions src/platform_impl/apple/appkit/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}

Expand All @@ -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<H: std::hash::Hasher>(&self, state: &mut H) {
unsafe {
ffi::CGDisplayCreateUUIDFromDisplayID(self.0).hash(state);
}
self.uuid().hash(state);
}
}

Expand Down Expand Up @@ -287,12 +286,10 @@ impl MonitorHandle {
}

pub(crate) fn ns_screen(&self, mtm: MainThreadMarker) -> Option<Retained<NSScreen>> {
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
})
}
Expand Down

0 comments on commit 87d8a93

Please sign in to comment.