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>
We have one. Yay. Lucky us. Go forth and celebrate.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Yong Bakos <ybakos@humanoriented.com>
The previously hardcoded button map for tapping is 1/2/3 to LRM. But the
middle button is a common feature on the desktop (used for paste, most
prominently) and three-finger tapping is almost impossible to do reliably on
some touchpads (e.g. the T440 has a recognition rate of ~1 in 5).
Left and right buttons have a prominent physical position (either softbuttons
or physical buttons) so make the tap order configurable. Those that require
middle buttons reliably can use the [software] buttons for left/right and
2-finger tap for a middle button.
https://bugs.freedesktop.org/show_bug.cgi?id=96962
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
These are internal functions, if we need them to return an error code we can
change that at any time. Meanwhile, if we only ever return 0 anyway we might
as well just make them voids to save on error paths.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Yong Bakos <ybakos@humanoriented.com>
Reviewed-by: Eric Engestrom <eric.engestrom@imgtec.com>
There are a number of use-cases where tapping may be desirable, but
tap-and-drag is not, e.g. where tapping is used to select multiple items in a
list. Having tap-and-drag on hinders this, and the nature of the interaction
means it cannot be detected based on timeouts, movement thresholds, etc.
Provide an option instead to turn tap-an-drag off. Tap-and-drag remains
enabled by default (though tapping is disabled by default).
For the touchpad tap state diagram, the new option disables the transition
from state TOUCH to state TAPPED and releases the button immediately instead.
This means that multitap-and-drag is disabled too since we now just loop
around in the single-tap state for multitap.
It also makes tapping more responsive - we don't have to wait for the timeout
before we know whether it's a tap event. The first touch time is noted, we now
send the button press with the time of the first touch and the release with
the time of the release. This ensures a realistic time diff between the two
events.
https://bugs.freedesktop.org/show_bug.cgi?id=93502
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.netto>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
tap-tap-down-move should emit 1 click + press, not 2 clicks + press
https://bugs.freedesktop.org/show_bug.cgi?id=92016
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
The following sequence currently generates a right-button event:
finger 1 down
finger 2 down
finger 1 up
finger 2 held down
This is easily triggered with short scroll events. There are two issues here:
first is that the tapping code elsewhere treats any tap with a second finger
down as a left-button tap, not a right button one. So if anything, we should
generate a left button click here, not a right button click.
Arguably, generating a button click here is wrong though, it's not a very well
defined sequence and relatively difficult to trigger intentionally. So the
best solution here is to simply ignore the release event and move straight
back to state HOLD - unless the second finger is released within the timeout.
If the finger is set down again during the timeout, we move straight to
TOUCH_2_HOLD - this could eventually be interpreted as a tap, but not for now.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
In order to provide higher precision event time stamps, change the
internal time measuring from milliseconds to microseconds.
Microseconds are chosen because it is the most fine grained time stamp
we can get from evdev.
The API is extended with high precision getters whenever the given
information is available.
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
That's the most likely area it will be resting in, if it's sitting anywhere
above that it's likely part of an interaction.
A thumb in the lowest 15mm needs to trigger the pressure threshold before it's
labelled a thumb. A thumb in the lowest 8mm is considered a thumb if it
remains there for 300ms. Regardless of the pressure, since we can't reliably
get pressure here. If a thumb moves out of the area, or starts outside of that
area it is never a thumb.
If edge scrolling is enabled, the 8mm threshold is ineffective since we'll
have normal interaction in that zone for horizontal scrolling.
The thumb tests now require all touchpads to be switched to clickfinger, if we
test for thumb detection on the bottom of the pad we won't get expected
motion events due to the software button area.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Most thumbs are detected a few events into the sequence. Work this into parts
of the tapping state machine. Only the most common use-case is handled here -
if the first finger ends up being marked as a thumb, we return to the idle
state and ignore that touch sequence.
At any other state, we handle thumbs like any other finger.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
All touchpad recordings seen so far show that a value above 100 is definitely
a thumb or a palm. Values below are harder to discern, and the same isn't true
for touchpads supporting ABS_PRESSURE instead of ABS_MT_PRESSURE.
The handling of a touch is as outlined in tp_thumb_detect:
* thumbs are ignored for pointer motion
* thumbs cancel gestures
* thumbs are ignored for clickfinger count
* edge scrolling doesn't care either way
* software buttons don't care either way
* tap: only if thumb on begin
The handling of thumbs while tapping is the simplest approach only, more to
come in follow-up patches.
Note that "thumb" is the synonym for "this touch is too big to be a
fingertip". Which means that a light thumb touch will still be counted as a
finger. The side-effect here is that thumbs resting a the bottom edge of the
touchpad will almost certainly not trigger the pressure threshold because
most of the thumb is off the touchpad.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>