Revert "fix(ui-tui): force full xterm.js alt-screen repaints"

This reverts commit bc9518f660.
This commit is contained in:
Brooklyn Nicholson 2026-04-23 11:55:09 -05:00
parent bc9518f660
commit 071bdb5a3f

View file

@ -70,7 +70,7 @@ import {
startSelection, startSelection,
updateSelection updateSelection
} from './selection.js' } from './selection.js'
import { isXtermJs, supportsExtendedKeys, SYNC_OUTPUT_SUPPORTED, type Terminal, writeDiffToTerminal } from './terminal.js' import { supportsExtendedKeys, SYNC_OUTPUT_SUPPORTED, type Terminal, writeDiffToTerminal } from './terminal.js'
import { import {
CURSOR_HOME, CURSOR_HOME,
cursorMove, cursorMove,
@ -728,17 +728,12 @@ export default class Ink {
} }
} }
// xterm.js occasionally leaves stale glyphs behind during incremental
// alt-screen updates. Force full repaint there; native terminals keep
// the cheaper diff path unless layout/overlay state says otherwise.
const forceFullAltScreenRepaint = this.altScreenActive && isXtermJs()
// Full-damage backstop: applies on BOTH alt-screen and main-screen. // Full-damage backstop: applies on BOTH alt-screen and main-screen.
// Layout shifts (spinner appears, status line resizes) can leave stale // Layout shifts (spinner appears, status line resizes) can leave stale
// cells at sibling boundaries that per-node damage tracking misses. // cells at sibling boundaries that per-node damage tracking misses.
// Selection/highlight overlays write via setCellStyleId which doesn't // Selection/highlight overlays write via setCellStyleId which doesn't
// track damage. prevFrameContaminated covers the cleanup frame. // track damage. prevFrameContaminated covers the cleanup frame.
if (didLayoutShift() || selActive || hlActive || this.prevFrameContaminated || forceFullAltScreenRepaint) { if (didLayoutShift() || selActive || hlActive || this.prevFrameContaminated) {
frame.screen.damage = { frame.screen.damage = {
x: 0, x: 0,
y: 0, y: 0,
@ -776,7 +771,7 @@ export default class Ink {
// renders the scrolled-but-not-yet-repainted intermediate state. // renders the scrolled-but-not-yet-repainted intermediate state.
// tmux is the main case (re-emits DECSTBM with its own timing and // tmux is the main case (re-emits DECSTBM with its own timing and
// doesn't implement DEC 2026, so SYNC_OUTPUT_SUPPORTED is false). // doesn't implement DEC 2026, so SYNC_OUTPUT_SUPPORTED is false).
SYNC_OUTPUT_SUPPORTED && !forceFullAltScreenRepaint SYNC_OUTPUT_SUPPORTED
) )
const diffMs = performance.now() - tDiff const diffMs = performance.now() - tDiff
@ -829,9 +824,7 @@ export default class Ink {
// erase+paint lands, then swaps in one go. Writing ERASE_SCREEN // erase+paint lands, then swaps in one go. Writing ERASE_SCREEN
// synchronously in handleResize would blank the screen for the ~80ms // synchronously in handleResize would blank the screen for the ~80ms
// render() takes. // render() takes.
const eraseBeforePaint = this.needsEraseBeforePaint || forceFullAltScreenRepaint if (this.needsEraseBeforePaint) {
if (eraseBeforePaint) {
this.needsEraseBeforePaint = false this.needsEraseBeforePaint = false
optimized.unshift(ERASE_THEN_HOME_PATCH) optimized.unshift(ERASE_THEN_HOME_PATCH)
} else { } else {