fix(viewer): kick render on focus and visibility resume#291
Open
mvanhorn wants to merge 1 commit intopascalorg:mainfrom
Open
fix(viewer): kick render on focus and visibility resume#291mvanhorn wants to merge 1 commit intopascalorg:mainfrom
mvanhorn wants to merge 1 commit intopascalorg:mainfrom
Conversation
`frameloop="never"` makes FrameLimiter's requestAnimationFrame loop the only render driver. Browsers throttle rAF when the tab is hidden, the window is unfocused, or the system marks the tab as occluded; when that happens advance() stops firing and the canvas freezes on whatever was last in the swap chain (blank on first paint, or the previous frame on subsequent freezes). Listen to visibilitychange (visible), focus, and pageshow alongside the existing rAF loop. Each event calls advance() synchronously so the next visible frame matches the current scene state without waiting for rAF to resume. Fixes pascalorg#275 Closes pascalorg#196
Contributor
Author
|
Before/after recorded locally on macOS Chrome 147 in the chrome MCP harness, which holds Frame 1 is the broken state on reload (blank canvas, faded toolbar). The click triggers a |
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.

What does this PR do?
frameloop="never"makes FrameLimiter'srequestAnimationFrameloop the only render driver. Browsers throttle rAF when the tab is hidden, the window is unfocused, or the system marks the tab as occluded. When that happensadvance()stops firing and the canvas stays whatever was last in the swap chain (blank on first paint, or the previous frame on subsequent freezes).This adds three event listeners alongside the existing rAF loop.
visibilitychange(transitioning tovisible), windowfocus, andpageshoweach calladvance()synchronously so the next visible frame matches the current scene state without waiting for rAF to resume.The fix is contained to
packages/viewer/src/components/viewer/frame-limiter.tsx(+21/-0). No new imports. No layer-boundary changes.Fixes #275
Closes #196
Why prior fixes don't cover this
navigator.gpuis undefinedNone of those address rAF throttling. Once the throttle hits, every render path stalls because
useFrameonly runs whenadvance()is called.How to test
bun install && bun dev, open the editor in Chrome or Firefox.Without the fix, the viewer can stay frozen (blank or stale) until you move the mouse over the canvas. With the fix, the viewer renders the current scene immediately on tab return.
A second reproducer: open Pascal in a focused tab, drag another window over Pascal so it occludes the canvas, then move that window away. Some Linux WMs (and Zen on Windows) trigger the same rAF throttle that this fix recovers from.
Screenshots / screen recording
Before/after recorded locally on macOS Chrome 147 in the chrome MCP harness, which holds
document.visibilityState === 'hidden'so the throttle path fires reliably. Frame 1 is the broken state on reload (blank canvas, faded toolbar). The click triggers afocusevent, the new handler callsadvance(), the scene renders.Checklist
bun devbun checkpasses)frame-limiter.tsxdocuments the rationalemainbranch