grid: cursor-only moves (CR, LF, cursor movement) still mark their row #454

Closed
opened 2026-09-25 14:50:51 +09:00 by natsukium · 0 comments
Owner

Found while measuring #447.

Problem

docs/explanation/rendering/damage-tracking.md "Correctness" says cursor-only moves must leave damage empty, since the cursor is a client-side overlay. The grid still marks the cursor row on many of them: carriage_return (crates/felis-grid/src/editing.rs), line_feed / reverse_index for the row they land on, and the cursor-movement handlers that call self.screen.damage.mark(self.screen.cursor.row.into()) (about twenty sites in editing.rs, one in sink.rs). These marks date from before the cursor became an overlay.

Since #447 a scroll moves the dirty marks with the rows, so the mark a \r leaves before each line feed now costs a whole row on the wire every frame. On a 212x93 window, less scrolling line by line and a program printing a line every 33 ms ship 3 rows per frame: the new bottom row, the default-cell entry that precedes it for 0.1.0 clients, and the row above it, which only the \r marked. Dropping the cursor-only marks would make that 2.

Proposal

Remove the damage mark from every handler that moves only the cursor (no cell, soft-wrap bit, or sized-cell change), leaving the marks on handlers that also write cells. Confirm with crates/felis-grid/tests/damage_correctness.rs (it compares every unmarked row against the directive-shifted prior screen, so an under-mark fails it) and the daemon mirror property every_mirror_ends_each_compose_holding_the_grids_cells, then remeasure the less and pager workloads.

Open question

  • Does any consumer read a cursor-row mark as a cursor signal (the renderer tracks the rows the cursor left and entered on its own; check the Kitty placeholder and hyperlink hover paths before removing)?
Found while measuring #447. ## Problem `docs/explanation/rendering/damage-tracking.md` "Correctness" says cursor-only moves must leave damage empty, since the cursor is a client-side overlay. The grid still marks the cursor row on many of them: `carriage_return` (`crates/felis-grid/src/editing.rs`), `line_feed` / `reverse_index` for the row they land on, and the cursor-movement handlers that call `self.screen.damage.mark(self.screen.cursor.row.into())` (about twenty sites in `editing.rs`, one in `sink.rs`). These marks date from before the cursor became an overlay. Since #447 a scroll moves the dirty marks with the rows, so the mark a `\r` leaves before each line feed now costs a whole row on the wire every frame. On a 212x93 window, `less` scrolling line by line and a program printing a line every 33 ms ship 3 rows per frame: the new bottom row, the default-cell entry that precedes it for 0.1.0 clients, and the row above it, which only the `\r` marked. Dropping the cursor-only marks would make that 2. ## Proposal Remove the damage mark from every handler that moves only the cursor (no cell, soft-wrap bit, or sized-cell change), leaving the marks on handlers that also write cells. Confirm with `crates/felis-grid/tests/damage_correctness.rs` (it compares every unmarked row against the directive-shifted prior screen, so an under-mark fails it) and the daemon mirror property `every_mirror_ends_each_compose_holding_the_grids_cells`, then remeasure the less and pager workloads. ## Open question - Does any consumer read a cursor-row mark as a cursor signal (the renderer tracks the rows the cursor left and entered on its own; check the Kitty placeholder and hyperlink hover paths before removing)?
Commenting is not possible because the repository is archived.
No description provided.