mirror of
https://github.com/rust-windowing/winit.git
synced 2026-09-03 07:10:05 -04:00
macOS: defer native transitions during event handling
This commit is contained in:
committed by
GitHub
parent
aa6410de30
commit
9e78b4c2a7
@@ -269,6 +269,10 @@ impl AppState {
|
|||||||
self.control_flow.set(value)
|
self.control_flow.set(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) fn is_handling_event(&self) -> bool {
|
||||||
|
self.event_handler.in_use()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn control_flow(&self) -> ControlFlow {
|
pub fn control_flow(&self) -> ControlFlow {
|
||||||
self.control_flow.get()
|
self.control_flow.get()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1102,6 +1102,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) {
|
fn handle_scale_factor_changed(&self, scale_factor: CGFloat) {
|
||||||
let window = self.window();
|
let window = self.window();
|
||||||
|
|
||||||
@@ -1710,6 +1724,10 @@ impl WindowDelegate {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_maximized(&self, maximized: bool) {
|
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 mtm = MainThreadMarker::from(self);
|
||||||
let is_zoomed = self.is_zoomed();
|
let is_zoomed = self.is_zoomed();
|
||||||
if is_zoomed == maximized {
|
if is_zoomed == maximized {
|
||||||
@@ -1755,9 +1773,6 @@ impl WindowDelegate {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
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() {
|
if self.ivars().is_simple_fullscreen.get() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1786,6 +1801,18 @@ impl WindowDelegate {
|
|||||||
return;
|
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
|
// If the fullscreen is on a different monitor, we must move the window
|
||||||
// to that monitor before we toggle fullscreen (as `toggleFullScreen`
|
// to that monitor before we toggle fullscreen (as `toggleFullScreen`
|
||||||
// does not take a screen parameter, but uses the current screen)
|
// does not take a screen parameter, but uses the current screen)
|
||||||
|
|||||||
Reference in New Issue
Block a user