This shouldn't have any effect in the current setup as there is
"coincidentally" no overlap between the two state machines so this is
effectively a noop.
Nonetheless, if we're about to send a tap button event we cannot be in
any other gesture than tapping so all swipe/pinch/holds need to be
cancelled.
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1042>
The tool used to generate diagrams (draw.io) is now diagrams.net.
Update the URL in the comments.
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
When 1 or 2 fingers are used to hold, use a faster timer to make the
"hold to stop kinetic scrolling" user interaction feel more immediate.
Also handle double tap and tap and drag interations to send only one
hold gesture instead of two.
Holding with 3 or 4 fingers remains the same to try to avoid callers
missusing hold gestures to build their own tap implementation.
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
Hold gestures are notifications about fingers on the touchpad.
There is no coordinate attached to a hold gesture, merely the number of fingers.
A hold gesture starts when the user places a finger on the touchpad and
ends when all fingers are lifted. It is cancelled when the finger(s) move
past applicable thresholds and trigger some other interaction like pointer
movement or scrolling.
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
This only affects the actual dragging part of the tap-and-drag interaction;
n-finger tap-and-drag is supposed to be performed with a n-finger tap
followed by a 1-finger drag.
Allowing a second finger in the middle of a drag is still necessary for a
finger swap, which users may need in long-distance drags, especially when
drag-lock is disabled.
Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org>
Some users reported problems triggering multi-finger tap-and-drag,
with reliability decreasing as the finger count increased.
This is plausible because they may shift towards moving the whole hand
up and down, which obviously takes more time than just a finger.
Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org>
This commit duplicates the tap states responsible for tap-and drag (TAPPED
and all DRAGGING* states) to cover two-finger and three-finger taps;
the code for the new states is shared with the existing machinery for
one-finger tap-and-drag.
Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org>
This is in preparation for three-finger tap-and-drag, which will start from
a completed tap with no fingers down.
Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org>
Where a touch is labelled as palm on TOUCH_BEGIN (edge palms) we would still
feed the touch through the tap state machine. This would trigger the PALM
transition for each state, usually reducing the touch count.
When the touches were later released, the touch count was out of sync,
resulting in an error message. In the case of #488, the trigger was
a single evdev frame with three fingers down, the third of which was an edge
palm:
- touch 1 transitions from IDLE to TOUCH
- touch 2 transitions from TOUCH to TOUCH_2
- touch 3 (the palm) transitioned from TOUCH_2 back to TOUCH
That third transition is invalid, the palm hasn't been seen by the tap state
machine so it should just be ignored.
Fix this by moving making the tap state processing conditional on a touch
state other than TOUCH_BEGIN.
Fixes#488
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
draw.io is playing up with old files and sending me into a redirect loop.
Duplicating files works but that changes the links. So to avoid dead links,
let's just remove the direct link and let anyone who cares enough about it ask
me.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
In the current implementation, movements > threshold and timeouts usually move
to HOLD state and continue from there. Where a finger is lifted, we go back
up the diagram into the previous finger count's HOLD state.
The side-effect of this is that a tap of a finger can be counted as tap even
after a movement:
- two fingers down, move to scroll, hold down
- third finger down, third finger up
This sequence triggers an erroneous three-finger tap. Once the motion
threshold is hit by any touch, no finger must trigger 2/3 finger tap events
while any touch is down.
The false tap is only triggered where the new finger can execute a tap without
any other finger changing any property. This can be triggered on the
reporter's Dell Precision 5520 but on most other touchpads, a new finger down
will trigger slight movement, pressure or touch size updates and thus the bug
cannot be triggered.
Fixes#382
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Instead of a simple yes/no/maybe for thumbs, have a more extensive state
machine that keeps track of the thumb. Since we only support one thumb anyway,
the tracking moves to the tp_dispatch struct.
Test case changes:
touchpad_clickfinger_3fg_tool_position:
with better thumb detection we can now handle this properly and expect a
right button (2fg) press for the test case
touchpad_thumb_no_doublethumb_with_timeout:
two thumbs are now always two fingers, so let's switch to axis events here
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Multitap sequences (more than 2 taps) had a 180ms timer set only on press,
not on release.
New taps within those 180ms could either trigger multitap+drag or another
multitap (for N+1 taps), resetting the timer on press once again.
If no new tap appears within those 180ms, the sequence was considered
complete.
This behavior differed from regular taps: for the very first tap of a
sequence the timer was set both on touch and on release.
The multitap timing caused misdetection of triple-tap-and-drag sequences as
the timer was hit frequently. Some of those were correctly detected, others
as tripletap only.
Changing the timer to be set on press **and** release gives us a more lenient
timeout. 180ms for tap-and-drag and 180ms for the next tap down after
release. This was also the behavior for the xorg synaptics driver.
Note that quadruple-tap-and-drag didn't suffer from this because the timeout
resulted in double-tap + double-tap-and-drag. Which has the same
user-visible effect.
When finger movement exceeded the motion threshold before the finger was
recognized as a thumb, it would never be regarded as a thumb by the tap system.
This prohibited tapping until the thumb was lifted.
This is fixed by moving the check for the thumb state up such that it
happens before the motion threshold check.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Semi-MT devices provide a bounding box of the fingers, and internally we don't
treat them as real MT device. Depending which finger currently provides
ABS_X/Y we may get a large jump when the other finger is released.
Basic sequence is finger 1 down, finger 2 down, finger 1 up.
On the last interaction, the ABS_X/Y which was on finger 1's coordinates now
jumps to finger 2's coordinates. This is interpreted as movement by the
tapping code, resulting in missed two-finger taps.
Ignore these movements on semi-mt devices.
https://bugs.freedesktop.org/show_bug.cgi?id=105043
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
We expected the first event after TAPPED to be a finger down. If that finger
has been recognised as palm, the finger state isn't TOUCH_BEGIN so we get an
invalid state in our FSM.
libinput bug: 0: invalid tap event TAP_EVENT_PALM in state TAP_STATE_TAPPED
https://bugs.freedesktop.org/show_bug.cgi?id=105370
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
If a single-touch touchpad drops below the pressure threshold in the same
frame where a fake finger is added, we begin a fake touch here. The subsequent
loop ends this fake touch because real_fingers_down is 0.
This causes the tapping code to have a mismatch of how many fingers are down
because it never sees the touch begin event for that finger.
https://bugs.freedesktop.org/show_bug.cgi?id=105160
Unlike the already-existing thumb detection, a touch may be labelled palm at
any time, not just during the initial touch down. This requires full
integration into the tap state machine to unwind properly. For most states, a
palm detection simply ignores the finger and reverts to the most recent state.
One exception is the case of two fingers down, one finger up followed by the
remaining finger detected as a palm finger. This triggers a single-finger tap
but with timestamps that may be from the wrong finger. Since we're within a
short tap timeout anyway this should not matter too much.
The special state PALM_UP is only handled in one condition (DEAD). Once a
touch is a palm we basically skip over it from then on. If we end up in the
DEAD state after a button press we still need to handle the palm up events
accordingly to be able to return to IDLE. That transition also requires us to
have an accurate count of the real fingers down (palms don't count) so we need
a separate nfingers_down counter for tapping.
https://bugs.freedesktop.org/show_bug.cgi?id=103210
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
There's no need for a custom error message everywhere, it's better to log the
current state and the event.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Do so on the synaptics serial touchpads at least, they're known to cause
cursor jumps when the third finger is down. Not detecting a tap move means
three-finger taps get more reliable on these touchpads.
This change affects gestures who now effectively have to wait for the tap
timeout to happen. It's a trade-off.
https://bugs.freedesktop.org/show_bug.cgi?id=101435https://bugzilla.redhat.com/show_bug.cgi?id=1455443
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This makes the tapping times shorter and hopefully more obvious. It also fixes
a bug where repeated tripletap (by tapping with one finger while leaving the
other two down) could cause incorrect timestamps.
https://bugs.freedesktop.org/show_bug.cgi?id=100796
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
For multitap, we're one tap behind with the button clicks, i.e. we send the
first full click button on the second tap, etc. Remember the timestamps of the
touches so we can send the events with the right timestamps. This makes
tapping more accurate because the time between taps and various timeouts
matter less for double-click detection.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Prefix device log messages with the device's sysname so it's more obvious
where the messages are coming from. This makes it much easier to grep for a
specific device's messages but also adds some identifier to messages that
were previously without any identifier (e.g. all the state machine debugging)
All info and error messages also automatically prefix the device name, so
those messages are standardised too, e.g
an info message now:
event4 - SynPS/2 Synaptics TouchPad: is tagged by udev as: Touchpad
a debug message now:
event4 - using pressure-based touch detection
And since this required changing a lot of the strings in messages anyway,
polish a few minor things too.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Set the dispatch type on creation, then check that whenever we try to get the
dispatch struct. This avoids a potential mismatch between the backends.
Plus, use of container_of means we're not dependent on the exact layout
anymore.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
We need to remember whether a tap was down or just hovering, otherwise we mess
up the state machine when we send tap release events for taps that never
switched to TOUCH_BEGIN. This is quick fix, really we should have a new state
here, but that's a lot harder to implement.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Now that the acceleration code doesn't use dpi-normalized coordinates anymore,
we don't need to use them in the touchpad code. Switch to physical distances
instead, it makes debugging a lot saner.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
When a finger moves less than the movement threshold, motion is filtered until
the timeout is hit. If the threshold is too high the responsiveness of the
pointer suffers.
Event analysis from several users showed that 95% of the touches move less
than 1.3mm long. Reducing the threshold should have almost no impact on most
tapping users but improves the reaction time of the pointer for normal
movements.
For a more details see:
http://who-t.blogspot.com/2016/12/libinput-touchpad-tap-analysis.html
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This is the timeout before we decide "this is just a finger down, not a tap".
Until this timeout is hit a finger's movement is filtered. To allow for a more
responsive touchpad, we want that timeout as short as possible.
Event analysis from several users showed that 95% of the touches are less than
100ms long. Reducing the threshold should have almost no impact on most
tapping users but improves the reaction time of the pointer for normal
movements.
For a more details see:
http://who-t.blogspot.com/2016/12/libinput-touchpad-tap-analysis.html
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>