mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-10 23:20:17 +01:00
doc: add docs for hold gestures
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
c96d414fdc
commit
38e2a434c5
1 changed files with 229 additions and 0 deletions
|
|
@ -150,3 +150,232 @@ The image above illustrates this ambiguity. The index and middle finger are
|
|||
set down first, the data stream from both finger positions looks identical.
|
||||
In this case, libinput assumes the fingers are in a horizontal arrangement
|
||||
(the right image above) and use a swipe gesture.
|
||||
|
||||
.. _gestures_hold:
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Hold gestures
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
A hold gesture is one where the user places one or more fingers on the
|
||||
device without significant movement. The exact conditions when a hold gesture
|
||||
transitions to pointer motion, scrolling or other gestures
|
||||
are implementation-defined.
|
||||
|
||||
The hold gesture is intended to allow for the implementation of two specific
|
||||
features:
|
||||
|
||||
- where a two-finger scrolling starts kinetic scrolling in the caller, a
|
||||
subsequent hold gesture can be used to stop that kinetic scroll motion,
|
||||
and
|
||||
- hold-to-trigger interactions where the interaction could be a click, a
|
||||
context menu, or some other context-specific interaction.
|
||||
|
||||
Hold gestures have three potential logical states:
|
||||
|
||||
- **begin**: one or more fingers are placed on the device at the same time
|
||||
- **end**: all fingers are removed and the device enters a neutral logical state
|
||||
- **end(cancelled)**: all fingers are part of a known interaction and the
|
||||
currenthold gesture is no longer active. This may also occurs when
|
||||
switching between hold gestures with different finger counts.
|
||||
|
||||
.. note:: By definition, a hold gesture does not move and thus no coordinate
|
||||
updates are available.
|
||||
|
||||
For example, a user that puts one finger, then a second finger down and
|
||||
releases them later may trigger the following event sequence:
|
||||
|
||||
============= ============ ============
|
||||
Action Event Finger count
|
||||
============= ============ ============
|
||||
Finger 1 down <no event>
|
||||
Finger 2 down **begin** 2
|
||||
Finger 2 up **end** 2
|
||||
Finger 1 up <no event>
|
||||
============= ============ ============
|
||||
|
||||
A hold gesture may by be **cancelled**. This occurs
|
||||
when the hold gesture changes into some other interaction and should no
|
||||
longer be considered the current hold gesture. A **end(cancelled)** event
|
||||
applies to the whole gesture (all fingers). For example, a pointer motion on
|
||||
a touchpad may trigger this sequence:
|
||||
|
||||
+----------------+---------------------+
|
||||
| Action | Event |
|
||||
+================+=====================+
|
||||
|Finger 1 down | **hold begin** |
|
||||
+----------------+---------------------+
|
||||
|Finger 1 motion | | **hold cancel** |
|
||||
| | | **pointer motion**|
|
||||
| | |
|
||||
+----------------+---------------------+
|
||||
|Finger 1 motion | **pointer motion** |
|
||||
+----------------+---------------------+
|
||||
|Finger 1 up | *no event* |
|
||||
+----------------+---------------------+
|
||||
|
||||
.. note:: Many interactions with a touchpad will start with a hold
|
||||
gesture that is then cancelled as that gesture turns into e.g.
|
||||
pointer motion. A caller **must** handle hold gesture
|
||||
cancellations correctly.
|
||||
|
||||
A two-finger scroll motion on a touchpad may trigger this sequence:
|
||||
|
||||
+------------------+---------------------+--------------+
|
||||
| Action | Event | Finger count |
|
||||
+==================+=====================+==============+
|
||||
|Finger 1 down | **hold begin** | 1 |
|
||||
+------------------+---------------------+--------------+
|
||||
|Finger 2 down | **hold cancel** | 1 |
|
||||
| | **hold begin** | 2 |
|
||||
+------------------+---------------------+--------------+
|
||||
|Finger 1+2 motion | | **hold cancel** | 2 |
|
||||
| | | **pointer axis** | |
|
||||
| | | |
|
||||
+------------------+---------------------+--------------+
|
||||
|Finger 1+2 motion | **pointer axis** | |
|
||||
+------------------+---------------------+--------------+
|
||||
| | Finger 1 up | **pointer axis** | |
|
||||
| | Finger 2 up | (scroll stop) | |
|
||||
| | | |
|
||||
+------------------+---------------------+--------------+
|
||||
|
||||
A three-finger-swipe on a touchpad may trigger this sequence:
|
||||
|
||||
+------------------+---------------------+--------------+
|
||||
| Action | Event | Finger count |
|
||||
+==================+=====================+==============+
|
||||
|Finger 1 down | **hold begin** | 1 |
|
||||
+------------------+---------------------+--------------+
|
||||
|Finger 2 down | **hold cancel** | 1 |
|
||||
| | **hold begin** | 2 |
|
||||
+------------------+---------------------+--------------+
|
||||
|Finger 3 down | **hold cancel** | 2 |
|
||||
| | **hold begin** | 3 |
|
||||
+------------------+---------------------+--------------+
|
||||
|Finger motion | | **hold cancel** | 3 |
|
||||
| | | **swipe begin** | 3 |
|
||||
| | | |
|
||||
+------------------+---------------------+--------------|
|
||||
|Finger motion | **swipe update** | 3 |
|
||||
+------------------+---------------------+--------------+
|
||||
| | Finger 1 up | **swipe end** | 3 |
|
||||
| | Finger 2 up | | |
|
||||
| | Finger 3 up | | |
|
||||
| | | |
|
||||
+------------------+---------------------+--------------+
|
||||
|
||||
Single-finger hold gestures
|
||||
...........................
|
||||
|
||||
libinput uses implementation-defined timeouts based on other interactions
|
||||
to determine whether a single-finger hold gestures should start. In other
|
||||
words, a caller **must not** rely on a hold gesture always being triggered
|
||||
as soon as a single finger is placed on the touchpad. This is true for any
|
||||
hold gesture but especially so for single-finger hold gestures.
|
||||
|
||||
Hold gestures with a single finger are prone to being extremely short-lived.
|
||||
On many devices it is impossible to hold a finger still enough for there to
|
||||
be no pointer motion events, even if those deltas are miniscule. Changing
|
||||
movement thresholds to rely on hold gestures would reduce device
|
||||
responsiveness.
|
||||
|
||||
It is thus the responsibility of the caller to determine where hold gestures
|
||||
transition in and out of other interactions. For example, a two-finger hold
|
||||
may produce a cancelled single-finger hold gesture first:
|
||||
|
||||
+----------------+---------------------+--------------+--------------+
|
||||
| Action | Event | Finger count | Notes |
|
||||
+================+=====================+==============+==============+
|
||||
|Finger 1 down | **hold begin** | 1 | |
|
||||
+----------------+---------------------+--------------+--------------+
|
||||
|Finger 1 motion | | **hold cancel** | 1 | tiny deltas |
|
||||
| | | **pointer motion**| | |
|
||||
| | | | |
|
||||
+----------------+---------------------+--------------+--------------+
|
||||
|Finger 2 down | **hold begin** | 2 | |
|
||||
+----------------+---------------------+--------------+--------------+
|
||||
| | Finger 1 up | **hold end** | | |
|
||||
| | Finger 2 up | | | |
|
||||
| | | | |
|
||||
+----------------+---------------------+--------------+--------------+
|
||||
|
||||
Note how the second hold gesture started with a finger count of 2 - without
|
||||
the user ever lifting the first finger. Cancellation of hold gesture does
|
||||
not imply the user has lifted a finger.
|
||||
|
||||
A hold gesture may start after a previous gesture completed. For example, a
|
||||
single finger move-and-hold may trigger different sequences for the same
|
||||
user interaction:
|
||||
|
||||
+----------------+---------------------+----------------+--------------+
|
||||
| Action | Device 1 | Device 2 | Notes |
|
||||
+================+=====================+================+==============+
|
||||
|Finger 1 down | **hold begin** | **hold begin** | |
|
||||
+----------------+---------------------+----------------+--------------+
|
||||
|Finger 1 motion | | **hold cancel** | | tiny deltas |
|
||||
| | | **pointer motion**| | |
|
||||
| | | | |
|
||||
+----------------+---------------------+----------------+--------------+
|
||||
| | **hold begin** | | |
|
||||
+----------------+---------------------+----------------+--------------+
|
||||
| Finger 1 up | **hold end** | **hold end** | |
|
||||
+----------------+---------------------+----------------+--------------+
|
||||
|
||||
A caller that wants to use hold gestures must thus be able to infer the same
|
||||
interaction based on a stream of pointer motion events with small deltas.
|
||||
|
||||
libinput may start a new hold begin gesture once the pointer stops moving.
|
||||
The time between the last pointer motion event and the hold begin event is
|
||||
implementation-defined.
|
||||
|
||||
|
||||
Hold gestures and thumb/palm detection
|
||||
......................................
|
||||
|
||||
Thumb and palm detection effectively remove touches from being counted
|
||||
towards an interaction, see :ref:`thumb_detection` and
|
||||
:ref:`palm_detection` for details.
|
||||
|
||||
In the context of hold gestures, thumbs and palms are treated by libinput as
|
||||
if the finger was removed from the device. Where other non-thumb/non-palm
|
||||
fingers remain on the device, an **hold update** event is sent. Otherwise,
|
||||
the hold gesture terminates with a **hold cancel** event.
|
||||
|
||||
Notably, libinput's thumb and palm detection is not a simple boolean per
|
||||
touch but specific to the state of that touch in the overall context. For
|
||||
example, a touch may be a thumb for tapping but not for clickfinger
|
||||
interactions. A caller must not infer the number of physical fingers from
|
||||
the hold gesture.
|
||||
|
||||
Likewise, libinput may classify a finger as thumb in the same hardware event
|
||||
as a new finger is placed on the touchpad. In that case, the hold gesture
|
||||
**may** continue as one-finger gesture despite there being two physical
|
||||
touch points.
|
||||
|
||||
Information to determine whether a touch is a thumb or a palm may not be
|
||||
available until some time into an interaction. Thus very short brushes
|
||||
of the touchpad by a palm may trigger a **hold begin** followed by an
|
||||
immediate **hold end** as libinput lacks sufficient information to identify
|
||||
the touch as thumb/palm and send the corresponding **hold cancel**
|
||||
event. A caller must not assume that a hold gesture always represents a
|
||||
valid finger down.
|
||||
|
||||
Hold gestures and tap-to-click
|
||||
..............................
|
||||
|
||||
:ref:`tapping` is the feature that enables short-lived touches to trigger
|
||||
button presses.
|
||||
|
||||
.. warning:: Summary: do not use hold gestures to do your own tap-to-click
|
||||
implementation
|
||||
|
||||
In the context of hold gestures, tap-to-click cancels current hold gestures
|
||||
and a finger dragging (see :ref:`tapndrag`) does not begin a hold
|
||||
gesture. Where tap-to-click is disabled a tap-like gesture may create
|
||||
**hold begin** followed by a **hold end** event. Callers **must not** use
|
||||
hold gestures for their own tap-to-click implementation as the data is not
|
||||
reliable enough. libinput may change internal timeouts and thresholds
|
||||
depending on whether tap-to-click is enabled and the hold gesture event may
|
||||
not match touch sequences that a user would expect to be a tap-to-click
|
||||
interaction.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue