-
Notifications
You must be signed in to change notification settings - Fork 24
Fix mouse wheel scrolling to use tmux copy-mode instead of sending arrow keys to shell #42
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
Closed
croakingtoad
wants to merge
3
commits into
gbasin:master
from
croakingtoad:fix/tmux-scroll-wheel-in-browser
Closed
Fix mouse wheel scrolling to use tmux copy-mode instead of sending arrow keys to shell #42
croakingtoad
wants to merge
3
commits into
gbasin:master
from
croakingtoad:fix/tmux-scroll-wheel-in-browser
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>
Contributor
Author
|
I didn't note that this the error was on Windows 11 using Chrome Version 143.0.7499.193 (Official Build) (64-bit) |
Owner
|
Check this, it hopefully does it for you. I want to keep the way PTY scrolling works currently as it's way lower latency: #43 |
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 @BrennerSpear - thank you for identifying the issue and initial implementation! Co-Authored-By: Brenner Spear <BrennerSpear@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> Co-authored-by: Brenner Spear <BrennerSpear@users.noreply.github.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! 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.
Problem
When scrolling with the mouse wheel in the browser, the terminal was scrolling through command history instead of the tmux scrollback buffer. This only affected browser usage - native tmux scrolling worked correctly.
Root Cause
The previous implementation sent SGR mouse sequences (
\x1b[<64;40;12M) viatmux send-keys -l, which had two issues:-lflag sends keys literally, bypassing tmux'sWheelUpPanebindingsend-keyssends input TO the pane, not to tmux itself, so tmux never intercepts the wheel eventsAs a result, the shell received these sequences and interpreted them as scroll events, translating them to Up/Down arrow keys for command history navigation.
Solution
This PR changes the approach to directly control tmux copy-mode:
tmux-scrollmessage type - bypassessend-keysentirelytmux copy-mode+tmux send-keys -X scroll-up/down#{scroll_position}and exits copy-mode when reaching position 0Changes
tmux-scrollmessage type toClientMessageunionhandleTmuxScrollfunction that:tmux-scrollinstead of SGR sequencestmux-scrollinstead of SGR sequencesTesting
Before: Scrolling with mouse wheel scrolled through shell command history
After:
Verified on: Desktop Chrome, Firefox, Safari
Commits
This fixes the longstanding issue where browser-based scrolling didn't match native tmux behavior.