Repository navigation
Keep the browse scroll view out of fullscreen transitions - #3
Open
Puellaquae wants to merge 1 commit into
Open
Puellaquae wants to merge 1 commit into
Puellaquae wants to merge 1 commit into
Conversation
AppKit aborts a window's display cycle when a SwiftUI scroll view keeps resizing its document view during a fullscreen animation: every pass marks vibrancy as needing an update, which asks for another pass, and the cycle ends in NSGenericException once there have been more passes than the window has views. The launch transition hits it whenever the pointer is inside the window and the library is still filling in, so the scroll view is absent until the transition's own display cycles are over. Notification delivery is synchronous, and the gate lifts only after two window updates, because both edges have to land outside the animation's display passes.
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.
Summary
EXC_BREAKPOINT; the uncaught exception isNSGenericException: The window has been marked as needing another Display Window pass, but it has already had more Display Window passes than there are views in the window.HostingScrollView.updateContext, which resizes the document view;NSClipView._reflectDocumentViewFrameChangere-clamps the scroll origin, which marks vibrancy needing an update, which asks for another pass. The next pass hit-tests (-[NSTrackingAreaAKManager setCursorForMouseLocation:]), and SwiftUI'sNSHostingView.hitTestforces a synchronous AttributeGraph update — back to the resize. AppKit gives up once passes exceed the view count (observed: 3246).ScrollViewout of the view tree for the duration of a fullscreen transition, so the loop has no receiver.NSHostingView.sizingOptions = []in 启动崩溃 #2 removes one input to the loop; this removes the step that re-enters it, so the two are complementary rather than alternative.Changes
AppModel.windowIsTransitioning(published) plus a pre-set at the app's owntoggleFullScreencall sites.ApplicationLifecycle.observeFullScreenTransition:willEnter/willExitset the gate synchronously (queue: nil+MainActor.assumeIsolated);didEnter/didExitonly arm the release, which happens after twoNSWindow.didUpdateNotificationpasses so the content is not re-inserted inside the animation's own display cycles.RootViewrenders the browseScrollViewonly when the gate is closed.Evidence
mainbefore the gate, launch with fullscreen--windowed(no transition)Test plan
--windowed) with the pointer resting inside the window and moving during the animation; repeat ~5 cold starts and confirm noMTV-*.ipsin~/Library/Logs/DiagnosticReportsEsc/Ctrl-Cmd-Fand re-enter from the settings row; content must return at the new sizemainalone: ifsizingOptions = []already prevents the loop in your environment, say so and the gate can be droppedKnown gap
Thirteen other
ScrollViewsites (SMB, metadata, tracks, About, panels) are not gated. They need the same three conditions — live resize, pending invalidations, and a hit test — so opening a panel and then toggling fullscreen is still exposed. Extending the gate to a shared view modifier is the obvious follow-up.