Use wrapper type for CFUUID (#4032)
This no longer exposes `CGDisplayCreateUUIDFromDisplayID` and instead uses `CFUUID` to avoid a leak. Monitor comparisons should also be more stable now.
This commit is contained in:
parent
69382fda9a
commit
24c226416e
1 changed files with 37 additions and 16 deletions
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -109,15 +110,42 @@ impl VideoModeHandle {
|
|||
#[derive(Clone)]
|
||||
pub struct MonitorHandle(CGDirectDisplayID);
|
||||
|
||||
type MonitorUuid = [u8; 16];
|
||||
|
||||
impl MonitorHandle {
|
||||
/// Internal comparisons of [`MonitorHandle`]s are done first requesting a UUID for the handle.
|
||||
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::from([
|
||||
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,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
// `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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -131,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,13 +290,11 @@ 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)
|
||||
};
|
||||
uuid == other_uuid
|
||||
let other = MonitorHandle::new(other_native_id);
|
||||
uuid == other.uuid()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue