Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions lib/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,14 @@ export class Terminal implements ITerminalCore {
// preserve selection when new data arrives. Selection is cleared by user actions
// like clicking or typing, not by incoming data.

// Save scroll state before writing. viewportY is relative to the
// bottom, so if new lines push content into scrollback we need to
// bump viewportY by the same amount to keep the viewport locked on
// the same content.
const savedViewportY = this.viewportY;
const savedScrollback = savedViewportY > 0
? this.wasmTerm!.getScrollbackLength() : 0;

// Write directly to WASM terminal (handles VT parsing internally)
this.wasmTerm!.write(data);

Expand All @@ -575,9 +583,14 @@ export class Terminal implements ITerminalCore {
// Invalidate link cache (content changed)
this.linkDetector?.invalidateCache();

// Phase 2: Auto-scroll to bottom on new output (xterm.js behavior)
if (this.viewportY !== 0) {
this.scrollToBottom();
// If the user had scrolled up, adjust viewportY so the viewport
// stays locked on the same content instead of drifting as new
// scrollback lines are added. Clamp to the current scrollback
// length in case old lines were dropped by the scrollback limit.
if (savedViewportY > 0) {
const newScrollback = this.wasmTerm!.getScrollbackLength();
const delta = newScrollback - savedScrollback;
this.viewportY = Math.min(savedViewportY + Math.max(0, delta), newScrollback);
}

// Check for title changes (OSC 0, 1, 2 sequences)
Expand Down