macOS:ios: use next objc2 version
A lot of CoreFoundation methods have been marked safe, and converted into methods. Note that the old functions are still available, just deprecated.
This commit is contained in:
parent
ed4d70fdd4
commit
24e2c6914a
9 changed files with 125 additions and 217 deletions
|
|
@ -3,7 +3,7 @@ use std::ptr::NonNull;
|
|||
use dispatch2::run_on_main;
|
||||
use objc2::rc::Retained;
|
||||
use objc2_app_kit::{NSEvent, NSEventModifierFlags, NSEventSubtype, NSEventType};
|
||||
use objc2_core_foundation::{CFData, CFDataGetBytePtr, CFRetained};
|
||||
use objc2_core_foundation::{CFData, CFRetained};
|
||||
use objc2_foundation::NSPoint;
|
||||
use smol_str::SmolStr;
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ pub fn get_modifierless_char(scancode: u16) -> Key {
|
|||
return Key::Unidentified(NativeKey::MacOS(scancode));
|
||||
};
|
||||
|
||||
let layout = unsafe { CFDataGetBytePtr(layout_data).cast() };
|
||||
let layout = layout_data.byte_ptr().cast();
|
||||
let keyboard_type = run_on_main(|_mtm| unsafe { ffi::LMGetKbdType() });
|
||||
|
||||
let mut result_len = 0;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// TODO: Upstream these
|
||||
|
||||
#![allow(dead_code, non_snake_case, non_upper_case_globals)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use std::ffi::c_void;
|
||||
|
||||
|
|
@ -9,27 +9,10 @@ use objc2::runtime::AnyObject;
|
|||
use objc2_core_foundation::{cf_type, CFString, CFUUID};
|
||||
use objc2_core_graphics::CGDirectDisplayID;
|
||||
|
||||
pub const kCGDisplayBlendNormal: f32 = 0.0;
|
||||
pub const kCGDisplayBlendSolidColor: f32 = 1.0;
|
||||
|
||||
pub type CGDisplayFadeReservationToken = u32;
|
||||
pub const kCGDisplayFadeReservationInvalidToken: CGDisplayFadeReservationToken = 0;
|
||||
|
||||
pub const IO1BitIndexedPixels: &str = "P";
|
||||
pub const IO2BitIndexedPixels: &str = "PP";
|
||||
pub const IO4BitIndexedPixels: &str = "PPPP";
|
||||
pub const IO8BitIndexedPixels: &str = "PPPPPPPP";
|
||||
pub const IO16BitDirectPixels: &str = "-RRRRRGGGGGBBBBB";
|
||||
pub const IO32BitDirectPixels: &str = "--------RRRRRRRRGGGGGGGGBBBBBBBB";
|
||||
|
||||
pub const kIO30BitDirectPixels: &str = "--RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB";
|
||||
pub const kIO64BitDirectPixels: &str = "-16R16G16B16";
|
||||
|
||||
pub const kIO16BitFloatPixels: &str = "-16FR16FG16FB16";
|
||||
pub const kIO32BitFloatPixels: &str = "-32FR32FG32FB32";
|
||||
|
||||
pub const IOYUV422Pixels: &str = "Y4U2V2";
|
||||
pub const IO8BitOverlayPixels: &str = "O8";
|
||||
|
||||
// `CGDisplayCreateUUIDFromDisplayID` comes from the `ColorSync` framework.
|
||||
// However, that framework was only introduced "publicly" in macOS 10.13.
|
||||
|
|
@ -58,7 +41,6 @@ extern "C" {
|
|||
pub struct TISInputSource(std::ffi::c_void);
|
||||
|
||||
cf_type!(
|
||||
#[encoding_name = "__TISInputSource"]
|
||||
unsafe impl TISInputSource {}
|
||||
);
|
||||
|
||||
|
|
@ -103,45 +85,3 @@ extern "C" {
|
|||
unicodeString: *mut UniChar,
|
||||
) -> OSStatus;
|
||||
}
|
||||
|
||||
// CGWindowLevel.h
|
||||
//
|
||||
// Note: There are two different things at play in this header:
|
||||
// `CGWindowLevel` and `CGWindowLevelKey`.
|
||||
//
|
||||
// It seems like there was a push towards using "key" values instead of the
|
||||
// raw window level values, and then you were supposed to use
|
||||
// `CGWindowLevelForKey` to get the actual level.
|
||||
//
|
||||
// But the values that `NSWindowLevel` has are compiled in, and as such has
|
||||
// to remain ABI compatible, so they're safe for us to hardcode as well.
|
||||
#[allow(dead_code, non_upper_case_globals)]
|
||||
mod window_level {
|
||||
const kCGNumReservedWindowLevels: i32 = 16;
|
||||
const kCGNumReservedBaseWindowLevels: i32 = 5;
|
||||
|
||||
pub const kCGBaseWindowLevel: i32 = i32::MIN;
|
||||
pub const kCGMinimumWindowLevel: i32 = kCGBaseWindowLevel + kCGNumReservedBaseWindowLevels;
|
||||
pub const kCGMaximumWindowLevel: i32 = i32::MAX - kCGNumReservedWindowLevels;
|
||||
|
||||
pub const kCGDesktopWindowLevel: i32 = kCGMinimumWindowLevel + 20;
|
||||
pub const kCGDesktopIconWindowLevel: i32 = kCGDesktopWindowLevel + 20;
|
||||
pub const kCGBackstopMenuLevel: i32 = -20;
|
||||
pub const kCGNormalWindowLevel: i32 = 0;
|
||||
pub const kCGFloatingWindowLevel: i32 = 3;
|
||||
pub const kCGTornOffMenuWindowLevel: i32 = 3;
|
||||
pub const kCGModalPanelWindowLevel: i32 = 8;
|
||||
pub const kCGUtilityWindowLevel: i32 = 19;
|
||||
pub const kCGDockWindowLevel: i32 = 20;
|
||||
pub const kCGMainMenuWindowLevel: i32 = 24;
|
||||
pub const kCGStatusWindowLevel: i32 = 25;
|
||||
pub const kCGPopUpMenuWindowLevel: i32 = 101;
|
||||
pub const kCGOverlayWindowLevel: i32 = 102;
|
||||
pub const kCGHelpWindowLevel: i32 = 200;
|
||||
pub const kCGDraggingWindowLevel: i32 = 500;
|
||||
pub const kCGScreenSaverWindowLevel: i32 = 1000;
|
||||
pub const kCGAssistiveTechHighWindowLevel: i32 = 1500;
|
||||
pub const kCGCursorWindowLevel: i32 = kCGMaximumWindowLevel - 1;
|
||||
}
|
||||
|
||||
pub use window_level::*;
|
||||
|
|
|
|||
|
|
@ -9,21 +9,12 @@ use dispatch2::run_on_main;
|
|||
use objc2::rc::Retained;
|
||||
use objc2::MainThreadMarker;
|
||||
use objc2_app_kit::NSScreen;
|
||||
use objc2_core_foundation::{
|
||||
CFArrayGetCount, CFArrayGetValueAtIndex, CFRetained, CFUUIDGetUUIDBytes,
|
||||
};
|
||||
#[allow(deprecated)]
|
||||
use objc2_core_foundation::{CFArray, CFRetained};
|
||||
use objc2_core_graphics::{
|
||||
CGDirectDisplayID, CGDisplayBounds, CGDisplayCopyAllDisplayModes, CGDisplayCopyDisplayMode,
|
||||
CGDisplayMode, CGDisplayModeCopyPixelEncoding, CGDisplayModeGetPixelHeight,
|
||||
CGDisplayModeGetPixelWidth, CGDisplayModeGetRefreshRate, CGDisplayModelNumber,
|
||||
CGGetActiveDisplayList, CGMainDisplayID,
|
||||
};
|
||||
#[allow(deprecated)]
|
||||
use objc2_core_video::{
|
||||
kCVReturnSuccess, CVDisplayLinkCreateWithCGDisplay,
|
||||
CVDisplayLinkGetNominalOutputVideoRefreshPeriod, CVTimeFlags,
|
||||
CGDisplayMode, CGDisplayModelNumber, CGGetActiveDisplayList, CGMainDisplayID,
|
||||
};
|
||||
use objc2_core_video::{kCVReturnSuccess, CVDisplayLink, CVTimeFlags};
|
||||
use objc2_foundation::{ns_string, NSNumber, NSPoint, NSRect};
|
||||
|
||||
use super::ffi;
|
||||
|
|
@ -76,7 +67,7 @@ impl VideoModeHandle {
|
|||
unsafe {
|
||||
#[allow(deprecated)]
|
||||
let pixel_encoding =
|
||||
CGDisplayModeCopyPixelEncoding(Some(&native_mode.0)).unwrap().to_string();
|
||||
CGDisplayMode::pixel_encoding(Some(&native_mode.0)).unwrap().to_string();
|
||||
let bit_depth = if pixel_encoding.eq_ignore_ascii_case(ffi::IO32BitDirectPixels) {
|
||||
32
|
||||
} else if pixel_encoding.eq_ignore_ascii_case(ffi::IO16BitDirectPixels) {
|
||||
|
|
@ -89,8 +80,8 @@ impl VideoModeHandle {
|
|||
|
||||
let mode = VideoMode {
|
||||
size: PhysicalSize::new(
|
||||
CGDisplayModeGetPixelWidth(Some(&native_mode.0)) as u32,
|
||||
CGDisplayModeGetPixelHeight(Some(&native_mode.0)) as u32,
|
||||
CGDisplayMode::pixel_width(Some(&native_mode.0)) as u32,
|
||||
CGDisplayMode::pixel_height(Some(&native_mode.0)) as u32,
|
||||
),
|
||||
refresh_rate_millihertz,
|
||||
bit_depth: NonZeroU16::new(bit_depth),
|
||||
|
|
@ -107,9 +98,12 @@ pub struct MonitorHandle(CGDirectDisplayID);
|
|||
impl MonitorHandle {
|
||||
/// Internal comparisons of [`MonitorHandle`]s are done first requesting a UUID for the handle.
|
||||
fn uuid(&self) -> u128 {
|
||||
// SAFETY: Valid to call.
|
||||
let ptr = unsafe { ffi::CGDisplayCreateUUIDFromDisplayID(self.0) };
|
||||
// SAFETY: `CGDisplayCreateUUIDFromDisplayID` is a "create" function, so the pointer has
|
||||
// +1 retain count.
|
||||
let cf_uuid = unsafe { CFRetained::from_raw(NonNull::new(ptr).unwrap()) };
|
||||
u128::from_ne_bytes(unsafe { CFUUIDGetUUIDBytes(&cf_uuid) }.into())
|
||||
u128::from_ne_bytes(cf_uuid.uuid_bytes().into())
|
||||
}
|
||||
|
||||
pub fn new(id: CGDirectDisplayID) -> Self {
|
||||
|
|
@ -126,38 +120,25 @@ impl MonitorHandle {
|
|||
let refresh_rate_millihertz = self.refresh_rate_millihertz();
|
||||
let monitor = self.clone();
|
||||
|
||||
unsafe {
|
||||
let modes = {
|
||||
let array = CGDisplayCopyAllDisplayModes(self.0, None)
|
||||
.expect("failed to get list of display modes");
|
||||
let array_count = CFArrayGetCount(&array);
|
||||
let modes: Vec<_> = (0..array_count)
|
||||
.map(move |i| {
|
||||
let mode = CFArrayGetValueAtIndex(&array, i) as *mut CGDisplayMode;
|
||||
CFRetained::retain(NonNull::new(mode).unwrap())
|
||||
})
|
||||
.collect();
|
||||
modes
|
||||
let array = unsafe { CGDisplayCopyAllDisplayModes(self.0, None) }
|
||||
.expect("failed to get list of display modes");
|
||||
// SAFETY: `CGDisplayCopyAllDisplayModes` is documented to return an array of display modes.
|
||||
let modes = unsafe { CFRetained::cast_unchecked::<CFArray<CGDisplayMode>>(array) };
|
||||
|
||||
modes.into_iter().map(move |mode| {
|
||||
let cg_refresh_rate_hertz =
|
||||
unsafe { CGDisplayMode::refresh_rate(Some(&mode)) }.round() as i64;
|
||||
|
||||
// CGDisplayModeGetRefreshRate returns 0.0 for any display that
|
||||
// isn't a CRT
|
||||
let refresh_rate_millihertz = if cg_refresh_rate_hertz > 0 {
|
||||
NonZeroU32::new((cg_refresh_rate_hertz * 1000) as u32)
|
||||
} else {
|
||||
refresh_rate_millihertz
|
||||
};
|
||||
|
||||
modes.into_iter().map(move |mode| {
|
||||
let cg_refresh_rate_hertz = CGDisplayModeGetRefreshRate(Some(&mode)).round() as i64;
|
||||
|
||||
// CGDisplayModeGetRefreshRate returns 0.0 for any display that
|
||||
// isn't a CRT
|
||||
let refresh_rate_millihertz = if cg_refresh_rate_hertz > 0 {
|
||||
NonZeroU32::new((cg_refresh_rate_hertz * 1000) as u32)
|
||||
} else {
|
||||
refresh_rate_millihertz
|
||||
};
|
||||
|
||||
VideoModeHandle::new(
|
||||
monitor.clone(),
|
||||
NativeDisplayMode(mode),
|
||||
refresh_rate_millihertz,
|
||||
)
|
||||
})
|
||||
}
|
||||
VideoModeHandle::new(monitor.clone(), NativeDisplayMode(mode), refresh_rate_millihertz)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn ns_screen(&self, mtm: MainThreadMarker) -> Option<Retained<NSScreen>> {
|
||||
|
|
@ -329,21 +310,21 @@ pub(crate) fn flip_window_screen_coordinates(frame: NSRect) -> NSPoint {
|
|||
|
||||
fn refresh_rate_millihertz(id: CGDirectDisplayID, mode: &NativeDisplayMode) -> Option<NonZeroU32> {
|
||||
unsafe {
|
||||
let refresh_rate = CGDisplayModeGetRefreshRate(Some(&mode.0));
|
||||
let refresh_rate = CGDisplayMode::refresh_rate(Some(&mode.0));
|
||||
if refresh_rate > 0.0 {
|
||||
return NonZeroU32::new((refresh_rate * 1000.0).round() as u32);
|
||||
}
|
||||
|
||||
let mut display_link = std::ptr::null_mut();
|
||||
#[allow(deprecated)]
|
||||
if CVDisplayLinkCreateWithCGDisplay(id, NonNull::from(&mut display_link))
|
||||
if CVDisplayLink::create_with_cg_display(id, NonNull::from(&mut display_link))
|
||||
!= kCVReturnSuccess
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let display_link = CFRetained::from_raw(NonNull::new(display_link).unwrap());
|
||||
#[allow(deprecated)]
|
||||
let time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(&display_link);
|
||||
let time = display_link.nominal_output_video_refresh_period();
|
||||
|
||||
// This value is indefinite if an invalid display link was specified
|
||||
if time.flags & CVTimeFlags::IsIndefinite.0 != 0 {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,8 @@ use std::time::Instant;
|
|||
use objc2::MainThreadMarker;
|
||||
use objc2_core_foundation::{
|
||||
kCFRunLoopCommonModes, kCFRunLoopDefaultMode, CFAbsoluteTimeGetCurrent, CFIndex, CFRetained,
|
||||
CFRunLoop, CFRunLoopActivity, CFRunLoopAddObserver, CFRunLoopAddTimer, CFRunLoopGetMain,
|
||||
CFRunLoopObserver, CFRunLoopObserverCallBack, CFRunLoopObserverContext,
|
||||
CFRunLoopObserverCreate, CFRunLoopPerformBlock, CFRunLoopTimer, CFRunLoopTimerCreate,
|
||||
CFRunLoopTimerInvalidate, CFRunLoopTimerSetNextFireDate, CFRunLoopWakeUp,
|
||||
CFRunLoop, CFRunLoopActivity, CFRunLoopObserver, CFRunLoopObserverCallBack,
|
||||
CFRunLoopObserverContext, CFRunLoopTimer,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
|
|
@ -95,11 +93,11 @@ impl RunLoop {
|
|||
// SAFETY: We have a MainThreadMarker here, which means we know we're on the main thread, so
|
||||
// scheduling (and scheduling a non-`Send` block) to that thread is allowed.
|
||||
let _ = mtm;
|
||||
RunLoop(unsafe { CFRunLoopGetMain() }.unwrap())
|
||||
RunLoop(CFRunLoop::main().unwrap())
|
||||
}
|
||||
|
||||
pub fn wakeup(&self) {
|
||||
unsafe { CFRunLoopWakeUp(&self.0) }
|
||||
self.0.wake_up();
|
||||
}
|
||||
|
||||
unsafe fn add_observer(
|
||||
|
|
@ -111,9 +109,9 @@ impl RunLoop {
|
|||
context: *mut CFRunLoopObserverContext,
|
||||
) {
|
||||
let observer =
|
||||
unsafe { CFRunLoopObserverCreate(None, flags.0, true, priority, handler, context) }
|
||||
unsafe { CFRunLoopObserver::new(None, flags.0, true, priority, handler, context) }
|
||||
.unwrap();
|
||||
unsafe { CFRunLoopAddObserver(&self.0, Some(&observer), kCFRunLoopCommonModes) };
|
||||
self.0.add_observer(Some(&observer), unsafe { kCFRunLoopCommonModes });
|
||||
}
|
||||
|
||||
/// Submit a closure to run on the main thread as the next step in the run loop, before other
|
||||
|
|
@ -178,7 +176,7 @@ impl RunLoop {
|
|||
let mode = unsafe { kCFRunLoopDefaultMode.unwrap() };
|
||||
|
||||
// SAFETY: The runloop is valid, the mode is a `CFStringRef`, and the block is `'static`.
|
||||
unsafe { CFRunLoopPerformBlock(&self.0, Some(mode), Some(&block)) }
|
||||
unsafe { self.0.perform_block(Some(mode), Some(&block)) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -224,7 +222,7 @@ pub struct EventLoopWaker {
|
|||
|
||||
impl Drop for EventLoopWaker {
|
||||
fn drop(&mut self) {
|
||||
unsafe { CFRunLoopTimerInvalidate(&self.timer) };
|
||||
self.timer.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +233,7 @@ impl EventLoopWaker {
|
|||
// Create a timer with a 0.1µs interval (1ns does not work) to mimic polling.
|
||||
// It is initially setup with a first fire time really far into the
|
||||
// future, but that gets changed to fire immediately in did_finish_launching
|
||||
let timer = CFRunLoopTimerCreate(
|
||||
let timer = CFRunLoopTimer::new(
|
||||
None,
|
||||
f64::MAX,
|
||||
0.000_000_1,
|
||||
|
|
@ -245,7 +243,7 @@ impl EventLoopWaker {
|
|||
ptr::null_mut(),
|
||||
)
|
||||
.unwrap();
|
||||
CFRunLoopAddTimer(&CFRunLoopGetMain().unwrap(), Some(&timer), kCFRunLoopCommonModes);
|
||||
CFRunLoop::main().unwrap().add_timer(Some(&timer), kCFRunLoopCommonModes);
|
||||
Self { timer, start_instant: Instant::now(), next_fire_date: None }
|
||||
}
|
||||
}
|
||||
|
|
@ -253,14 +251,14 @@ impl EventLoopWaker {
|
|||
pub fn stop(&mut self) {
|
||||
if self.next_fire_date.is_some() {
|
||||
self.next_fire_date = None;
|
||||
unsafe { CFRunLoopTimerSetNextFireDate(&self.timer, f64::MAX) };
|
||||
self.timer.set_next_fire_date(f64::MAX);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start(&mut self) {
|
||||
if self.next_fire_date != Some(self.start_instant) {
|
||||
self.next_fire_date = Some(self.start_instant);
|
||||
unsafe { CFRunLoopTimerSetNextFireDate(&self.timer, f64::MIN) };
|
||||
self.timer.set_next_fire_date(f64::MIN);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -273,13 +271,11 @@ impl EventLoopWaker {
|
|||
Some(instant) => {
|
||||
if self.next_fire_date != Some(instant) {
|
||||
self.next_fire_date = Some(instant);
|
||||
unsafe {
|
||||
let current = CFAbsoluteTimeGetCurrent();
|
||||
let duration = instant - now;
|
||||
let fsecs = duration.subsec_nanos() as f64 / 1_000_000_000.0
|
||||
+ duration.as_secs() as f64;
|
||||
CFRunLoopTimerSetNextFireDate(&self.timer, current + fsecs);
|
||||
}
|
||||
let current = CFAbsoluteTimeGetCurrent();
|
||||
let duration = instant - now;
|
||||
let fsecs = duration.subsec_nanos() as f64 / 1_000_000_000.0
|
||||
+ duration.as_secs() as f64;
|
||||
self.timer.set_next_fire_date(current + fsecs);
|
||||
}
|
||||
},
|
||||
None => {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,10 @@ use objc2_app_kit::{
|
|||
};
|
||||
use objc2_core_foundation::{CGFloat, CGPoint};
|
||||
use objc2_core_graphics::{
|
||||
CGAcquireDisplayFadeReservation, CGAssociateMouseAndMouseCursorPosition, CGDisplayCapture,
|
||||
CGDisplayFade, CGDisplayRelease, CGDisplaySetDisplayMode, CGReleaseDisplayFadeReservation,
|
||||
kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, kCGDisplayFadeReservationInvalidToken,
|
||||
kCGFloatingWindowLevel, kCGNormalWindowLevel, CGAcquireDisplayFadeReservation,
|
||||
CGAssociateMouseAndMouseCursorPosition, CGDisplayCapture, CGDisplayFade, CGDisplayRelease,
|
||||
CGDisplaySetDisplayMode, CGReleaseDisplayFadeReservation,
|
||||
CGRestorePermanentDisplayConfiguration, CGShieldingWindowLevel, CGWarpMouseCursorPosition,
|
||||
};
|
||||
use objc2_foundation::{
|
||||
|
|
@ -1500,7 +1502,7 @@ impl WindowDelegate {
|
|||
|
||||
let display_id = monitor.native_id() as _;
|
||||
|
||||
let mut fade_token = ffi::kCGDisplayFadeReservationInvalidToken;
|
||||
let mut fade_token = kCGDisplayFadeReservationInvalidToken;
|
||||
|
||||
if matches!(old_fullscreen, Some(Fullscreen::Borderless(_))) {
|
||||
self.ivars().save_presentation_opts.replace(Some(app.presentationOptions()));
|
||||
|
|
@ -1513,8 +1515,8 @@ impl WindowDelegate {
|
|||
CGDisplayFade(
|
||||
fade_token,
|
||||
0.3,
|
||||
ffi::kCGDisplayBlendNormal,
|
||||
ffi::kCGDisplayBlendSolidColor,
|
||||
kCGDisplayBlendNormal,
|
||||
kCGDisplayBlendSolidColor,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
|
|
@ -1538,12 +1540,12 @@ impl WindowDelegate {
|
|||
|
||||
// After the display has been configured, fade back in
|
||||
// asynchronously
|
||||
if fade_token != ffi::kCGDisplayFadeReservationInvalidToken {
|
||||
if fade_token != kCGDisplayFadeReservationInvalidToken {
|
||||
CGDisplayFade(
|
||||
fade_token,
|
||||
0.6,
|
||||
ffi::kCGDisplayBlendSolidColor,
|
||||
ffi::kCGDisplayBlendNormal,
|
||||
kCGDisplayBlendSolidColor,
|
||||
kCGDisplayBlendNormal,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
|
|
@ -1560,7 +1562,7 @@ impl WindowDelegate {
|
|||
// Window level must be restored from `CGShieldingWindowLevel()
|
||||
// + 1` back to normal in order for `toggleFullScreen` to do
|
||||
// anything
|
||||
window.setLevel(ffi::kCGNormalWindowLevel as NSWindowLevel);
|
||||
window.setLevel(kCGNormalWindowLevel as NSWindowLevel);
|
||||
window.toggleFullScreen(None);
|
||||
}
|
||||
|
||||
|
|
@ -1629,7 +1631,7 @@ impl WindowDelegate {
|
|||
|
||||
// Restore the normal window level following the Borderless fullscreen
|
||||
// `CGShieldingWindowLevel() + 1` hack.
|
||||
self.window().setLevel(ffi::kCGNormalWindowLevel as NSWindowLevel);
|
||||
self.window().setLevel(kCGNormalWindowLevel as NSWindowLevel);
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
|
|
@ -1676,10 +1678,19 @@ impl WindowDelegate {
|
|||
|
||||
#[inline]
|
||||
pub fn set_window_level(&self, level: WindowLevel) {
|
||||
// Note: There are two different things at play here:
|
||||
// `CGWindowLevel` and `CGWindowLevelKey`.
|
||||
//
|
||||
// It seems like there was a push towards using "key" values instead of the
|
||||
// raw window level values, and then you were supposed to use
|
||||
// `CGWindowLevelForKey` to get the actual level.
|
||||
//
|
||||
// But the values that `NSWindowLevel` has are compiled in, and as such has
|
||||
// to remain ABI compatible, so they're safe for us to hardcode as well.
|
||||
let level = match level {
|
||||
WindowLevel::AlwaysOnTop => ffi::kCGFloatingWindowLevel as NSWindowLevel,
|
||||
WindowLevel::AlwaysOnBottom => (ffi::kCGNormalWindowLevel - 1) as NSWindowLevel,
|
||||
WindowLevel::Normal => ffi::kCGNormalWindowLevel as NSWindowLevel,
|
||||
WindowLevel::AlwaysOnTop => kCGFloatingWindowLevel as NSWindowLevel,
|
||||
WindowLevel::AlwaysOnBottom => (kCGNormalWindowLevel - 1) as NSWindowLevel,
|
||||
WindowLevel::Normal => kCGNormalWindowLevel as NSWindowLevel,
|
||||
};
|
||||
self.window().setLevel(level);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue