diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 7aecefc1..b168b4f6 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -1,756 +1,1094 @@ - - + + + + + - - - - - - - + + + + + + + - IDLE + + IDLE - + - TOUCH + + TOUCH - + - first - finger down + + first + + finger down - - - + + + - finger up + + finger up - - - + + + - button 1 - press + + button 1 + + press - + - timeout + + timeout - - - + + + - move > - threshold + + move > + + threshold - - - + + + - second - finger down + + second + + finger down - - - + + + - TOUCH_2 + + TOUCH_2 - + - second - finger up + + second + + finger up - - - + + + - button 2 - press + + button 2 + + press - + - move > - threshold + + move > + + threshold - + - timeout + + timeout - - - - - + + + + + - button 1 - release + + button 1 + + release - + - button 2 - release + + button 2 + + release - - - - - + + + + + - TAPPED + + TAPPED - + - timeout + + timeout - - - + + + - first - finger down + + first + + finger down - - - + + + - DRAGGING + + DRAGGING - + - first - finger up + + first + + finger up - + - btn1 - release + + btn1 + + release - - - - - - - + + + + + + + - IDLE + + IDLE - + - third - finger down + + third + + finger down - - - + + + - TOUCH_3 + + TOUCH_3 - - - + + + - button 3 - press + + button 3 + + press - + - button 3 - release + + button 3 + + release - - - + + + - move > - threshold + + move > + + threshold - - - + + + - IDLE + + IDLE - + - timeout + + timeout - - - + + + - first - finger up + + first + + finger up - - - + + + - IDLE + + IDLE - + - fourth - finger down + + fourth + + finger down - - - - - + + + + + - DRAGGING_OR_DOUBLETAP + + DRAGGING_OR_DOUBLETAP - - - + + + - timeout + + timeout - - - + + + - first - finger up + + first + + finger up - - - + + + - button 1 - release + + button 1 + + release - + - button 1 - press + + button 1 + + press - + - btn1 - release + + btn1 + + release - - - - - - - - - + + + - second - finger down + + second + + finger down - - - + + + - move > - threshold + + move > + + threshold - - - - - + + + + + - HOLD + + HOLD - + - first - finger up + + first + + finger up - - - - - + + + + + - second - finger down + + second + + finger down - - - - - - - + + + + + + + - TOUCH_2_HOLD + + TOUCH_2_HOLD - + - second - finger up + + second + + finger up - - - + + + - first - finger up + + first + + finger up - - - - - - - + + + + + + + - third - finger down + + third + + finger down - - - - - - - + + + + + + + - TOUCH_3_HOLD + + TOUCH_3_HOLD - - - + + + - fourth - finger down + + fourth + + finger down - + - DEAD + + DEAD - - - - - - - + + + + + + + - any finger up + + any finger up - + - fourth - finger up + + fourth + + finger up - + - any finger up + + any finger up - - - - + + + + - - yes + + + yes - + - any finger up + + any finger up - - - - - - - - - + + + + + + + + + - IDLE + + IDLE - + - if finger - count == 0 + + if finger + + count == 0 - - - - - - - + + + + + + + - second - finger up + + second + + finger up - + - DRAGGING_2 + + DRAGGING_2 - - - - - + + + + + - first - finger up + + first + + finger up - - - - - - - + + + + + + + - second - finger down + + second + + finger down - - - - - - - + + + + + + + - third - finger down + + third + + finger down - - - + + + - btn1 - release + + btn1 + + release - - - + + + - clickpad - button - press + + phys + + button + + press - - - - - - - - - - - - - + + + + + + + + + + + + + - clickpad - button - press + + phys + + button + + press - - - + + + - button 1 - release + + button 1 + + release - - - - - - - - - - - + + + + + + + + + + + - DRAGGING_WAIT + + DRAGGING_WAIT - + - timeout + + timeout - - - - - - - + + + + + + + - first - finger down + + first + + finger down - - - + + + - TOUCH_TOUCH + + TOUCH_TOUCH - + - TOUCH_IDLE + + TOUCH_IDLE - - - - - - - - - + + + + + + + + + - TOUCH_DEAD + + TOUCH_DEAD - - - - - - - - - - + + + + + + + + + + - - yes + + + yes - + - TOUCH_DEAD + + TOUCH_DEAD - - - - - - - + + + + + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_TOUCH + + TOUCH_TOUCH - - - - - + + + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_TOUCH + + TOUCH_TOUCH - - - + + + - that finger - TOUCH_IDLE + + that finger + + TOUCH_IDLE - - - + + + - TOUCH_DEAD + + TOUCH_DEAD - - - - - - - + + + + + + + - that finger - TOUCH_IDLE + + that finger + + TOUCH_IDLE - - - - + + + + - - no + + + no - + - TOUCH_TOUCH + + TOUCH_TOUCH - - - + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + - TOUCH_TOUCH + + TOUCH_TOUCH - - - + + + - TOUCH_DEAD + + TOUCH_DEAD - - - - - + + + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_TOUCH + + TOUCH_TOUCH - - - - - + + + + + - TOUCH_TOUCH + + TOUCH_TOUCH - - - + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_TOUCH + + TOUCH_TOUCH - - - + + + - TOUCH_IDLE + + TOUCH_IDLE - - - + + + - TOUCH_TOUCH + + TOUCH_TOUCH - - - + + + - that finger - TOUCH_IDLE + + that finger + + TOUCH_IDLE - - - + + + - TOUCH_DEAD + + TOUCH_DEAD - - - + + + - TOUCH_DEAD + + TOUCH_DEAD - + - TOUCH_DEAD + + TOUCH_DEAD - + - TOUCH_DEAD + + TOUCH_DEAD - - - + + + - TOUCH_DEAD + + TOUCH_DEAD - - - + + + - TOUCH_DEAD + + TOUCH_DEAD - - - + + + - state == - TOUCH_TOUCH + + state == + + TOUCH_TOUCH - + - that finger state == - TOUCH_TOUCH + + that finger state == + + TOUCH_TOUCH - - + + - - no + + + no - + - TOUCH_DEAD + + TOUCH_DEAD - - - + + + - TOUCH_DEAD + + TOUCH_DEAD - + - TOUCH_DEAD + + TOUCH_DEAD + + + + first + + finger down + + + + + MULTITAP + + + + + + + + + timeout + + + + + + + + + IDLE + + + + + + + + + + + MULTITAP_DOWN + + + + + button 1 + + press + + + + + + + + + first + + finger up + + + + + + + button 1 + + release + + + + + + + timeout + + + + + second + + finger down + + + + + move > + + threshold + + + + + + + + + + + button 1 + + release + + + + + button 1 + + press + + + + + + + + + + + button 1 + + release + + + + + button 1 + + press + + + + + + + + + + + button 1 + + release + + + + + button 1 + + press + + + + + + + + + + + + + TOUCH_TOUCH + + + + + + + TOUCH_IDLE + + + + + + + phys + + button + + press + + + + + + + diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 49fabb50..0f25e267 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -74,6 +74,8 @@ tap_state_to_str(enum tp_tap_state state) { CASE_RETURN_STRING(TAP_STATE_DRAGGING_WAIT); CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_DOUBLETAP); CASE_RETURN_STRING(TAP_STATE_DRAGGING_2); + CASE_RETURN_STRING(TAP_STATE_MULTITAP); + CASE_RETURN_STRING(TAP_STATE_MULTITAP_DOWN); CASE_RETURN_STRING(TAP_STATE_DEAD); } return NULL; @@ -351,11 +353,9 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DRAGGING_2; break; case TAP_EVENT_RELEASE: - tp->tap.state = TAP_STATE_IDLE; + tp->tap.state = TAP_STATE_MULTITAP; tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); - tp_tap_clear_timer(tp); + tp_tap_set_timer(tp, time); break; case TAP_EVENT_MOTION: case TAP_EVENT_TIMEOUT: @@ -443,6 +443,79 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp, } } +static void +tp_tap_multitap_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) +{ + struct libinput *libinput = tp->device->base.seat->libinput; + + switch (event) { + case TAP_EVENT_RELEASE: + log_bug_libinput(libinput, + "invalid tap event, no fingers are down\n"); + break; + case TAP_EVENT_TOUCH: + tp->tap.state = TAP_STATE_MULTITAP_DOWN; + tp->tap.multitap_last_time = time; + tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_set_timer(tp, time); + break; + case TAP_EVENT_MOTION: + log_bug_libinput(libinput, + "invalid tap event, no fingers are down\n"); + 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); + break; + case TAP_EVENT_BUTTON: + tp->tap.state = TAP_STATE_IDLE; + tp_tap_clear_timer(tp); + break; + } +} + +static void +tp_tap_multitap_down_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, + uint64_t time) +{ + switch (event) { + case TAP_EVENT_RELEASE: + tp->tap.state = TAP_STATE_MULTITAP; + tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_set_timer(tp, time); + break; + case TAP_EVENT_TOUCH: + tp->tap.state = TAP_STATE_DRAGGING_2; + tp_tap_notify(tp, + tp->tap.multitap_last_time, + 1, + LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_clear_timer(tp); + break; + case TAP_EVENT_MOTION: + case TAP_EVENT_TIMEOUT: + tp->tap.state = TAP_STATE_DRAGGING; + tp_tap_notify(tp, + tp->tap.multitap_last_time, + 1, + LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_clear_timer(tp); + break; + case TAP_EVENT_BUTTON: + tp->tap.state = TAP_STATE_DEAD; + tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_clear_timer(tp); + break; + } +} + static void tp_tap_dead_handle_event(struct tp_dispatch *tp, struct tp_touch *t, @@ -511,6 +584,12 @@ tp_tap_handle_event(struct tp_dispatch *tp, case TAP_STATE_DRAGGING_2: tp_tap_dragging2_handle_event(tp, t, event, time); break; + case TAP_STATE_MULTITAP: + tp_tap_multitap_handle_event(tp, t, event, time); + break; + case TAP_STATE_MULTITAP_DOWN: + tp_tap_multitap_down_handle_event(tp, t, event, time); + break; case TAP_STATE_DEAD: tp_tap_dead_handle_event(tp, t, event, time); break; @@ -610,6 +689,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) case TAP_STATE_DRAGGING_OR_DOUBLETAP: case TAP_STATE_TOUCH_2: case TAP_STATE_TOUCH_3: + case TAP_STATE_MULTITAP_DOWN: filter_motion = 1; break; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 7b7600c3..97b17cde 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -97,6 +97,8 @@ enum tp_tap_state { TAP_STATE_DRAGGING, TAP_STATE_DRAGGING_WAIT, TAP_STATE_DRAGGING_2, + TAP_STATE_MULTITAP, + TAP_STATE_MULTITAP_DOWN, TAP_STATE_DEAD, /**< finger count exceeded */ }; @@ -256,6 +258,7 @@ struct tp_dispatch { enum tp_tap_state state; uint32_t buttons_pressed; unsigned int tap_finger_count; + uint64_t multitap_last_time; } tap; struct { diff --git a/test/touchpad.c b/test/touchpad.c index ac8ffb92..5ff4a366 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -123,6 +123,394 @@ START_TEST(touchpad_1fg_tap) } END_TEST +START_TEST(touchpad_1fg_doubletap) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + uint32_t oldtime, curtime; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + libinput_dispatch(li); + + litest_timeout_tap(); + + libinput_dispatch(li); + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + oldtime = 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); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_le(oldtime, curtime); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_lt(oldtime, curtime); + oldtime = curtime; + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_le(oldtime, curtime); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_1fg_multitap) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + uint32_t oldtime = 0, + curtime; + int i, ntaps; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(li); + + for (i = 3; i < 8; i++) { + + for (ntaps = 0; ntaps <= i; ntaps++) { + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + libinput_dispatch(li); + msleep(10); + } + + litest_timeout_tap(); + libinput_dispatch(li); + + for (ntaps = 0; ntaps <= i; ntaps++) { + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_ge(curtime, oldtime); + oldtime = curtime; + } + litest_timeout_tap(); + litest_assert_empty_queue(li); + } +} +END_TEST + +START_TEST(touchpad_1fg_multitap_n_drag_move) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + uint32_t oldtime = 0, + curtime; + int i, ntaps; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(li); + + for (i = 3; i < 8; i++) { + + for (ntaps = 0; ntaps <= i; ntaps++) { + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + libinput_dispatch(li); + msleep(10); + } + + libinput_dispatch(li); + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_to(dev, 0, 50, 50, 70, 50, 10, 4); + libinput_dispatch(li); + + for (ntaps = 0; ntaps <= i; ntaps++) { + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_ge(curtime, oldtime); + oldtime = curtime; + } + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_MOTION); + + litest_touch_up(dev, 0); + litest_assert_button_event(li, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); + } +} +END_TEST + +START_TEST(touchpad_1fg_multitap_n_drag_2fg) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + uint32_t oldtime = 0, + curtime; + int i, ntaps; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(li); + + for (i = 3; i < 8; i++) { + + for (ntaps = 0; ntaps <= i; ntaps++) { + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + libinput_dispatch(li); + msleep(10); + } + + libinput_dispatch(li); + litest_touch_down(dev, 0, 50, 50); + msleep(10); + litest_touch_down(dev, 1, 70, 50); + libinput_dispatch(li); + + for (ntaps = 0; ntaps <= i; ntaps++) { + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_ge(curtime, oldtime); + oldtime = curtime; + } + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + litest_touch_move_to(dev, 1, 70, 50, 90, 50, 10, 4); + + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_MOTION); + + litest_touch_up(dev, 1); + litest_touch_up(dev, 0); + litest_timeout_tap(); + litest_assert_button_event(li, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); + } +} +END_TEST + +START_TEST(touchpad_1fg_multitap_n_drag_click) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + uint32_t oldtime = 0, + curtime; + int i, ntaps; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(li); + + for (i = 3; i < 8; i++) { + + for (ntaps = 0; ntaps <= i; ntaps++) { + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + libinput_dispatch(li); + msleep(10); + } + + litest_touch_down(dev, 0, 50, 50); + libinput_dispatch(li); + litest_button_click(dev, BTN_LEFT, true); + litest_button_click(dev, BTN_LEFT, false); + libinput_dispatch(li); + + for (ntaps = 0; ntaps <= i; ntaps++) { + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_ge(curtime, oldtime); + oldtime = curtime; + } + + litest_assert_button_event(li, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + litest_touch_up(dev, 1); + litest_timeout_tap(); + + litest_assert_empty_queue(li); + } +} +END_TEST + +START_TEST(touchpad_1fg_multitap_n_drag_timeout) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + uint32_t oldtime = 0, + curtime; + int i, ntaps; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(li); + + for (i = 3; i < 8; i++) { + + for (ntaps = 0; ntaps <= i; ntaps++) { + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + libinput_dispatch(li); + msleep(10); + } + + libinput_dispatch(li); + litest_touch_down(dev, 0, 50, 50); + libinput_dispatch(li); + + litest_timeout_tap(); + libinput_dispatch(li); + + for (ntaps = 0; ntaps <= i; ntaps++) { + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_ge(curtime, oldtime); + oldtime = curtime; + } + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + curtime = libinput_event_pointer_get_time(ptrev); + libinput_event_destroy(event); + ck_assert_int_gt(curtime, oldtime); + + litest_touch_move_to(dev, 0, 50, 50, 70, 50, 10, 4); + + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_MOTION); + + litest_touch_up(dev, 0); + litest_assert_button_event(li, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); + } +} +END_TEST + START_TEST(touchpad_1fg_tap_n_drag) { struct litest_device *dev = litest_current_device(); @@ -3636,6 +4024,12 @@ int main(int argc, char **argv) { litest_add("touchpad:motion", touchpad_2fg_no_motion, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:tap", touchpad_1fg_tap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_doubletap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_multitap, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_multitap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_multitap_n_drag_move, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_1fg_multitap_n_drag_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:tap", touchpad_1fg_multitap_n_drag_click, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_1fg_tap_n_drag_timeout, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_2fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);