Follow kitty's Kitty graphics image lifetime rules #98

Merged
natsukium merged 4 commits from fix/image-lifetime into main 2026-10-12 00:39:59 +09:00
Owner

Part of #84 (image lifetime). Three commits:

  1. Screen clears follow kitty's grman_clear: ED 2 / DECSED 2 / RIS drop every on-screen placement (C=1 included), ED 3 also scrollback ones, then every unreferenced image is freed. ED 0/1, EL and DECSTR no longer touch images. Stashed primary-screen placements count as references (kitty keeps that screen's images in its own store), which also fixes d=A on the alternate screen.
  2. An image sent without i=/I= is freed once a delete or a scroll leaves it unplaced.
  3. Byte-cap eviction follows apply_storage_quota: unreferenced images first, then least recently transmitted/placed.

Checked side by side with kitty: an EL redraw beside an image keeps it, ED 2 clears everything, and re-placing a cleared image answers ENOENT in both.

Part of #84 (image lifetime). Three commits: 1. Screen clears follow kitty's `grman_clear`: ED 2 / DECSED 2 / RIS drop every on-screen placement (`C=1` included), ED 3 also scrollback ones, then every unreferenced image is freed. ED 0/1, EL and DECSTR no longer touch images. Stashed primary-screen placements count as references (kitty keeps that screen's images in its own store), which also fixes `d=A` on the alternate screen. 2. An image sent without `i=`/`I=` is freed once a delete or a scroll leaves it unplaced. 3. Byte-cap eviction follows `apply_storage_quota`: unreferenced images first, then least recently transmitted/placed. Checked side by side with kitty: an EL redraw beside an image keeps it, ED 2 clears everything, and re-placing a cleared image answers `ENOENT` in both.
felis dropped every non-C=1 placement a partial erase touched (ED 0,
ED 1, EL) and every placement on DECSTR, while ED 2 spared C=1
placements and freed no image. kitty does the opposite on each count:
screen_erase_in_display calls grman_clear only for ED 2 and ED 3 (and
their selective DECSED twins), the clear ignores C=1, and it then frees
every image left without a reference; screen_reset does the same for
RIS, and DECSTR touches no image. A TUI that redraws one line beside an
image lost the image, and transmit-only images piled up after `clear`
until the byte cap evicted them.

The grid now reports a clear's scope instead of a row range, and the
daemon frees unreferenced images after it. The primary screen's stashed
placements count as references: kitty keeps that screen's images in a
store of its own, so vim clearing the alternate screen must not free
them. d=A shares the same path, which also closes that hole for it.

Assisted-by: Claude Code
An image transmitted without i= or I= can never be placed again, yet
felis kept it after its placements were deleted or scrolled away, so
yazi's anonymous previews held their share of the byte cap until
eviction pushed out images a producer could still use.

kitty frees such an image as soon as nothing references it: filter_refs
(every delete) and modify_refs (every scroll) both drop images with no
refs and no client id. The store now records which entries were sent
without an id, and the daemon sweeps those after each delete and each
scroll into history. The primary screen's stashed placements count as
references, as in the screen-clear path.

Assisted-by: Claude Code
grid, daemon: evict Kitty graphics images by kitty's storage quota rule
Some checks failed
darwin / detect relevant changes (pull_request) Successful in 8s
darwin / darwin docs-only no-op (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 2m16s
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m10s
bench / Criterion regression gate (pull_request) Failing after 2m27s
pr / nix flake check (pull_request) Successful in 59s
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
3f2e725cca
felis evicted strictly in transmit order, placed or not, so a still
image placed a moment ago could go before a transmit-only image nobody
displays. kitty's apply_storage_quota frees every unreferenced image
first and only then the oldest by atime, which it bumps on transmit and
on every put.

The store now keeps a logical clock and stamps an entry on insert and
on each real or virtual placement; the daemon trims unreferenced images,
then evicts the smallest stamp. Images the stashed primary screen shows
are left alone in both phases: kitty keeps each screen's images in its
own store, so a full-screen program cannot evict the shell screen's.

Assisted-by: Claude Code
natsukium force-pushed fix/image-lifetime from 3f2e725cca
Some checks failed
darwin / detect relevant changes (pull_request) Successful in 8s
darwin / darwin docs-only no-op (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 2m16s
pr / cargo build / clippy / test / deny (pull_request) Has been cancelled
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m10s
bench / Criterion regression gate (pull_request) Failing after 2m27s
pr / nix flake check (pull_request) Successful in 59s
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 2ebb023c02
Some checks failed
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m46s
pr / nix flake check (pull_request) Successful in 37s
pr / cargo build / clippy / test / deny (pull_request) Successful in 3m8s
pr / wire schema is compatible with the base (pull_request) Successful in 2s
windows / cargo clippy (Windows cross) (pull_request) Successful in 28s
bench / Criterion full-suite snapshot (pull_request) Has been skipped
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 1m9s
bench / Criterion regression gate (pull_request) Successful in 2m32s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 50s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 8s
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
2026-10-11 14:14:27 +09:00
Compare
natsukium force-pushed fix/image-lifetime from 2ebb023c02
Some checks failed
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m46s
pr / nix flake check (pull_request) Successful in 37s
pr / cargo build / clippy / test / deny (pull_request) Successful in 3m8s
pr / wire schema is compatible with the base (pull_request) Successful in 2s
windows / cargo clippy (Windows cross) (pull_request) Successful in 28s
bench / Criterion full-suite snapshot (pull_request) Has been skipped
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 1m9s
bench / Criterion regression gate (pull_request) Successful in 2m32s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 50s
windows / windows docs-only no-op (pull_request) Has been skipped
windows / detect relevant changes (pull_request) Successful in 8s
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
to 18e65c5197
Some checks failed
windows / detect relevant changes (pull_request) Successful in 14s
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo nextest (Windows) (pull_request) Failing after 9s
windows / frontend smoke (Windows) (pull_request) Has been skipped
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 9s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m9s
bench / Criterion regression gate (pull_request) Failing after 2m4s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 2m5s
pr / nix flake check (pull_request) Successful in 44s
pr / cargo build / clippy / test / deny (pull_request) Successful in 2m32s
pr / wire schema is compatible with the base (pull_request) Successful in 2s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 29s
windows / cargo clippy (Windows cross) (pull_request) Successful in 15s
2026-10-11 23:30:54 +09:00
Compare
natsukium force-pushed fix/image-lifetime from 18e65c5197
Some checks failed
windows / detect relevant changes (pull_request) Successful in 14s
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
windows / windows docs-only no-op (pull_request) Has been skipped
windows / cargo nextest (Windows) (pull_request) Failing after 9s
windows / frontend smoke (Windows) (pull_request) Has been skipped
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 9s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m9s
bench / Criterion regression gate (pull_request) Failing after 2m4s
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 2m5s
pr / nix flake check (pull_request) Successful in 44s
pr / cargo build / clippy / test / deny (pull_request) Successful in 2m32s
pr / wire schema is compatible with the base (pull_request) Successful in 2s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 29s
windows / cargo clippy (Windows cross) (pull_request) Successful in 15s
to d64070d119
Some checks failed
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 9s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m9s
bench / Criterion 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 00:03:20 +09:00
Compare
natsukium force-pushed fix/image-lifetime from d64070d119
Some checks failed
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 9s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m9s
bench / Criterion 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 ce639a5f8f
Some checks failed
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 9s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m8s
bench / Criterion regression gate (pull_request) Failing after 2m6s
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 00:07:15 +09:00
Compare
natsukium force-pushed fix/image-lifetime from ce639a5f8f
Some checks failed
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 9s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m8s
bench / Criterion regression gate (pull_request) Failing after 2m6s
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 c5267686f4
Some checks failed
windows / detect relevant changes (pull_request) Successful in 13s
windows / windows docs-only no-op (pull_request) Has been skipped
fuzz / cargo fuzz smoke (per target) (pull_request) Successful in 1m56s
pr / cargo build / clippy / test / deny (pull_request) Successful in 2m27s
pr / wire schema is compatible with the base (pull_request) Successful in 2s
pr / frontend smoke (x86_64-linux) (pull_request) Successful in 28s
windows / cargo clippy (Windows cross) (pull_request) Successful in 15s
windows / cargo nextest (Windows) (pull_request) Successful in 3m37s
bench / Criterion full-suite snapshot (pull_request) Has been skipped
fuzz / cargo fuzz nightly long-run (pull_request) Has been skipped
darwin / detect relevant changes (pull_request) Successful in 9s
darwin / darwin docs-only no-op (pull_request) Has been skipped
darwin / build felis (aarch64-darwin) (pull_request) Successful in 1m8s
bench / Criterion regression gate (pull_request) Successful in 2m8s
pr / nix flake check (pull_request) Failing after 20s
windows / frontend smoke (Windows) (pull_request) Successful in 1m22s
windows / package felis (x86_64-pc-windows-msvc) (pull_request) Has been skipped
2026-10-12 00:11:45 +09:00
Compare
natsukium deleted branch fix/image-lifetime 2026-10-12 00:39:59 +09:00
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!98
No description provided.