Commit graph

45 commits

Author SHA1 Message Date
Velimir Lisec
ff132b2cfb touchpad: increase drag timeout
libinput supports lifting a finger during dragging and setting it back down
again to continue the drag. Curently the drag timeout is set to
DEFAULT_TAP_TIMEOUT. That is to short, when we're dragging the finger needs to
have enough time to move from one edge of the touchpad to the other. 180ms is
too short for that and causes false timeouts and thus button releases that
cancel the drag.

Introduce DEFAULT_DRAG_TIMEOUT and set it to 500 ms.

Signed-off-by: Velimir Lisec <lisec.velimir@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2015-05-04 10:22:58 +10:00
Peter Hutterer
182b7b7da9 touchpad: fix double/multitap timeouts
The current doubletap timeout was incorrect, it gave the user only 180ms to
touch, release, touch, release to recognise a doubletap. But it would also set
a timeout on the second release, delaying the button events by 180ms.

Instead, re-arm the timer on the second touch down. This gives the user 180ms
to release and touch again (or time out). This makes doubletap much more
reliable and reduces the delay between the release and the button events
arriving since the finger down time is already counted.

Same fix for MULTITAP, though we already armed the timer on touch down so we
just have to remove the new timer on touch release which did little but delay
everything.

https://bugs.freedesktop.org/show_bug.cgi?id=90172

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2015-05-04 10:22:58 +10:00
Peter Hutterer
8ead828e6f Fix a couple of coding style issues
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-05-01 12:09:57 +10:00
Peter Hutterer
abdca33387 touchpad: introduce MULTITAP for multi-tap-and-drag
Once we have a doubletap, enter a loop in the state machine where we can tap
multiple times and either get a multi-click or a multi-click drag-and-drop.

The sequence down/up down/up down/up produces a triple-click. The sequence
down/up down/up down/up down produces a triple-click with a button down for
dragging. Yes, that glorious octuple-tap-and-drag, it is now possible. World
domination has been achieved, thank you for playing.

We don't know when we finish tapping now, so add a timeout to send the last
click event once the finger has been released for the last time. This
guarantees that the timestamp of the last button down is later than the
last release. This avoids the bug fixed in synaptics commit
xf86-input-synaptics-1.8.0-21-g37d34f0 (some application don't handle
doubletap correctly without the timestamps).

This works for double-tap immediately, for multi-tap we need to remember the
timestamp of the first press event and use it for the release event so that
there's a forced gap between the release and the second press.

https://bugs.freedesktop.org/show_bug.cgi?id=89511

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2015-04-17 12:59:22 +10:00
Peter Hutterer
39f1125347 touchpad: don't allow taps in the top half of the palm exclusion zone.
Touches in the exclusion zone are ignored for palm detection and don't move
the cursor. Tapping however triggers before we know whether something is a
palm or not, so we get erroneous button clickst.

If a tap happens in the top half of the touchpad, within the palm exclusion
zones, ignore it for tap purposes. To avoid further complicating the state
machine simply pretend there was a movement > threshold on that finger. This
advances the tap state machine properly that no button events are sent for
this finger.

https://bugs.freedesktop.org/show_bug.cgi?id=89625

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2015-04-16 15:47:34 +10:00
Peter Hutterer
120199514b touchpad: extend two debug messages
Makes it quicker to know where it's coming from.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-04-15 15:38:44 +10:00
Peter Hutterer
ec0b927c5b touchpad: remove trailing semicolon from macro
Avoids empty statements

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-04-09 07:52:13 +10:00
Peter Hutterer
591a41f9dd touchpad: count the tapping fingers separately from the main touchpad code
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>
2015-04-08 11:42:53 +02:00
Hans de Goede
674490ca60 Add a normalized_length helper function and use this where applicable
Add a normalized_length helper function and use this where applicable,
just a minor cleanup.

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>
2015-03-25 09:18:59 +10:00
Hans de Goede
fe93145f86 Add a delta_coords type and use it were applicable
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>
2015-03-25 09:18:55 +10:00
Peter Hutterer
8101e43774 touchpad: switch delta handling to typesafe coordinates
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2015-03-17 09:01:39 +10:00
Peter Hutterer
614dc10fd1 touchpad: switch touch point, hysteresis, initial coords to typesafe coords
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2015-03-17 09:01:39 +10:00
Peter Hutterer
38ee2c7aac touchpad: change tap motion threshold to 3 mm
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>
2015-03-10 07:09:23 +10:00
Peter Hutterer
9b865ba212 touchpad: enable tapping by default on buttonless touchpads
This affects the touch device on graphics tablets.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2015-03-05 13:30:49 +10:00
Peter Hutterer
ca9da65cff cosmetic: fix a whitespace issue
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-02-23 09:01:25 +10:00
Peter Hutterer
d61f050d7f touchpad: fix a clang compiler warning
Causes the valgrind tests to fail as tp is considered uninitialized.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2015-01-06 09:53:30 +10:00
Hans de Goede
36017fbd3c touchpad: Use remove callback to unlink event listener and stop timers
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>
2014-12-09 09:55:36 +01:00
Hans de Goede
a78a25e62e touchpad: Make tap code follow state machine diagram part 3
We should only mark touches dead on a button click if we're dealing with a
clickpad.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2014-11-06 11:18:29 +01:00
Hans de Goede
d2c44df7c3 touchpad: Make tap code follow state machine diagram part 2
Mark touches as idle, rather then dead, on release. This causes no functional
changes since we only evert check for tap-touch-state == touch, and neither
being idle or dead == touch.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2014-11-06 11:18:29 +01:00
Hans de Goede
7a64815faa touchpad: Make tap code follow state machine diagram part 1
According to the diagram, we should only check the tap-touch-state before
sending a button press / release when in state touch_2 or touch_3.

tp_tap_notify always checks the tap-touch-state. This is problematic when in
state tapped, or one of the follow up states, since this could cause the
button 1 release to never happen.

In practice this is never a problem since the touch passed into tp_tap_notify
is NULL when called for timeout or button events, and in the 2 affected paths
where we're dealing with a touch or release tap-touch-state always is
TAP_TOUCH_STATE_TOUCH.

However we should not rely on this and properly follow the diagram, this
commit therefor drops the touch argument to tp_tap_notify, and adds explicit
tap-touch-state checks in the places where they are present in the diagram too.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
2014-11-06 11:18:29 +01:00
Hans de Goede
23031c8fd7 touchpad: Don't send scroll events during 2 finger tap-n-drag
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>
2014-11-06 11:04:17 +01:00
Hans de Goede
1d18a99fe6 touchpad: Fix log_bug_libinput calls on tap enable with fingers down
Before this commit the tap code deals with enabled being set to false,
by waiting for tap.state to become IDLE, and then ignoring any events from
that point on.

This causes a problem when enabled gets set to true again while fingers are
down, because when in IDLE no release events are expected, so once a release
event for one of the fingers is send, log_bug_libinput gets called.

This commit fixes this by making enabled use the same mechanism for enabled
state transitions as the tap suspend / resume code.

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>
2014-11-06 15:31:59 +10:00
Hans de Goede
cab012eefe touchpad: Add tap suspend / resume
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>
2014-11-06 15:31:59 +10:00
Hans de Goede
7dc2ea22ed touchpad: Rewrite / fix tp_release_all_taps
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>
2014-11-06 15:31:56 +10:00
Peter Hutterer
45a7edb3fb touchpad: hook up sendevents configuration
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>
2014-09-18 13:29:42 +10:00
Peter Hutterer
504c7667e9 touchpad: fix tap-and-drag handling for timeouts
Doing a tap-and-drag gesture but just holding the finger instead of moving
should trigger a timeout and still switchin into tap-and-drag.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2014-09-18 11:30:15 +10:00
Jonas Ådahl
94c59ef201 touchpad: Only break out of tap FSM for clickpad button presses
It should be possible to initiate a drag by tapping-drag, but continue
it by pressing a physical button continuing to drag by subsequent finger
motions.

As the generic evdev layer helps us ignore multiple button presses we
can have the tap machine run completely separate from and uneffected by
regular physical button presses, making the tap FSM much simpler than
adding new states for handling button presse life times from outside
of the tap state machine.

A touchpad test is updated to test click while tapping instead of tap
FSM break out. The updated test is re-added but only for clickpads only.

The tap FSM svg is updated to say "clickpad button press" instead of
"phys button press".

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2014-09-02 10:14:11 +10:00
Peter Hutterer
d635b1da2d touchpad: silence Coverity warnings about uninitialized use
container_of() accesses tp for offset calculation. Which is fine, but
Coverity doesn't know that.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-08-26 11:04:42 +10:00
Peter Hutterer
7b66f16c2a touchpad: mark a intentional switch case fallthrough as such
Both motion and timeout expiry transition into the TOUCH_2_HOLD state, but
only for motion do we need to cancel the current timeout.

Found by Coverity.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-08-26 11:04:42 +10:00
Jonas Ådahl
3a3d70a3a8 evdev: Keep track of button/key press count per device
Keep track of the number of times a given button or key is pressed on a
device. For regular mouse devices or keyboard devices, such a count will
never exceed 1, but counting button presses could help when button
presses with the same code can originate from different sources. One could
for example implement overlapping tap-drags with button presses by
having them deal with their own life-time independently, sorting out
when the user should receive button presses or not depending on the
pressed count.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-08-18 22:35:19 +02:00
Peter Hutterer
d9cf649199 Use an enum to enable/disable tapping configuration
More expressive in the caller and less ambiguous about return values (is it 1?
is it non-zero? can it be negative?)

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2014-07-22 08:19:29 +10:00
Peter Hutterer
2219c12c3a touchpad: hook up to the tapping configuration
Now that we have run-time changes of the tap.enabled state move the check
to the IDLE state only. Otherwise the tap machine may hang if tapping is
disabled while a gesture is in progress.

Two basic tests are added to check for the tap default setting - which is now
"tap disabled by default", for two reasons:
* if you don't know that tapping is a thing (or enabled by default), you get
  spurious button events that make the desktop feel buggy.
* if you do know what tapping is and you want it, you usually know where to
  enable it, or at least you can search for it.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-07-03 13:51:11 +10:00
Peter Hutterer
8fa5d0bf51 touchpad: disable tapping for fingers exceeding the timeout/motion threshold
The current code triggers multi-finger tapping even if the finger released was
previously held on the touchpad for a while. For an event sequence of:
1. first finger down
2. first finger move past threshold/wait past timeout
3. second finger down
4. first finger up

The second finger initiates the two-finger tap state, but the button event is
sent when the first finger releases - despite that finger not meeting the
usual tap constraints. This sequence can happen whenever a user swaps fingers.

Add the finger state to the actual touchpoints and update them whenever the
constrains are broken. Then, discard button events if the respective touch
did not meet the conditions.

http://bugs.freedesktop.org/76760

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2014-07-02 08:12:37 +10:00
Peter Hutterer
97a6bf10f9 Change the logging system to be per-context
Rather than a single global logging function, make the logging dependent on
the individual context. This way we won't stomp on each other's feet in the
(admittedly unusual) case of having multiple libinput contexts.

The userdata argument to the log handler was dropped. The caller has a ref to
the libinput context now, any userdata can be attached to that context
instead.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
2014-06-23 15:39:08 +10:00
Peter Hutterer
5a0c06b0d1 touchpad: Prefix tap-debugging message
For consistency with the butto state debugging

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-06-11 09:58:55 +10:00
Peter Hutterer
c433017388 touchpad: log the invalid event as bug, not just as info
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-06-11 09:58:55 +10:00
Hans de Goede
04c7987443 evdev-mt-touchpad-tap: Switch over to new timer subsystem
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>
2014-06-10 20:55:18 +10:00
Stephen Chandler Paul
e912d620d0 s/libinput_pointer_button_state/libinput_button_state/
Button states are applicable to more then just the pointer, so having a
non-generic name name for a generic enumerator value like
libinput_pointer_button_state doesn't make sense. Changing it to something
generic like libinput_button_state allows it to be reused by other devices that
may potentially be added to libinput in the future.

Signed-off-by: Stephen Chandler Paul <thatslyude@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-06-09 20:48:05 +02:00
Peter Hutterer
fd27450ae0 touchpad: break up a long line
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-06-04 11:29:09 +10:00
Hans de Goede
89165da6d6 Change internal timestamps to uint64_t to properly deal with wrapping
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>
2014-05-22 14:51:41 +02:00
Peter Hutterer
ae875520d1 touchpad: reset the tap timer_fd to -1 on destroy
No real effect, just for safety

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>
2014-05-22 14:39:00 +02:00
Peter Hutterer
e49a9888bf touchpad: clean up tap bits on destroy
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-03-25 16:43:35 +10:00
Peter Hutterer
67d1943ca4 touchpad: use log_error instead of fprintf
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-03-25 16:37:42 +10:00
Peter Hutterer
0d759edc3f touchpad: Filter motion in a certain number of tap states
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-03-24 14:56:41 +10:00
Peter Hutterer
d4bd05184a touchpad: add support for multi-finger tapping
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2014-03-24 14:56:40 +10:00