-
Notifications
You must be signed in to change notification settings - Fork 24
fix: handle mouse wheel scroll in pipe-pane mode #43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Conversation
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
…heel scrolling When scrolling with the mouse wheel in the browser, the previous implementation sent SGR mouse sequences (\x1b[<64;..M) via `tmux send-keys -l`, which has two issues: 1. The `-l` flag sends keys literally, which doesn't trigger tmux's WheelUpPane binding 2. Even without `-l`, `send-keys` sends input TO the pane, not to tmux itself This caused the shell to receive the sequences instead of tmux entering copy-mode, resulting in command history scrolling instead of scrollback buffer scrolling. The fix: - Added new `tmux-scroll` message type to bypass send-keys entirely - Directly invoke `tmux copy-mode` and `tmux send-keys -X scroll-up/down` - Works consistently with both desktop mouse wheel and touch scrolling - Matches native tmux behavior when connected directly This ensures mouse wheel scrolling in the browser enters tmux copy-mode and scrolls the scrollback buffer, just like scrolling in native tmux. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
After scrolling, check tmux's pane_in_mode status and report it to the client. When scrolling down reaches the bottom, tmux automatically exits copy-mode, and we now detect this and update the UI accordingly. This eliminates the need to press 'q' to exit copy-mode - just scroll down to the bottom and it exits automatically, matching native tmux behavior. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Tmux doesn't auto-exit copy-mode when reaching the bottom - it stays in
copy-mode until explicitly exited. Now we check #{scroll_position} after
scrolling down, and if it's 0 (at the bottom), we explicitly send the
cancel command to exit copy-mode.
This provides the expected behavior: scroll down to bottom → automatically
exits copy-mode and returns to live terminal.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Instead of intercepting scroll events client-side and sending a separate tmux-scroll message, handle SGR mouse scroll sequences directly in PipePaneTerminalProxy.write(). This approach: - Only affects pipe-pane mode (where send-keys -l doesn't trigger tmux mouse handling) - Leaves PTY mode unchanged (native tmux mouse handling works correctly) - Reduces complexity by keeping scroll logic server-side - Avoids extra WebSocket message round-trips The fix intercepts ESC[<64;col;rowM (scroll-up) and ESC[<65;col;rowM (scroll-down) sequences before they're sent as literal text to the shell, and instead: 1. Enters tmux copy-mode (idempotent) 2. Sends scroll-up or scroll-down via send-keys -X Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Improvements to SGR mouse scroll handling in pipe-pane mode: - Support modifier keys (Shift/Alt/Ctrl) by masking off modifier bits (button & 67) to extract the base wheel button (64=up, 65=down) - Handle batched scroll sequences in a single write() call - Only enter copy-mode once per write batch for efficiency - Properly handle mixed scroll + text input - Ignore release events (lowercase 'm') Added tests for: - Shift+scroll, Ctrl+scroll, Alt+Shift+scroll variants - Multiple scroll sequences in one write - Mixed scroll and text input - Release event handling Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
After scroll-down events in pipe-pane mode, check #{scroll_position}
and cancel copy-mode when at position 0 (bottom). This prevents getting
stuck in copy-mode from incidental scroll-down input (especially common
with trackpads that generate many down deltas).
Added tests for:
- Copy-mode exit when scroll_position=0
- No exit when scrolled up (position > 0)
- Scroll-up does not trigger position check
Co-Authored-By: Brenner Spear <BrennerSpear@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
39b4518 to
9c389d5
Compare
gbasin
added a commit
that referenced
this pull request
Feb 4, 2026
## Summary - Fixes mouse wheel scrolling in pipe-pane terminal mode by intercepting SGR scroll sequences server-side - Only affects pipe-pane mode - PTY mode continues to use native tmux mouse handling ## Changes - Intercept `ESC[<64;col;rowM` (scroll-up) and `ESC[<65;col;rowM` (scroll-down) in `PipePaneTerminalProxy.write()` - Enter tmux copy-mode and send scroll commands instead of passing sequences as literal text to shell - Added unit tests for scroll handling ## Why this approach The original PR (#42) intercepted scroll events client-side and sent a separate `tmux-scroll` WebSocket message. This refactor: - Keeps scroll logic server-side in the proxy that needs it - Avoids extra WebSocket round-trips - Leaves PTY mode completely unchanged (no performance impact) Based on PR #42 by @croakingtoad - thank you for identifying the issue and initial implementation! Co-Authored-By: Marty Martin <croakingtoad@users.noreply.github.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Marty <marty@example.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
gbasin
added a commit
that referenced
this pull request
Feb 4, 2026
## Summary - Fixes mouse wheel scrolling in pipe-pane terminal mode by intercepting SGR scroll sequences server-side - Only affects pipe-pane mode - PTY mode continues to use native tmux mouse handling ## Changes - Intercept `ESC[<64;col;rowM` (scroll-up) and `ESC[<65;col;rowM` (scroll-down) in `PipePaneTerminalProxy.write()` - Enter tmux copy-mode and send scroll commands instead of passing sequences as literal text to shell - Added unit tests for scroll handling ## Why this approach The original PR (#42) intercepted scroll events client-side and sent a separate `tmux-scroll` WebSocket message. This refactor: - Keeps scroll logic server-side in the proxy that needs it - Avoids extra WebSocket round-trips - Leaves PTY mode completely unchanged (no performance impact) Based on PR #42 by @croakingtoad - thank you for identifying the issue and initial implementation! 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Marty Martin <croakingtoad@users.noreply.github.com> Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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.
Summary
Changes
ESC[<64;col;rowM(scroll-up) andESC[<65;col;rowM(scroll-down) inPipePaneTerminalProxy.write()Why this approach
The original PR (#42) intercepted scroll events client-side and sent a separate
tmux-scrollWebSocket message. This refactor:Co-Authored-By: Marty Martin croakingtoad@users.noreply.github.com
🤖 Generated with Claude Code