fix(maestro): reliable touch scrollback on mobile
ci / rust (push) Failing after 1m49s

xterm's native touch scrolling crawled a line at a time and stalled after a
few. Map finger drags on the viewport to term.scrollLines (skipped on the alt
screen, which the app owns) and claim vertical pans via touch-action: pan-y.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 15:59:49 +00:00
co-authored by Claude Opus 4.8
parent 3b69c98cca
commit a1b6c85f8d
2 changed files with 48 additions and 0 deletions
+45
View File
@@ -130,6 +130,51 @@ export function createAttachConnection(
term.loadAddon(fit);
term.open(body);
// Touch scrollback: xterm's built-in touch handling on the viewport is jittery
// (drags crawl a line at a time and stall after a few), so map finger drags to
// term.scrollLines ourselves. Skipped on the alternate screen (full-screen
// TUIs like tmux/Claude Code) — there's no scrollback to move and the app owns
// the gesture. `touch-action: pan-y` (CSS) tells the browser we handle Y.
{
const vp = el.querySelector(".xterm-viewport") as HTMLElement | null;
const cellH = () => {
const core = (term as unknown as {
_core?: { _renderService?: { dimensions?: { css?: { cell?: { height: number } } } } };
})._core;
return core?._renderService?.dimensions?.css?.cell?.height || 16;
};
if (vp) {
let lastY = 0;
let remainder = 0;
vp.addEventListener(
"touchstart",
(e) => {
if (e.touches.length !== 1) return;
lastY = e.touches[0].clientY;
remainder = 0;
},
{ passive: true },
);
vp.addEventListener(
"touchmove",
(e) => {
if (e.touches.length !== 1) return;
if (term.buffer.active.type === "alternate") return; // app-owned
const y = e.touches[0].clientY;
const px = lastY - y + remainder; // finger up → scroll toward newer
lastY = y;
const lines = Math.trunc(px / cellH());
remainder = px - lines * cellH();
if (lines !== 0) {
term.scrollLines(lines);
e.preventDefault();
}
},
{ passive: false },
);
}
}
// Mobile: the special-key bar is only useful while the soft keyboard is up,
// so reveal it only when the terminal's hidden textarea is focused (CSS still
// gates it to coarse pointers). Tapping a keycap keeps focus via pointerdown
+3
View File
@@ -1148,6 +1148,9 @@ textarea {
.attach-body .xterm .xterm-viewport {
overflow-y: auto;
scrollbar-width: none;
/* We drive scrollback from touchmove (see attach.ts); claim vertical pans so
the browser doesn't fight the handler or trigger gestures mid-scroll. */
touch-action: pan-y;
}
.attach-body .xterm .xterm-viewport::-webkit-scrollbar {