Skip to content

Conversation

@emamulandalib
Copy link
Contributor

@emamulandalib emamulandalib commented Dec 23, 2025

Closes #18930

Summary

  • Fix fast Macbook trackpad/mouse scrolling in terminal applications with mouse mode enabled

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():

if mouse_mode {
let point = grid_point(
e.position - self.last_content.terminal_bounds.bounds.origin,
self.last_content.terminal_bounds,
self.last_content.display_offset,
);

That max(scroll_lines, 1) meant we'd send at least 1 scroll event even when scroll_lines was 0.

.map(|report| repeat(report).take(max(scroll_lines, 1) as usize))

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:

  • tmux (pane navigation, scrollback)
  • neovim (buffer scrolling)
  • opencode (TUI navigation)
    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:

  • Fixed trackpad scrolling being too fast in terminal applications with mouse mode enabled (tmux, neovim, opencode, etc.)
@cla-bot
Copy link

cla-bot bot commented Dec 23, 2025

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'.

@emamulandalib
Copy link
Contributor Author

@cla-bot check

@cla-bot
Copy link

cla-bot bot commented Dec 23, 2025

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
Copy link

cla-bot bot commented Dec 23, 2025

The cla-bot has been summoned, and re-checked this pull request!

@emamulandalib
Copy link
Contributor Author

@cla-bot check

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Dec 24, 2025
@cla-bot
Copy link

cla-bot bot commented Dec 24, 2025

The cla-bot has been summoned, and re-checked this pull request!

@emamulandalib
Copy link
Contributor Author

Checking in to see if there is any update on this review?

@MrSubidubi MrSubidubi changed the title Fix fast scrolling in terminal mouse mode (tmux, neovim, opencode etc.) Jan 17, 2026
@MrSubidubi MrSubidubi changed the title terminal: Fix fast scrolling with mouse mode Jan 17, 2026
Copy link
Member

@MrSubidubi MrSubidubi left a 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
@emamulandalib
Copy link
Contributor Author

@MrSubidubi completely agree and makes sense. Just updated accordingly and tested locally. Please review again.

Copy link
Member

@MrSubidubi MrSubidubi left a 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! 🎉

@MrSubidubi MrSubidubi merged commit 6c712d8 into zed-industries:main Jan 19, 2026
26 checks passed
@emamulandalib emamulandalib deleted the tmux-scrolling-speed branch January 19, 2026 16:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement

2 participants