BRUCE BLOG / INTERACTION

Distance, not time: investigating terminal scrolling

Seven rounds of measurements could not explain a heavy scroll. The turning point was measuring how far the view moved for the same gesture.

Yang Yong’an + Claude Code · Published · Originally recorded

“It does not follow my hand” is not yet a diagnosis

The original report was specific: a full-screen TUI inside Bruce scrolled smoothly under inertia, yet felt heavy during repeated changes of direction. The reference was a familiar IDE terminal. We interpreted the problem as slow response and started measuring latency.

This article adapts a development record from September 2026. Its numbers belong to the device, versions and fixtures used then; they are not performance promises for every terminal or computer. The useful part is the method for turning an accurate physical description into measurements that distinguish possible causes.

Healthy numbers, the wrong explanation

We checked writing, transport, program responses, parsing, frame timing and the glyph atlas. Some improvements were real: shorter batching windows, better scheduling and preventing a blocked write from holding up other work. None explained the consistent heavy feeling.

The fixture mattered too. A minimal browser page, an empty newly started TUI and the native window someone is using are different scenes. We added a development evaluation channel into the actual window, so a request could inspect live state and return a result. Only then could we identify the path taken by a real gesture.

One trace showed the terminal moving its own scrollback. The gesture never entered the path we had been optimizing, which sends wheel reports to the program. Establishing who owns the gesture should come before optimizing its handling.

The turning point was a simpler comparison

The developer repeated the gesture in another terminal and described the difference more precisely: it was not taking too long; it was not traveling far enough. Time and distance finally became separate questions. A responsive system can still feel sluggish when its displacement gain is wrong.

A recorded three-second gesture contained 165 events totaling roughly 1002px, averaging about 6.1px per event. The relevant path converted pixels into rows and multiplied events below 50px by an additional 0.3. A trackpad split the gesture into many small steps, nearly all of which were reduced. At the measured row height of about 15px, roughly 66 reports were expected, but only about 20 arrived.

This affected wheel reports sent to the full-screen application, not every kind of scrolling. When two paths are mixed together, healthy latency measurements cannot establish whether the distance is correct.

Apply the correction to the path that needs it

Our first compensation targeted the wrong path. It amplified already healthy scrollback and produced overshoot. The corrected condition was narrower: the event must go to the program, use pixel mode, and fall within the original range affected by the reduction. This snippet preserves only the core decision used at the time.

This is not a global sensitivity increase. Larger mouse steps did not receive the same reduction and must not be amplified with them. We also turned equal total travel with different event partitions into regression cases and submitted the issue and a proposed fix upstream at the time. Local behavior still needed its own verification.

const sensitivity = toProgram && pixelMode && Math.abs(deltaY) < 50
  ? configured / 0.3
  : configured;

Leave the next investigation a shorter route

The durable result was more than a scroll correction. Access to the actual window, instruments that report their own failures and a habit of comparing the same gesture can help the next developer or Agent avoid applying correct numbers to the wrong scene.

  • Identify the surface and processing path that own the event.
  • Check both elapsed time and displacement when something feels unresponsive.
  • Record the device, version, content and foreground state with the measurement.
  • Turn the decisive comparison into a regression case, rather than leaving only a feeling of improvement.

Download Markdown