Forward mouse events to the PTY when the app asks for them - #182
Open
phil-kremidas-unitedmasters wants to merge 1 commit into
Open
Forward mouse events to the PTY when the app asks for them#182phil-kremidas-unitedmasters wants to merge 1 commit into
phil-kremidas-unitedmasters wants to merge 1 commit into
Conversation
astex
force-pushed
the
forward-mouse-events
branch
from
August 3, 2026 18:32
a829201 to
de7149a
Compare
mandelbot never sent mouse reports, so the wheel and clicks were dead inside tmux, vim, less, htop and anything else that enables mouse tracking. Worse, inside the alternate screen our own grid keeps no scrollback, so the wheel had nowhere to go at all. Add a pure encoder in src/widget/mouse_report.rs covering SGR (1006), legacy X10 and UTF-8 extended coordinates, plus the alternate-scroll arrow-key translation, and wire it into the existing mouse arms of the terminal widget. Precedence, highest first: our own scrollbar (it is chrome, never app input), then shift-held events (the conventional escape hatch, so text selection and copy/paste still work inside a mouse-aware app), then application reporting, then local scrollback and selection. Behavior with reporting off is unchanged. Motion reports fire only when the cursor crosses into a new cell, and a release is only sent for a button whose press we forwarded, so the application never sees an unbalanced press. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
astex
force-pushed
the
forward-mouse-events
branch
from
August 13, 2026 16:30
de7149a to
88dc65e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
mandelbot never sent mouse reports —
grep -rn 'MOUSE\|SGR' src/came back empty. The wheel and clicks were dead inside tmux, vim, less, htop and anything else that enables mouse tracking. Worse, inside the alternate screen our own grid keeps no scrollback (history_size() == 0), soMessage::Scrollwas a no-op and the wheel had nowhere to go at all.What's here
A pure encoder in
src/widget/mouse_report.rs— grid coordinates and modifiers in, PTY bytes out, no widget state — covering:CSI < Cb ; Cx ; Cy M/m) whenSGR_MOUSEis set.CSI M Cb Cx Cy,+32offset, 1-based coordinate clamped at 223) otherwise, with UTF-8 extended coordinates whenUTF8_MOUSEis set.+32motion bit, and modifier bits (shift 4, meta 8, control 16).ALTERNATE_SCROLL: on the alt screen with mode 1007 and no mouse reporting, the wheel becomes cursor-key presses (ESC O A/ESC [ Aper line, honoringAPP_CURSOR). This is what makeslessscroll.Wired into the existing
WheelScrolled,ButtonPressed,ButtonReleasedandCursorMovedarms of the terminal widget.Precedence
Highest first:
TermMode::MOUSE_MODEis set.Two details worth flagging:
pixel_to_gridreturns.pixel_to_screen_cellis a separate helper for exactly that reason.Verification
14 unit tests on the encoder (SGR press/release/drag/wheel/no-button, X10
+32offset and the 223 clamp, X10 release reporting button 3, modifier bits individually and combined, UTF-8 wide coordinates, SGR winning over UTF-8, alternate scroll arrows andAPP_CURSOR).cargo buildandcargo testpass — 92 tests, up from 78.Also verified live in a real mandelbot window by capturing the exact bytes reaching the PTY:
ESC [ < 0 ; 69 ; 5 M, dragESC [ < 32 ; ... Memitted once per cell crossed with no duplicates, releaseESC [ < 0 ; 52 ; 13 m— correct button identity, lowercase final byte. Wheel gave64up /65down. Double- and triple-click forwarded as three press/release pairs rather than becoming local selection. Shift-held drag produced no reports at all (no report anywhere in the capture carried the+4shift bit).ESC [ Aper line, wheel downESC [ B.vimwith:set mouse=a— clicks move the cursor, wheel scrolls.less— wheel scrolls via the alternate-scroll path. Confirmed by the repo owner clicking in the window; I could not synthesize input myself (this environment denies Accessibility and Screen Recording), so the app-level confirmation is observational rather than captured.tmux specifically was not exercised — it isn't installed on this machine. Its path is the SGR one that the probe covers byte-for-byte.
Merge note
Touches the
WheelScrolledarm, where a sibling change is adding wheel delta accumulation. The diff there is deliberately tight — oneshell.publish(Message::Scroll(lines))becomes amatchonself.wheel_report(...)— but whoever merges second will need to rebase that arm. The accumulatedlinesvalue should feedwheel_reportunchanged.Out of scope
Mouse forwarding only. Not touched: the alt-screen scrollbar being hidden when
history_size == 0(correct as-is once the wheel reaches the app), focus reporting (mode 1004), and pixel-precision mouse mode (1016).🤖 Generated with Claude Code