Give the alternate screen a Kitty image store of its own #107

Merged
natsukium merged 2 commits from fix/per-screen-image-store into main 2026-10-12 14:37:30 +09:00
Owner

Closes #89.

kitty keeps one Kitty image store per screen. felis shared one, so a full-screen program on the alternate screen could free or overwrite the shell's images by clearing its screen, by d=r/d=R, by filling the byte cap, or by reusing an i=.

  • The session stashes the primary screen's store with its placements on entering the alternate screen, which starts empty under the same cap. ?47l keeps the alternate screen's store with the buffer it keeps, and the next entry resumes both. The grid's screen-switch effect now says whether a leave keeps the buffer and whether an entry resumed it.
  • The client still mirrors one store. A switch removes the placements and deletes the images of the screen left, then re-sends the images and placements of the screen coming up. A mirror of both stores would need a screen field on every image message; re-sending on leave was chosen instead.
  • The status report counts both stores against twice the per-screen cap. REQ-1008 is now per screen.
  • The upgrade dump carries the saved screens. DUMP_VERSION stays at 2: that version is unreleased, and it moves once per release.
  • The mirror property test now also checks that every image the window shows is stored, and toggles ?47.
Closes #89. kitty keeps one Kitty image store per screen. felis shared one, so a full-screen program on the alternate screen could free or overwrite the shell's images by clearing its screen, by `d=r`/`d=R`, by filling the byte cap, or by reusing an `i=`. - The session stashes the primary screen's store with its placements on entering the alternate screen, which starts empty under the same cap. `?47l` keeps the alternate screen's store with the buffer it keeps, and the next entry resumes both. The grid's screen-switch effect now says whether a leave keeps the buffer and whether an entry resumed it. - The client still mirrors one store. A switch removes the placements and deletes the images of the screen left, then re-sends the images and placements of the screen coming up. A mirror of both stores would need a screen field on every image message; re-sending on leave was chosen instead. - The status report counts both stores against twice the per-screen cap. REQ-1008 is now per screen. - The upgrade dump carries the saved screens. `DUMP_VERSION` stays at 2: that version is unreleased, and it moves once per release. - The mirror property test now also checks that every image the window shows is stored, and toggles `?47`.
kitty keeps one image store per screen. felis shared one store across
both, with the primary screen's placements stashed while the alternate
screen was up, so a full-screen program could free the shell's images:
a clear freed every unplaced one, `d=r`/`d=R` reached them by id, the
byte cap's least-recently-used step evicted them, and an `i=` the
program reused overwrote the shell's image outright.

The session now stashes the primary screen's store together with its
placements on `?1049h` and starts the alternate screen with an empty
store under the same cap. The client still mirrors one store: the
switch deletes the screen left behind from it and re-sends the screen
coming up. A mirror holding both stores would spare that re-send but
needs a screen field on every image message and a second store in
every client; the primary screen's images are usually few.

A session can now hold a full store per screen, so the status report
counts both and names twice the per-screen cap as the session's.

The dump's saved-screen field changes shape without a version bump:
dump version 2 is unreleased, and the version moves once per release.

The mirror property now also checks that every placement the window
shows has its image.

Assisted-by: Claude Code
grid, daemon: keep the alternate screen's Kitty images across ?47l
Some checks failed
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 8s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m7s
windows / detect relevant changes (pull_request) Successful in 10s
windows / windows docs-only no-op (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m52s
windows / cargo nextest (Windows) (pull_request) Successful in 4m40s
bench / instruction-count regression gate (pull_request) Failing after 23s
pr / nix flake check (pull_request) Successful in 45s
windows / frontend smoke (Windows) (pull_request) Successful in 59s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
pr / cargo build / clippy / test / deny (pull_request) Failing after 1m8s
pr / wire schema is compatible with the base (pull_request) Successful in 3s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 30s
windows / cargo clippy (Windows cross) (pull_request) Successful in 17s
5ee9018f0f
`?47l` keeps the alternate buffer so the next `?47h` resumes it, and
kitty keeps that screen's image store with it. The daemon dropped the
alternate store on every leave, so the text came back without its
images.

The screen switch now says whether the leave keeps the alternate
buffer and whether the entry resumed it, and the daemon keeps the
alternate store under the same rule. Taking the rule from the grid
rather than tracking `?47` in the daemon keeps the two from drifting:
RIS and `?1047l`/`?1049l` drop the grid's kept buffer, and an entry
that does not resume it never brings back stale images.

Assisted-by: Claude Code
natsukium force-pushed fix/per-screen-image-store from 5ee9018f0f
Some checks failed
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 8s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m7s
windows / detect relevant changes (pull_request) Successful in 10s
windows / windows docs-only no-op (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m52s
windows / cargo nextest (Windows) (pull_request) Successful in 4m40s
bench / instruction-count regression gate (pull_request) Failing after 23s
pr / nix flake check (pull_request) Successful in 45s
windows / frontend smoke (Windows) (pull_request) Successful in 59s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
pr / cargo build / clippy / test / deny (pull_request) Failing after 1m8s
pr / wire schema is compatible with the base (pull_request) Successful in 3s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 30s
windows / cargo clippy (Windows cross) (pull_request) Successful in 17s
to 5eb2e960a4
Some checks failed
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 8s
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m8s
bench / instruction-count regression gate (pull_request) Has been cancelled
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
2026-10-12 13:34:41 +09:00
Compare
natsukium force-pushed fix/per-screen-image-store from 5eb2e960a4
Some checks failed
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 8s
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m8s
bench / instruction-count regression gate (pull_request) Has been cancelled
fuzz / cargo fuzz smoke (per target) (pull_request) Has been cancelled
pr / nix flake check (pull_request) Has been cancelled
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
pr / wire schema is compatible with the base (pull_request) Has been cancelled
pr / frontend smoke (x86_64-linux) (pull_request) Has been cancelled
windows / detect relevant changes (pull_request) Has been cancelled
windows / cargo clippy (Windows cross) (pull_request) Has been cancelled
windows / cargo nextest (Windows) (pull_request) Has been cancelled
windows / frontend smoke (Windows) (pull_request) Has been cancelled
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / windows docs-only no-op (pull_request) Has been cancelled
to 28030181dc
All checks were successful
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 8s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m10s
windows / detect relevant changes (pull_request) Successful in 15s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo nextest (Windows) (pull_request) Successful in 7m9s
bench / instruction-count regression gate (pull_request) Successful in 1m44s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 3m36s
pr / nix flake check (pull_request) Successful in 1m25s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 32s
windows / cargo clippy (Windows cross) (pull_request) Successful in 26s
pr / cargo build / clippy / test / deny (pull_request) Successful in 4m6s
pr / wire schema is compatible with the base (pull_request) Successful in 3s
windows / frontend smoke (Windows) (pull_request) Successful in 1m3s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
2026-10-12 13:47:07 +09:00
Compare
Sign in to join this conversation.
No reviewers
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
felis-terminal/felis!107
No description provided.