diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 10739c68..7aecefc1 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -2,755 +2,755 @@ - - - - - - - + + + + + + + - 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 - - - + + + - phys - button - press + clickpad + button + press - - - - - - - - - - - - - + + + + + + + + + + + + + - phys - button - press + clickpad + 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 diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index c05b45ce..357a50a6 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -542,7 +542,10 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) struct tp_touch *t; int filter_motion = 0; - if (tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) + /* Handle queued button pressed events from clickpads. For touchpads + * with separate physical buttons, ignore button pressed events so they + * don't interfere with tapping. */ + if (tp->buttons.is_clickpad && tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) tp_tap_handle_event(tp, NULL, TAP_EVENT_BUTTON, time); tp_for_each_touch(tp, t) { diff --git a/test/touchpad.c b/test/touchpad.c index 86b2c91b..eae92025 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -256,14 +256,17 @@ START_TEST(touchpad_1fg_tap_click) litest_drain_events(dev->libinput); - /* finger down, button click, finger up - -> only one button left event pair */ + /* Finger down, finger up -> tap button press + * Physical button click -> no button press/release + * Tap timeout -> tap button release */ litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_event(dev, EV_KEY, BTN_LEFT, 0); litest_event(dev, EV_SYN, SYN_REPORT, 0); - litest_touch_up(dev, 0); + libinput_dispatch(li); + msleep(200); libinput_dispatch(li); @@ -286,6 +289,42 @@ START_TEST(touchpad_2fg_tap_click) litest_drain_events(dev->libinput); + /* two fingers down, left button click, fingers up + -> one left button, one right button event pair */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 70, 50); + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_up(dev, 1); + litest_touch_up(dev, 0); + + libinput_dispatch(li); + + assert_button_event(li, BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + assert_button_event(li, BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + assert_button_event(li, BTN_RIGHT, + LIBINPUT_BUTTON_STATE_PRESSED); + assert_button_event(li, BTN_RIGHT, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(clickpad_2fg_tap_click) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(dev->libinput); + /* two fingers down, button click, fingers up -> only one button left event pair */ litest_touch_down(dev, 0, 50, 50); @@ -684,6 +723,38 @@ START_TEST(touchpad_btn_left) } END_TEST +START_TEST(clickpad_1fg_tap_click) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + libinput_device_config_tap_set_enabled(dev->libinput_device, + LIBINPUT_CONFIG_TAP_ENABLED); + + litest_drain_events(dev->libinput); + + /* finger down, button click, finger up + -> only one button left event pair */ + litest_touch_down(dev, 0, 50, 50); + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_up(dev, 0); + libinput_dispatch(li); + msleep(200); + + libinput_dispatch(li); + + assert_button_event(li, BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + assert_button_event(li, BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); +} +END_TEST + START_TEST(clickpad_btn_left) { struct litest_device *dev = litest_current_device(); @@ -1553,8 +1624,9 @@ int main(int argc, char **argv) { litest_add("touchpad:tap", touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:tap", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - 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_1fg_tap_click, LITEST_TOUCHPAD, LITEST_CLICKPAD); + litest_add("touchpad:tap", touchpad_2fg_tap_click, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_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); @@ -1575,6 +1647,9 @@ int main(int argc, char **argv) { litest_add("touchpad:tap", touchpad_tap_is_available, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:tap", touchpad_tap_is_not_available, LITEST_ANY, LITEST_TOUCHPAD); + litest_add("touchpad:tap", clickpad_1fg_tap_click, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:tap", clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD); + litest_add_no_device("touchpad:clickfinger", touchpad_1fg_clickfinger); litest_add_no_device("touchpad:clickfinger", touchpad_2fg_clickfinger);