Skip to content

demos: a snapshot holds the window's layout, so seeks back are fast - #675

Merged
foxnne merged 1 commit into
mainfrom
demos/layout-snapshot
Oct 19, 2026
Merged

foxnne merged 1 commit into
mainfrom
demos/layout-snapshot

Conversation

@foxnne

@foxnne foxnne commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up to #669 and #634 (no plan step).

What changes

Seeking back in the tour is fast again. #669 took the tour's mid-tour keyframes out, so each chapter carries on in the window the last one left. But a snapshot didn't hold the layout: restore turned away any snapshot taken in another arrangement (layoutPrint). So a seek back across the sidebar split, the float or its close went past every snapshot and replayed from the keyframe. That cost up to ~195 replay frames, ~8 displayed frames at the player's budget.

Now a demo snapshot (Demo.Snapshot) holds how the window was arranged, and a restore puts it back:

  • The app's places, as layout.zon would remember them (Editor.collectSavedRegions: extents, assignments, orders, Single/Multiple, splits, floats), kept as ZON sorted by name. They are put back with Layout.State.clearArrangement (new: resetLayout without forgetting widget sizes, the seed tree or the floats) followed by Editor.applySavedRegions. A float the snapshot had keeps its window and moves back to where it was. The others go.
  • The seed tree (DockLayout.Snapshot, ZON), rebuilt only when it differs.
  • Each place's widget state and view: _size / _shown / _open / _peek (it comes back shut or open at rest, with no ease) and the host's selection (which view a place shows, and which tab is in front in a pane). The explorer is still opened or shut by explorer_closed, as before.
  • The documents' panes: Workbench.arrangement / Workbench.arrange (new) record which panes there are, the one in front and their tree (panes.zon's form). Each document's grouping is set back as well. A restore no longer refuses a document that has moved to another pane. Where the app arranges the panes (FIZZY_WORKSPACES=1), a restore still refuses a different set of panes.

Anything already the same is left alone, so a restore within one arrangement does what it did before.

layoutPrint no longer gates a restore. It is now part of the stage's fingerprint, so a seek that lands on a wrongly arranged window counts as a mismatch. It no longer counts a float that is flying shut (layout.zon doesn't either). That was the one mismatch the stronger fingerprint turned up.

Seek times

Measured with the tour's seeks in tests/demos.zig (the same random and chapter-start seeks both times), headless, ReleaseFast, on this Mac. "Frames" are the replay runs a seek needed; wall time is the whole seek.

seek main (#669) this PR
57490 → Materials 39490 keyframe, 190 frames, 62.3 ms snapshot, 2 frames, 1.2 ms
7480 → Materials 37740 148 frames, 52.4 ms 3 frames, 1.6 ms
3600 → Plugins 42510 151 frames, 62.4 ms 5 frames, 2.2 ms
46940 → Plugins 44540 keyframe, 195 frames, 75.6 ms snapshot, 2 frames, 1.1 ms
51000 → Floats 28990 keyframe, 187 frames, 72.4 ms snapshot, 35 frames, 16.0 ms (lands mid float drag, which replays a frame per 16 ms)
37740 → Floats 22120 keyframe, 120 frames, 31.2 ms snapshot, 5 frames, 2.3 ms
64290 → Places 11610 keyframe, 108 frames, 25.9 ms snapshot, 5 frames, 1.6 ms
11610 → History 57790 keyframe, 94 frames, 58.1 ms snapshot, 4 frames, 2.9 ms

After this PR, every seek in that run landed from a snapshot. On main, 12 of the 24 replayed from the keyframe.

SDK impact

  • Additive: Host.clearSelectionForKey, beside setSelectionForKey, so the app stops writing the Host's selection map directly. The fingerprint is unchanged (test-sdk-version passes), and plugins see the method at the next SDK release. Workbench, Layout.State and Demo are not on the plugin boundary.

Verified

  • macOS: scripts/check-fmt.sh, zig build, zig build test, zig build test-integration (81/81 steps), zig build check-web, zig build test-sdk-version. tests/demos.zig now fails a seek back that replays from the keyframe when its scene has a snapshot before the moment (it fails on main), and its fingerprint check now covers the layout.
  • Windows: CI
  • Linux: CI (test-integration)
  • Web: check-web only

Review (code-review, medium)

Fixed:

  • A restore that failed partway still returned true. restoreArrangement now does everything that can fail first (parsing the ZON, building the seed tree, the panes via Workbench.arrange, which is all or nothing), then changes things. It also runs before anything else in restore, so a failure leaves the app as it was and the seek falls back to an earlier snapshot.
  • Floats kept on restore lost their stacking order and, when popped out, their OS window's position. Floats are now kept only as far as they match the snapshot bottom to top, rect included. From the first one that differs, they are re-made from the snapshot in its order.
  • A place drawn now that the snapshot didn't have (a split made since) kept its widget state, so a split of the same name made again would open at the old size. Its widget state is now forgotten (State.forgetWidgetSize, now public).
  • The Host's selection map was written directly. That now goes through Host.clearSelectionForKey.

Left as is:

  • The rebuilt trees are animated = true. That only enables later splits and closes to slide; a tree built from a snapshot starts at rest. loadTree does the same.
  • A plugin's own by-name places (not the workbench panes) are not put back. Neither did layoutPrint's gate before this.
  • Each capture now serializes the layout as ZON. Captures happen only at calm moments while a demo plays, at a few KB each.
  • With FIZZY_WORKSPACES=1 the same panes in another order are refused. That mode is behind a flag, and a refusal just replays.
  • The new test assertion would also fail a demo that closes a document mid-scene, which correctly refuses a snapshot. The comment says to give such a demo a keyframe after the close.

The seek times above were measured before the review fixes, which change only how a restore that differs is ordered.

Follow-ups

  • None planned.

🤖 Generated with Claude Code

…gain

A demo snapshot now keeps how the window was arranged — the app's places as
`layout.zon` would remember them, the seed tree, each place's size and view, the
floats and the documents' panes — and a restore puts it back, instead of
refusing a window arranged otherwise and replaying from the keyframe.
@foxnne
foxnne force-pushed the demos/layout-snapshot branch from 2dd372d to 6981e91 Compare October 19, 2026 23:01
@foxnne
foxnne marked this pull request as ready for review October 19, 2026 23:13
@foxnne
foxnne added this pull request to the merge queue Oct 19, 2026
Merged via the queue into main with commit 5216544 Oct 19, 2026
11 checks passed
@foxnne
foxnne deleted the demos/layout-snapshot branch October 19, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant