Skip to content
Open
Show file tree
Hide file tree
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
26 changes: 23 additions & 3 deletions lib/input-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -894,16 +894,36 @@ export class InputHandler {
if (this.isDisposed) return;
if (!this.mouseConfig?.hasMouseTracking()) return;

this.sendWheelMouseEvent(event);

// Prevent default scrolling when mouse tracking is active
event.preventDefault();
}

/**
* Send a wheel event as a mouse tracking sequence.
* Public so that Terminal can forward wheel events when mouse tracking is
* active (the Terminal-level capture handler stops propagation to prevent
* browser scrolling, so this method allows explicit forwarding).
*/
handleWheelEvent(event: WheelEvent): void {
if (this.isDisposed) return;

this.sendWheelMouseEvent(event);
}

/**
* Encode and send a wheel event as a mouse tracking escape sequence.
* Button 64 = scroll up, button 65 = scroll down, with cell coordinates.
*/
private sendWheelMouseEvent(event: WheelEvent): void {
const cell = this.pixelToCell(event);
if (!cell) return;

// Wheel events: button 64 = scroll up, button 65 = scroll down
const button = event.deltaY < 0 ? 64 : 65;

this.sendMouseEvent(button, cell.col, cell.row, false, event);

// Prevent default scrolling when mouse tracking is active
event.preventDefault();
}

/**
Expand Down
14 changes: 14 additions & 0 deletions lib/terminal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,20 @@ export class Terminal implements ITerminalCore {
return;
}

// When mouse tracking is active, the application wants to receive mouse
// wheel events with coordinates so it can determine which pane/zone the
// cursor is over (critical for TUIs with multiple scroll regions like
// tmux, vim splits, etc.). Delegate to the InputHandler which sends
// proper SGR/X10 mouse sequences with the cell position.
if (this.wasmTerm?.hasMouseTracking()) {
// InputHandler.handleWheel is registered on the same container but in
// the bubbling phase. Since we already called stopPropagation() above
// (to prevent the browser from scrolling the page), we need to forward
// the event explicitly.
this.inputHandler?.handleWheelEvent(e);
return;
}

// Check if in alternate screen mode (vim, less, htop, etc.)
const isAltScreen = this.wasmTerm?.isAlternateScreen() ?? false;

Expand Down