feat(tui): accelerate Alt-modified wheel scrolling (#9166)

This commit is contained in:
Alexey Zaytsev 2026-09-05 08:14:11 -03:00 • committed by GitHub
parent 1382777ed8
commit ab9e6f89b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 24 additions and 2 deletions

View file

@ -72,6 +72,7 @@ const END_SYNCHRONIZED_OUTPUT = "\x1b[?2026l";
const OSC133_ZONE_PREFIX = /^(?:\x1b\]133;[ABC](?:\x07|\x1b\\))+/;
const OSC133_PROMPT_START = /^\x1b\]133;A(?:\x07|\x1b\\)/;
const PAGE_SCROLL_OVERLAP = 4;
const ALT_WHEEL_SCROLL_MULTIPLIER = 5;
const MAX_CACHED_OFFSCREEN_KITTY_IMAGES = 16;
const MAX_CACHED_OFFSCREEN_KITTY_TRANSMISSION_BYTES = 32 * 1024 * 1024;
const MAX_CACHED_OFFSCREEN_KITTY_DECODED_BYTES = 64 * 1024 * 1024;
@ -680,7 +681,7 @@ export class TuiAltScreen extends TuiBase implements ViewportTUI {
const wheelEvent = this.parseWheelEvent(data);
if (wheelEvent) {
const event = this.createMouseEvent("wheel", wheelEvent.button, wheelEvent.x, wheelEvent.y, {
wheelDelta: wheelEvent.direction * this.wheelScrollLines,
wheelDelta: wheelEvent.direction * this.getWheelScrollLines(wheelEvent.button),
});
const overlay = this.dispatchMouseToOverlay(event);
const result = overlay.result ?? (overlay.hit ? undefined : this.dispatchMouseToLayout(event));
@ -964,8 +965,13 @@ export class TuiAltScreen extends TuiBase implements ViewportTUI {
return undefined;
}
private getWheelScrollLines(button: number): number {
// SGR mouse button codes use bit 3 (value 8) for the Alt modifier.
return (button & 8) !== 0 ? this.wheelScrollLines * ALT_WHEEL_SCROLL_MULTIPLIER : this.wheelScrollLines;
}
private routeWheel(event: WheelEvent): void {
let remaining = event.direction * this.wheelScrollLines;
let remaining = event.direction * this.getWheelScrollLines(event.button);
const seen = new Set<ScrollView>();
for (const scrollView of this.currentLayout ? getScrollViewsAt(this.currentLayout, event.x, event.y) : []) {
seen.add(scrollView);

View file

@ -273,6 +273,22 @@ describe("TuiAltScreen", () => {
tui.stop();
});
it("scrolls faster while Alt is held during wheel input", async () => {
const terminal = new VirtualTerminal(20, 4);
const tui = new TuiAltScreen(terminal);
const text = new Text(Array.from({ length: 12 }, (_, index) => `line ${index + 1}`).join("\n"), 0, 0);
tui.addChild(text);
tui.start();
await terminal.waitForRender();
assert.strictEqual(tui.viewportTop, 8);
// Alt modifier sets bit 8 on the wheel button (72 = 64 + 8).
terminal.sendInput("\x1b[<72;1;1M");
await terminal.waitForRender();
assert.strictEqual(tui.viewportTop, 3);
tui.stop();
});
it("does not vertically redispatch misses through horizontal layout containers", async () => {
const terminal = new VirtualTerminal(20, 2);
const tui = new TuiAltScreen(terminal);