Starting with kernel v5.0 two new axes are available for high-resolution wheel
scrolling: REL_WHEEL_HI_RES and REL_HWHEEL_HI_RES. Both axes send data in
fractions of 120 where each multiple of 120 amounts to one logical scroll
event. Fractions of 120 indicate a wheel movement less than one detent.
This commit adds a new API for scroll events. Three new event types that encode
the axis source in the event type name and a new API to get a normalized-to-120
value that also used by Windows and the kernel (each multiple of 120 represents
a logical scroll click).
This addresses a main shortcoming with the existing API - it was unreliable to
calculate the click angle based on the axis value+discrete events and thus any
caller using the axis value alone would be left with some ambiguity. With the
v120 API it's now possible to (usually) calculate the click angle, but more
importantly it provides the simplest hw-independent way of scrolling by a
click or a fraction of a click.
A new event type is required, the only way to integrate the v120 value
otherwise was to start sending events with a discrete value of 0. This
would break existing xf86-input-libinput (divide by zero, fixed in 0.28.2) and
weston (general confusion). mutter, kwin are unaffected.
With the new API, the old POINTER_AXIS event are deprecated - callers should use
the new API where available and discard any POINTER_AXIS events.
Notable: REL_WHEEL/REL_HWHEEL are emulated by the kernel but there's no
guarantee that they'll come every accumulated 120 values, e.g. Logitech mice
often send events that don't add up to 120 per detent.
We use the kernel's wheel click emulation instead of doing our own.
libinput guarantees high-resolution events even on pre-5.0 kernels.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
The way touchpads (generally) work is that they get the position of each
finger on each scanout. The kernel filters touches that haven't moved to
reduce bandwidth so any touch that is logically down that we don't see an
update for is in the same position as during the last scanout.
Previously, touches that didn't sent events were effectively ignored, causing
our jump detection to fail:
- time t0: touch moves to position x/y, motion history time is set to t0
- time t1..t5: touch remains at position for several frames, no updates to the
motion history
- time t6: touch jumps to position x+a/y+b
- tp_detect_jumps() sees the last update time is t0 which is too long ago
and exits without detecting a jump
This is fixed by pushing to the motion history any time we have *any* update -
if the touchpad notices a state change on any touch update all touches with
their current position, whether it changed or not.
This obsoletes the `time` field in the tp_touch struct, most of this patch is
passing down the current time to the few users of t->time.
Fixes#578
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
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>
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>
Introduced in commit 8e7f99c27a we only allowed horizontal edge scrolling
on devices larger than 50mm to leave enough reactive space on the touchpad.
Looking at a ruler, a 50mm high touchpad is still large enough to leave the
bottom 7mm as an horizontal edge scroll area. Reduce the minimum size to 40mm
instead, that's closer to where it starts to get a bit iffy.
https://bugzilla.redhat.com/show_bug.cgi?id=1422221
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
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>
If a touch was down (and up again) before the device was switched to edge
scrolling, libinput reported an error message:
litest error: libinput bug: unexpected scroll event 0 in area state
While edge scrolling was disabled, any new touch would be set to the area
state but it was never reset on touch release.
https://bugs.freedesktop.org/show_bug.cgi?id=97425
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Wherever we use an absolute size in mm on the touchpad, switch to the new
helper functions. In a few cases we only need one coordinate so just leave the
other one as 0 in those cases.
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>
We simply don't have enough space on those touchpads to have an area carved
out for horizontal scrolling. Given that horizontal scrolling is rarely needed
anyway users of these touchpads will just have to cling to scroll bars or use
two-finger scrolling.
Exception are small clickpads because they already have an area blocked off
for software buttons and those small clickpads generally come from a time when
clickfinger wasn't much of a thing yet.
https://bugs.freedesktop.org/show_bug.cgi?id=96910
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
No need to handle events properly in the edge scroll state machine when it's
not enabled. Just set any beginning touch to state AREA and move on. The rest
of the code guarantees neutral state when edge scrolling is enabled or
disabled.
This reduces the debug output produced by libinput-debug-events when edge
scrolling is disabled, preventing users from seemingly identifying
bugs where there are none.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
For short and quick scroll gestures, those that should only trigger a few
lines of scroll the pointer acceleration is wildly unpredictable. Since we
average the motion of both fingers it's hard enough to intuitively predict
what the motion will be like. On top of that is the small threshold before we
start scrolling, so some of the initial motion gets swallowed before we
accelerate, making the next motion even more unpredictable.
The end result is that multiple seemingly identical finger motions cause
wildly different scroll motion.
Drop pointer acceleration for two-finger and edge scrolling. This makes short
scroll motions much more predictable and doesn't seem to have much effect on
long scroll motions. Plus, in natural scroll mode it really feels like the
content is stuck to your fingers now. Go wash your hands.
https://bugzilla.redhat.com/show_bug.cgi?id=1249365
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Instead of going straight to pointer_notify_axis, go through
evdev_notify_axis() which flips the scroll direction around for us.
https://bugs.freedesktop.org/show_bug.cgi?id=91597
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>
When the touch leaves the area for edge scrolling after starting to scroll,
discard any movement. This signals to the user that they've left the area and
forces them to lift the finger to switch back to motion. If the finger moves
back into the area, scrolling continues.
https://bugs.freedesktop.org/show_bug.cgi?id=91323
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Rather than magic percentages of the touchpad axis ranges, make it a fixed
size of 7mm.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
We use width/height often enough that storing it once is better than
calculating it on each event.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
When edge scrolling is triggered by exceeding the motion threshold (5mm) we
sent the whole delta as the first scroll event, causing a big jump.
Instead, send only the current delta. This effectively introduces a 5mm dead
zone when edge scrolling, still better than the jump.
https://bugs.freedesktop.org/show_bug.cgi?id=90990
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Most scroll motions would be labelled a palm.
https://bugs.freedesktop.org/show_bug.cgi?id=90980
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
To quote Bryce Harrington from [1]:
"MIT has released software under several slightly different licenses,
including the old 'X11 License' or 'MIT License'. Some code under this
license was in fact included in X.org's Xserver in the past. However,
X.org now prefers the MIT Expat License as the standard (which,
confusingly, is also referred to as the 'MIT License'). See
http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
When Wayland started, it was Kristian Høgsberg's intent to license it
compatibly with X.org. "I wanted Wayland to be usable (license-wise)
whereever X was usable." But, the text of the older X11 License was
taken for Wayland, rather than X11's current standard. This patch
corrects this by swapping in the intended text."
libinput is a fork of weston and thus inherited the original license intent
and the license boilerplate itself.
See this thread on wayland-devel here for a discussion:
http://lists.freedesktop.org/archives/wayland-devel/2015-May/022301.html
[1] http://lists.freedesktop.org/archives/wayland-devel/2015-June/022552.html
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Acked-by: Jonas Ådahl <jadahl@gmail.com>
The current code labels a touch as palm if it started within the typing
timeouts. To move the pointer even after the timeout expires, a user has to
lift the finger which is quite annoying and different to the old synaptics
driver behaviour (which had a simple on/off toggle on whether to let events
through or not).
Be smarter about this: if a touch starts _after_ the last key press event,
release it for pointer motion once the timeout expires. Touches started before
the last key press remain labelled as palms. This makes it possible to rest
the palm on the touchpad while typing without getting interference but also
provides a more responsive UI when moving from typing to using the touchpad
normally.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Change tp_filter_motion to use normalized_coords, rather then having it take
separate x and y values.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
tp_normalize_coords is one of the last functions taking separate x, y
values rather a coordinate pair, this commit cleans this up.
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 DEFAULT_SCROLL_THRESHOLD value is a TP_MM_TO_DPI_NORMALIZED value and as
such should be compared to a normalized value. But since commit 8101e43774
("touchpad: switch delta handling to typesafe coordinates"), the
initial_dx / initial_dy values initial_delta points to are no longer in
normalized coordinates, as the result of tp_normalize_delta is now stored
into the normalized value.
This commit changes the check to use the delta pointer which does point to
the normalized x/y values. While at it also use the zero variable to
set normalized to zero rather then manually setting x and y to 0.
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>
Everywhere else in the touchpad code we use "t" for the struct tp_touch.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>