desklets: stop grabbing the pointer where a window covers them - #13979
Open
Fantu wants to merge 1 commit into
Open
desklets: stop grabbing the pointer where a window covers them#13979Fantu wants to merge 1 commit into
Fantu wants to merge 1 commit into
Conversation
Whether desklets belong to the stage input region was decided by polling, every 500 ms, whether the pointer was sitting on a window, and the answer was applied to every desklet at once. The stacking at the pointer position was never consulted, so a desklet under a window could stay in the input region and take the pointer events aimed at that window: the event is either swallowed by the window actor picked above the desklet, or handed to the desklet itself while the window actor above is being animated away, which is why the desklet sometimes ends up stuck to the pointer as if dragged. Decide it per desklet from the window geometry instead: a desklet a window overlaps is taken out of the input region. The input region is made of rectangles, so a desklet partly behind a window can only be all in or all out of it, and keeping it in is what takes the events away from that window; the visible part of such a desklet is no longer clickable, which is a fair trade for the window above it staying usable. Check on 'restacked' as well as on the timeout, so that raising, minimizing or unminimizing a window is noticed right away instead of up to half a second later. This also drops the mouseTrackEnabled cache, which had to be poisoned by hand after a desklet drag to force a refresh, and which left a desklet permanently in the input region when it was recreated while the cached state said the desklets were tracked - the likely reason some reports describe a window that stays uninteractive over a desklet until the session is restarted. Assisted-by: Claude Code:claude-opus-5
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
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.
Fixes the long-standing "desklets steal mouse input from the window on top of them" behaviour: #12567, and previously reported in #1746, #3701, #9190 and #10315 (also Debian #952972, and linuxmint/cinnamon-spices-desklets#1390).
The problem
Whether desklets are part of the stage input region was decided by a 500 ms timeout asking a single global question — is the pointer sitting on a window? — and applying the answer to every desklet at once:
The stacking at the position being clicked was never consulted, so a desklet under a window can stay in the input region and take the pointer events aimed at that window. Two things can then happen, and both are in the bug reports:
The cached
mouseTrackEnabledflag made it worse:_trackMouse()/_untrackMouse()only ran when the aggregate answer flipped, so a desklet created or re-created while the cache said "tracked" was never untracked afterwards. That matches the reports of a window staying uninteractive over a desklet for hours, until the session is restarted, and it is also whyacceptDrop()/cancelDrag()had to poison the cache withmouseTrackEnabled = -1to force a refresh.The change
Decide it per desklet, from the window geometry: a desklet that a window overlaps is taken out of the input region, and it goes back in as soon as nothing covers it. The input region is a list of rectangles, so a desklet partly behind a window can only be all in or all out of it: keeping it in is exactly what takes the events away from that window, so the visible part of a partly covered desklet is no longer clickable. That is a deliberate trade - the window on top staying usable matters more, and the behaviour is predictable instead of depending on where the pointer happened to be half a second earlier.
Desklets raised above the windows keep the input region, as they hold a modal grab anyway.
The check also runs on
restacked, not only on the timeout, so raising, minimizing or unminimizing a window is noticed at once instead of up to half a second later. The timeout stays as the backstop for window moves and resizes.Testing
Tested on a Debian sid VM (Cinnamon 6.6.9, X11, clock desklet at 400,300 172x94, a gnome-terminal window moved over it, clicks driven with xdotool, state read back through
org.Cinnamon.Eval). The exact same diff applies to 6.6.9 and to master. Each case checks whether the desklet is in the input region and whether it received the click:One race remains, and it is inherent to updating an input region after the fact: a click issued in the very same instant as the window is raised, before the main loop can run, is still misrouted. It is reproducible only by sending both in the same batch of X requests — a 50 ms delay is already enough for the new code to behave — whereas the old code was wrong for up to 500 ms.