Fix AppKit live resize redraw timing#4588
Draft
yay wants to merge 1 commit into
Draft
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This fixes macOS live-resize behavior for layer-backed winit views.
While investigating resize artifacts in a downstream app, I found that AppKit can update and ask a layer-backed content view to display during live resize through paths that winit was not fully using for surface resize/redraw timing.
The main issue is that during live resize, especially when resizing from the top or left edge, the view backing size and redraw timing need to stay synchronized with AppKit's resize/display callbacks. Otherwise surface users can render with stale size information or miss redraw opportunities during the event-tracking run loop.
This PR changes the AppKit view path to:
NSViewLayerContentsRedrawDuringViewResizefor the content viewsetFrameSize:by updating the surface size and requesting redraw during live resizeviewDidChangeBackingPropertiesfor backing-scale/backing-size changesdisplayLayer:as a redraw signal during live resizeconvertRectToBacking(bounds)instead of deriving it from the window/frame sizeThe main issue is that during live resize, especially when resizing from the top or left edge, the view backing size and redraw timing need to stay synchronized with AppKit's resize/display callbacks. Otherwise surface users can render with stale size information or miss redraw opportunities during the event-tracking run loop. In practice this shows up as visible wobble/jitter and stale or stretched frames while the window edge is being dragged.
I also looked at other AppKit/Metal applications with smooth live resize behavior while narrowing this down.
Validation
I used a small winit +
CAMetalLayerdemo that:WindowEvent::RedrawRequestedCAMetalLayer.presentsWithTransactionI recorded the same demo before and after the fix:
Before (notice the ghosting):
before-the-fix.mp4
After:
after-the-fix.mp4
In the before video, live resize shows stale/stretched frames. In the after video, resizing from all four edges stays synchronized and smooth.
I also validated the same change against winit
0.30.13, since that is the version used by the downstream app where I first reproduced the issue.