diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 50ebc713..10739c68 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -1,771 +1,756 @@ -IDLETOUCHfirstfinger downfinger upbutton -1presstimeoutmove > thresholdsecondfinger downTOUCH_2secondfinger upbutton -2pressmove > -thresholdtimeoutbutton 1releasebutton -2releaseTAPPEDtimeoutfirstfinger downDRAGGINGfirstfinger upbtn1releaseIDLEthirdfinger downTOUCH_3secondfinger upbutton 3pressbutton 3releasemove > thresholdIDLEtimeoutthirdfinger upfirstfinger upIDLEfourthfinger downDRAGGING_OR_DOUBLETAPtimeoutfirstfinger upbutton -1releasebutton -1pressbtn1releasesecondfinger downmove > thresholdHOLDfirstfinger upsecondfinger downTOUCH_2_HOLDsecondfinger upfirstfinger upthirdfinger downTOUCH_3_HOLDsecondfinger upthirdfinger upfourthfinger downDEADsecondfinger upthirdfinger upfourthfinger downfirstfinger upfirstfinger upfirstfinger upIDLEif fingercount == 0secondfinger upDRAGGING_2firstfinger upsecondfinger downthirdfinger downbtn1releasephysbuttonpressfourthfinger downphysbuttonpressbutton 1releaseDRAGGING_WAITtimeoutfirstfinger down + + + + + + + + + + + + + IDLE + + + + TOUCH + + + + first + finger down + + + + + + finger up + + + + + + button 1 + press + + + + timeout + + + + + + move > + threshold + + + + + + second + finger down + + + + + + TOUCH_2 + + + + second + finger up + + + + + + button 2 + press + + + + move > + threshold + + + + timeout + + + + + + + + button 1 + release + + + + button 2 + release + + + + + + + + TAPPED + + + + timeout + + + + + + first + finger down + + + + + + DRAGGING + + + + first + finger up + + + + btn1 + release + + + + + + + + + + IDLE + + + + third + finger down + + + + + + TOUCH_3 + + + + + + button 3 + press + + + + button 3 + release + + + + + + move > + threshold + + + + + + IDLE + + + + timeout + + + + + + first + finger up + + + + + + IDLE + + + + fourth + finger down + + + + + + + + DRAGGING_OR_DOUBLETAP + + + + + + timeout + + + + + + first + finger up + + + + + + button 1 + release + + + + button 1 + press + + + + btn1 + release + + + + + + + + + + + + second + finger down + + + + + + move > + threshold + + + + + + + + HOLD + + + + first + finger up + + + + + + + + second + finger down + + + + + + + + + + TOUCH_2_HOLD + + + + second + finger up + + + + + + first + finger up + + + + + + + + + + third + finger down + + + + + + + + + + TOUCH_3_HOLD + + + + + + fourth + finger down + + + + DEAD + + + + + + + + + + any finger up + + + + fourth + finger up + + + + any finger up + + + + + + + + yes + + + + any finger up + + + + + + + + + + + + IDLE + + + + if finger + count == 0 + + + + + + + + + + second + finger up + + + + DRAGGING_2 + + + + + + + + first + finger up + + + + + + + + + + second + finger down + + + + + + + + + + third + finger down + + + + + + btn1 + release + + + + + + phys + button + press + + + + + + + + + + + + + + + + phys + button + press + + + + + + button 1 + release + + + + + + + + + + + + + + DRAGGING_WAIT + + + + timeout + + + + + + + + + + first + finger down + + + + + + TOUCH_TOUCH + + + + TOUCH_IDLE + + + + + + + + + + + + TOUCH_DEAD + + + + + + + + + + + + + + yes + + + + TOUCH_DEAD + + + + + + + + + + TOUCH_IDLE + + + + + + TOUCH_TOUCH + + + + + + + + TOUCH_IDLE + + + + + + TOUCH_IDLE + + + + + + TOUCH_IDLE + + + + + + TOUCH_TOUCH + + + + + + that finger + TOUCH_IDLE + + + + + + TOUCH_DEAD + + + + + + + + + + that finger + TOUCH_IDLE + + + + + + + + no + + + + TOUCH_TOUCH + + + + + + TOUCH_IDLE + + + + + + TOUCH_TOUCH + + + + + + TOUCH_DEAD + + + + + + + + TOUCH_IDLE + + + + + + TOUCH_TOUCH + + + + + + + + TOUCH_TOUCH + + + + + + TOUCH_IDLE + + + + + + TOUCH_IDLE + + + + + + TOUCH_TOUCH + + + + + + TOUCH_IDLE + + + + + + TOUCH_TOUCH + + + + + + that finger + TOUCH_IDLE + + + + + + TOUCH_DEAD + + + + + + TOUCH_DEAD + + + + TOUCH_DEAD + + + + TOUCH_DEAD + + + + + + TOUCH_DEAD + + + + + + TOUCH_DEAD + + + + + + state == + TOUCH_TOUCH + + + + that finger state == + TOUCH_TOUCH + + + + + + no + + + + TOUCH_DEAD + + + + + + TOUCH_DEAD + + + + TOUCH_DEAD + + + diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 25412184..8a129634 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -95,12 +95,16 @@ tap_event_to_str(enum tap_event event) { static void tp_tap_notify(struct tp_dispatch *tp, + struct tp_touch *t, uint64_t time, int nfingers, enum libinput_button_state state) { int32_t button; + if (t && t->tap.state == TAP_TOUCH_STATE_DEAD) + return; + switch (nfingers) { case 1: button = BTN_LEFT; break; case 2: button = BTN_RIGHT; break; @@ -128,7 +132,9 @@ tp_tap_clear_timer(struct tp_dispatch *tp) } static void -tp_tap_idle_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_idle_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; @@ -151,7 +157,9 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t } static void -tp_tap_touch_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_touch_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -161,7 +169,7 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t break; case TAP_EVENT_RELEASE: tp->tap.state = TAP_STATE_TAPPED; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_PRESSED); tp_tap_set_timer(tp, time); break; case TAP_EVENT_TIMEOUT: @@ -176,7 +184,9 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t } static void -tp_tap_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_hold_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -197,7 +207,9 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t } static void -tp_tap_tapped_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_tapped_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; @@ -213,17 +225,19 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_ 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, t, 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, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; } } static void -tp_tap_touch2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_touch2_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -233,8 +247,8 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_ break; case TAP_EVENT_RELEASE: tp->tap.state = TAP_STATE_HOLD; - tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, t, time, 2, LIBINPUT_BUTTON_STATE_RELEASED); tp_tap_clear_timer(tp); break; case TAP_EVENT_MOTION: @@ -249,7 +263,9 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_ } static void -tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -271,7 +287,9 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, ui } static void -tp_tap_touch3_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_touch3_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -286,8 +304,8 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_ break; case TAP_EVENT_RELEASE: tp->tap.state = TAP_STATE_TOUCH_2_HOLD; - tp_tap_notify(tp, time, 3, LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, time, 3, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, t, time, 3, LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; @@ -296,7 +314,9 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_ } static void -tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -317,7 +337,9 @@ tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, enum tap_event event, ui } static void -tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { case TAP_EVENT_TOUCH: @@ -325,9 +347,9 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, enum tap_event break; case TAP_EVENT_RELEASE: tp->tap.state = TAP_STATE_IDLE; - 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_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_PRESSED); + tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); tp_tap_clear_timer(tp); break; case TAP_EVENT_MOTION: @@ -336,13 +358,15 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, enum tap_event 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, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; } } static void -tp_tap_dragging_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_dragging_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -359,13 +383,15 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp, enum tap_event event, uint6 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, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; } } static void -tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -378,17 +404,19 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, enum tap_event event, 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, t, 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, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; } } static void -tp_tap_dragging2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_dragging2_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) { switch (event) { @@ -397,7 +425,7 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint break; case TAP_EVENT_TOUCH: tp->tap.state = TAP_STATE_DEAD; - tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); + tp_tap_notify(tp, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; case TAP_EVENT_MOTION: case TAP_EVENT_TIMEOUT: @@ -405,13 +433,16 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp, enum tap_event event, uint 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, t, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; } } static void -tp_tap_dead_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_dead_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, + uint64_t time) { switch (event) { @@ -428,7 +459,10 @@ tp_tap_dead_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t } static void -tp_tap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) +tp_tap_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; enum tp_tap_state current; @@ -440,43 +474,43 @@ tp_tap_handle_event(struct tp_dispatch *tp, enum tap_event event, uint64_t time) switch(tp->tap.state) { case TAP_STATE_IDLE: - tp_tap_idle_handle_event(tp, event, time); + tp_tap_idle_handle_event(tp, t, event, time); break; case TAP_STATE_TOUCH: - tp_tap_touch_handle_event(tp, event, time); + tp_tap_touch_handle_event(tp, t, event, time); break; case TAP_STATE_HOLD: - tp_tap_hold_handle_event(tp, event, time); + tp_tap_hold_handle_event(tp, t, event, time); break; case TAP_STATE_TAPPED: - tp_tap_tapped_handle_event(tp, event, time); + tp_tap_tapped_handle_event(tp, t, event, time); break; case TAP_STATE_TOUCH_2: - tp_tap_touch2_handle_event(tp, event, time); + tp_tap_touch2_handle_event(tp, t, event, time); break; case TAP_STATE_TOUCH_2_HOLD: - tp_tap_touch2_hold_handle_event(tp, event, time); + tp_tap_touch2_hold_handle_event(tp, t, event, time); break; case TAP_STATE_TOUCH_3: - tp_tap_touch3_handle_event(tp, event, time); + tp_tap_touch3_handle_event(tp, t, event, time); break; case TAP_STATE_TOUCH_3_HOLD: - tp_tap_touch3_hold_handle_event(tp, event, time); + tp_tap_touch3_hold_handle_event(tp, t, event, time); break; case TAP_STATE_DRAGGING_OR_DOUBLETAP: - tp_tap_dragging_or_doubletap_handle_event(tp, event, time); + tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time); break; case TAP_STATE_DRAGGING: - tp_tap_dragging_handle_event(tp, event, time); + tp_tap_dragging_handle_event(tp, t, event, time); break; case TAP_STATE_DRAGGING_WAIT: - tp_tap_dragging_wait_handle_event(tp, event, time); + tp_tap_dragging_wait_handle_event(tp, t, event, time); break; case TAP_STATE_DRAGGING_2: - tp_tap_dragging2_handle_event(tp, event, time); + tp_tap_dragging2_handle_event(tp, t, event, time); break; case TAP_STATE_DEAD: - tp_tap_dead_handle_event(tp, event, time); + tp_tap_dead_handle_event(tp, t, event, time); break; } @@ -508,19 +542,34 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) int filter_motion = 0; if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) - tp_tap_handle_event(tp, TAP_EVENT_BUTTON, time); + tp_tap_handle_event(tp, NULL, TAP_EVENT_BUTTON, time); tp_for_each_touch(tp, t) { if (!t->dirty || t->state == TOUCH_NONE) continue; - if (t->state == TOUCH_BEGIN) - tp_tap_handle_event(tp, TAP_EVENT_TOUCH, time); - else if (t->state == TOUCH_END) - tp_tap_handle_event(tp, TAP_EVENT_RELEASE, time); - else if (tp->tap.state != TAP_STATE_IDLE && - tp_tap_exceeds_motion_threshold(tp, t)) - tp_tap_handle_event(tp, TAP_EVENT_MOTION, time); + if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) + t->tap.state = TAP_TOUCH_STATE_DEAD; + + if (t->state == TOUCH_BEGIN) { + t->tap.state = TAP_TOUCH_STATE_TOUCH; + tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time); + } else if (t->state == TOUCH_END) { + tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time); + t->tap.state = TAP_TOUCH_STATE_DEAD; + } else if (tp->tap.state != TAP_STATE_IDLE && + tp_tap_exceeds_motion_threshold(tp, t)) { + struct tp_touch *tmp; + + /* Any touch exceeding the threshold turns all + * touches into DEAD */ + tp_for_each_touch(tp, tmp) { + if (tmp->tap.state == TAP_TOUCH_STATE_TOUCH) + tmp->tap.state = TAP_TOUCH_STATE_DEAD; + } + + tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time); + } } /** @@ -550,8 +599,17 @@ static void tp_tap_handle_timeout(uint64_t time, void *data) { struct tp_dispatch *tp = data; + struct tp_touch *t; - tp_tap_handle_event(tp, TAP_EVENT_TIMEOUT, time); + tp_tap_handle_event(tp, NULL, TAP_EVENT_TIMEOUT, time); + + tp_for_each_touch(tp, t) { + if (t->state == TOUCH_NONE || + t->tap.state == TAP_TOUCH_STATE_IDLE) + continue; + + t->tap.state = TAP_TOUCH_STATE_DEAD; + } } int diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 7afb3c46..494725a6 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -88,6 +88,12 @@ enum tp_tap_state { TAP_STATE_DEAD, /**< finger count exceeded */ }; +enum tp_tap_touch_state { + TAP_TOUCH_STATE_IDLE = 16, /**< not in touch */ + TAP_TOUCH_STATE_TOUCH, /**< touching, may tap */ + TAP_TOUCH_STATE_DEAD, /**< exceeded motion/timeout */ +}; + struct tp_motion { int32_t x; int32_t y; @@ -131,6 +137,10 @@ struct tp_touch { enum button_event curr; struct libinput_timer timer; } button; + + struct { + enum tp_tap_touch_state state; + } tap; }; struct tp_dispatch { diff --git a/test/touchpad.c b/test/touchpad.c index 288805ef..3e5ee202 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -320,6 +320,82 @@ START_TEST(touchpad_2fg_tap_click_apple) } END_TEST +START_TEST(touchpad_no_2fg_tap_after_move) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_drain_events(dev->libinput); + + /* one finger down, move past threshold, + second finger down, first finger up + -> no event + */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_to(dev, 0, 50, 50, 90, 90, 10); + litest_drain_events(dev->libinput); + + litest_touch_down(dev, 1, 70, 50); + litest_touch_up(dev, 0); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_no_2fg_tap_after_timeout) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_drain_events(dev->libinput); + + /* one finger down, wait past tap timeout, + second finger down, first finger up + -> no event + */ + litest_touch_down(dev, 0, 50, 50); + libinput_dispatch(dev->libinput); + msleep(300); + libinput_dispatch(dev->libinput); + litest_drain_events(dev->libinput); + + litest_touch_down(dev, 1, 70, 50); + litest_touch_up(dev, 0); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_no_first_fg_tap_after_move) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + + litest_drain_events(dev->libinput); + + /* one finger down, second finger down, + second finger moves beyond threshold, + first finger up + -> no event + */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 70, 50); + libinput_dispatch(dev->libinput); + litest_touch_move_to(dev, 1, 70, 50, 90, 90, 10); + libinput_dispatch(dev->libinput); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + libinput_dispatch(dev->libinput); + + while ((event = libinput_get_event(li))) { + ck_assert_int_ne(libinput_event_get_type(event), + LIBINPUT_EVENT_POINTER_BUTTON); + libinput_event_destroy(event); + } +} +END_TEST + START_TEST(touchpad_1fg_double_tap_click) { struct litest_device *dev = litest_current_device(); @@ -1127,6 +1203,11 @@ int main(int argc, char **argv) { litest_add("touchpad:tap", touchpad_1fg_tap_click, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_2fg_tap_click, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); litest_add("touchpad:tap", touchpad_2fg_tap_click_apple, LITEST_APPLE_CLICKPAD, LITEST_ANY); + litest_add("touchpad:tap", touchpad_no_2fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:tap", touchpad_no_2fg_tap_after_timeout, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:tap", touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:tap", touchpad_no_first_fg_tap_after_move, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + /* Real buttons don't interfere with tapping, so don't run those for pads with buttons */ litest_add("touchpad:tap", touchpad_1fg_double_tap_click, LITEST_CLICKPAD, LITEST_ANY);