Repository navigation
Emit kitty virtual placements per placeholder run from the viewport - #685
Merged
Merged
Conversation
Adapt to the ghostty-vt module API since ab0b9da9e: - Terminal.Options.max_scrollback is max_scrollback_bytes - DynamicPalette.changeDefault takes an allocator and can fail - Stream.initAlloc is gone; use Stream.init with an options struct - the write_pty effect receives a plain slice - kitty Image.data is a union; read it through renderData().bytes() - kitty Placement.Location gained a relative variant, drawn via the resolved parent chain when it roots at a pin, clipped on all four edges like upstream, with pruned anchor pins skipped Stored kitty images are never PNG anymore (the decode hook converts them at transmit time), so the PNG pass-through and the is-png parameter of the Elisp display functions are removed.
Two plain-ghostel (evil-free) regression scenarios plus their shared setup helper. kitty-ghostel.json (GUI) covers pinned and relative placements, deletion, the overlay path, virtual placeholders, and placement eviction; scrollback-ghostel.json (TTY) covers eviction, a DECSTBM region scroll, wrapped-line rejoin on a widening resize, and a DECCOLM round trip.
The Elisp side scanned the whole buffer for U+10EEEE on every redraw and sized the image by counting placeholders per line, so a stale virtual placement taxed every redraw and the slice row came from buffer line order rather than the placeholder's diacritics. The walk starts from the previous redraw's active top with libghostty's placement iterator instead and hand Elisp one run at a time with its image row, column and width; the grid size comes from the placement's c=/r= or the image size. Closes #673
dakra
force-pushed
the
fix/kitty-virtual-viewport-scan
branch
from
September 15, 2026 05:42
f59f1da to
fab456e
Compare
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.
Closes #673.
Once any kitty virtual placement (unicode placeholders, as used by yazi and
kitten icat --unicode-placeholder) had been shown, the Elisp side scanned the whole buffer for U+10EEEE on every redraw and sized the image by counting placeholders per line. Large scrollback, such asrgoutput over long JSON lines, made every prompt repaint pay for that scan. The slice row also came from buffer line order rather than the placeholder's diacritics.The native side now walks the active area with libghostty's placement iterator and calls
ghostel--kitty-display-virtualonce per placeholder run with the image row, column and run width. The grid size comes from the placement'sc=/r=or the image size, matching libghostty's own resolution. The Elisp tags exactly that run's placeholders plus their combining marks, so two images on one row, or text between two runs, each get their own slice.Scrollback rows are not revisited: they keep the slices they received while visible, and rows that scrolled out before a redraw get none, the same as pinned placements.
Tests: native tests feed a real 2x2 PNG and placeholder rows through
ghostel--write-vtand check one callback per row with the row taken from the diacritics, the screen-row offset once lines have scrolled into scrollback, and no callback for a placement whose placeholders left the active area. Elisp tests cover a single run and two runs on one row with gap text.