Skip to content

Fix desktop zoom scrolling the window under the pointer, and Super opening the menu after zooming - #854

Open
AlexB7 wants to merge 2 commits into
linuxmint:masterfrom
AlexB7:zoom-fix-master
Open

Fix desktop zoom scrolling the window under the pointer, and Super opening the menu after zooming#854
AlexB7 wants to merge 2 commits into
linuxmint:masterfrom
AlexB7:zoom-fix-master

Conversation

@AlexB7

@AlexB7 AlexB7 commented Aug 18, 2026

Copy link
Copy Markdown

Fixes #695
Addresses linuxmint/cinnamon#12587 (and the long lineage behind it: linuxmint/cinnamon#5163, #10084, #10148, #11728)

The bugs

With Accessibility → Zoom enabled and a mouse-wheel modifier set, two things go wrong on X11:

  1. Scroll passthrough: zooming also scrolls the window under the pointer — vertically with Super, horizontally with Shift, app-zoom with Ctrl. As diagnosed in Desktop Zoom Mouse Wheel scrolling also scrolls XInput2 application window contents #695, this only affects XInput2-aware clients (GTK3 apps, Chromium/Electron, Firefox with MOZ_USE_XINPUT2=1), which is by now nearly everything.
  2. Bonus bug from Desktop Zoom Mouse Wheel scrolling also scrolls XInput2 application window contents #695: with Super as the modifier, releasing Super after zooming pops up the Cinnamon menu.

Note:

  1. These issues do not affect Linux Mint 22.3 Wayland except for the super key bringing up the menu. The first commit solves this issue for both Wayland and X11.
  2. With a stable Wayland coming in the next release of Mint, one could argue that this very old bug doesn't really need to be fixed but end of support for 22.x isn't until April 2029.

Root causes

Passthrough: muffin's zoom capture uses passive XIGrabButton grabs on buttons 4/5. Those only ever intercept the emulated legacy scroll button events. With XI 2.1 smooth scrolling, the X server delivers the smooth-scroll XI_Motion valuator event to the client under the pointer before the emulated button event activates the passive grab — motion events cannot trigger a passive button grab. So muffin gets the button event (zoom works) and the client gets the motion event (window scrolls). This was confirmed with xev vs xinput test-xi2, and with Firefox/Emacs XInput2 on/off builds (see #695).

Menu popup: scroll events consumed by the zoom branch in events.c bypass meta_keybindings_process_event, so the modifier-only ("overlay key") state is never cancelled; Super-press → zoom → Super-release looks like a bare Super tap.

The fix

Commit 1 cancels the pending modifier-only state when a zoom scroll is consumed (and on scroll events generally, matching the existing button/touch behavior). Fixes the menu popup on both X11 and Wayland.

Commit 2 takes an active grab on the virtual core pointer for the duration of a zoom scroll burst. The first consumed zoom scroll engages the grab (via the existing meta_backend_grab_device()); each further scroll refreshes a 1 s idle timer. The grab is released on timeout, on a button press, or as soon as the zoom modifier is released (tracked through XkbStateNotify, which muffin already receives — no key grabs involved). While the grab is held, smooth-scroll motion events route to muffin and cannot reach the client.

The grab is intentionally not held for the whole time the modifier is down. Modifier+click interactions (Shift+click selection, Ctrl+click) must keep working, and re-injecting a swallowed click via XTest is not possible: the physical press has already registered in the master device's button state, so the synthetic press is discarded by the server as a duplicate (verified with xev: no ButtonPress delivered, EnterNotify state 0x111).

Wayland is unaffected by commit 2 (guarded, and not needed — muffin consumes the events before delivery there).

Known limitations

  • The first scroll event of each burst can still leak to an XI2 client (it has been processed by the time the grab can engage). Subsequent events in the burst are fully captured. Using the Super key may be the best choice as it won't interfere with side scrolling, browser zooming etc.
  • The engage can fail transiently (AlreadyGrabbed) if another client holds a pointer grab (open menu, button held); it retries on the next scroll event and zoom itself keeps working through the passive grabs.
  • A click landing within the 1 s idle window after the last zoom scroll is consumed by the grab teardown.

Testing this PR on the stable 6.6.x series (Mint 22.3)

This PR targets master, but the patches apply cleanly to the current stable release, so anyone affected can try them on a test installation of Linux Mint 22.x / muffin 6.6.x:

Pre-rebased branch (easiest): a backport onto the 6.6.3 tag is at AlexB7/muffin branch zoom-fix-6.6.3:

git clone --branch zoom-fix-6.6.3 https://github.com/AlexB7/muffin
cd muffin
sudo apt build-dep muffin        # needs a deb-src line enabled
dpkg-buildpackage -us -uc -b
sudo apt install ../libmuffin0_*.deb ../muffin_*.deb ../muffin-common_*.deb ../gir1.2-meta-muffin-0.0_*.deb

Or apply this PR's commits yourself:

git clone https://github.com/linuxmint/muffin && cd muffin
git checkout -b zoom-test 6.6.3
curl -L https://github.com/linuxmint/muffin/pull/854.patch | git am -3

Either way, install the full package set (the fix lives in libmuffin0) and log out/in afterwards. To verify: enable Accessibility → Zoom with a mouse wheel modifier, hold the modifier and scroll over Chromium or any GTK3 app — the window content should no longer scroll while zooming (apart from at most the first tick of a burst), and with Super as the modifier the menu should no longer open when you release the key.

Reverting: the locally built version (6.6.3) sorts below the distro's (6.6.3+<codename>), so going back to stock is just

sudo apt install --reinstall --allow-downgrades muffin libmuffin0 muffin-common gir1.2-meta-muffin-0.0

and a log out/in. For the same reason, Update Manager will offer to replace the patched build with the stock package at the next update — hold the packages (sudo apt-mark hold muffin libmuffin0 muffin-common gir1.2-meta-muffin-0.0) if you want to keep testing through updates, and unhold when done.

Testing done

On Linux Mint 22.3, muffin 6.6.3 + these patches, X11:

  • Super/Shift + wheel over Chromium, GNOME Terminal, and MOZ_USE_XINPUT2=1 Firefox: zoom works, window content no longer scrolls (previously reproduced reliably in all three).
  • Super release after zooming no longer opens the menu (also verified over VNC, where only the legacy-button path exists).
  • Shift as modifier: Shift+click and Shift+drag text selection in xed work with zoom enabled; Shift horizontal scroll correctly suppressed while zooming.
  • Plain Super tap still opens the menu; Alt-Tab, window drag, unmodified scrolling unchanged.
  • Wayland session: no regressions; passthrough does not occur there by design.

🤖 Generated with Claude Code

AlexB7 added 2 commits August 17, 2026 20:00
Scroll events consumed for the a11y mouse-wheel zoom bypass
meta_keybindings_process_event entirely, so nothing cleared the
modifier-only key state: pressing Super, zooming with the wheel and
releasing Super still looked like a bare modifier tap and activated the
overlay-key binding, popping up the Cinnamon menu after every zoom.

Cancel the pending modifier-only state when a zoom scroll is consumed,
and treat scroll events like button presses and touches when tracking
modifier-only key state.

Ref: linuxmint#695
Ref: linuxmint/cinnamon#12587

Co-Authored-By: Claude Fable 5
The a11y mouse-wheel zoom relies on passive button 4/5 grabs, which
only intercept the emulated legacy scroll button events.  XInput2-aware
clients (GTK3 apps, Chromium/Electron, Firefox with MOZ_USE_XINPUT2=1)
scroll with the smooth-scroll XI_Motion valuator events instead, and
those are delivered to the client before any passive button grab can
activate.  As a result, zooming also scrolled the window under the
pointer.

Take an active grab on the virtual core pointer when a zoom scroll is
consumed and hold it for the duration of the scroll burst; it is
released after a short idle timeout, on a button press, or as soon as
the zoom modifier is released (tracked via XkbStateNotify).  While the
grab is held, the smooth-scroll motion events are routed to muffin and
can no longer leak to the client.

The grab is deliberately not held for the whole time the modifier is
down: modifier+click interactions (Shift+click selection, Ctrl+click)
must keep working, and a click swallowed by an active grab cannot be
re-injected - the physical press has already registered in the master
device's button state, so a synthetic press is discarded by the server
as a duplicate.  The only remaining leak is the first scroll event of a
burst, which has been processed by the time the grab can engage.

Wayland sessions are unaffected: muffin sees all events there and
already consumes them before delivery to the client.

Fixes linuxmint#695
Ref: linuxmint/cinnamon#12587

Co-Authored-By: Claude Fable 5
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.

Desktop Zoom Mouse Wheel scrolling also scrolls XInput2 application window contents

1 participant