Fix slow pointer navigation with flat acceleration in Quattro - #6343
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves Quattro launcher + Omarchy menu pointer navigation by making hover/selection updates respond immediately and consistently, while preventing accidental selection from stale cursor state when surfaces become visible.
Changes:
- Updates
PointerMoveGateto accumulate sub-threshold pointer motion and optionally allow a single “initial sample” when a transition is known to originate from the mouse. - Ensures menu/launcher rows sample pointer position on
onEntered(not onlyonPositionChanged) so highlighting updates as soon as a row is entered. - Propagates “from pointer” intent into subordinate menus so mouse-opened routes don’t revert to first-row selection semantics.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
shell/Ui/PointerMoveGate.qml |
Adds initial-sample opt-in and jitter accumulation so slow pointer movement crosses the threshold naturally. |
shell/plugins/menu/Menu.qml |
Carries pointer intent through menu navigation and samples pointer position on row entry for immediate highlight updates. |
shell/plugins/launcher/Launcher.qml |
Prevents stale hidden-pointer selection on open and samples pointer position on row entry. |
test/shell.d/pointer-move-gate-test.sh |
Extends coverage for new gate behavior and adds an optional quickshell runtime fixture check. |
test/shell.d/fixtures/pointer-move-gate/shell.qml |
New runtime fixture validating the gate’s movement/initial-sample semantics end-to-end. |
test/shell.d/menu-test.sh |
Updates assertions for pointer-intent propagation and row-entry sampling in the menu plugin. |
test/shell.d/launcher-search-test.sh |
Updates assertions for launcher open semantics and row-entry sampling. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Accumulate sub-threshold movement so slow motion with a flat acceleration profile updates selection. Sample pointer state on row entry and carry pointer intent through subordinate menus while preserving predictable keyboard selection.
caea5f2 to
de7e3fc
Compare
|
What hardware are you seeing the slowness on? |
Sorry for the long reply, but I had to dig a little deeper for science :) I’m using a Logitech G PRO X Superlight at 1600 DPI / 1000 Hz. Under the same mouse and This is not general rendering or hardware latency. Hyprland’s The gate accepts movement only when either axis changes by strictly more than 1 logical pixel. However, the existing implementation also replaces its reference position after every rejected event. Consecutive small movements therefore never accumulate: every event is compared only with the immediately preceding one, allowing legitimate pointer movement to be discarded indefinitely. To isolate this, I captured a real slow movement from the PRO X before libinput applied its acceleration profile, replayed that identical input through both profiles, and then applied both gate algorithms to the processed output. I repeated the test with a Logitech M90 at 1000 DPI / 125 Hz using a separate physical movement:
Each comparison was repeated five times with the same raw input delivered to both profiles. The two mice used separate physical recordings, so their total event counts are not a performance comparison; the relevant comparison is between the existing and proposed gates within each row. The one-event range in the PRO X The before-fix video shows the severe PRO X + The polling rates offer a likely explanation for the different severity. At 1000 Hz, slow movement can be divided across reports roughly 1 ms apart; at 125 Hz, roughly 8 ms of movement can be delivered together, making each M90 event more likely to exceed the gate’s per-event threshold. Because these were separate physical recordings, this is a technically consistent explanation rather than an isolated measurement of polling rate alone. It also illustrates why the gate should accumulate movement instead of making selection behavior depend on how each device divides motion into reports. I also checked Walker v2.16.2’s mouse handling. Walker did not gate every selection update against a per-event threshold. After keyboard navigation disabled mouse targeting, it recorded an initial pointer sample and re-enabled GTK list targeting on any coordinate change from that sample; GTK then handled pointer interaction continuously. Quattro’s native implementation introduced the per-event gate that advances its reference position even when movement is rejected, which explains why this behavior appeared with the transition away from Walker. The proposed change retains the last accepted pointer position, allowing consecutive sub-threshold movements to accumulate until they cross the threshold. It keeps the strict threshold and stable launcher-card coordinates used to filter stationary-pointer jitter. Therefore, For completeness, the launcher was displayed on an HP OMEN X 25f at 1920×1080 / 240 Hz with scale |
Fix slow pointer navigation with flat acceleration in Quattro
Summary
With Hyprland's
input.accel_profileset toflat, slow pointer movement in Quattro's native launcher and Omarchy menu could leave the highlight behind the cursor. On the tested hardware, Omarchy's defaultadaptiveprofile produced large enough event deltas to mask the problem.The pointer gate compared each event with the immediately preceding event, so every sub-threshold event replaced the movement reference point. As a result, a stream of small movements could be ignored indefinitely. Testing the affected paths also exposed two related pointer-selection inconsistencies:
This change makes pointer selection responsive while keeping keyboard behavior predictable:
Before
old.mp4
After
fix.mp4
Testing
qmllint shell/Ui/PointerMoveGate.qml shell/plugins/launcher/Launcher.qml shell/plugins/menu/Menu.qml test/shell.d/fixtures/pointer-move-gate/shell.qmlbash test/shell.d/pointer-move-gate-test.shbash test/shell.d/launcher-search-test.shbash test/shell.d/menu-test.shbash test/shell.d/clipboard-test.shbash test/shell.d/manifest-entrypoints-test.shSUPER+SPACE.SUPER+ALT+SPACE.Acceleration profile comparison
flatadaptive, sensitivity0