From 90f71b301c9f9eca8d270c64d7946a04b4fb221b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Tue, 29 Nov 2022 12:43:15 +0100 Subject: [PATCH] Do fullscreen logic synchronously on main thread --- src/platform_impl/macos/util/async.rs | 24 +++++++++++------------- src/platform_impl/macos/window.rs | 24 +++++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/platform_impl/macos/util/async.rs b/src/platform_impl/macos/util/async.rs index f85d39bd10..6edbd8db6f 100644 --- a/src/platform_impl/macos/util/async.rs +++ b/src/platform_impl/macos/util/async.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use dispatch::Queue; use objc2::foundation::{is_main_thread, CGFloat, NSPoint, NSSize, NSString}; -use objc2::rc::{autoreleasepool, Id, Shared}; +use objc2::rc::autoreleasepool; use crate::{ dpi::LogicalSize, @@ -90,9 +90,9 @@ pub(crate) fn set_ignore_mouse_events_sync(window: &NSWindow, ignore: bool) { // `toggleFullScreen` is thread-safe, but our additional logic to account for // window styles isn't. -pub(crate) fn toggle_full_screen_async(window: Id, not_fullscreen: bool) { +pub(crate) fn toggle_full_screen_sync(window: &WinitWindow, not_fullscreen: bool) { let window = MainThreadSafe(window); - Queue::main().exec_async(move || { + run_on_main(move || { // `toggleFullScreen` doesn't work if the `StyleMask` is none, so we // set a normal style temporarily. The previous state will be // restored in `WindowDelegate::window_did_exit_fullscreen`. @@ -103,7 +103,7 @@ pub(crate) fn toggle_full_screen_async(window: Id, not_full if !curr_mask.contains(required) { set_style_mask(&window, required); window - .lock_shared_state("toggle_full_screen_async") + .lock_shared_state("toggle_full_screen_sync") .saved_style = Some(curr_mask); } } @@ -115,8 +115,8 @@ pub(crate) fn toggle_full_screen_async(window: Id, not_full }); } -pub(crate) unsafe fn restore_display_mode_async(ns_screen: u32) { - Queue::main().exec_async(move || { +pub(crate) unsafe fn restore_display_mode_sync(ns_screen: u32) { + run_on_main(move || { unsafe { ffi::CGRestorePermanentDisplayConfiguration() }; assert_eq!( unsafe { ffi::CGDisplayRelease(ns_screen) }, @@ -126,14 +126,10 @@ pub(crate) unsafe fn restore_display_mode_async(ns_screen: u32) { } // `setMaximized` is not thread-safe -pub(crate) fn set_maximized_async( - window: Id, - is_zoomed: bool, - maximized: bool, -) { +pub(crate) fn set_maximized_sync(window: &WinitWindow, is_zoomed: bool, maximized: bool) { let window = MainThreadSafe(window); - Queue::main().exec_async(move || { - let mut shared_state = window.lock_shared_state("set_maximized_async"); + run_on_main(move || { + let mut shared_state = window.lock_shared_state("set_maximized_sync"); // Save the standard frame sized if it is not zoomed if !is_zoomed { shared_state.standard_frame = Some(window.frame()); @@ -150,6 +146,7 @@ pub(crate) fn set_maximized_async( .styleMask() .contains(NSWindowStyleMask::NSResizableWindowMask) { + drop(shared_state); // Just use the native zoom if resizable window.zoom(None); } else { @@ -160,6 +157,7 @@ pub(crate) fn set_maximized_async( } else { shared_state.saved_standard_frame() }; + drop(shared_state); window.setFrame_display(new_rect, false); } }); diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index faf40ae0b5..f605b6a467 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -826,7 +826,7 @@ impl WinitWindow { if is_zoomed == maximized { return; }; - util::set_maximized_async(self.retain(), is_zoomed, maximized); + util::set_maximized_sync(self, is_zoomed, maximized); } #[inline] @@ -956,23 +956,22 @@ impl WinitWindow { } } - let mut shared_state_lock = self.lock_shared_state("set_fullscreen"); - shared_state_lock.fullscreen = fullscreen.clone(); + self.lock_shared_state("set_fullscreen").fullscreen = fullscreen.clone(); match (&old_fullscreen, &fullscreen) { (&None, &Some(_)) => { - util::toggle_full_screen_async(self.retain(), old_fullscreen.is_none()); + util::toggle_full_screen_sync(self, old_fullscreen.is_none()); } (&Some(Fullscreen::Borderless(_)), &None) => { // State is restored by `window_did_exit_fullscreen` - util::toggle_full_screen_async(self.retain(), old_fullscreen.is_none()); + util::toggle_full_screen_sync(self, old_fullscreen.is_none()); } (&Some(Fullscreen::Exclusive(ref video_mode)), &None) => { unsafe { - util::restore_display_mode_async(video_mode.monitor().native_identifier()) + util::restore_display_mode_sync(video_mode.monitor().native_identifier()) }; // Rest of the state is restored by `window_did_exit_fullscreen` - util::toggle_full_screen_async(self.retain(), old_fullscreen.is_none()); + util::toggle_full_screen_sync(self, old_fullscreen.is_none()); } (&Some(Fullscreen::Borderless(_)), &Some(Fullscreen::Exclusive(_))) => { // If we're already in fullscreen mode, calling @@ -984,7 +983,8 @@ impl WinitWindow { // that the menu bar is disabled. This is done in the window // delegate in `window:willUseFullScreenPresentationOptions:`. let app = NSApp(); - shared_state_lock.save_presentation_opts = Some(app.presentationOptions()); + self.lock_shared_state("set_fullscreen") + .save_presentation_opts = Some(app.presentationOptions()); let presentation_options = NSApplicationPresentationOptions::NSApplicationPresentationFullScreen @@ -997,8 +997,10 @@ impl WinitWindow { self.setLevel(window_level); } (&Some(Fullscreen::Exclusive(ref video_mode)), &Some(Fullscreen::Borderless(_))) => { - let presentation_options = - shared_state_lock.save_presentation_opts.unwrap_or_else(|| { + let presentation_options = self + .lock_shared_state("set_fullscreen") + .save_presentation_opts + .unwrap_or_else(|| { NSApplicationPresentationOptions::NSApplicationPresentationFullScreen | NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock | NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar @@ -1006,7 +1008,7 @@ impl WinitWindow { NSApp().setPresentationOptions(presentation_options); unsafe { - util::restore_display_mode_async(video_mode.monitor().native_identifier()) + util::restore_display_mode_sync(video_mode.monitor().native_identifier()) }; // Restore the normal window level following the Borderless fullscreen