Merge branch 'wip/touchpad-tap-timestamps'

This commit is contained in:
Peter Hutterer 2017-05-04 11:51:36 +10:00
commit fc470291f1
10 changed files with 390 additions and 72 deletions

View file

@ -27,6 +27,7 @@ header_files = \
$(srcdir)/tablet-support.dox \
$(srcdir)/tapping.dox \
$(srcdir)/test-suite.dox \
$(srcdir)/timestamps.dox \
$(srcdir)/tools.dox \
$(srcdir)/touchpad-jumping-cursors.dox \
$(srcdir)/touchpad-pressure.dox \

View file

@ -24,10 +24,11 @@
- @subpage tablet-support
@page general General setup
@page general General
- @subpage udev_config
- @subpage seats
- @subpage timestamps
@page misc Users

36
doc/timestamps.dox Normal file
View file

@ -0,0 +1,36 @@
/**
@page timestamps Timestamps
@section event_timestamps Event timestamps
Most libinput events provide a timestamp in millisecond and/or microsecond
resolution. These timestamp usually increase monotonically, but libinput
does not guarantee that this always the case. In other words, it is possible
to receive an event with a timestamp earlier than the previous event.
For example, if a touchpad has @ref tapping enabled, a button event may have a
lower timestamp than an event from a different device. Tapping requires the
use of timeouts to detect multi-finger taps and/or @ref tapndrag.
Consider the following event sequences from a touchpad and a mouse:
<pre>
Time Touchpad Mouse
---------------------------------
t1 finger down
t2 finger up
t3 movement
t4 tap timeout
</pre>
For this event sequence, the first event to be sent to a caller is in
response to the mouse movement: an event of type @ref
LIBINPUT_EVENT_POINTER_MOTION with the timestamp t3.
Once the timeout expires at t4, libinput generates an event of
@ref LIBINPUT_EVENT_POINTER_BUTTON (press) with a timestamp t1 and an event
@ref LIBINPUT_EVENT_POINTER_BUTTON (release) with a timestamp t2.
Thus, the caller gets events with timestamps in the order t3, t1, t2,
despite t3 > t2 > t1.
*/

View file

@ -152,7 +152,7 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_TOUCH;
tp->tap.first_press_time = time;
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE:
@ -182,15 +182,17 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_TOUCH_2;
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE:
tp_tap_notify(tp,
tp->tap.first_press_time,
tp->tap.saved_press_time,
1,
LIBINPUT_BUTTON_STATE_PRESSED);
if (tp->tap.drag_enabled) {
tp->tap.state = TAP_STATE_TAPPED;
tp->tap.saved_release_time = time;
tp_tap_set_timer(tp, time);
} else {
tp_tap_notify(tp,
@ -226,6 +228,7 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_TOUCH_2;
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE:
@ -258,15 +261,22 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP;
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_TIMEOUT:
tp->tap.state = TAP_STATE_IDLE;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
1,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case TAP_EVENT_BUTTON:
tp->tap.state = TAP_STATE_DEAD;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
1,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case TAP_EVENT_THUMB:
break;
@ -282,10 +292,12 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_TOUCH_3;
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE:
tp->tap.state = TAP_STATE_TOUCH_2_RELEASE;
tp->tap.saved_release_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_MOTION:
@ -311,6 +323,7 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_TOUCH_3;
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_RELEASE:
@ -341,8 +354,14 @@ tp_tap_touch2_release_handle_event(struct tp_dispatch *tp,
tp_tap_clear_timer(tp);
break;
case TAP_EVENT_RELEASE:
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_press_time,
2,
LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
2,
LIBINPUT_BUTTON_STATE_RELEASED);
tp->tap.state = TAP_STATE_IDLE;
break;
case TAP_EVENT_MOTION:
@ -376,7 +395,10 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp,
case TAP_EVENT_RELEASE:
tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
if (t->tap.state == TAP_TOUCH_STATE_TOUCH) {
tp_tap_notify(tp, time, 3, LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_notify(tp,
tp->tap.saved_press_time,
3,
LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_notify(tp, time, 3, LIBINPUT_BUTTON_STATE_RELEASED);
}
break;
@ -424,7 +446,11 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_RELEASE:
tp->tap.state = TAP_STATE_MULTITAP;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
1,
LIBINPUT_BUTTON_STATE_RELEASED);
tp->tap.saved_release_time = time;
break;
case TAP_EVENT_MOTION:
case TAP_EVENT_TIMEOUT:
@ -432,7 +458,10 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_BUTTON:
tp->tap.state = TAP_STATE_DEAD;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
1,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case TAP_EVENT_THUMB:
break;
@ -568,7 +597,11 @@ tp_tap_multitap_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_MULTITAP_DOWN;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_notify(tp,
tp->tap.saved_press_time,
1,
LIBINPUT_BUTTON_STATE_PRESSED);
tp->tap.saved_press_time = time;
tp_tap_set_timer(tp, time);
break;
case TAP_EVENT_MOTION:
@ -577,8 +610,14 @@ tp_tap_multitap_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_TIMEOUT:
tp->tap.state = TAP_STATE_IDLE;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_press_time,
1,
LIBINPUT_BUTTON_STATE_PRESSED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
1,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case TAP_EVENT_BUTTON:
tp->tap.state = TAP_STATE_IDLE;
@ -598,7 +637,11 @@ tp_tap_multitap_down_handle_event(struct tp_dispatch *tp,
switch (event) {
case TAP_EVENT_RELEASE:
tp->tap.state = TAP_STATE_MULTITAP;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
1,
LIBINPUT_BUTTON_STATE_RELEASED);
tp->tap.saved_release_time = time;
break;
case TAP_EVENT_TOUCH:
tp->tap.state = TAP_STATE_DRAGGING_2;
@ -611,7 +654,10 @@ tp_tap_multitap_down_handle_event(struct tp_dispatch *tp,
break;
case TAP_EVENT_BUTTON:
tp->tap.state = TAP_STATE_DEAD;
tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_notify(tp,
tp->tap.saved_release_time,
1,
LIBINPUT_BUTTON_STATE_RELEASED);
tp_tap_clear_timer(tp);
break;
case TAP_EVENT_THUMB:

View file

@ -1262,6 +1262,28 @@ tp_handle_state(struct tp_dispatch *tp,
tp_clickpad_middlebutton_apply_config(tp->device);
}
static inline void
tp_debug_touch_state(struct tp_dispatch *tp,
struct evdev_device *device)
{
char buf[1024] = {0};
struct tp_touch *t;
size_t i = 0;
tp_for_each_touch(tp, t) {
if (i >= tp->nfingers_down)
break;
sprintf(&buf[strlen(buf)],
"slot %zd: %04d/%04d p%03d %s |",
i++,
t->point.x,
t->point.y,
t->pressure,
tp_touch_active(tp, t) ? "" : "inactive");
}
evdev_log_debug(device, "touch state: %s\n", buf);
}
static void
tp_interface_process(struct evdev_dispatch *dispatch,
struct evdev_device *device,
@ -1285,6 +1307,9 @@ tp_interface_process(struct evdev_dispatch *dispatch,
break;
case EV_SYN:
tp_handle_state(tp, time);
#if 0
tp_debug_touch_state(tp, device);
#endif
break;
}
}

View file

@ -321,7 +321,8 @@ struct tp_dispatch {
struct libinput_timer timer;
enum tp_tap_state state;
uint32_t buttons_pressed;
uint64_t first_press_time;
uint64_t saved_press_time,
saved_release_time;
enum libinput_config_tap_button_map map;
enum libinput_config_tap_button_map want_map;

View file

@ -136,6 +136,8 @@ struct libinput {
int refcount;
struct list device_group_list;
uint64_t last_event_time;
};
typedef void (*libinput_seat_destroy_func) (struct libinput_seat *seat);

View file

@ -25,6 +25,7 @@
#include "config.h"
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -73,6 +74,43 @@ check_event_type(struct libinput *libinput,
return rc;
}
static inline const char *
event_type_to_str(enum libinput_event_type type)
{
switch(type) {
CASE_RETURN_STRING(LIBINPUT_EVENT_DEVICE_ADDED);
CASE_RETURN_STRING(LIBINPUT_EVENT_DEVICE_REMOVED);
CASE_RETURN_STRING(LIBINPUT_EVENT_KEYBOARD_KEY);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_MOTION);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_AXIS);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_DOWN);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_UP);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_MOTION);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_CANCEL);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_FRAME);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_AXIS);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_TIP);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_RING);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_STRIP);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_END);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_BEGIN);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_UPDATE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
CASE_RETURN_STRING(LIBINPUT_EVENT_SWITCH_TOGGLE);
case LIBINPUT_EVENT_NONE:
abort();
}
return NULL;
}
struct libinput_source {
libinput_source_dispatch_t dispatch;
void *user_data;
@ -2026,6 +2064,17 @@ post_device_event(struct libinput_device *device,
struct libinput_event *event)
{
struct libinput_event_listener *listener, *tmp;
#if 0
struct libinput *libinput = device->seat->libinput;
if (libinput->last_event_time > time) {
log_bug_libinput(device->seat->libinput,
"out-of-order timestamps for %s time %" PRIu64 "\n",
event_type_to_str(type),
time);
}
libinput->last_event_time = time;
#endif
init_event_base(event, device, type);
@ -2660,43 +2709,6 @@ gesture_notify_pinch_end(struct libinput_device *device,
finger_count, cancelled, &zero, &zero, scale, 0.0);
}
static inline const char *
event_type_to_str(enum libinput_event_type type)
{
switch(type) {
CASE_RETURN_STRING(LIBINPUT_EVENT_DEVICE_ADDED);
CASE_RETURN_STRING(LIBINPUT_EVENT_DEVICE_REMOVED);
CASE_RETURN_STRING(LIBINPUT_EVENT_KEYBOARD_KEY);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_MOTION);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_POINTER_AXIS);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_DOWN);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_UP);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_MOTION);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_CANCEL);
CASE_RETURN_STRING(LIBINPUT_EVENT_TOUCH_FRAME);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_AXIS);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_TIP);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_RING);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_STRIP);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_SWIPE_END);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_BEGIN);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_UPDATE);
CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
CASE_RETURN_STRING(LIBINPUT_EVENT_SWITCH_TOGGLE);
case LIBINPUT_EVENT_NONE:
abort();
}
return NULL;
}
void
switch_notify_toggle(struct libinput_device *device,
uint64_t time,

View file

@ -972,6 +972,9 @@ libinput_event_device_notify_get_base_event(struct libinput_event_device_notify
/**
* @ingroup event_keyboard
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event
*/
uint32_t
@ -980,6 +983,9 @@ libinput_event_keyboard_get_time(struct libinput_event_keyboard *event);
/**
* @ingroup event_keyboard
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event in microseconds
*/
uint64_t
@ -1035,6 +1041,9 @@ libinput_event_keyboard_get_seat_key_count(
/**
* @ingroup event_pointer
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event
*/
uint32_t
@ -1043,6 +1052,9 @@ libinput_event_pointer_get_time(struct libinput_event_pointer *event);
/**
* @ingroup event_pointer
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event in microseconds
*/
uint64_t
@ -1400,6 +1412,9 @@ libinput_event_pointer_get_base_event(struct libinput_event_pointer *event);
/**
* @ingroup event_touch
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event
*/
uint32_t
@ -1408,6 +1423,9 @@ libinput_event_touch_get_time(struct libinput_event_touch *event);
/**
* @ingroup event_touch
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event in microseconds
*/
uint64_t
@ -1564,6 +1582,9 @@ libinput_event_touch_get_base_event(struct libinput_event_touch *event);
/**
* @ingroup event_gesture
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event
*/
uint32_t
@ -1572,6 +1593,9 @@ libinput_event_gesture_get_time(struct libinput_event_gesture *event);
/**
* @ingroup event_gesture
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @return The event time for this event in microseconds
*/
uint64_t
@ -2300,6 +2324,9 @@ libinput_event_tablet_tool_get_seat_button_count(struct libinput_event_tablet_to
/**
* @ingroup event_tablet
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @param event The libinput tablet tool event
* @return The event time for this event
*/
@ -2309,6 +2336,9 @@ libinput_event_tablet_tool_get_time(struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @param event The libinput tablet tool event
* @return The event time for this event in microseconds
*/
@ -2735,6 +2765,9 @@ libinput_event_tablet_pad_get_mode_group(struct libinput_event_tablet_pad *event
/**
* @ingroup event_tablet_pad
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @param event The libinput tablet pad event
* @return The event time for this event
*/
@ -2744,6 +2777,9 @@ libinput_event_tablet_pad_get_time(struct libinput_event_tablet_pad *event);
/**
* @ingroup event_tablet_pad
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @param event The libinput tablet pad event
* @return The event time for this event in microseconds
*/
@ -2799,6 +2835,9 @@ libinput_event_switch_get_base_event(struct libinput_event_switch *event);
/**
* @ingroup event_switch
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @param event The libinput switch event
* @return The event time for this event
*/
@ -2808,6 +2847,9 @@ libinput_event_switch_get_time(struct libinput_event_switch *event);
/**
* @ingroup event_switch
*
* @note Timestamps may not always increase. See @ref event_timestamps for
* details.
*
* @param event The libinput switch event
* @return The event time for this event in microseconds
*/

View file

@ -69,8 +69,11 @@ START_TEST(touchpad_1fg_doubletap)
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 50);
msleep(10);
litest_touch_up(dev, 0);
msleep(10);
litest_touch_down(dev, 0, 50, 50);
msleep(10);
litest_touch_up(dev, 0);
libinput_dispatch(li);
@ -90,7 +93,7 @@ START_TEST(touchpad_1fg_doubletap)
LIBINPUT_BUTTON_STATE_RELEASED);
curtime = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(event);
ck_assert_int_le(oldtime, curtime);
ck_assert_int_lt(oldtime, curtime);
event = libinput_get_event(li);
ptrev = litest_is_button_event(event,
@ -107,7 +110,7 @@ START_TEST(touchpad_1fg_doubletap)
LIBINPUT_BUTTON_STATE_RELEASED);
curtime = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(event);
ck_assert_int_le(oldtime, curtime);
ck_assert_int_lt(oldtime, curtime);
litest_assert_empty_queue(li);
}
@ -125,6 +128,7 @@ START_TEST(touchpad_1fg_multitap)
ntaps;
litest_enable_tap(dev->libinput_device);
litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@ -173,6 +177,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_move)
ntaps;
litest_enable_tap(dev->libinput_device);
litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@ -242,6 +247,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_2fg)
return;
litest_enable_tap(dev->libinput_device);
litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@ -313,6 +319,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_click)
ntaps;
litest_enable_tap(dev->libinput_device);
litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
@ -361,6 +368,54 @@ START_TEST(touchpad_1fg_multitap_n_drag_click)
}
END_TEST
START_TEST(touchpad_1fg_multitap_timeout)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct libinput_event *event;
struct libinput_event_pointer *ptrev;
uint32_t ptime, rtime;
int range = _i, /* looped test */
ntaps;
litest_enable_tap(dev->libinput_device);
litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
for (ntaps = 0; ntaps <= range; ntaps++) {
litest_touch_down(dev, 0, 50, 50);
msleep(10);
litest_touch_up(dev, 0);
libinput_dispatch(li);
msleep(10);
}
libinput_dispatch(li);
litest_timeout_tap();
libinput_dispatch(li);
for (ntaps = 0; ntaps <= range; ntaps++) {
event = libinput_get_event(li);
ptrev = litest_is_button_event(event,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
ptime = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(event);
event = libinput_get_event(li);
ptrev = litest_is_button_event(event,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
rtime = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(event);
ck_assert_int_lt(ptime, rtime);
}
litest_assert_empty_queue(li);
}
END_TEST
START_TEST(touchpad_1fg_multitap_n_drag_timeout)
{
struct litest_device *dev = litest_current_device();
@ -373,11 +428,13 @@ START_TEST(touchpad_1fg_multitap_n_drag_timeout)
ntaps;
litest_enable_tap(dev->libinput_device);
litest_enable_drag_lock(dev->libinput_device);
litest_drain_events(li);
for (ntaps = 0; ntaps <= range; ntaps++) {
litest_touch_down(dev, 0, 50, 50);
msleep(10);
litest_touch_up(dev, 0);
libinput_dispatch(li);
msleep(10);
@ -405,7 +462,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_timeout)
LIBINPUT_BUTTON_STATE_RELEASED);
curtime = libinput_event_pointer_get_time(ptrev);
libinput_event_destroy(event);
ck_assert_int_ge(curtime, oldtime);
ck_assert_int_gt(curtime, oldtime);
oldtime = curtime;
}
@ -449,6 +506,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap)
for (ntaps = 0; ntaps <= range; ntaps++) {
litest_touch_down(dev, 0, 50, 50);
msleep(10);
litest_touch_up(dev, 0);
libinput_dispatch(li);
msleep(10);
@ -522,6 +580,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap_click)
for (ntaps = 0; ntaps <= range; ntaps++) {
litest_touch_down(dev, 0, 50, 50);
msleep(10);
litest_touch_up(dev, 0);
libinput_dispatch(li);
msleep(10);
@ -916,6 +975,9 @@ START_TEST(touchpad_2fg_tap)
struct libinput *li = dev->libinput;
enum libinput_config_tap_button_map map = _i; /* ranged test */
unsigned int button = 0;
struct libinput_event *ev;
struct libinput_event_pointer *ptrev;
uint64_t ptime, rtime;
litest_enable_tap(dev->libinput_device);
litest_set_tap_map(dev->libinput_device, map);
@ -940,11 +1002,20 @@ START_TEST(touchpad_2fg_tap)
libinput_dispatch(li);
litest_assert_button_event(li, button,
LIBINPUT_BUTTON_STATE_PRESSED);
litest_timeout_tap();
litest_assert_button_event(li, button,
LIBINPUT_BUTTON_STATE_RELEASED);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
button,
LIBINPUT_BUTTON_STATE_PRESSED);
ptime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
button,
LIBINPUT_BUTTON_STATE_RELEASED);
rtime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
ck_assert_int_lt(ptime, rtime);
litest_assert_empty_queue(li);
}
@ -956,6 +1027,9 @@ START_TEST(touchpad_2fg_tap_inverted)
struct libinput *li = dev->libinput;
enum libinput_config_tap_button_map map = _i; /* ranged test */
unsigned int button = 0;
struct libinput_event *ev;
struct libinput_event_pointer *ptrev;
uint64_t ptime, rtime;
litest_enable_tap(dev->libinput_device);
litest_set_tap_map(dev->libinput_device, map);
@ -980,11 +1054,20 @@ START_TEST(touchpad_2fg_tap_inverted)
libinput_dispatch(li);
litest_assert_button_event(li, button,
LIBINPUT_BUTTON_STATE_PRESSED);
litest_timeout_tap();
litest_assert_button_event(li, button,
LIBINPUT_BUTTON_STATE_RELEASED);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
button,
LIBINPUT_BUTTON_STATE_PRESSED);
ptime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
button,
LIBINPUT_BUTTON_STATE_RELEASED);
rtime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
ck_assert_int_lt(ptime, rtime);
litest_assert_empty_queue(li);
}
@ -1379,11 +1462,18 @@ START_TEST(touchpad_3fg_tap)
}
for (i = 0; i < 3; i++) {
uint64_t ptime, rtime;
struct libinput_event *ev;
struct libinput_event_pointer *ptrev;
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 50);
msleep(5);
litest_touch_down(dev, 1, 70, 50);
msleep(5);
litest_touch_down(dev, 2, 80, 50);
msleep(10);
litest_touch_up(dev, (i + 2) % 3);
litest_touch_up(dev, (i + 1) % 3);
@ -1391,13 +1481,73 @@ START_TEST(touchpad_3fg_tap)
libinput_dispatch(li);
litest_assert_button_event(li, button,
LIBINPUT_BUTTON_STATE_PRESSED);
litest_timeout_tap();
litest_assert_button_event(li, button,
LIBINPUT_BUTTON_STATE_RELEASED);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
button,
LIBINPUT_BUTTON_STATE_PRESSED);
ptime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
button,
LIBINPUT_BUTTON_STATE_RELEASED);
rtime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
litest_assert_empty_queue(li);
ck_assert_int_lt(ptime, rtime);
}
}
END_TEST
START_TEST(touchpad_3fg_tap_tap_again)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
int i;
if (libevdev_get_abs_maximum(dev->evdev, ABS_MT_SLOT) <= 2)
return;
litest_enable_tap(dev->libinput_device);
uint64_t ptime, rtime;
struct libinput_event *ev;
struct libinput_event_pointer *ptrev;
litest_drain_events(li);
litest_touch_down(dev, 0, 50, 50);
msleep(5);
litest_touch_down(dev, 1, 70, 50);
msleep(5);
litest_touch_down(dev, 2, 80, 50);
msleep(10);
litest_touch_up(dev, 0);
msleep(10);
litest_touch_down(dev, 0, 80, 50);
msleep(10);
litest_touch_up(dev, 0);
litest_touch_up(dev, 1);
litest_touch_up(dev, 2);
libinput_dispatch(li);
for (i = 0; i < 2; i++) {
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
BTN_MIDDLE,
LIBINPUT_BUTTON_STATE_PRESSED);
ptime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
ev = libinput_get_event(li);
ptrev = litest_is_button_event(ev,
BTN_MIDDLE,
LIBINPUT_BUTTON_STATE_RELEASED);
rtime = libinput_event_pointer_get_time_usec(ptrev);
libinput_event_destroy(ev);
ck_assert_int_lt(ptime, rtime);
}
}
END_TEST
@ -2182,6 +2332,7 @@ litest_setup_tests_touchpad_tap(void)
litest_add("tap-1fg:1fg", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY);
litest_add("tap-1fg:1fg", touchpad_1fg_doubletap, LITEST_TOUCHPAD, LITEST_ANY);
litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_tap, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
litest_add_ranged("tap-multitap:1fg", touchpad_1fg_multitap_n_drag_move, LITEST_TOUCHPAD, LITEST_ANY, &multitap_range);
@ -2210,6 +2361,7 @@ litest_setup_tests_touchpad_tap(void)
litest_add_ranged("tap-3fg:3fg", touchpad_3fg_tap_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range);
litest_add_ranged("tap-3fg:3fg", touchpad_3fg_tap_btntool_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range);
litest_add_ranged("tap-3fg:3fg", touchpad_3fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &tap_map_range);
litest_add("tap-3fg:3fg", touchpad_3fg_tap_tap_again, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("tap-3fg:3fg", touchpad_3fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
litest_add("tap-4fg:4fg", touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
litest_add("tap-4fg:4fg", touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);