Repository navigation
v3.6.3 - The trackpad scrolls the terminal again
v3.6.3 - The trackpad scrolls the terminal again
You scrolled a session terminal with the MacBook trackpad. The text moved late, a beat behind your fingers. At the bottom of the session, a scroll up did nothing for a full screen of finger travel, then the view jumped. A mouse wheel worked. A finger on a phone worked. Only the trackpad felt broken. This release fixes the trackpad and leaves the other two alone.
See it
Higher-quality video: dispatch-v3.6.3-trackpad-scroll.mp4
Why only the trackpad broke
The mobile scroll work in v2.7 enabled xterm's smooth scroll option, a 120ms glide on every wheel event. A mouse wheel sends one event per notch, so each notch gets a clean glide. A trackpad sends 60 to 120 events per second, and xterm restarts the glide on every one of them. The glide never finishes, and the view trails the fingers by about 120ms. Worse, xterm clamps its scroll target to the full scroll height, not to the last scroll position. A push into the bottom edge, which every flick down makes, accumulates up to one screen of overshoot. The next scroll up has to cancel that overshoot before the view moves. Measured in Chrome: 252px of upward travel did nothing.
Chrome on macOS gives a page no way to tell a trackpad from a mouse wheel. Both arrive as pixel deltas, and a slow mouse notch is the same size as a trackpad tick. So the fix is not a trackpad mode. It is one scroll path that is correct for both.
What changed
Dispatch now owns wheel scrolling in the terminal. Each wheel event adds its distance to a pool, clamped to the rows the buffer can still scroll. On every animation frame, the terminal releases half of the pooled rows as whole rows. A trackpad stream tracks the fingers within a frame. A mouse notch still glides, over about three frames instead of 120ms, and lands on the same rows as before. Alt plus wheel keeps xterm's fast-scroll multiplier. At an edge, the pool empties, so a reversal moves the view after one row of travel.
Touch scrolling on a phone is unchanged. The kinetic scroller still sends its own line ticks, and this handler passes them to xterm. A pane that owns the mouse, for example tmux with mouse mode on, still receives wheel reports as before.
What changed underneath
The client registers a custom wheel handler with xterm, which xterm consults before its mouse-report path and before its viewport path. The handler takes pixel-mode wheel events in the normal buffer and drains the pool through term.scrollLines, never through scrollTop. Whole rows keep the buffer position as the single source of truth, and the terminal never writes scrollTop itself. xterm's smooth scroll option is back at its default of zero, and the kinetic scroller no longer zeroes and restores it around a gesture.
Measured against a real ttyd in a real headless Chrome, before and after: reverse travel at the bottom edge went from 252px to 18px. Lag at the end of a trackpad drag went from 21px to 12px at the probe's cadence, with the remaining sub-row remainder under 9px. A 100px mouse notch lands on 5 or 6 rows in both builds. Four other paths behave as before. They are scrolling while the pane streams output, tmux mouse mode, a touch drag under phone emulation, and select plus copy after a scroll.
Known limits
A mouse notch glides for about 50ms now, not 120ms. Line-mode mouse wheels on Windows and Linux, and Shift+PageUp, move instantly instead of gliding. The repo's own mobile fixture check fails on this machine with Chrome 152 before the page loads, on the unmodified client too. So a separate phone-emulation probe verified the touch path.
Upgrade notes
There is no configuration step. Restart the running Dispatch after you upgrade, then reload the board so the terminal loads the new client.
Full changelog: v3.6.2...v3.6.3
Requires Node ≥ 22.22, tmux, ttyd, git, and the Claude Code CLI. Setup is in the README.
