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>
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>
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>
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>
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>
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 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>
commit 3925936 introduced changes to container_of, this is hopefully the
last part of it.
In the linux kernel, container_of() takes a type name, and not a
variable. Without this, in some cases it is needed to declare an unused
variable in order to call container_of().
example:
return container_of(dispatch, struct fallback_dispatch, base);
instead of:
struct fallback_dispatch *p;
return container_of(dispatch, p, base);
This introduce also list_first_entry(), a simple wrapper around
container_of() to retrieve the first element of a non empty list. It
allows to simplify list_for_each() and list_for_each_safe().
Signed-off-by: Gabriel Laskar <gabriel@lse.epita.fr>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
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>
A leftover from synaptics where we do this detection in the driver. libinput
pushes this to the hwdb and sets the model flags accordingly.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
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>
Don't rely on BTN_TOUCH for "finger down", the value for that is hardcoded in
the kernel and not always suitable. Some devices need a different value to
avoid reacting to accidental touches or hovering fingers.
Implement a basic Schmitt trigger, same as we have in the synaptics driver. We
also take the default values from there but these will likely see some
updates.
A special case is when we have more fingers down than slots. Since we can't
detect the pressure on fake fingers (we only get a bit for 'is down') we
assume that *all* fingers are down with sufficient pressure. It's too much of
a niche case to have this work any other way.
This patch drops the handling of ABS_DISTANCE because it's simply not needed
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>
Add listener for lid switch events, disable touchpad on switch event.
Signed-off-by: James Ye <jye836@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
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>
Move the code from the touchpad code into the more generic evdev code
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Some trackpoints, notably the one on the Lenovo T460s have a tendency to send
the odd event even when they're not actually used. Trackpoint events trigger
palm detection (see 0210f1fee1) and thus effectively disable the touchpad,
causing the touchpad to appear nonresponsive.
Fix this by requiring at least 3 events from a trackpoint before palm
detection is enabled. For normal use it's hard enough to trigger a single
event anyway so this should not affect the normal use-case.
https://bugzilla.redhat.com/show_bug.cgi?id=1364850
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
So far we've relied on the wacom kernel module to do touch arbitration for us
but that won't be the case in upcoming kernels. Implement touch arbitration in
userspace by pairing the two devices and suspending the touch device whenever
a tool comes into proximity.
In the future more sophisticated arbitration can be done (e.g. only touches
which are close to the pen) but let's burn that bridge when we have to cross
it.
Note that touch arbitration is "device suspend light", i.e. we leave the
device enabled and the fd is active. Tablet interactions are comparatively
short-lived, so closing the fd and asking logind for a new one every time the
pen changes proximity is suboptimal. Instead, we just keep a boolean around
and discard all events while it is set.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>
Inspired by the syndaemon -K switch and Anton Lindqvist's patch.
https://patchwork.freedesktop.org/patch/102417/
We already ignored modifiers for dwt. Now we also ignore modifier + key
combinations, i.e. hitting Ctrl+s to save does not trigger dwt, the touchpad
remains immediately usable.
However, if dwt is already active and a modifier combination is pressed, dwt
remains active, i.e. while typing, a shift + key does not disable dwt.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
All these effectively returned bools anyway, switch the signature over to be
less ambiguous.
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>
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>
Expose the middle button emulation on software buttons as proper config
option. When enabled, remove the middle button software button area.
https://bugs.freedesktop.org/show_bug.cgi?id=96663
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
We will reinstate the hysteresis for all devices making the negative
pressure check unncessary.
This reverts commit ef48c07a96.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
And change the various callers, especially those where we only had the
separate struct for indentation purposes.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Quite a few bugs are caused by touchpad ranges being out of whack. If we get
input events significantly outside the expected range (5% width/height as
error margin) print a warning to the log.
And add a new doc page to explain what is happening and how to fix it.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Middle button interaction is most commonly to paste and it is a single-event
interaction (button press). We provided middle button in software button mode
by emulating it with a two-finger press with L+R down at the same time. This
is also what many touchpads are spectacularly bad at, it is very common to
detect the physical button down event before the second finger registers,
resulting in left or right clicks where a middle button should be triggered.
Unless the fingers are resting on the touchpad for at least one scanout, the
success rate for middle button emulation is only at 70% or so.
This patch adds a 25%-width middle button area between the left and the right
software button, everything else stays the same. To avoid immediate breakage,
the middle button emulation remains but may be removed in the future.
The doc is updated to only refer to the middle button area now.
https://bugs.freedesktop.org/show_bug.cgi?id=94755
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Resetting the motion history has the side-effect of swallowing movements, we
don't calculate deltas until we have 4 motion events. During a finger release,
we're likely to get a large pressure change between two events, resetting the
motion history prevents the cursor from jumping on release.
The value of 7 found by trial-and-error, tested on the T440 and T450 hardware.
The absolute value is highly variable but recordings show that the pressure
changes only by 1 or 2 units during normal interaction. Higher pressure
changes are during finger position changes but since those should not cause a
jump anyway, we tend to win there too.
Currently only enabled for negative pressure changes, let's see how we go with
that.
https://bugs.freedesktop.org/show_bug.cgi?id=94379
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
The touchpad's sensors are too far apart (or the firmware interferes), causing
in a jerky movement visible especially on slow motion. We get a bunch of
normal motion events, then only ABS_MT_PRESSURE updates without x/y updates.
After about one mm of movement x/y updates resume, with the first event
covering the distance between the last motion event. That event is usually
accelerated and thus causes a large jump. Subsequent events are sufficiently
fine-grained again.
This patch counts the number of non-motion events. Once we hit 10 in a row, we
mark the first motion update as non-dirty, effectively discarding the motion
and thus stopping the pointer jumps.
https://bugs.freedesktop.org/show_bug.cgi?id=94379
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
We previously used the half-way mark of the touchpad's y axis to decide where
to ignore tapping. Move this down to the top edge of the software buttons
instead. Users may tap with a finger in the software button areas, on the rest
of the touchpad it's unlikely that they tap within 5% of the edge.
On touchpads with physical buttons or if clickfinger is enabled, the
no-tapping zone extends to the bottom of the touchpad. This required splitting
the tests into clickfinger, softbuttons and hardbuttons.
https://bugs.freedesktop.org/show_bug.cgi?id=93947
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
If a key enables dwt and is held down when the timeout expires, re-issue the
timeout.
There is a corner case where dwt may not work as expected:
1. key down and held down
2. dwt timer expires, dwt is re-issued
3. touch starts
4. key is released
5. dwt timer expires
6. touch now starts moving the pointer
This is an effect of the smart touch detection. A touch starting after the
last key press is released for pointer motion once dwt turns off again. This
is what happens in the above case, the dwt timer expiring is the last virtual
key press. This is a corner case and likely hard to trigger by a real user.
https://bugs.freedesktop.org/show_bug.cgi?id=93984
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.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>