Skip to content

feat(Touchscreen): edge-swipe gesture detection for handheld#571

Open
honjow wants to merge 8 commits intoShadowBlip:mainfrom
honjow:pr/touchscreen-gestures
Open

feat(Touchscreen): edge-swipe gesture detection for handheld#571
honjow wants to merge 8 commits intoShadowBlip:mainfrom
honjow:pr/touchscreen-gestures

Conversation

@honjow
Copy link
Copy Markdown
Contributor

@honjow honjow commented Mar 29, 2026

Summary

Adds single-finger edge-swipe gesture detection to the touchscreen source device, allowing touchscreen edges to be mapped to gamepad buttons via device profiles — enabling gestures like swiping from the left edge to open the Steam menu, or from the right edge to open the Quick Access Menu, without requiring changes to the compositor.

Tested and verified on GPD Win5 and ONEXPLAYER X1 Mini.


How gesture detection works

Touch coordinates are normalized to [0.0, 1.0]. A gesture is recognized when the touch starts within 3% of a screen edge, travels inward by at least 12%, and completes within 400 ms.

+-----------------------------------+
|###################################|
|#                                 #|
|#   +--------------------------+  #|
|#   |                          |  #|
|#   |     normal touch area    |  #|
|#   |                          |  #|
|#   +--------------------------+  #|
|#                                 #|
|###################################|
+-----------------------------------+
  ^                               ^
  # = edge zone (3% of each side)

Gesture names describe the direction of finger movement (e.g. swiping inward from the left edge moves rightward → SwipeRight). Each direction carries a Top/Bottom zone qualifier split at 33% along the perpendicular axis.

Default profile mappings:

Gesture Action
SwipeRight:Bottom Guide
SwipeLeft:Bottom QuickAccess

Two operating modes: passthrough vs. grab

Passthrough (grab: false, default): Raw touch events are forwarded normally alongside any gesture events. Suitable for desktop use; avoid in game compositors as gestures will also register as taps.

Grab (grab: true): The touchscreen is exclusively captured via EVIOCGRAB. Touches starting within 1% of an edge are held back until the gesture outcome is known — confirmed gestures suppress the touch, unconfirmed ones replay it as a normal tap. Multi-finger touch immediately cancels gesture detection and passes all events through. If EVIOCGRAB fails, the source falls back to passthrough with a warning.

Grab mode is recommended for devices running a game compositor such as Gamescope.


Why MIN_FRAME_TIME was moved to TargetDriver

Gesture detection emits press and release nearly simultaneously. Without a minimum press duration, both events fall within a single HID poll interval and the compositor sees a report where the button was never pressed.

steam_deck already handled this with an 80 ms minimum, but only for itself. This PR moves the enforcement into TargetDriver so every target benefits automatically, and removes the now-redundant steam_deck implementation.

honjow added 8 commits March 30, 2026 04:49
Add Touchscreen as a new top-level Capability variant with Touch and
Gesture sub-types. Gesture covers single-finger edge-swipe directions
(SwipeLeft/Right/Up/Down) with optional zone qualifiers (Top/Bottom).

Update InputValue translation, evdev/dbus event enums, and capability
map config to handle the new types.
… replay

Implement single-finger edge-swipe gesture detection in the touchscreen
source device:
- Detect swipes starting from left/right/top/bottom screen edges
- Optional exclusive grab mode: suppresses raw touch events while a
  gesture is being evaluated, replaying them as a tap if no gesture
  is confirmed
- Orientation config to rotate coordinates for rotated displays
- TouchscreenConfig extended with grab and orientation fields
…le mapping

- Pass Touchscreen capability events through translate_event so they
  can be mapped to gamepad buttons via device profiles
- Bypass intercept-mode checks for touchscreen events (gesture handling
  is always active)
- Add Touchscreen capability to the output capability lists of
  DualSense, SteamDeckUhid and UnifiedGamepad target devices
Map SwipeRight:Bottom to Guide and SwipeLeft:Bottom to QuickAccess in
the default profile, matching hhd-style Steam/QAM gestures.

Update composite_device_v1.json to add grab field to TouchscreenConfig.
Update device_profile_v1.json to include Touchscreen gesture capability
definitions.
Button press+release pairs arriving within 80ms now have their release
delayed at the TargetDriver layer, so all target devices benefit
automatically. Previously this logic only existed in steam_deck.

Add ScheduledNativeEvent::event() accessor to support filtering
scheduled events during ClearState.

Also clear pending button events when ClearState is called to avoid
ghost releases after intercept mode resets device state.
…NEXPLAYER X1

GPD Win5: enable touchscreen source with grab mode.
ONEXPLAYER X1 Mini: enable touchscreen source with grab mode and
left orientation (display is rotated 90 degrees).
@honjow honjow changed the title feat(Touchscreen): edge-swipe gesture detection for handheld game controllers feat(Touchscreen): edge-swipe gesture detection for handheld Mar 30, 2026
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