Skip to content

input/touch: adopt the current surface location on motion - #2203

Draft
cunninghamcard-bit wants to merge 2 commits into
Smithay:masterfrom
cunninghamcard-bit:touch-motion-current-surface-location
Draft

cunninghamcard-bit wants to merge 2 commits into
Smithay:masterfrom
cunninghamcard-bit:touch-motion-current-surface-location

Conversation

@cunninghamcard-bit

Copy link
Copy Markdown

The default touch grab converts every motion event to surface-local coordinates using the location of the focused surface as it was at touch-down. When the surface moves while being touched, the client keeps receiving coordinates relative to the old position.

Real-world case (niri + a floating on-screen keyboard, fortime/fcitx5-osk#82): dragging the keyboard with a finger made it run away from the finger — a 200px finger travel moved the window 658px, because the whole finger travel since press was re-applied on every event. Every compositor where a client can move a surface mid-touch (layer-shell panels, virtual keyboards) is affected.

The touch focus itself stays locked to the surface from touch-down, as the wl_touch protocol requires. But the compositor already reports a fresh (surface, location) pair with every motion — this PR makes the default grab adopt it as the current origin whenever it is still the same surface, keeping the surface-local coordinates correct as the surface moves.

Compositors that pass None, or pass a surface under the finger that differs from the locked focus, get the previous behavior. No API change: SeatHandler::TouchFocus already requires PartialEq.

Related to #1223, which proposes changing the motion API to take relative coordinates (motivated by per-window scale factors, and was not merged). This PR intentionally does not touch the API: whatever shape the arguments take, the default grab still needs a fresh surface origin to keep surface-local coordinates correct while the surface moves, so this behavior fix is orthogonal and compatible with that direction.

The default touch grab converted every motion event with the location
of the focused surface as it was at touch-down. When the surface moved
while being touched — e.g. a layer-shell surface dragged by the finger
— the client kept receiving coordinates relative to the old position,
so the dragged window drifted away from the finger and the whole finger
travel was applied again on every event.

The touch focus itself stays locked to the surface from touch-down, as
the wl_touch protocol requires. But the compositor already reports a
fresh (surface, location) pair with every motion — adopt it as the
current origin whenever it is still the same surface, keeping the
surface-local coordinates correct as the surface moves.

Compositors that pass None, or pass a surface under the finger that
differs from the locked focus, get the previous behavior.
Forward the compositor-provided focus to the inner touch handler instead of reusing the touch-down origin. Keep the locked target and retain the last origin when focus is absent or different.

Replace let chains with tuple matching to preserve Rust 1.87 support. Add public TouchHandle regression tests for moving surfaces and fallback behavior.

This branch has not been deployed

No deployments
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.

1 participant