diff options
| author | cashmere <cashmere@autistici.org> | 2026-03-29 06:54:09 +0200 |
|---|---|---|
| committer | cashmere <cashmere@autistici.org> | 2026-03-29 06:54:09 +0200 |
| commit | e5ee5bb0e498c66b473e7eecc8c31e29f503d85c (patch) | |
| tree | f4930dd28b4db70b61fef0d712613baced9e7a73 /kitty-graphics.el | |
| parent | 09b88bbf00bf4019ea71a893061d7f8edbf5d39f (diff) | |
| download | kitty-graphics-e5ee5bb0e498c66b473e7eecc8c31e29f503d85c.tar.gz | |
feat: heading-aware scroll and buffer-change handling
Fix scroll/buffer-switch behavior for heading overlays:
- on-window-change: preserve heading overlay position caches
(images clear theirs for re-placement, but headings need
old→new comparison to erase multicell blocks properly)
- on-buffer-change: erase heading multicell blocks when their
buffer becomes hidden, preventing ghost artifacts if the new
buffer's content doesn't fully overwrite the heading cells
- on-buffer-change: preserve heading caches for visible buffers
(same rationale as on-window-change)
The existing two-phase refresh already handles scroll correctly:
phase 1 detects position changes and erases moved headings,
phase 2 re-emits all visible headings. These fixes ensure the
cache state is correct for that comparison to work.
Diffstat (limited to 'kitty-graphics.el')
| -rw-r--r-- | kitty-graphics.el | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/kitty-graphics.el b/kitty-graphics.el index 3f54177..4d26d04 100644 --- a/kitty-graphics.el +++ b/kitty-graphics.el @@ -1316,19 +1316,30 @@ then invalidates position caches and schedules a refresh." (buffer-name)) (dolist (ov kitty-gfx--overlays) (when (overlay-buffer ov) - (let ((id (overlay-get ov 'kitty-gfx-id)) - (pid (overlay-get ov 'kitty-gfx-pid))) - (if (overlay-get ov 'kitty-gfx-last-row) - (when (and id pid) - (kitty-gfx--delete-placement id pid)) - (kitty-gfx--log "on-buffer-change: ov pid=%s has no last-row (never placed or already cleaned)" pid))) - (overlay-put ov 'kitty-gfx-last-row nil) - (overlay-put ov 'kitty-gfx-last-col nil))))))) + (if (overlay-get ov 'kitty-gfx-heading) + ;; Heading overlay — erase multicell block to prevent + ;; ghost artifacts if the new buffer doesn't fully + ;; overwrite the heading's terminal cells. + (when (overlay-get ov 'kitty-gfx-last-row) + (kitty-gfx--erase-heading ov) + (overlay-put ov 'kitty-gfx-last-row nil) + (overlay-put ov 'kitty-gfx-last-col nil)) + ;; Image overlay — delete terminal placement + (let ((id (overlay-get ov 'kitty-gfx-id)) + (pid (overlay-get ov 'kitty-gfx-pid))) + (if (overlay-get ov 'kitty-gfx-last-row) + (when (and id pid) + (kitty-gfx--delete-placement id pid)) + (kitty-gfx--log "on-buffer-change: ov pid=%s has no last-row (never placed or already cleaned)" pid))) + (overlay-put ov 'kitty-gfx-last-row nil) + (overlay-put ov 'kitty-gfx-last-col nil)))))))) ;; Reset cache for visible buffers so they re-place correctly. + ;; Heading overlays preserve cache (same rationale as on-window-change). (dolist (buf (buffer-list)) (with-current-buffer buf (dolist (ov kitty-gfx--overlays) - (when (overlay-buffer ov) + (when (and (overlay-buffer ov) + (not (overlay-get ov 'kitty-gfx-heading))) (overlay-put ov 'kitty-gfx-last-row nil) (overlay-put ov 'kitty-gfx-last-col nil))))) ;; Longer debounce: cancel any fast leading-edge cooldown and @@ -1354,10 +1365,15 @@ buffer before settling to one)." (setq kitty-gfx--cell-pixel-width nil kitty-gfx--cell-pixel-height nil) ;; Reset position cache so images get re-placed at correct positions. + ;; Heading overlays PRESERVE their cache — the refresh cycle needs + ;; old→new position comparison to erase multicell blocks properly. + ;; Images can clear cache because re-placing with the same PID is + ;; idempotent (the terminal replaces the old placement). (dolist (buf (buffer-list)) (with-current-buffer buf (dolist (ov kitty-gfx--overlays) - (when (overlay-buffer ov) + (when (and (overlay-buffer ov) + (not (overlay-get ov 'kitty-gfx-heading))) (overlay-put ov 'kitty-gfx-last-row nil) (overlay-put ov 'kitty-gfx-last-col nil))))) ;; Longer debounce: cancel any fast leading-edge cooldown and |
