Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions winit-appkit/src/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ impl AppState {
self.control_flow.set(value)
}

pub(super) fn is_handling_event(&self) -> bool {
self.event_handler.in_use()
}

pub fn control_flow(&self) -> ControlFlow {
self.control_flow.get()
}
Expand Down
33 changes: 30 additions & 3 deletions winit-appkit/src/window_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,20 @@ impl WindowDelegate {
});
}

fn defer_if_handling_event(&self, f: impl FnOnce(Retained<Self>) + 'static) -> bool {
// AppKit state transitions such as zoom/fullscreen can synchronously run resize/display
// callbacks. Starting them from inside a winit event callback prevents those callbacks
// from being delivered immediately, so defer the transition to the next run-loop turn.
if !self.ivars().app_state.is_handling_event() {
return false;
}

let mtm = MainThreadMarker::from(self);
let this = self.retain();
MainRunLoop::get(mtm).queue_closure(move || f(this));
true
}

fn handle_scale_factor_changed(&self, scale_factor: CGFloat) {
let window = self.window();

Expand Down Expand Up @@ -1378,6 +1392,10 @@ impl WindowDelegate {

#[inline]
pub fn set_maximized(&self, maximized: bool) {
if self.defer_if_handling_event(move |this| this.set_maximized(maximized)) {
return;
}

let mtm = MainThreadMarker::from(self);
let is_zoomed = self.is_zoomed();
if is_zoomed == maximized {
Expand Down Expand Up @@ -1423,9 +1441,6 @@ impl WindowDelegate {

#[inline]
pub(crate) fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
let mtm = MainThreadMarker::from(self);
let app = NSApplication::sharedApplication(mtm);

if self.ivars().is_simple_fullscreen.get() {
return;
}
Expand All @@ -1440,6 +1455,18 @@ impl WindowDelegate {
return;
}

if !self.ivars().initial_fullscreen.get()
&& self.defer_if_handling_event({
let fullscreen = fullscreen.clone();
move |this| this.set_fullscreen(fullscreen)
})
{
return;
}

let mtm = MainThreadMarker::from(self);
let app = NSApplication::sharedApplication(mtm);

// If the fullscreen is on a different monitor, we must move the window
// to that monitor before we toggle fullscreen (as `toggleFullScreen`
// does not take a screen parameter, but uses the current screen)
Expand Down
Loading