https://bugs.kde.org/show_bug.cgi?id=478321
[email protected] changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected] --- Comment #5 from [email protected] --- I can reproduce this reliably on a fast 4-finger swipe (touchpad, Plasma 5.27.12 / libinput, Wayland), and traced down what I believe is the actual root cause. **Mechanism** GlobalShortcutsManager wires BOTH SwipeGesture::triggered and SwipeGesture::cancelled to the same QAction::trigger(), via Qt::QueuedConnection (globalshortcuts.cpp). Meanwhile, GestureRecognizer::updateSwipeGesture() (gestures.cpp) eliminates the "wrong direction" sibling gesture candidate on the very first update of a swipe, not after some threshold of travel. On a fast swipe, by the time that queued cancelled signal actually runs (it's delayed behind the current libinput event batch), the direct progress() callback has already pushed VirtualDesktopManager's accumulated offset past the switch threshold from the OTHER (still-active) gesture. So you get: 1. The real gesture's progress callback commits a desktop switch (correct). 2. The eliminated sibling gesture's queued `cancelled` fires late, and because `cancelled` is ALSO wired to the switch action, it commits a second, spurious switch. This explains why the bug caps at exactly one extra switch per fast swipe (never more) - there's only one eliminated sibling to produce one stray queued signal. **Why "just treat cancelled as a no-op" doesn't work** I first assumed the fix was to stop `cancelled` from ever triggering a switch. That's wrong: `VirtualDesktopManager`'s `endSwipeGesture()` legitimately commits a switch via the `cancelled` path too, for any swipe that ends between roughly 25-99% of the travel threshold. Removing that would break normal partial swipes. **Fix that actually works, tested locally** Add a way to ask "is a swipe still structurally active right now": - `GestureRecognizer::hasActiveSwipeGesture()` - trivial, `!m_activeSwipeGestures.isEmpty()`. - `GlobalShortcutsManager::isSwipeGestureInProgress()` - exposes that through the shortcuts manager. Then, at the top of `VirtualDesktopManager::gestureReleasedX()`/`gestureReleasedY()`, return early (skip the queued release) if a swipe gesture is still in progress. A queued release firing while another swipe is still structurally active is exactly the late-sibling-cancellation case above; a genuine end-of-gesture release (whether via `triggered` or `cancelled`) only ever fires once nothing else is active, so this doesn't affect normal swipes at all. I've built and tested this on 5.27.12 (backported from master's `VirtualDesktopManager`/`GestureRecognizer`/`GlobalShortcutsManager`), and it's fixed the double-switch for me across repeated fast-swipe testing with no regressions on normal partial swipes. Happy to clean this up into a proper MR against master if that's useful - let me know. -- You are receiving this mail because: You are watching all bug changes.
