We ran a userstudy, evaluating three different accel methods. Detailed results are
available at:
http://www.who-t.net/publications/hutterer2014_libinput_ptraccel_study.pdf
We found that there was little difference between the method we had in
libinput 0.6 and this three-line function. Users didn't really notice a
difference, but measured data suggests that it has slight advantages in some
use-cases.
The method proposed here is the one labeled "linear" in the paper, its profile
looks roughly like this:
_____________
/
____/
/
/
where the x axis is the speed, y is the acceleration factor.
The first plateau is at the acceleration factor 1 (i.e. unaccelerated
movement), the second plateau is at the max acceleration factor. The threshold
in the code defines where and how long the plateau is.
Differences to the previous accel function:
- both inclines are linear rather than curved
- the second incline is less steep than the current method
From a maintainer's point-of-view, this function is significantly easier to
understand and manipulate than the previous one.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Make it easier to hit the topbutton area when the touchpad is disabled,
normally we don't want to make the topbutton area too big, so as to not
interfere with normal touchpad operation, but when disabled we have no such
worries.
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>
On a TOPBUTTONPAD, we can't disable the touchpad altogether - the trackstick
relies on the touchpad's top software buttons.
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>
For touchpads with top softbuttons we don't want to fully disable the touchpad
on suspend, as we want to keep the top softbuttons working for the trackpoint.
So in the suspended state some of the touchpad sub-statemachines will keep
running (e.g. buttons) where others (e.g. tap) will not. This means that
we will need to clear the touchpad state on resume too, to avoid things
being in an inconsistent state after resume.
This commit factors out the state clearing code into a helper functions, so
that the same code can be used on resume.
No functional changes.
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>
The touchpad top softbuttons such as found on the Lenove T440 are intended for
use with the trackstick. Route their events through the trackstick, so that
they can be used for e.g. middle button scrolling with the trackstick.
Note that sending top button events to a disabled trackpoint makes no sense
(and will mess up internal state). Likely a user with a disabled trackpoint
will still expect the top buttons to work, so rather than not sending events
in that case, simply treat a suspendeded trackpoint as not being there, and
send the events directly from the touchpad device.
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>
The top soft buttons are intended for use with a trackpoint, and to e.g.
make middle button scrolling work correctly, we must post the events for
these "buttons" through the trackpoint device.
This commit is a preparation patch for this, it adds a link to the
trackpoint to the touchpad, but does not yet do anything with it.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
We have the ability for a device to form a link to another device through the
device_added / device_removed callbacks. A device having such a link to
another device may also want to know when that other device is disabled /
enabled (suspended / resumed). So add a notification mechanism for this too.
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>
So that it can be used for middle button trackpoint scrolling too.
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>
For conditional touchpad disabling we need two pieces of knowledge: is the
device an internal touchpad and is another device an external mouse-like
device. For that use-case it's enough to tag any device that's on USB and
Bluetooth with pointer capabilities as external mouse. A more complex can be
done when needed.
The tag function is part of the dispatch interface (to save on udev code) and
called before the caller is notified about the new device, i.e. the device is
fully configured by the time it needs to be tagged, and other devices can rely
on the tags being assigned by the time they get notified about the new device.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
When a device is added or removed, notify all internal devices about the
device change. This allows all devices to configure themselves depending on
other devices in the system. Prime use-case here is an internal touchpad that
wants to know if an external mouse is connected.
On device added, notification goes both ways: existing devices are notified
about the new device, and the new device is notified about existing devices.
On device removed, notification only goes one way.
In both cases, the internal notification is complete before the event is sent
to the caller.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
We may be in the middle of a software button click or a tap, so make sure we
go back to the device-neutral state by unwinding.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
It's up to a evdev device backend to configure seat capabilities it
supports. Even though it may be possible for a touchpad to have extra
keys, there is currently no support for sending keyboard events from the
touchpad driver, and if that would be implemented, it'd be a detail of
the touchpad driver, not the generic evdev device part.
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
On semi-mt touchpads the reported position of the first finger down may
jump when the pad switches from st to mt mode. When this happens a large
delta gets seen on the first finger at the same time the second fingers
is first seen down, causing a spurious 2 finger scroll event.
Reset the motion history when nfingers changes on semi-mt pads to avoid 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>
Force a cast of the input arguments to a double before the divide, rather
than after the divide.
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>
Multi-touch pads may track less touches then they can report fingers being
present through BTN_TOOL_FOO. So create fake touches for fingers reported
by BTN_TOOL_FOO on multi-touch pads too (when necessary).
This fixes e.g. 3 finger tap not working on the T440s.
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>
Don't process fake touches, e.g. re-adding the same position to the motion
history when they are not dirty. This could trigger for example on a button
press.
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>
They were already protected against being called twice between SYN_REPORT, but not
for being called twice before a SYN_REPORT arrives.
This allows simplifying tp_process_fake_touch a bit. Note while at it also
also flip the if condition in tp_process_fake_touch so that the if is
true when the finger is down, and remove the bogus t->state = TOUCH_NONE.
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>
They don't set resolution so we can't calculate the size but we know they're
big enough to need palm detection.
And fix the descriptor for the bcm5974. For some reason this was advertising
synaptics coordinates. Fix it to represent (one of) the apple touchpads.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
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>