diff --git a/winit-appkit/src/lib.rs b/winit-appkit/src/lib.rs index 3ff9c82f49..e8a0779f85 100644 --- a/winit-appkit/src/lib.rs +++ b/winit-appkit/src/lib.rs @@ -101,6 +101,13 @@ use self::window::Window as AppKitWindow; /// Additional methods on [`Window`] that are specific to MacOS. pub trait WindowExtMacOS { + /// This is `true` only while the user is interactively resizing the window + /// or AppKit is running an equivalent native resize transition. + fn is_live_resizing(&self) -> bool; + + /// Returns whether AppKit is currently entering or exiting native fullscreen. + fn is_fullscreen_transition(&self) -> bool; + /// Returns whether or not the window is in simple fullscreen mode. fn simple_fullscreen(&self) -> bool; @@ -210,6 +217,18 @@ pub trait WindowExtMacOS { } impl WindowExtMacOS for dyn Window + '_ { + #[inline] + fn is_live_resizing(&self) -> bool { + let window = self.cast_ref::().unwrap(); + window.maybe_wait_on_main(|w| w.is_live_resizing()) + } + + #[inline] + fn is_fullscreen_transition(&self) -> bool { + let window = self.cast_ref::().unwrap(); + window.maybe_wait_on_main(|w| w.is_fullscreen_transition()) + } + #[inline] fn simple_fullscreen(&self) -> bool { let window = self.cast_ref::().unwrap(); diff --git a/winit-appkit/src/window_delegate.rs b/winit-appkit/src/window_delegate.rs index 8bc14e3df8..f564fd513b 100644 --- a/winit-appkit/src/window_delegate.rs +++ b/winit-appkit/src/window_delegate.rs @@ -147,6 +147,7 @@ define_class!( #[unsafe(method(windowDidResize:))] fn window_did_resize(&self, _: Option<&AnyObject>) { let _entered = debug_span!("windowDidResize:").entered(); + self.refresh_maximized(); // NOTE: WindowEvent::SurfaceResized is reported using NSViewFrameDidChangeNotification. self.emit_move_event(); } @@ -162,6 +163,7 @@ define_class!( #[unsafe(method(windowDidEndLiveResize:))] fn window_did_end_live_resize(&self, _: Option<&AnyObject>) { let _entered = debug_span!("windowDidEndLiveResize:").entered(); + self.refresh_maximized(); self.set_resize_increments_inner(NSSize::new(1., 1.)); } @@ -279,6 +281,7 @@ define_class!( let _entered = debug_span!("windowDidEnterFullScreen:").entered(); self.ivars().initial_fullscreen.set(false); self.ivars().in_fullscreen_transition.set(false); + self.request_redraw(); if let Some(target_fullscreen) = self.ivars().target_fullscreen.take() { self.set_fullscreen(target_fullscreen); } @@ -291,6 +294,7 @@ define_class!( self.restore_state_from_fullscreen(); self.ivars().in_fullscreen_transition.set(false); + self.request_redraw(); if let Some(target_fullscreen) = self.ivars().target_fullscreen.take() { self.set_fullscreen(target_fullscreen); } @@ -1187,6 +1191,10 @@ impl WindowDelegate { self.ivars().app_state.queue_redraw(window_id(self.window())); } + fn refresh_maximized(&self) { + self.ivars().maximized.set(self.is_zoomed()); + } + #[inline] pub fn pre_present_notify(&self) {} @@ -1522,6 +1530,7 @@ impl WindowDelegate { let event = NSApplication::sharedApplication(mtm).currentEvent().ok_or(RequestError::Ignored)?; self.window().performWindowDragWithEvent(&event); + self.refresh_maximized(); Ok(()) } @@ -1530,6 +1539,14 @@ impl WindowDelegate { Err(NotSupportedError::new("drag_resize_window is not supported")) } + pub fn is_live_resizing(&self) -> bool { + self.window().inLiveResize() + } + + pub fn is_fullscreen_transition(&self) -> bool { + self.ivars().in_fullscreen_transition.get() + } + #[inline] pub fn show_window_menu(&self, _position: Position) {} @@ -1606,6 +1623,7 @@ impl WindowDelegate { let mtm = MainThreadMarker::from(self); let is_zoomed = self.is_zoomed(); if is_zoomed == maximized { + self.ivars().maximized.set(maximized); return; }; @@ -1643,7 +1661,7 @@ impl WindowDelegate { #[inline] pub fn is_maximized(&self) -> bool { - self.is_zoomed() + self.ivars().maximized.get() } #[inline] @@ -2085,6 +2103,16 @@ fn restore_and_release_display(monitor: &MonitorHandle) { } impl WindowExtMacOS for WindowDelegate { + #[inline] + fn is_live_resizing(&self) -> bool { + WindowDelegate::is_live_resizing(self) + } + + #[inline] + fn is_fullscreen_transition(&self) -> bool { + WindowDelegate::is_fullscreen_transition(self) + } + #[inline] fn simple_fullscreen(&self) -> bool { self.ivars().is_simple_fullscreen.get() diff --git a/winit/src/changelog/unreleased.md b/winit/src/changelog/unreleased.md index e2f7326ea6..e961d4cde4 100644 --- a/winit/src/changelog/unreleased.md +++ b/winit/src/changelog/unreleased.md @@ -48,6 +48,8 @@ changelog entry. - On Redox, add support for `EventLoopExtPumpEvents::pump_app_events`. - Implement `Send` and `Sync` for `OwnedDisplayHandle`. - Use new macOS 15 cursors for resize icons. +- On macOS, add `WindowExtMacOS::is_live_resizing` and + `WindowExtMacOS::is_fullscreen_transition`. - On Android, added scancode conversions for more obscure key codes. - On Wayland, added `HoldGesture` event for multi-finger hold gestures - On Wayland, added ext-background-effect-v1 support. @@ -78,3 +80,4 @@ changelog entry. - On macOS, fix IME being locked on (regardless of requests to disable) after being enabled once. - On macOS, fix a panic and incorrect cursor position in Ime::Preedit when the preedit string contains special characters (ie. emojis) caused by incorrect UTF-16 to UTF-8 offset conversion. - On Wayland, fix a protocol error when setting a custom cursor on compositors with `wl_surface` version below 3. +- On macOS, avoid querying AppKit's zoom state from `Window::is_maximized`.