On small touchpads, a touch that intends to go across the width of the
touchpad is likely to start in the edge zone. Likewise, on those touchpads the
chances of a palm event happening on the edge is small.
A minimum width of 8cm determined by an elaborate process of completely
unscientific guesswork: the x220 is roughly 7.5cm across and doesn't suffer
much from edge events, the T440s is 10cm across and definitely suffers from
it. So the trigger width likely somewhere in between which makes 8cm about as
valid as any other guess.
Note that this disables palm detection for resolution-less touchpads too - if
we don't know how big the touchpad is we can't know if palm detection on the
edges is necessary.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Any legitimate finger movement that starts in the palm area is expected to
move out of the palm area at an angle roughly orthogonal to the edge of the
touchpad. Check for the direction of the movement vector, and if it is within
the accepted cardinal/ordinal directions then proceed.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
On small touchpads a touch that is intended to traverse much of the screen
width may start at the very edge, i.e. in the palm zone.
In that case, and if the touch moves out of the palm zone quickly enough, drop
the palm label and make it a normal touchpoint.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
A large part of palm events are situated on the far edges of the touchpad. In
a test run on a T440s while typing a long email all but 2 touch points were
located in the outer ~5% of the touchpad. Define a 5% exclusion zone on the
left and right edges in which new touchpoint is automatically assigned to be a
palm.
A finger may move into that exclusion zone without being marked as palm, it
just can't start in one.
On clickpads, the exclusion zone does not extend into the software buttons.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
The current touch may not be the pointer touch, so it's pointless checking the
history size on that touch. Instead, search for the pointer touch first, check
if it's dirty and then check the history size.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
In an attempt to bring method into the madness, normalize the touchpad deltas
to those of a USB mouse with 400 dpi. This way the data we're dealing with in
the acceleration code is of a known quantity.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
The resolution-based scaling may result in deltas of 0. The accel code doesn't
handle 0 deltas too well. 0/0 deltas can't happen for EV_REL devices, so the
code just isn't designed for it.
Most notably, events with delta 0/0 have no direction. That messes up the
history-based velocity calculation which stops whenever the current vector's
direction changes from the one in the trackers.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
For better consistency with filter_dispatch(). And move the things around to keep
the consumable API together.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
The old touchpad accel code was clamping touchpad acceleration between
0.2 and 0.4, and on the test devices I have the constant_factor ended up
such that in practice the accel was almost always 0.2, so rather than having
a velocity based acceleration curve, in essence it was just always using an
acceleration of 0.2 .
This commit introduces actual velocity based acceleration based on the
recently added smooth simple acceleration code from filter.c .
Before feeding motion events to filter.c, they first get adjusted for touchpad
resolution. For touchpads where the driver does not provide resolution info,
scale based on the diagonal-size in units instead.
While at it rename tp_init_accel's dispatch parameter from touchpad to tp
to be consistent with all other functions.
Since the acceleration is also used for scrolling also adjust the scroll
start threshold for these changes.
Note that switching to the smooth simple accel code, as an added bonus gives
the tp code an accel profile with a threshold and a speed parameter, which
is exactly what is needed for the upcoming configuration interface support.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Once we get beyond the:
if (abs(diff) <= margin)
return center;
test, then diff is either > margin or < -margin, otherwise the test would
have triggered.
So the "return center + diff;" at the end will never be reached, and the
"else if (diff < -margin)" can be turned into a simple "else".
This commit does not just simplify tp_hysteresis, but (arguably more
important) also makes it clearer to the reader what it does.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
There is no need to loop over the touch points twice.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
If the user puts down to fingers to scroll, then changes his mind and
lifts them, without having them moved past the initial scroll threshold in
either direction, then any movement which he has done will cause a spurious
scroll event when the second finger down is lifted first.
The problem is that t->is_pointer was not being set to false in this case,
since that is done in tp_post_twofinger_scroll after checking scroll.state
which never gets set in this scenario.
Instead of changing the order, simply completely remove scroll.state completely
it is a boolean, and everywhere we check for it we also check for the axis bits
in state.direction, so it is not necessary.
Also add a check to ensure there are no spurious motion events.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
To provide a generic naming system of type_direction. That will become more
important once we add new axes as part of the ongoing work to support graphics
tablets.
[edit: and switch to the new defines]
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
A button event consumed by the softbutton or clickpad code does not feed into
the tap state machine, leaving it in its current state. The touch generating
that event however may have triggered state changes.
For some tap/click combinations this gives us either double press/release
events or an inconsistent order of events. Those issues include:
* a really short physical click causes a click + tap-click
* a really short physical click on the right software button causes a right
click + left tap-click
* tap + click causes double button left press events
To avoid these, notify the tap code that a button event has occured and
process that accordingly. Depending on the state this may either continue to
the DEAD state or release the current tap button and then go to the DEAD
state.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Besides being a nice cleanup, this gives us proper per touch timeouts.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Fixed point numbers can easily overflow, and double to fixed point
conversion is lossy. Use floating point (double) where fixed point
numbers where previously used and remove the li_fixed_t type.
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
The direction lock was intended to avoid erroneous horizontal scroll events
when scrolling vertically (and vice versa). Some testing on my touchpad here
shows that it is too easy to accidentally lock the direction when no lock is
intended (e.g. moving around an image). And quite hard to figure out what a
pure vertical gesture is.
I get movements from 90 degrees to 70 degrees for something my brain would
consider vertical scrolling. Depending on the hand position, the fingers
actually perform a slight curve, not a straight line.
Hence - drop the direction lock, but increase the threshold a little. It
doesn't totally avoid horizontal scroll events but keeps them minimal.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
The x and y absolute axis may have different resolutions, meaning 1 unit
long motion delta on one axis is not physically as long as 1 unit motion
delta on the other axis.
In order to make these anisotropic input motion deltas output as isotropic
motion deltas, apply scaling to one of the axis making it have the same
dimension as the other, before passing it through the motion filter
which assumes all deltas are isotropic.
https://bugs.freedesktop.org/show_bug.cgi?id=79056
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
On a button click / tap the scrolling event handler no longer gets called,
ensure that any in progress scrolling is stopped.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Put the actual scroll event posting in the straight path.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Setting tp->scroll.direction = 0 before checking tp->scroll.direction
to see if we need to send stop scroll events for vert / horz scrolling does
not really work well.
Also we need to check direction with an axis mask, not the axis number.
While at it also add a tp_stop_scroll_events() helper function for this.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
When doing 2 finger scrolling we don't want any spurious movement events after
scrolling. touchpad_2fg_no_motion tests for this, but it lifts touch 0
(which is the pointer as it came down first) first, so it only catches the
case where touch 1 suddenly gets promoted to being the pointer.
However if touch 1 is lifted first, then touch 0 is still the pointer and
will cause spurious movement events. Swap the 2 litest_touch_up calls to
catch this (and make the test fail), and add code to clear the is_pointer
flag on all touched when doing 2 finger scrolling to fix it again.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Alter the so far hard coded parameters a bit to make the pointer
acceleration profile accelerate the pointer movement a bit more than
before.
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
We store timestamps in ms since system boot (CLOCK_MONOTONIC). This will wrap
after circa 50 days.
I've considered making our code wrapping safe, but that won't work. We also
use our internal timestamps to program timer-fds for timeouts. And we store
ms in a single integer but the kernel uses 2 integers, one for seconds and
one for usec/nanosec. So at 32 bits our ms containing integer will wrap
in 50 days, while the kernels seconds storing integer lasts a lot longer.
So when we wrap our ms timestamps, we will be programming the timer-fds
with a seconds value in the past.
So change all our internal timestamps to uint64_t to avoid the wrapping
when programming the timer-fds. Note that we move from 64-bit timestamps to
32-bit timestamps when calling the foo_notify_bar functions from
libinput-private.h. Having 64 bit timestamps has no use past this point,
since the wayland input protocol uses 32 bit timestamps (and clients will
have to deal with wrapping).
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This is no longer needed now that we take the button area and pinned fingers
into account.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
And warn if INPUT_PROP_BUTTONPAD mismatches right/middle buttons presence.
Also fix the bcm5974 to properly advertise INPUT_PROP_BUTTONPAD.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
We don't want touches in the button area to cause the pointer to move. So
instead of making a touch the pointer when it moves to TOUCH_BEGIN, wait
with making it the pointer until its buttons state moves to BUTTON_STATE_AREA.
Note that a touch in the main area of the touchpad will move to
BUTTON_STATE_AREA immediately. If software-buttons are not enabled, any finger
is in the BUTTON_STATE_AREA.
While at it also refactor the is_pointer setting in general, removing
code duplicition wrt checking that another touch is not already
the pointer on unpinning a finger, and add safeguards that unpinning
does not make a finger which is not in button state BUTTON_STATE_AREA the
pointer, nor that the button code makes a pinned finger the pointer.
All these sanity checks are combined into a new tp_button_active function,
since they should be taken into account for 2 finger scrolling, etc. too.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Almost all non Apple touchpads have visible markings for software button areas,
so limit clickfinger behavior to Apple clickpads, and implement software button
areas for others.
This is a slightly fancier implementation than the simplest model and ported
over from libtouchpad. It implements a state machine for the software buttons
with left and right buttons currently implemented. Buttons are oriented
left-to-right, in a horizontal bar. No random button placement allowed.
In general, the procedure is:
- if a finger sets down in the left button area, a click is a left click
- if a finger sets down in the right button area, a click is a right click
- if a finger leaves the button area, a click is a left click
- if a finger starts outside the button area, a click is a left click
Two timeouts are used to handle buttons more smoothly:
- if a finger sets down in a button area but "immediately" moves over
to a different area, that area takes effect on a click.
- if a finger leaves a button area and "immediately" clicks or moves back into
the area, the button still takes effect on a click.
- if a finger changes between areas and stays there for a timeout, that area
takes effect on a click.
Note the button area states are named BOTTOM_foo to make it easier to later
add support for a top button area such as can be found on the Thinkpad [2-5]40
series.
Co-authored-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This is about to become more complicated with the support for software button
areas. Move it to a separate file to have it logically grouped together.
No functional changes.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
On clickpads, clicking the pad usually causes some motion events. To avoid
erroneous movements, lock all fingers into position on the click and don't
allow for motion events until a finger moves past a given threshold
(currently 2% of the touchpad diagonal).
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
A single-touch touchpad that provides BTN_TOOL_TRIPLETAP has 3 touches, etc.
There aren't a lot of these out there, but some touchpads don't have slots but
do provide two- or three-finger detection.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Check the value returned by calloc.
Signed-off-by: Carlos Olmedo Escobar <carlos.olmedo.e@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
On a clickpad, one finger has be on the trackpad to trigger a physical button
press. For drag and drop, we still want motion events though when a second
finger is down.
This patch adds finger-pinning. If the touchpad is pressed, the pressing
finger is "pinned" and ignored for further motion events. A second finger may
then be used to drag.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Unused at the moment, but will be used later to determine if a finger should
trigger motion events.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
On touchpads without physical buttons, the number of fingers on the touchpad
at the time the physical click happens decides the button type. 1/2/3 fingers
is handled left/right/middle.
We also swallow the motion event on the actual click event, this reduces
erroneous motion events by a bit. More processing is needed here though.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This enables two-finger scrolling and two- and three-finger tapping on a
single-touch touchpad if BTN_TOOL_DOUBLETAP and BTN_TOOL_TRIPLETAP is set.
These require a bit of special processing:
BTN_TOUCH is set with the first finger down, but somewhat randomly unset and
re-set when switching between the various BTN_TOOL_*TAP values.
BTN_TOOL_<N>TAP is only set for N fingers down, thus a double->triple move
will see a release for DOUBLETAP and a press for TRIPLETAP. This may happen in
the same event, or across two consecutive events.
This patch adds a fake_touches mask to the touchpad struct. The mask is set
for each matching BTN_* event and used to count the number of expected
fake touchpoints. From that we begin/end the number of actual touchpoints
required. Fake touchpoints take their x/y coordinates from the first
touchpoint, which reads ABS_X/ABS_Y.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Touchpads without ABS_MT_SLOT create 5 slots by default (for up to QUINTTAP)
and ABS_X/Y is mapped to the 0-slot touchpoint. This commit adds handling for
a single finger, no BTN_TOOL_DOUBLETAP or similar is being processed yet.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>