fix(terminal): skip scroll restore on alt-buffer after split to avoid TUI cursor drift#1413
Open
fix(terminal): skip scroll restore on alt-buffer after split to avoid TUI cursor drift#1413
Conversation
… TUI cursor drift PR #1298 schedules scroll-restore + terminal.refresh(0, rows-1) at ~32ms and 200ms after a split to preserve scrollback through DOM reparenting. When a full-screen TUI (Claude Code, vim, less) is drawing at that moment, forceViewportScrollbarSync's scrollLines(-1)/(+1) jiggle and the buffer repaint race the TUI's next write — the TUI's cursor lands one row below where it expects and a residual fragment is left at the old row. Alt-buffer has no scrollback, so scroll restore has nothing legitimate to do there. Gate the restore + refresh behind buffer.active.type, but keep the WebGL reattach callback firing so #1298's dead-canvas fix is preserved. Normal-buffer splits are unchanged. Bisected against origin/main: bug appears at b4f1f0e (#1298), absent at its parent be0e3c2. Co-authored-by: Orca <help@stably.ai>
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.
Summary
Targeted follow-up to #1298. When a full-screen TUI (Claude Code, vim, less) is drawing at the moment a split completes,
scheduleSplitScrollRestore's 32ms and 200ms phases race the TUI's output — typed input lands one row below where the TUI expects and a residual fragment is left at the old cursor row.The fix gates the scroll restore + refresh pair behind
buffer.active.type. On alt-buffer we skip it (the TUI owns the screen, and alt-buffer has no scrollback, so scroll restore has nothing legitimate to do). WebGL reattach still fires on every path, so #1298's dead-canvas-after-split fix is preserved.What stays intact from #1298
Evidence
Bisected against
origin/main. Bug reproduces at HEAD, persists at8ae11955(parent of #1363) and5dc7fbda(parent of #1344), and is absent atbe0e3c2f(parent of #1298). Introduction:b4f1f0ea(#1298).Root cause in
pane-split-scroll.ts::scheduleSplitScrollRestore:forceViewportScrollbarSyncdoesscrollLines(-1); scrollLines(1)mid-drawrefresh(0, rows-1)repaints rows from the xterm buffer, racing the TUI's next writeTest plan
pnpm vitest run src/renderer/src/lib/pane-manager/— 76/76 pass (including 3 new tests)pnpm typecheck— cleanpnpm lint— clean on changed filesrt-style residual fragmentMade with Orca 🐋