-
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
terminal: Fix fast scrolling during mouse mode #45600
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
terminal: Fix fast scrolling during mouse mode #45600
Conversation
|
We require contributors to sign our Contributor License Agreement, and we don't have @emamulandalib on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
|
@cla-bot check |
|
We require contributors to sign our Contributor License Agreement, and we don't have @emamulandalib on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
|
The cla-bot has been summoned, and re-checked this pull request! |
|
@cla-bot check |
|
The cla-bot has been summoned, and re-checked this pull request! |
|
Checking in to see if there is any update on this review? |
19e56f2 to
84eec06
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice find and digging, thanks for this and the thorough explanation!
Minor thing, but can we instead go for something like
if let Some(scroll_lines) = self.determine_scroll_lines(e, scroll_multiplier)
&& scroll_lines != 0 {
...instead?
I think it makes sense to a degree that determine_scroll_lines can return Some(0) (in theory, one could also make an argument for this not making sense, I am also open for fixing this within determine_scroll_lines), however, I do not think it makes any sense that we do any action within scroll_wheel when the determined scroll_lines is 0.
Given that we now check for it in two of three places and the place where we not check for this handles this implicitly, how about we just introduce one check for this all, instead of having separate ones?
Other than that, makes sense and looks good, nice consise fix!
Scrolling with a trackpad in tmux, neovim, or any terminal app that
enables mouse mode was way too fast. A gentle swipe would send you
flying through hundreds of lines.
The culprit was in how we handle mouse scroll reports. When the
terminal is in mouse mode, we send escape sequences to tell the app
about scroll events. The problem was we sent these events even when
no full line of scroll had accumulated yet.
Deep in scroll_report(), there was this:
repeat(report).take(max(scroll_lines, 1) as usize)
That max(scroll_lines, 1) meant we'd send at least 1 scroll event
even when scroll_lines was 0. On macOS, trackpad gestures fire many
small pixel deltas due to scroll acceleration. Each tiny movement
triggered a scroll event to tmux, even though we hadn't accumulated
enough pixels for a full line yet.
The fix is simple - just don't send mouse reports when scroll_lines
is zero:
if mouse_mode && scroll_lines != 0 {
Tested with tmux, neovim, and opencode - all scroll as expected now.
Closes zed-industries#18930
84eec06 to
2fb76e3
Compare
|
@MrSubidubi completely agree and makes sense. Just updated accordingly and tested locally. Please review again. |
MrSubidubi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good now, thank you! And congratulations to your first contribution! 🎉
Closes #18930
Summary
The Problem
Scrolling with a trackpad in tmux, neovim, or any terminal app that enables mouse mode was too fast. A gentle swipe would send me through hundreds of lines, making these apps practically unusable in Zed's terminal.
Root Cause
When the terminal is in mouse mode, we send escape sequences to report scroll events to the application. The bug was in
scroll_report():zed/crates/terminal/src/terminal.rs
Lines 1983 to 1988 in ca47822
That
max(scroll_lines, 1)meant we'd send at least 1 scroll event even whenscroll_lineswas 0.zed/crates/terminal/src/mappings/mouse.rs
Line 96 in ca47822
On macOS, trackpad gestures fire many small pixel deltas due to scroll acceleration. Each tiny movement triggered a scroll event, even though we hadn't accumulated enough pixels for a full line yet. This is a known issue alacritty/alacritty#2869 - macOS sends fractional line deltas (like 0.1) instead of whole lines.
The Fix
Don't send mouse reports when no full line has accumulated
This aligns with Alacritty's approach - accumulate partial scroll amounts and only report when complete lines are ready.
https://github.com/alacritty/alacritty/blob/6ee6e53ee3457c24137f117237b0ff1d84f6f836/alacritty/src/input/mod.rs#L700-L730
Testing
Tested trackpad scrolling in:
All scroll smoothly now.
Demo
The demo shows the behavior of the scrolling. I can go fast or I can go slow
Screen.Recording.2025-12-23.at.22.53.25.mov
Release Notes: