Skip to content

feat(input): bypass mouse reporting while Shift is held - #103

Merged
roramirez merged 1 commit into
mainfrom
feat/shift-bypass-mouse-reporting
Aug 16, 2026
Merged

feat(input): bypass mouse reporting while Shift is held#103
roramirez merged 1 commit into
mainfrom
feat/shift-bypass-mouse-reporting

Conversation

@roramirez

Copy link
Copy Markdown
Owner

Summary

Inside any application that turns on mouse reporting — vim, tmux, htop, Claude Code — clicking a URL did nothing and dragging selected nothing. handle_mouse_input forwarded every left/middle/right click straight to the PTY whenever mouse_mode >= 1000, before the local selection and link paths ran, so the terminal's own mouse features were unreachable for as long as the application held the mouse. Plain-text URL detection (Grid::scan_urls) and OSC 8 links both worked at a shell prompt and both went dead inside those applications.

This adds the xterm convention every other terminal implements: holding Shift on press bypasses mouse reporting for that interaction. The application still owns unmodified clicks, so no existing behaviour changes.

The bypass is latched at press time rather than sampled per event, so releasing Shift mid-drag does not hand the release to the application and leave a selection half-finished.

Changes

  • src/app_state.rs — new AppState.mouse_bypass_reporting: bool, set on a Shift press and cleared on release. Session-only, never persisted.
  • src/app_event.rs — new forward_click_to_pty(mouse_mode, btn_code, bypass) decides between the PTY and local handling; handle_mouse_input latches the flag from self.modifiers and consults the helper. handle_cursor_moved skips report_pty_mouse_move while the flag is set, so the drag paints a local selection instead of streaming motion reports.
  • src/app_event_test.rs — tests for the forwarding rule.
  • CHANGELOG.md — entry under [Unreleased]Added.
  • README.md — note the Shift modifier on the hyperlinks feature line.

Design notes: mouse_selecting could not be reused as the bypass flag — send_pty_mouse_click already sets it to mean "left button is down" while reporting is active, so a separate flag keeps the two meanings apart. The helper is a free function of (mouse_mode, btn_code, bypass) so the rule is testable without a window, an event loop, or a PTY.

How to test

Automated:

cargo fmt --check
cargo clippy --locked -- -D warnings
cargo test

New tests: click_is_forwarded_when_application_enabled_mouse_reporting, click_is_handled_locally_without_mouse_reporting, shift_click_bypasses_mouse_reporting, buttons_beyond_right_are_never_forwarded. Full suite: 1248 tests pass.

Manual (end-to-end):

  1. cargo run, then start something that grabs the mouse — vim, tmux, or Claude Code over SSH — and print a URL inside it.
  2. Click the URL with no modifier: the click reaches the application, exactly as before.
  3. Shift+click the URL: it opens in the browser on the machine running mmterm.
  4. Shift+drag across text, release, then middle-click or paste: the selection was copied.
  5. Back at a plain shell prompt (no mouse reporting), confirm ordinary click, double-click word select, triple-click line select, and link clicks are unchanged.

Applications that enable mouse reporting (?1000/1002/1006h) received every
click, so text selection and link opening were unreachable while they ran.
Holding Shift on press now keeps the whole press-drag-release local, the
xterm convention other terminals follow.
@roramirez
roramirez merged commit bfa31d5 into main Aug 16, 2026
2 checks passed
@roramirez
roramirez deleted the feat/shift-bypass-mouse-reporting branch August 16, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant