fix-mouse-wheel-2

Fix: mouse wheel sending arrow keys to inner app instead of scrolling outer scrollback (regression from implement-tui-scroll)

Metadata

Statusdone
Assignedagent-1169
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Created2026-04-29T19:27:34.299310701+00:00
Started2026-04-29T19:27:58.851453218+00:00
Completed2026-04-29T19:42:22.507436516+00:00
Tagspriority-high,bug,tui,input,regression, eval-scheduled
Eval score0.82
└ blocking impact0.90
└ completeness0.80
└ constraint fidelity0.70
└ coordination overhead0.85
└ correctness0.85
└ downstream usability0.80
└ efficiency0.85
└ intent fidelity0.92
└ style adherence0.90

Description

Description

Regression report 2026-04-29 evening. Mouse wheel scrolling in the wg TUI is now passing arrow-key events through to the inner app (claude / codex) instead of scrolling the outer scrollback. Claude itself is detecting this and emitting the warning:

'Scroll wheel is sending arrow keys · use PgUp/PgDn to scroll in claude code'

Symptoms:

  • Affects BOTH claude and codex chat views
  • Worse under tmux (where it previously worked with both touch AND wheel)
  • Touch scroll behavior also degraded
  • Worked correctly earlier today

User quote: 'getting this error now: Scroll wheel is sending arrow keys · use PgUp/PgDn to scroll in claude code... happens now in the tui in both claude code and codex chat views. and it worked before... also this happens in tmux but before i could scroll with finger and scroll wheel.'

Likely culprit

implement-tui-scroll (commit bfb231c7e) shipped the keyboard scroll-mode toggle. It almost certainly wired wheel-to-key translation as the implementation mechanism for in-scroll-mode wheel scrolling, but failed to scope it correctly:

  • Translating wheel events to arrows ALWAYS (not just in scroll mode)
  • OR routing translated keys to the inner-app PTY (where claude sees them) instead of the outer-pane scrollback handler
  • OR clobbering fix-mouse-wheel (commit 8ddeb9e42)'s direct wheel→scroll wiring

Expected behavior (regression target)

  • Outside scroll mode: mouse wheel scrolls the OUTER scrollback. Inner app sees nothing. (This is what fix-mouse-wheel shipped.)
  • Inside scroll mode: mouse wheel scrolls the OUTER scrollback (same as outside). PgUp/Down/arrows from keyboard ALSO scroll the OUTER scrollback. Inner app sees nothing.
  • Outer scrollback only: wheel events should NEVER be translated into arrow-key events forwarded to the inner app's PTY. That's the bug.

Investigation

  1. Inspect the wheel-event handling added/changed in implement-tui-scroll. Look for any translation from MouseEventKind::ScrollUp/Down to KeyCode::Up/Down being forwarded to the PTY's stdin instead of routed to the scrollback navigator.
  2. Check whether scroll-mode's keymap implementation created a unified handler that handles wheel and key events the same way — that would explain why wheel events end up looking like keypresses.
  3. Verify fix-mouse-wheel's wiring is still intact post-implement-tui-scroll. If it was rewritten / replaced, that's the regression.
  4. Check tmux interaction: under tmux, mouse events route through tmux's mouse mode first. Tmux can be configured to translate wheel events to arrows for legacy apps. If our TUI is ALSO translating, the user gets double-translated arrows. The fix should make our TUI consume wheel events at the outer layer regardless of tmux mode.

Validation

  • Failing test or repro: open claude chat in wg TUI, mouse wheel up. Pre-fix: claude shows the 'arrow keys' warning. Post-fix: outer scrollback scrolls; claude sees nothing.
  • Same for codex chat
  • Test under tmux: same behavior — wheel scrolls OUTER, inner app sees nothing
  • Test with touch scroll: behavior is identical to wheel (no asymmetry — both consumed at outer layer)
  • No regression of fix-mouse-wheel original repro (wheel scrolls codex scrollback)
  • No regression of implement-tui-scroll keyboard mode (toggle still works, PgUp/Down/arrows still scroll outer in scroll mode)
  • cargo build + cargo test pass
  • Permanent smoke scenario added: simulate ScrollUp event into the TUI, assert it does NOT produce a write of arrow-key bytes to any PTY child stdin, and DOES advance the active pane's scroll offset
  • cargo install --path . was run before claiming done

Process note

This is the kind of bug where 'cargo test passes' is meaningless — the bug is in event routing, which unit tests can't easily catch unless someone wrote them at the routing layer. The smoke scenario above (ScrollUp event → assertion on PTY stdin bytes) is the real test. Don't ship without that scenario passing.

Depends on

Required by

Log