Regression introduced by 3979b9e16a, bug 105258.
With that commit, we only ended real touches when we had less than nslots fake
fingers down. i.e. tripletap on a 2 slot touchpad would not end the
first/second touch even if the pressure goes below the threshold. e.g. Lenovo
x270 needs this, see https://bugs.freedesktop.org/attachment.cgi?id=137672, it
dips below the pressure threshold for the first slot and ends the second slot
in the same frame as the third finger is detected. Fun times.
Anyway, this breaks semi-mt touchpads, another fine category of devices,
because some of those can detect hovering fingers at low pressure, see bug
105535. Because semi-mt devices are generally garbage, we treat them as
single-touch devices instead. So whenever two fingers are down, we treat both
as above the pressure threshold, even when they're physicall hovering.
Fix this by making the x270 fix conditional on at least 2 slots.
https://bugs.freedesktop.org/show_bug.cgi?id=105535
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 3f5ff113a8)
We're left-shifting the bits but weren't comparing against the l_r_l mask
itself. So if we get a sequence of [1, 1, 0, 1] we didn't detect a wobble
because 0b1101 != 0b101 (what we're looking for).
Fix this by turning it into a right shift, that way the bits fall off
the mask automatic
al
ly
y
y
y
y
. .
_._v.___
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 5883ac7d98)
Otherwise a hovering touch stays around forever even after the finger has
discontinued. This doesn't matter on slots, but for fake fingers the finger
may suddenly end up being forced down/up as a result of the pressure changes
on the real fingers.
So when in maybe_end_touch, switch them back to NONE immediately - hovering
touches do not need to trigger a TOUCH_END event.
https://bugs.freedesktop.org/show_bug.cgi?id=105258
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit d8db6b5927)
This changes the hysteresis region to an ellipse (usually a circle), where
previously it was a rectangle (usually square).
Using an ellipse means the algorithm is no longer more sensitive in some
directions than others. It is now omnidirectional, which solves a few
problems:
* Moving a finger in small circles now creates circles, not squares.
* Moving a finger in a curve no longer snaps the cursor to vertical
or horizontal lines. The cursor now follows a similar curve to the
finger.
https://bugs.freedesktop.org/page.cgi?id=splinter.html&bug=105306
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 6936a15558)
This state is used by the pre-processing of the touch states to indicate that
the touch point has ended and is changed to TOUCH_END as soon as that
pre-processing is finished.
Sometimes we have to resurrect a touch point that has physically or logically
ended but needs to be kept around to keep the BTN_TOOL_* fake finger count
happy. Particularly on Synaptics touchpads, where a BTN_TOOL_TRIPLETAP can
cause a touch point to end (i.e. 1 touch down + TRIPLETAP) but that touch
restarts in the next sequence. We had a quirk for this in place already, but
if we end the touch and then re-instate it with tp_begin_touch(), we may lose
some information about thumb/palm/etc. states that touch already had. As a
result, the state machines can get confused and a touch that was previously
ignored as thumb suddenly isn't one anymore and triggers assertions.
The specific sequence in bug 10528 is:
* touch T1 down
* touch T2 down, detected as speed-based thumb, tap state machine ignores
it
* frame F: TRIPLETAP down, touch T2 up
* frame F+1: touch T2 down in next frame, but without the thumb bit
* frame F+n: touch T2 ends, tap state machine gets confused because
that touch should not trigger a release
https://bugs.freedesktop.org/show_bug.cgi?id=105258
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 6ccd8e934f)
If we have more BTN_TOOL_*TAP fingers down than we have slots, ignore any
below-threshold pressure changes on the slots. When a touchpad only detects
two touches, guessing whether the third touch has sufficient pressure is
unreliable. Instead, always assume that all touches have sufficient pressure
when we exceed the slot number.
Exception: if all real fingers are below the pressure threshold, the fake
fingers are ignored too.
Related to https://bugs.freedesktop.org/show_bug.cgi?id=105258
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
(cherry picked from commit 3979b9e16a)
The details are explained in comment in the code. That aside, I shall
mention the check is so light, that it shouldn't influence CPU
performance even a bit, and can blindly be kept always enabled.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104828
Signed-off-by: Konstantin Kharlamov <Hi-Angel@yandex.ru>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Konstantin Kharlamov <Hi-Angel@yandex.ru>
(cherry picked from commit 400aadd53a)
Signed-off-by: Konstantin Kharlamov <Hi-Angel@yandex.ru>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Konstantin Kharlamov <Hi-Angel@yandex.ru>
(cherry picked from commit e8dffbd73a)
Prep work for the wobbling detection patch
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Konstantin Kharlamov <Hi-Angel@yandex.ru>
(cherry picked from commit e43bd4ae3a)
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
(cherry picked from commit 01a633b6eb)
Previously, touchpad deltas were converted to 1000-dpi normalized coordinates
and handled from there. This changed in bdd4264d61 (1.6)
when the filter functions started taking device coordinates instead. Since
then, we used to convert the device delta to normalized coordinates, then
(often immediately) convert back to device coordinates, albeit for equal x/y
resolution. This isn't necessary, we can just convert the device coordinates
to x/y-equal resolution device coordinates and pass those on.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
On the very first event, the last_motion_time set by tp_begin_touch is not yet
set because we are called before the pressure-based touch detection takes
effect. And any event timestamp is more than 80ms after a zero timestamp,
causing the hysteresis to always be disabled.
https://bugs.freedesktop.org/show_bug.cgi?id=98839#c74
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This was never true, we for the first part 3 lines above and return early. So
if we get here, it's always false.
commit aa87d2b25b added the new condition above, so since then this code
was inactive and can be removed.
https://bugs.freedesktop.org/show_bug.cgi?id=104279
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
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>
This has no real effect at the moment because the fallback interface doesn't
care much about SYN_REPORT, it processes events as they come in. But it's a
bug nonetheless, the process() callback expects correct event frames.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
needed for the razer blade keybard which provides multiple event nodes for
one physical device but it's hard/impossible to identify which one is the real
event node we care about.
https://bugs.freedesktop.org/show_bug.cgi?id=103156
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Touchpads that require the hysteresis do not have filtering in the firmware
and holding a finger still causes continuous cursor movements. This implies
that we get a continuous stream of events with motion data.
If the finger is on the touchpad but we don't see any motion, the finger is
stationary and the touchpad firmware does filtering. In that case, we don't
need to add a hysteresis on top.
https://bugs.freedesktop.org/show_bug.cgi?id=98839
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
The main purpose of the edge zone is to detect palms in the area where we
cannot assume a full finger size and thus cannot use any other palm detection
mechanism. 8mm should be large enough that a finger should be detected based
on other properties (size, pressure, ...).
https://bugs.freedesktop.org/show_bug.cgi?id=103330
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
The main purpose of the edge zone is to detect palms in the area where we
cannot assume a full finger size and thus cannot use any other palm detection
mechanism. 8mm should be large enough that a finger should be detected based
on other properties (size, pressure, ...).
https://bugs.freedesktop.org/show_bug.cgi?id=103330
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Daniel Martin <consume.noise@gmail.com>
Better for self-documentation than comments and makes it more obvious if we
initialize something wrongly.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
A touchpad that was disabled by toggling the sendevents option would come back
normally after a lid resume, despite still being nominally disabled.
https://bugzilla.redhat.com/show_bug.cgi?id=1448962
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
On some devices with a tablet mode switch, the touchpad is inacessible when
in tablet mode and we don't really need this except to avoid possible ghost
touches (none have been mentioned so far). On other devices like the Lenovo
Yoga, the touchpad points to the back of the device and it's hard to use the
device without accidentally using the touchpad. For those, disabling the
touchpad is the best solution.
https://bugs.freedesktop.org/show_bug.cgi?id=102408
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Calculate the speed of the touch and compare it against a fixed speed limit.
If a touch exceeds the speed when a second touch is set down, that second
touch is marked as a thumb and ignored (unless it's right next to the other
finger, then it's likely a 2fg scroll).
The speed calculation is simple but has to lag behind by one sample - we reset
the motion history whenever a new finger is set down (to avoid pointer jumps)
so we need to know if the finger was moving fast *before* this happens. Plus,
with the pointer jumps we're more likely to get false positives if we
calculate the speed on actual finger down.
This is the simplest version for now, the speed varies greatly between
movements and should probably be averaged across the last 3-or-so samples.
https://bugs.freedesktop.org/show_bug.cgi?id=99703
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Bluetooth wreaks havoc with the timestamp of the input events coming
from the touchpad, enable timestamp smoothing support to counter this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
There's no guarantee that libinput does the right thing if memory allocation
fails and it's such a niche case on the systems we're targeting that it just
doesn't matter. Simply abort if zalloc ever fails.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Apple touchpads don't use ABS_MT_PRESSURE but they are multitouch touchpads,
so the current pressure-based handling code doesn't apply because it expects
slot-based pressure for mt touchpads.
Apple does however send useful data for ABS_MT_WIDTH_MAJOR/MINOR, so let's use
that instead. The data provided in those is more-or-less random, so we need a
hwdb entry to track the acceptable thresholds.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
If the keyboard is removed while dwt thinks it is in active state, that state
is never reset and subsequent touches are ignored.
https://bugs.freedesktop.org/show_bug.cgi?id=101743
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This reduces unexpected cursor moves when placing the thumb near the border
of trackpoint buttons and upper edge of touchpad.
https://bugs.freedesktop.org/show_bug.cgi?id=101574
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
If the touchpad is suspended and resumed (e.g. lid switch), the initial slot
state may be out of sync. If a touch happened while the touchpad was suspended
and the next touch down is on exactly the same x and/or y coordinate, our
touch point would still have the coordinates of the most recently seen touch
(i.e. before touchpad suspend). This could cause a pointer jump or test case
failures.
The real-world impact of this is minimal, putting the finger down in exactly
the same spot is virtually impossible. It could cause a test case failure in the
lid_disable_touchpad() test though, the second touch sequence was on the same
y coordinate and the touch location for that whole sequence was x/0.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
If a touch goes past the fixed pressure threshold it is labelled as a palm and
stays a palm. Default value is one that works well here on a T440 and is
virtually impossible to trigger by a normal finger or thumb. A udev property
is exposed so we can handle this in the udev hwdb and the new tool introduce a
few commits ago can help finding the palm detection threshold.
Unlike the other palm detection features, once a palm goes past the threshold
it remains a palm until the touch is released. This means palm overrides any
other palm detection features. For code simplicity, we don't combine the
states but merely check for pressure before and after the other palm detection
functions. If the pressure triggers, it will trigger before anything else. And
if something else is already active (e.g. edge where the pressure doesn't work
well) it will trigger as soon as the palm is released.
The palm threshold should thus be chosen with some room to spare between the
highest finger pressure.
https://bugs.freedesktop.org/show_bug.cgi?id=94236
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Most modern touchpads are around 100mm wide, so this provides a ca 8mm edge
zone on each side. The extra 3mm should provide for more reliable palm
detection, a few touches happen to be just on the edge of the 5mm mark.
https://bugs.freedesktop.org/show_bug.cgi?id=101433
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>