docs/demos/native-wheel-scrolling.html
Ref: Size: 6.2 KiB History
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>mux · Wheel scrolling</title>
<style>
:root{color-scheme:dark;font-family:system-ui,sans-serif;background:#17191d;color:#e8e9ed}
*{box-sizing:border-box}body{max-width:960px;margin:auto;padding:36px 22px 64px;line-height:1.65}
h1{font-size:clamp(2rem,6vw,3.8rem);line-height:1.1;margin:12px 0 20px;letter-spacing:-.04em}h2{font-size:1.25rem;margin-top:32px}
a{color:#99ded6}p{max-width:75ch}.eyebrow{font-size:.8rem;letter-spacing:.13em;text-transform:uppercase;color:#a1b5b3}
video{width:100%;display:block;background:#101114;border-radius:10px;margin:22px 0 8px;border:1px solid #393f46}
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin:28px 0}.card{padding:18px;border:1px solid #393f46;border-radius:10px}.card strong{display:block}.muted{color:#adb5bf}code{font-size:.9em;background:#272c32;padding:2px 5px;border-radius:4px}li{margin:8px 0}.status{color:#aadbd0}
@media(max-width:650px){.cards{grid-template-columns:1fr}body{padding-top:24px}}
</style>
<p class="eyebrow">mux native · GUI / TUI parity</p>
<h1>Scroll the pane<br>under your pointer.</h1>
<p>Use the wheel to browse shell history, scroll alternate-screen applications such as less, and send wheel reports to applications that request mouse input. Each pane keeps its own scroll position and fractional movement. Keyboard focus stays where you left it.</p>
<p class="status">Implemented · Final checks passed · Demo acceptance pending</p>
<video controls playsinline preload="metadata" poster="preview.png"><source src="demo.mp4" type="video/mp4">Your browser can <a href="demo.mp4">download the recording</a>.</video>
<p class="muted">27-second continuous recording · NVIDIA RTX 3080 · Wayland at 200% scale · <a href="demo.mp4">Open video</a></p>
<div class="cards"><div class="card"><strong>Shell history</strong>Three rows per notch. Scroll down to live output, or type to return immediately.</div><div class="card"><strong>Application input</strong>Alternate-screen arrows honor cursor-key mode; mouse-aware apps receive the encoding they request.</div><div class="card"><strong>History selection</strong>Drag to copy the displayed history rows. The highlight follows its text when you scroll, including away and back.</div></div>
<h2>What the recording shows</h2>
<p class="muted">The recording below predates the selection-preservation fix. The highlight also now survives live counter updates and redraws. These fixes are ready for hands-on review; no replacement recording was requested.</p>
<p>Three panes on two daemons. Scroll an unfocused shell pane, select a history row, read its text with a separate desktop clipboard client, return to live output, then scroll a real less process. Pointer motion, selection and wheel events go through the Wayland compositor. Setup commands use the ordinary SDL keyboard event path.</p>
<h2>Controls</h2>
<ul><li>Wheel over terminal content to scroll that pane without moving keyboard focus.</li><li>At a shell prompt, wheel up browses history and wheel down returns toward live output. Typing into that pane returns it to live.</li><li>Drag across displayed text and release to copy; Ctrl+Shift+C also copies the current selection.</li><li>Menus, headers, dividers and command mode consume wheel events. Horizontal wheel behavior remains outside this slice.</li></ul>
<h2>Validation</h2>
<p id="validation">Full CI, native integration, focused client/native tests and real offscreen/Wayland acceptance passed. Core policy tests also run without GUI library metadata.</p>
<p>Independent PTY readers check exact arrow sequences and X10, UTF-8, SGR, URXVT and SGR-pixel wheel reports. Pixel reports and real PTY sizes pass at 200%, 100%, 150% and 200%. Clipboard checks use a separate Wayland client. Deterministic wire tests cover delayed replies, same-origin cancellation, resize, resync, timeout and mode frames queued before wheel input.</p>
<h2>Hardware timing and earlier misses</h2>
<p>The final separate raw-output stress run passed: frame p99 <strong>18.745 ms</strong> against the 20 ms limit, and sampled input-to-painted response at most <strong>65.3 ms</strong> against 250 ms (5 ms polling). Earlier runs missed the frame limit. The old release also failed under the same isolated NVIDIA Wayland conditions at 60 Hz and 200% scale. These observations do not establish that wheel scrolling improves or worsens rendering performance; the final pass does not explain the earlier misses.</p>
<ul><li>Initial wheel build: frame p99 20.199 ms.</li><li>Previous release comparison: frame p99 21.449 ms.</li><li>Wheel build comparison: frame p99 22.244 ms.</li></ul>
<p>Most of the measured frame time was in draw/swap. Recordings and other GUI test fixtures were stopped during measurements. All failed logs and independent input-to-painted samples are retained with the sprint evidence. The renderer follow-up still owns the earlier unexplained timing misses and offscreen-growth artifacts.</p>
<h2>Design and limits</h2>
<p>The daemon still owns terminal parsing and history extraction. The native client reuses the existing protocol and keeps a separate history grid for display. One outstanding fetch is retained until its reply arrives; cancelled replies cannot replace a newer view. History refreshes as output arrives, keeping the same distance from live. While a refresh is pending, stale text cannot be copied.</p>
<p>Continuous output can delay a safe history refresh or a wheel waiting behind pending mode frames. The wire has no source-version precondition, so an atomic historical-frame copy during concurrent output is not promised. Tests cover Linux; macOS validation remains open.</p>
<p>Application click/drag forwarding and application clipboard requests are next. <strong>Shift+drag to force native selection is required for that slice.</strong> GUI paste, edge autoscroll, word/line/rectangular selection and ligatures remain deferred.</p>
<p class="muted">Passing checks is separate from demo approval. Feedback requested: scrolling speed, pane targeting and history selection. After acceptance, this demo's owned server will be stopped; its page and recording will be retained.</p>
</html>