Less ambiguous since real_touches can be interpreted to "current number of
real touches as opposed to fake touches". Which it isn't, this variable holds
the number of slots.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
tp->nfingers_down gives us the current state of the touchpad but in the case
of the tapping state we need the touchpoints separately. If all touchpoints
end in the same SYN_REPORT frame, tp->nfingers_down is 0 when we handle the
touch releases. This changes the tap state to IDLE on the first release and
then logs a bug when the remaining touches are released while the touchpad is
in IDLE.
Avoid this by counting the fingers separately for the tap state, this way we
can count up/down with the down/up events as we process them for the tapping
state machine.
This also adds tests for 4 and 5-finger tapping which is how the bug was
discovered in the first place.
https://bugs.freedesktop.org/show_bug.cgi?id=89800
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
What we really need is not a specific delta type, but a type which can hold
non discrete device coordinates, this is e.g. also needed for the center
coordinates of gestures. So rename delta_coords to device_float_coords to
properly reflect what we really need.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
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>
This way the unaccelerated deltas returned by libinput are correct.
To maintain the current behavior we slow down the input speed by the magic
factor and likewise the accelerated output speed. This produces virtually the
same accelerated deltas as the previous code.
The magic factor is applied to the default denominator for guessing a
resolution based on the touchpad diagonal. We can't really get around this
without having a resolution from the touchpad; meanwhile this produces
virtually the same coordinates before/after.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Now that we've separate handling of the EDGE_NEW vs EDGE states in
tp_edge_scroll_post_events() we can drop the threshold variable, in EDGE_NEW
we always want to check against DEFAULT_SCROLL_THRESHOLD and in the EDGE
state we only want to make sure that the delta != 0.0 which is already
checked later on in tp_edge_scroll_post_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>
The previous setting of 10 wasn't 10 mm, it was used against the deltas
normalized to a 1000DPI mouse, i.e. closer to 4mm. It was also also per-event,
so a slow movement or a high-frequency touchpad can struggle to meet the
threshold.
Change the trigger to be ~5 mm from the initial touch down, accumulated until
we either meet the threshold or the timeout expires. The first scroll event
includes the delta since the touch down rather than the most recent delta.
This removes the delay otherwise seen in scrolling and makes the scroll motion
match the finger motion. This accumulated delta only applies when exceeding
the motion threshold, when the timeout triggers the switch to scrolling the
first delta posted is the current delta.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Previous code used a device coordinate threshold of 300 which won't work on
Elantech touchpads (1280 vs the ~4000 that synaptics has).
Convert to normalized DPI and reduce the threshold to 3mm.
https://bugs.freedesktop.org/show_bug.cgi?id=89206
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Ideally we want to specify various thresholds in mm, but not all touchpads
set the hardware resolutions. Rather than conditions to check for resolutions
everywhere, use a macro to give us a normalized value that we use for motion
as well.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
All callers except the tap motion threshold call
tp_get_delta() followed by tp_filter_motion() - the latter normalized it
before calling into the accleration code.
Move the normalization into tp_get_delta() so we don't deal with
device-specific coordinates but normalized deltas instead.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Just moving some code around, no functional changes.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Handle everything which is not handled by the tap, (soft)button or edge-scroll
code/statemachines in a unified way. Everything is treated as a X-finger
gesture now, and the action to take on finger movement is decided by
the gesture.finger_count setting. Pointer control now simply is seen as a
1 finger gesture, and 2fg scrolling as a 2fg gesture.
This removed the need for special-casing things like switching back to
pointer mode when lifting a finger in 2fg scrolling mode, and also lays the
groundwork for adding 3+ fg gesture support.
Note that 1 test-case needs to be updated to wait for the finger mode
switching when switching mode while a gesture has already been started.
This is actually an improvement as this stops sending spurious pointer
motion events at the end of 2fg scrolling when not lifting both fingers at
exactly the same time.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Allow switching between softbuttons and clickfinger on any mt-capable
clickpad.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
[hdegoede@redhat.com] Keep top softbuttons working when enabling clickfinger
[hdegoede@redhat.com] Simply touchpad click method switching
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Some touchpads provide touch information while the finger hovers over the
touchpad, i.e. before BTN_TOUCH. Add a touch state for those touchpads so we
can ignore the touches until they actually start.
The approach is now: instead of BEGIN we mark a new touch as HOVERING.
Use the BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP information during
tp_process_state() to mark any touches that are hovering as down or ended.
i.e. provided BTN_TOUCH is down: if BTN_TOOL_FINGER is down, one hovering
touch gets marked as down, if DOUBLETAP is down, two touches are marked as
down, etc.
When ending touches, switch them back into HOVERING if the BTN_TOOL_FINGER
is still set, otherwise end them properly.
https://bugs.freedesktop.org/show_bug.cgi?id=87197
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
We need this for determining hovering touches on some semi-mt touchpads.
This makes the fake_touches mask use bit 0 for BTN_TOUCH, and the other bits
for BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, etc. BTN_TOUCH is independent of the
rest, the others are mutually exclusive in the kernel.
Since the mask isn't a straightforward bitmask anymore, abstract it all
through helper functions.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Add a boolean state machine for two-finger scrolling so we know when we're
currently scrolling. If we were scrolling and it stops, pick the active
touch as pointer touch so we can go back to pointer movement without having to
lift the finger off the touchpad.
https://bugs.freedesktop.org/show_bug.cgi?id=86807
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
We use 2 mechanisms to unregister the trackpoint event listener depending on
device removal order.
1) We have a device_removed callback, if the trackpoint gets removed before
the touchpad, this gets called, sees the device being removed is the trackpoint
and unregisters the listener
2) If the touchpad gets removed first, then in tp_destroy we unregister the
listener
2) May be delayed beyond the destruction of the trackpoint itself if the
libinput user has a reference to the libinput_device for the touchpad.
When this happens the trackpoint still has an eventlistener at destroy time
and an assert triggers.
To fix this we must do 2) at the same time as we do 1), so at remove time.
While working on this I noticed that the touchpad code was also cancelling
timers at destroy time rather then remove time, which means that they may
expire between remove and destroy time, and cause events to be emitted from
a removed device, so this commit moves the cancelling of the timers to the
remove callback as well.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
For certain applications (such as FPS games) it is necessary to use
unaccelerated motion events (the motion vector that is passed to the
acceleration filter) to get a more natural feeling. Supply this
information by passing both accelerated and unaccelerated motion
vectors to the existing motion event.
Note that the unaccelerated motion event is not equivalent to 'raw'
events as read from devices.
Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Add edge-scrolling support for non multi-touch touchpads as well as for
users who prefer edge-scrolling (as long as they don't have a clickpad).
Note the percentage to use of the width / height as scroll-edge differs from
one manufacturer to the next, the various per model percentages were taken
from xf86-input-synaptics.
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=85635
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>
This is useful to know in some cases, it is e.g. necessary to figure out
which percentage of a touchpads range to use as edge for edge-scrolling.
Note this is a slightly cleaned up copy of the same code in
xf86-input-synaptics.
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>
We're about to add natural scroll support to other devices as well, let's
share the code.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Default to 2fg scrolling for now, once we have edge-scrolling we can default
to edge-scrolling on touchpads which cannot detect more than 1 touch.
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 avoid confusion with scroll mode configuration.
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 tap code explicitly supports 2 finger tap-n-drag, this commit
adds a test-case for this, which fails due to the 2 finger scrolling code
sending scroll events during a 2 finger tap-n-drag.
And this commit fixes the test-case, by not sending scroll events while a
tap-n-drag is active.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Some laptops with both a clickpad and a trackpoint have such a large touchpad,
that parts of the users hands will touch the pad when using the trackpoint.
Examples of this are the Lenovo T440s and the Toshiba Tecra Z40-A.
This commit makes libinput automatically disable the touchpad while using
the trackpoint on these devices, except for the buttons, as people may want
to use the touchpad (hardware or soft) buttons while using the trackpoint.
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>
While e.g. disabling the touchpad while the trackpoint is used, we want to
stop sending tap (or scroll or motion) events. We cannot use tp_clear_state at
this time as that will also release any touchpad buttons pressed, breaking
dragging with the trackpoint using the touchpad or clickpad buttons.
Calling tp_release_all_taps() and then ensuring that we do not call
tp_tap_handle_state as long as the trackpoint is in use, is enough to disable
taps when the trackpoint is in use.
However when the trackpoint stops being used, we cannot simply start calling
tp_tap_handle_state() again, we first need to sync the tap.state to the current
reality, specifically if fingers are down it must be TAP_STATE_DEAD, so that
their releases do not trigger the log_bug_libinput on a release in
tp_tap_idle_handle_event.
Directly messing with tap.state from outside evdev-mt-touchpad-tap.c is not
good, so add tp_tap_suspend and tp_tap_resume functions 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>
Before this commit tp_release_all_taps would call tp_tap_handle_timeout, which
is a nop when in state DRAGGING. tp_clear_state then releases all touches and
calls touchpad_handle_state which moves the state to DRAGGING_WAIT, and the
button 1 release will only be done after the tap-timeout, rather then directly
as it should on tp_clear_state.
This commit fixes this by instead of calling tp_tap_handle_timeout, directly
releasing pressed buttons and switching to state DEAD or IDLE depending on
fingers_down.
Besides fixing this issue, this rewrite also makes it possible to use
tp_release_all_taps outside of tp_clear_state, which will be used to add
tap suspend / resume functionality in a follow up commit.
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>
We don't need a separate filter struct, we can use the parent evdev device.
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>
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>
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>
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>
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>
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>
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>
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 original intention of this state was to prevent an accidental move out of
the bottom software button to start moving the cursor. That ends up actually
preventing a number of normal moves that start low enough. Simply drop the
state.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>