Repository navigation
feat(windows): reopen every window of the last session - #990
Merged
Merged
Conversation
Main keeps window-state-v2.json and restore-progress-v1.json, so an existing session is main's entry with no migration. Every window-* label gets window-state/<label>.json and restore-progress/<label>.json, each written only by the window that owns the label, so windows closing at once (quit) can no longer overwrite one another. New commands: forget_window_state drops the caller's snapshot and breadcrumb; reopen_remembered_windows rebuilds each remembered window under its saved label through the same factory as tear-off windows. clear_window_state now clears every window's state. The window-state plugin no longer folds window-* labels into one "secondary" entry, so each window gets its own size and position back.
Each window restores its own snapshot under the existing crash guard, now keyed by its label. Main restores first, then reopens the other remembered windows; a reopened window skips the tab-transfer claim and the pinned-group load, so its snapshot owns its tabs. A window is remembered on quit, when it is the last one, and on update. Closing one of several windows, merging it away, or closing its last tab forgets it, the same predicate #962 uses to decide hot exit. Unsaved backups follow their window: a reopened window takes its own record, and main takes only records no open or just-reopened window will claim. With restore off nothing is reopened and every backup still lands in main. Tests: the single-slot contract is replaced. lastWindowWritesSession becomes perWindowSession (each window writes or forgets its own entry regardless of who else is open). windowTagPerWindow now checks that a new window cannot read main's snapshot, and that a reopened window gets its own tag back. Source-shape markers follow the new settleForExit signature.
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 this is
Quitting with several windows open now brings all of them back on the next launch, each with its own tabs, unsaved changes (#962), position and size. Before, only the main window restored its tabs, and other windows' unsaved changes were merged into it.
Closing one of several windows still forgets it, as VS Code does. Quit, or closing the last window, remembers every window.
Mechanism
Restore-state had one slot,
window-state-v2.json, read only by the main window, and secondary windows got a new random label every launch. Nothing a secondary window saved could be claimed by the window that replaced it.window-state/<label>.jsonand its own crash guard inrestore-progress/<label>.json. The main window keepswindow-state-v2.jsonandrestore-progress-v1.json, so existing data needs no migration and an older build still reads it. Paths are derived in Rust from the calling window, with the same label validation and symlink refusal as feat(editor): keep unsaved changes when quitting #962.ownsSnapshot) is gone.keeps_unsaved_on_close). Closing one of several windows, merging a window away, or closing its last tab forgets it. Turning off restore-on-reopen discards every snapshot.reopen_remembered_windowsrecreates the others and returns their labels. The main window skips their backups, using that list rather than the window registry, which lags until each frontend registers. Each reopened window restores its own snapshot and its ownunsaved-recovery/<label>.json. Backups with no remembered window, for example after a crash, still go to the main window.Scope
Tests
claimableRecordsdecides which backups the main window takes, with a behaviour test.lastWindowWritesSessionbecameperWindowSession: each window writes or forgets only its own snapshot.windowTagPerWindownow checks that a new window doesn't read the main window's snapshot and that a reopened window gets its own tag back. It used to assert that a detached window never restores.Verification
npm run check0 errors,npm test1134 pass,npx vitest run515 pass,cargo test200 pass,cargo fmt --checkandcargo clippy --all-targets -- -D warningsclean.macOS 27, release test bundle:
kill -9with an unsaved tab in a secondary window, the main window came back holding that tab.Not run on Windows or Linux.