graphics: smaller Kitty graphics differences from kitty to decide on #84

Closed
opened 2026-10-09 21:51:17 +09:00 by natsukium · 2 comments
Owner

Smaller differences from kitty found while auditing the Kitty graphics path. Each needs a follow-kitty-or-keep decision; several are documented as intended today.

  • Image numbers (I=). resolve_image_id (crates/felis-daemon/src/graphics.rs) uses I= as the image id. kitty assigns a fresh id per I= transmit, replies i=<assigned>,I=<n>, and a=p,I=n targets the newest image with that number. felis replies i=n,I=n and replaces the image. i= together with I= should be EINVAL ("Must not specify both image id and image number"); felis lets i= win. d=n / d=N are answered ENOTSUP; kitty implements them and, like every successful delete, sends no reply.
  • Replies to commands without i= or I=. kitty sends none (finish_command_response). felis answers a=T without an id with \e_Gi=4294967295;OK\e\\ (an internal allocated id) and a=t / a=q without an id with \e_G;OK\e\\, which an interactive shell echoes as garbage. A test pins the id-less OK (graphics/tests.rs).
  • S= / O= on t=f and t=t. read_file_payload / read_temp_file_payload read the whole file; only t=s honors size and offset. kitty applies them to files too.
  • Erase. ED 0/1 and EL drop placements without C=1 that intersect the erased rows, whatever columns the erase covers: \e[K at the far right of a row drops every such image spanning that row. kitty clears images only on ED 2/3, and EL never touches them, so a program rewriting a line across an image loses the image in felis.
  • Error codes. A failed file open answers EIO (kitty EBADF); an undecodable PNG answers EBADF (kitty EBADPNG).
  • Anonymous images. An image without a client id is not freed when its last placement goes (kitty frees it even on a lowercase delete, per graphics.c); felis keeps it until eviction.
  • Eviction ignores placements. evict_oldest_to_fit evicts the oldest image first even when it is still placed: a placed i=1 followed by twelve 64 MiB transmits is gone in felis (a=p,i=1 answers ENOENT) and still placeable in kitty.
Smaller differences from kitty found while auditing the Kitty graphics path. Each needs a follow-kitty-or-keep decision; several are documented as intended today. - **Image numbers (`I=`).** `resolve_image_id` (`crates/felis-daemon/src/graphics.rs`) uses `I=` as the image id. kitty assigns a fresh id per `I=` transmit, replies `i=<assigned>,I=<n>`, and `a=p,I=n` targets the newest image with that number. felis replies `i=n,I=n` and replaces the image. `i=` together with `I=` should be `EINVAL` ("Must not specify both image id and image number"); felis lets `i=` win. `d=n` / `d=N` are answered `ENOTSUP`; kitty implements them and, like every successful delete, sends no reply. - **Replies to commands without `i=` or `I=`.** kitty sends none (`finish_command_response`). felis answers `a=T` without an id with `\e_Gi=4294967295;OK\e\\` (an internal allocated id) and `a=t` / `a=q` without an id with `\e_G;OK\e\\`, which an interactive shell echoes as garbage. A test pins the id-less OK (`graphics/tests.rs`). - **`S=` / `O=` on `t=f` and `t=t`.** `read_file_payload` / `read_temp_file_payload` read the whole file; only `t=s` honors size and offset. kitty applies them to files too. - **Erase.** ED 0/1 and EL drop placements without `C=1` that intersect the erased rows, whatever columns the erase covers: `\e[K` at the far right of a row drops every such image spanning that row. kitty clears images only on ED 2/3, and EL never touches them, so a program rewriting a line across an image loses the image in felis. - **Error codes.** A failed file open answers `EIO` (kitty `EBADF`); an undecodable PNG answers `EBADF` (kitty `EBADPNG`). - **Anonymous images.** An image without a client id is not freed when its last placement goes (kitty frees it even on a lowercase delete, per `graphics.c`); felis keeps it until eviction. - **Eviction ignores placements.** `evict_oldest_to_fit` evicts the oldest image first even when it is still placed: a placed `i=1` followed by twelve 64 MiB transmits is gone in felis (`a=p,i=1` answers `ENOENT`) and still placeable in kitty.
Author
Owner

One more, from the placement identity fix: an id-less put gets a daemon-assigned placement id counted down from u32::MAX. If a producer later puts the same image with that exact p=, felis moves the id-less placement to a fresh id and to the end of the table (the client mirrors this with a remove and a re-add), so among equal-z overlapping placements it now stacks above placements made after it. kitty keeps both refs in their original order, since an id-less ref has no client id to collide with. Matching kitty needs the wire to carry an id-less placement's identity separately from the producer's p=, or a positioned insert.

One more, from the placement identity fix: an id-less put gets a daemon-assigned placement id counted down from `u32::MAX`. If a producer later puts the same image with that exact `p=`, felis moves the id-less placement to a fresh id and to the end of the table (the client mirrors this with a remove and a re-add), so among equal-z overlapping placements it now stacks above placements made after it. kitty keeps both refs in their original order, since an id-less ref has no client id to collide with. Matching kitty needs the wire to carry an id-less placement's identity separately from the producer's `p=`, or a positioned insert.
Author
Owner

All items now follow kitty: replies and error codes (#95), erase, anonymous images and eviction (#98), S=/O= on file transmissions (#101), image numbers and d=n/d=N (#102).

All items now follow kitty: replies and error codes (#95), erase, anonymous images and eviction (#98), S=/O= on file transmissions (#101), image numbers and d=n/d=N (#102).
Sign in to join this conversation.
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#84
No description provided.