Skip to content

AppKit: Fix window content scaling like a static image on programmatic maximize/restore#4589

Open
yay wants to merge 1 commit into
rust-windowing:masterfrom
yay:steady/macos-defer-reentrant-zoom
Open

AppKit: Fix window content scaling like a static image on programmatic maximize/restore#4589
yay wants to merge 1 commit into
rust-windowing:masterfrom
yay:steady/macos-defer-reentrant-zoom

Conversation

@yay

@yay yay commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

This fixes a macOS programmatic maximize/restore case that shows up with custom titlebars.

When a resizable AppKit window is maximized through Window::set_maximized, winit calls NSWindow::zoom. AppKit runs that zoom animation synchronously and emits intermediate live-resize callbacks while the animation is in progress.

If set_maximized is requested from inside a winit event callback, winit is already handling an event when NSWindow::zoom starts. In that state, the intermediate resize/redraw work cannot be delivered to the application until after the zoom call returns. The visible result is that the window animation stretches the previous layer contents like a static image instead of redrawing the app at the intermediate window sizes.

This PR defers only the reentrant macOS set_maximized path to the next main run-loop turn. That lets AppKit run the zoom animation after the current winit event callback returns, so intermediate resize/display callbacks can be processed normally during the animation.

This is related to but separate from #4588. That PR improves AppKit live-resize redraw timing once AppKit is driving resize callbacks. This PR avoids starting AppKit's zoom animation while winit is already inside an application event callback.

I used a small eframe/wgpu demo with a custom toolbar to reproduce this: double-clicking the toolbar background sends ViewportCommand::Maximized(...). Before this fix, maximize/restore visually stretches the old window contents during the native animation. After this fix, the app relayouts/redraws during the animation.

Before:

winit-zoom-before.mp4

After:

winit-zoom-after.mp4

@yay yay marked this pull request as ready for review June 7, 2026 17:07
@yay yay requested a review from madsmtm as a code owner June 7, 2026 17:07
@yay yay force-pushed the steady/macos-defer-reentrant-zoom branch from 50006da to 11ad85f Compare June 13, 2026 18:03
@kchibisov

Copy link
Copy Markdown
Member

Wouldn't it be an issue for fullscreen,etc? Basically state changes that trigger animation? If so would be nice to have similar logic in them as well?

@yay yay force-pushed the steady/macos-defer-reentrant-zoom branch from 11ad85f to 73130e8 Compare June 25, 2026 08:50
@yay

yay commented Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

@kchibisov Good point. I generalized the deferral into defer_if_handling_event and now use it for both set_maximized and fullscreen transitions.

@yay yay changed the title Defer macOS zoom during event handling macOS: Fix window content scaling like a static image on programmatic maximize/restore Jun 27, 2026
@yay yay changed the title macOS: Fix window content scaling like a static image on programmatic maximize/restore AppKit: Fix window content scaling like a static image on programmatic maximize/restore Jun 27, 2026
@yay yay force-pushed the steady/macos-defer-reentrant-zoom branch from 73130e8 to 762e17f Compare June 27, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants