From: Peter Hutterer Date: Mon, 31 Aug 2015 01:10:58 +0000 (+1000) Subject: touchpad: don't tap for 2fg down, followed by a single finger up X-Git-Tag: 1.1.0~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=79570fd492691b4ce97360e7775965e5765a702b;p=platform%2Fupstream%2Flibinput.git touchpad: don't tap for 2fg down, followed by a single finger up The following sequence currently generates a right-button event: finger 1 down finger 2 down finger 1 up finger 2 held down This is easily triggered with short scroll events. There are two issues here: first is that the tapping code elsewhere treats any tap with a second finger down as a left-button tap, not a right button one. So if anything, we should generate a left button click here, not a right button click. Arguably, generating a button click here is wrong though, it's not a very well defined sequence and relatively difficult to trigger intentionally. So the best solution here is to simply ignore the release event and move straight back to state HOLD - unless the second finger is released within the timeout. If the finger is set down again during the timeout, we move straight to TOUCH_2_HOLD - this could eventually be interpreted as a tap, but not for now. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index b1c5995b..9fee48ac 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -35,11 +35,11 @@ - + - + button 1 - + press @@ -72,20 +72,20 @@ TOUCH_2 - + - + second - + finger up - - - + + + - + button 2 - + press @@ -104,45 +104,45 @@ - + - + button 1 - + release - + - + button 2 - + release - - - - - + + + + + - + TAPPED - + - + timeout - - - + + + - + first - + finger down - - + + @@ -164,10 +164,10 @@ - - - - + + + + @@ -226,18 +226,18 @@ - + - + first - + finger up - - - + + + - + IDLE @@ -249,8 +249,8 @@ - - + + @@ -344,8 +344,6 @@ - - @@ -371,7 +369,7 @@ - + @@ -558,8 +556,8 @@ press - - + + @@ -607,15 +605,15 @@ TOUCH_TOUCH - + - + TOUCH_IDLE - - - - + + + + @@ -631,15 +629,8 @@ - - - - - - - - yes - + + @@ -667,27 +658,20 @@ - - - - TOUCH_IDLE - - - - + - + TOUCH_IDLE - - - + + + - + TOUCH_IDLE - - + + @@ -736,8 +720,8 @@ TOUCH_TOUCH - - + + @@ -860,13 +844,6 @@ - - - - state == - - TOUCH_TOUCH - @@ -874,13 +851,6 @@ TOUCH_TOUCH - - - - - - no - @@ -1197,5 +1167,97 @@ + + + + TOUCH_2_RELEASE + + + + + second + + finger up + + + + + + + timeout + + + + + + + move > + + threshold + + + + + + + + + + + + + first + + finger down + + + + + + + + + TOUCH_IDLE + + + + + + + first + + finger up + + + + + + + + + second + + finger down + + + + + + + TOUCH_DEAD + + + + + TOUCH_DEAD + + + + + + + + + diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index de4945e6..753fc6b5 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -69,6 +69,7 @@ tap_state_to_str(enum tp_tap_state state) CASE_RETURN_STRING(TAP_STATE_TAPPED); CASE_RETURN_STRING(TAP_STATE_TOUCH_2); CASE_RETURN_STRING(TAP_STATE_TOUCH_2_HOLD); + CASE_RETURN_STRING(TAP_STATE_TOUCH_2_RELEASE); CASE_RETURN_STRING(TAP_STATE_TOUCH_3); CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD); CASE_RETURN_STRING(TAP_STATE_DRAGGING); @@ -275,12 +276,8 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp, tp_tap_set_timer(tp, time); break; case TAP_EVENT_RELEASE: - tp->tap.state = TAP_STATE_HOLD; - if (t->tap.state == TAP_TOUCH_STATE_TOUCH) { - tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_PRESSED); - tp_tap_notify(tp, time, 2, LIBINPUT_BUTTON_STATE_RELEASED); - } - tp_tap_clear_timer(tp); + tp->tap.state = TAP_STATE_TOUCH_2_RELEASE; + tp_tap_set_timer(tp, time); break; case TAP_EVENT_MOTION: tp_tap_clear_timer(tp); @@ -322,6 +319,35 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, } } +static void +tp_tap_touch2_release_handle_event(struct tp_dispatch *tp, + struct tp_touch *t, + enum tap_event event, uint64_t time) +{ + + switch (event) { + case TAP_EVENT_TOUCH: + tp->tap.state = TAP_STATE_TOUCH_2_HOLD; + t->tap.state = TAP_TOUCH_STATE_DEAD; + 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.state = TAP_STATE_IDLE; + break; + case TAP_EVENT_MOTION: + case TAP_EVENT_TIMEOUT: + tp->tap.state = TAP_STATE_HOLD; + break; + case TAP_EVENT_BUTTON: + tp->tap.state = TAP_STATE_DEAD; + break; + case TAP_EVENT_THUMB: + break; + } +} + static void tp_tap_touch3_handle_event(struct tp_dispatch *tp, struct tp_touch *t, @@ -649,6 +675,9 @@ tp_tap_handle_event(struct tp_dispatch *tp, case TAP_STATE_TOUCH_2_HOLD: tp_tap_touch2_hold_handle_event(tp, t, event, time); break; + case TAP_STATE_TOUCH_2_RELEASE: + tp_tap_touch2_release_handle_event(tp, t, event, time); + break; case TAP_STATE_TOUCH_3: tp_tap_touch3_handle_event(tp, t, event, time); break; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 5f87c3f3..f42fb02d 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -97,6 +97,7 @@ enum tp_tap_state { TAP_STATE_TAPPED, TAP_STATE_TOUCH_2, TAP_STATE_TOUCH_2_HOLD, + TAP_STATE_TOUCH_2_RELEASE, TAP_STATE_TOUCH_3, TAP_STATE_TOUCH_3_HOLD, TAP_STATE_DRAGGING_OR_DOUBLETAP, diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index 62c7a5c3..334d7977 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -966,6 +966,50 @@ START_TEST(touchpad_2fg_tap_inverted) } END_TEST +START_TEST(touchpad_2fg_tap_n_hold_first) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_enable_tap(dev->libinput_device); + + litest_drain_events(dev->libinput); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 70, 70); + litest_touch_up(dev, 1); + + libinput_dispatch(li); + + litest_assert_empty_queue(li); + litest_timeout_tap(); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_2fg_tap_n_hold_second) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + litest_enable_tap(dev->libinput_device); + + litest_drain_events(dev->libinput); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 70, 70); + litest_touch_up(dev, 0); + + libinput_dispatch(li); + + litest_assert_empty_queue(li); + litest_timeout_tap(); + + litest_assert_empty_queue(li); +} +END_TEST + START_TEST(touchpad_2fg_tap_quickrelease) { struct litest_device *dev = litest_current_device(); @@ -1755,6 +1799,8 @@ litest_setup_tests(void) litest_add("touchpad:tap", touchpad_2fg_tap_n_drag_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:tap", touchpad_2fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); litest_add("touchpad:tap", touchpad_2fg_tap_inverted, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:tap", touchpad_2fg_tap_n_hold_first, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:tap", touchpad_2fg_tap_n_hold_second, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); litest_add("touchpad:tap", touchpad_2fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); litest_add("touchpad:tap", touchpad_1fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_CLICKPAD); litest_add("touchpad:tap", touchpad_2fg_tap_click, LITEST_TOUCHPAD|LITEST_BUTTON, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD);