Do fullscreen logic synchronously on main thread (#2575)

This commit is contained in:
Mads Marquart 2022-11-30 14:49:18 +01:00 committed by GitHub
parent bf92f3e97b
commit 2e4d79f57a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 24 deletions

View file

@ -2,7 +2,7 @@ use std::ops::Deref;
use dispatch::Queue; use dispatch::Queue;
use objc2::foundation::{is_main_thread, CGFloat, NSPoint, NSSize, NSString}; use objc2::foundation::{is_main_thread, CGFloat, NSPoint, NSSize, NSString};
use objc2::rc::{autoreleasepool, Id, Shared}; use objc2::rc::autoreleasepool;
use crate::{ use crate::{
dpi::LogicalSize, 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 // `toggleFullScreen` is thread-safe, but our additional logic to account for
// window styles isn't. // window styles isn't.
pub(crate) fn toggle_full_screen_async(window: Id<WinitWindow, Shared>, not_fullscreen: bool) { pub(crate) fn toggle_full_screen_sync(window: &WinitWindow, not_fullscreen: bool) {
let window = MainThreadSafe(window); let window = MainThreadSafe(window);
Queue::main().exec_async(move || { run_on_main(move || {
// `toggleFullScreen` doesn't work if the `StyleMask` is none, so we // `toggleFullScreen` doesn't work if the `StyleMask` is none, so we
// set a normal style temporarily. The previous state will be // set a normal style temporarily. The previous state will be
// restored in `WindowDelegate::window_did_exit_fullscreen`. // restored in `WindowDelegate::window_did_exit_fullscreen`.
@ -103,7 +103,7 @@ pub(crate) fn toggle_full_screen_async(window: Id<WinitWindow, Shared>, not_full
if !curr_mask.contains(required) { if !curr_mask.contains(required) {
set_style_mask(&window, required); set_style_mask(&window, required);
window window
.lock_shared_state("toggle_full_screen_async") .lock_shared_state("toggle_full_screen_sync")
.saved_style = Some(curr_mask); .saved_style = Some(curr_mask);
} }
} }
@ -115,8 +115,8 @@ pub(crate) fn toggle_full_screen_async(window: Id<WinitWindow, Shared>, not_full
}); });
} }
pub(crate) unsafe fn restore_display_mode_async(ns_screen: u32) { pub(crate) unsafe fn restore_display_mode_sync(ns_screen: u32) {
Queue::main().exec_async(move || { run_on_main(move || {
unsafe { ffi::CGRestorePermanentDisplayConfiguration() }; unsafe { ffi::CGRestorePermanentDisplayConfiguration() };
assert_eq!( assert_eq!(
unsafe { ffi::CGDisplayRelease(ns_screen) }, 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 // `setMaximized` is not thread-safe
pub(crate) fn set_maximized_async( pub(crate) fn set_maximized_sync(window: &WinitWindow, is_zoomed: bool, maximized: bool) {
window: Id<WinitWindow, Shared>,
is_zoomed: bool,
maximized: bool,
) {
let window = MainThreadSafe(window); let window = MainThreadSafe(window);
Queue::main().exec_async(move || { run_on_main(move || {
let mut shared_state = window.lock_shared_state("set_maximized_async"); let mut shared_state = window.lock_shared_state("set_maximized_sync");
// Save the standard frame sized if it is not zoomed // Save the standard frame sized if it is not zoomed
if !is_zoomed { if !is_zoomed {
shared_state.standard_frame = Some(window.frame()); shared_state.standard_frame = Some(window.frame());
@ -150,6 +146,7 @@ pub(crate) fn set_maximized_async(
.styleMask() .styleMask()
.contains(NSWindowStyleMask::NSResizableWindowMask) .contains(NSWindowStyleMask::NSResizableWindowMask)
{ {
drop(shared_state);
// Just use the native zoom if resizable // Just use the native zoom if resizable
window.zoom(None); window.zoom(None);
} else { } else {
@ -160,6 +157,7 @@ pub(crate) fn set_maximized_async(
} else { } else {
shared_state.saved_standard_frame() shared_state.saved_standard_frame()
}; };
drop(shared_state);
window.setFrame_display(new_rect, false); window.setFrame_display(new_rect, false);
} }
}); });

View file

@ -826,7 +826,7 @@ impl WinitWindow {
if is_zoomed == maximized { if is_zoomed == maximized {
return; return;
}; };
util::set_maximized_async(self.retain(), is_zoomed, maximized); util::set_maximized_sync(self, is_zoomed, maximized);
} }
#[inline] #[inline]
@ -956,23 +956,22 @@ impl WinitWindow {
} }
} }
let mut shared_state_lock = self.lock_shared_state("set_fullscreen"); self.lock_shared_state("set_fullscreen").fullscreen = fullscreen.clone();
shared_state_lock.fullscreen = fullscreen.clone();
match (&old_fullscreen, &fullscreen) { match (&old_fullscreen, &fullscreen) {
(&None, &Some(_)) => { (&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) => { (&Some(Fullscreen::Borderless(_)), &None) => {
// State is restored by `window_did_exit_fullscreen` // 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) => { (&Some(Fullscreen::Exclusive(ref video_mode)), &None) => {
unsafe { 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` // 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(_))) => { (&Some(Fullscreen::Borderless(_)), &Some(Fullscreen::Exclusive(_))) => {
// If we're already in fullscreen mode, calling // 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 // that the menu bar is disabled. This is done in the window
// delegate in `window:willUseFullScreenPresentationOptions:`. // delegate in `window:willUseFullScreenPresentationOptions:`.
let app = NSApp(); 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 = let presentation_options =
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
@ -997,8 +997,10 @@ impl WinitWindow {
self.setLevel(window_level); self.setLevel(window_level);
} }
(&Some(Fullscreen::Exclusive(ref video_mode)), &Some(Fullscreen::Borderless(_))) => { (&Some(Fullscreen::Exclusive(ref video_mode)), &Some(Fullscreen::Borderless(_))) => {
let presentation_options = let presentation_options = self
shared_state_lock.save_presentation_opts.unwrap_or_else(|| { .lock_shared_state("set_fullscreen")
.save_presentation_opts
.unwrap_or_else(|| {
NSApplicationPresentationOptions::NSApplicationPresentationFullScreen NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock | NSApplicationPresentationOptions::NSApplicationPresentationAutoHideDock
| NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar | NSApplicationPresentationOptions::NSApplicationPresentationAutoHideMenuBar
@ -1006,7 +1008,7 @@ impl WinitWindow {
NSApp().setPresentationOptions(presentation_options); NSApp().setPresentationOptions(presentation_options);
unsafe { 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 // Restore the normal window level following the Borderless fullscreen