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 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<WinitWindow, Shared>, 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<WinitWindow, Shared>, 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<WinitWindow, Shared>, 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<WinitWindow, Shared>,
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);
}
});

View file

@ -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