touchpad: allow tap-and-drag for two-finger and three-finger taps
authorsatrmb <10471-satrmb_true-email-is-private_contact-via-web@gitlab.freedesktop.org>
Tue, 23 Jun 2020 22:20:57 +0000 (00:20 +0200)
committerPeter Hutterer <peter.hutterer@who-t.net>
Fri, 25 Sep 2020 06:01:28 +0000 (06:01 +0000)
This commit duplicates the tap states responsible for tap-and drag (TAPPED
and all DRAGGING* states) to cover two-finger and three-finger taps;
the code for the new states is shared with the existing machinery for
one-finger tap-and-drag.

Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org>
src/evdev-mt-touchpad-tap.c
src/evdev-mt-touchpad.h
src/libinput.h
test/test-touchpad-tap.c

index 8ee0089c00f2304c7434cdbd59fe01b34a600b89..ad5b610f5eb150d8e9b5f1069333b0f0e0cc6f13 100644 (file)
@@ -60,7 +60,9 @@ tap_state_to_str(enum tp_tap_state state)
        CASE_RETURN_STRING(TAP_STATE_IDLE);
        CASE_RETURN_STRING(TAP_STATE_HOLD);
        CASE_RETURN_STRING(TAP_STATE_TOUCH);
-       CASE_RETURN_STRING(TAP_STATE_TAPPED);
+       CASE_RETURN_STRING(TAP_STATE_1FGTAP_TAPPED);
+       CASE_RETURN_STRING(TAP_STATE_2FGTAP_TAPPED);
+       CASE_RETURN_STRING(TAP_STATE_3FGTAP_TAPPED);
        CASE_RETURN_STRING(TAP_STATE_TOUCH_2);
        CASE_RETURN_STRING(TAP_STATE_TOUCH_2_HOLD);
        CASE_RETURN_STRING(TAP_STATE_TOUCH_2_RELEASE);
@@ -68,11 +70,21 @@ tap_state_to_str(enum tp_tap_state state)
        CASE_RETURN_STRING(TAP_STATE_TOUCH_3_HOLD);
        CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE);
        CASE_RETURN_STRING(TAP_STATE_TOUCH_3_RELEASE_2);
-       CASE_RETURN_STRING(TAP_STATE_DRAGGING);
-       CASE_RETURN_STRING(TAP_STATE_DRAGGING_WAIT);
-       CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_DOUBLETAP);
-       CASE_RETURN_STRING(TAP_STATE_DRAGGING_OR_TAP);
-       CASE_RETURN_STRING(TAP_STATE_DRAGGING_2);
+       CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING);
+       CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING);
+       CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING);
+       CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_WAIT);
+       CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_WAIT);
+       CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_WAIT);
+       CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP);
+       CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP);
+       CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP);
+       CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_OR_TAP);
+       CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_OR_TAP);
+       CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_OR_TAP);
+       CASE_RETURN_STRING(TAP_STATE_1FGTAP_DRAGGING_2);
+       CASE_RETURN_STRING(TAP_STATE_2FGTAP_DRAGGING_2);
+       CASE_RETURN_STRING(TAP_STATE_3FGTAP_DRAGGING_2);
        CASE_RETURN_STRING(TAP_STATE_DEAD);
        }
        return NULL;
@@ -119,7 +131,7 @@ tp_tap_notify(struct tp_dispatch *tp,
 
        assert(tp->tap.map < ARRAY_LENGTH(button_map));
 
-       if (nfingers > 3)
+       if (nfingers < 1 || nfingers > 3)
                return;
 
        button = button_map[tp->tap.map][nfingers - 1];
@@ -211,7 +223,7 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp,
                              1,
                              LIBINPUT_BUTTON_STATE_PRESSED);
                if (tp->tap.drag_enabled) {
-                       tp->tap.state = TAP_STATE_TAPPED;
+                       tp->tap.state = TAP_STATE_1FGTAP_TAPPED;
                        tp->tap.saved_release_time = time;
                        tp_tap_set_timer(tp, time);
                } else {
@@ -288,30 +300,38 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp,
 static void
 tp_tap_tapped_handle_event(struct tp_dispatch *tp,
                           struct tp_touch *t,
-                          enum tap_event event, uint64_t time)
+                          enum tap_event event, uint64_t time,
+                          int nfingers_tapped)
 {
        switch (event) {
        case TAP_EVENT_MOTION:
        case TAP_EVENT_RELEASE:
                log_tap_bug(tp, t, event);
                break;
-       case TAP_EVENT_TOUCH:
-               tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP;
+       case TAP_EVENT_TOUCH: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
+                       TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
+                       TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                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,
                              tp->tap.saved_release_time,
-                             1,
+                             nfingers_tapped,
                              LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_BUTTON:
                tp->tap.state = TAP_STATE_DEAD;
                tp_tap_notify(tp,
                              tp->tap.saved_release_time,
-                             1,
+                             nfingers_tapped,
                              LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_THUMB:
@@ -353,7 +373,6 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp,
                break;
        case TAP_EVENT_PALM:
                tp->tap.state = TAP_STATE_TOUCH;
-               tp_tap_set_timer(tp, time); /* overwrite timer */
                break;
        case TAP_EVENT_PALM_UP:
                break;
@@ -411,11 +430,16 @@ tp_tap_touch2_release_handle_event(struct tp_dispatch *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;
+               if (tp->tap.drag_enabled) {
+                       tp->tap.state = TAP_STATE_2FGTAP_TAPPED;
+                       tp_tap_set_timer(tp, time);
+               } else {
+                       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:
                tp_tap_move_to_dead(tp, t);
@@ -440,8 +464,7 @@ tp_tap_touch2_release_handle_event(struct tp_dispatch *tp,
                              1,
                              LIBINPUT_BUTTON_STATE_PRESSED);
                if (tp->tap.drag_enabled) {
-                       tp->tap.state = TAP_STATE_TAPPED;
-                       tp_tap_set_timer(tp, time);
+                       tp->tap.state = TAP_STATE_1FGTAP_TAPPED;
                } else {
                        tp_tap_notify(tp,
                                      tp->tap.saved_release_time,
@@ -570,6 +593,14 @@ tp_tap_touch3_release_handle_event(struct tp_dispatch *tp,
                tp->tap.state = TAP_STATE_TOUCH_2_HOLD;
                break;
        case TAP_EVENT_BUTTON:
+               tp_tap_notify(tp,
+                             tp->tap.saved_press_time,
+                             3,
+                             LIBINPUT_BUTTON_STATE_PRESSED);
+               tp_tap_notify(tp,
+                             tp->tap.saved_release_time,
+                             3,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                tp->tap.state = TAP_STATE_DEAD;
                break;
        case TAP_EVENT_THUMB:
@@ -607,11 +638,16 @@ tp_tap_touch3_release2_handle_event(struct tp_dispatch *tp,
                              tp->tap.saved_press_time,
                              3,
                              LIBINPUT_BUTTON_STATE_PRESSED);
-               tp_tap_notify(tp,
-                             tp->tap.saved_release_time,
-                             3,
-                             LIBINPUT_BUTTON_STATE_RELEASED);
-               tp->tap.state = TAP_STATE_IDLE;
+               if (tp->tap.drag_enabled) {
+                       tp->tap.state = TAP_STATE_3FGTAP_TAPPED;
+                       tp_tap_set_timer(tp, time);
+               } else {
+                       tp_tap_notify(tp,
+                                     tp->tap.saved_release_time,
+                                     3,
+                                     LIBINPUT_BUTTON_STATE_RELEASED);
+                       tp->tap.state = TAP_STATE_IDLE;
+               }
                break;
        case TAP_EVENT_MOTION:
                tp_tap_notify(tp,
@@ -636,6 +672,14 @@ tp_tap_touch3_release2_handle_event(struct tp_dispatch *tp,
                tp->tap.state = TAP_STATE_HOLD;
                break;
        case TAP_EVENT_BUTTON:
+               tp_tap_notify(tp,
+                             tp->tap.saved_press_time,
+                             3,
+                             LIBINPUT_BUTTON_STATE_PRESSED);
+               tp_tap_notify(tp,
+                             tp->tap.saved_release_time,
+                             3,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                tp->tap.state = TAP_STATE_DEAD;
                break;
        case TAP_EVENT_THUMB:
@@ -645,11 +689,15 @@ tp_tap_touch3_release2_handle_event(struct tp_dispatch *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;
+               if (tp->tap.drag_enabled) {
+                       tp->tap.state = TAP_STATE_2FGTAP_TAPPED;
+               } else {
+                       tp_tap_notify(tp,
+                                     tp->tap.saved_release_time,
+                                     2,
+                                     LIBINPUT_BUTTON_STATE_RELEASED);
+                       tp->tap.state = TAP_STATE_IDLE;
+               }
                break;
        case TAP_EVENT_PALM_UP:
                break;
@@ -659,17 +707,25 @@ tp_tap_touch3_release2_handle_event(struct tp_dispatch *tp,
 static void
 tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
                                          struct tp_touch *t,
-                                         enum tap_event event, uint64_t time)
+                                         enum tap_event event, uint64_t time,
+                                         int nfingers_tapped)
 {
        switch (event) {
-       case TAP_EVENT_TOUCH:
-               tp->tap.state = TAP_STATE_DRAGGING_2;
+       case TAP_EVENT_TOUCH: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING_2,
+                       TAP_STATE_2FGTAP_DRAGGING_2,
+                       TAP_STATE_3FGTAP_DRAGGING_2,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                break;
+       }
        case TAP_EVENT_RELEASE:
-               tp->tap.state = TAP_STATE_TAPPED;
+               tp->tap.state = TAP_STATE_1FGTAP_TAPPED;
                tp_tap_notify(tp,
                              tp->tap.saved_release_time,
-                             1,
+                             nfingers_tapped,
                              LIBINPUT_BUTTON_STATE_RELEASED);
                tp_tap_notify(tp,
                              tp->tap.saved_press_time,
@@ -679,21 +735,35 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
                tp_tap_set_timer(tp, time);
                break;
        case TAP_EVENT_MOTION:
-       case TAP_EVENT_TIMEOUT:
-               tp->tap.state = TAP_STATE_DRAGGING;
+       case TAP_EVENT_TIMEOUT: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING,
+                       TAP_STATE_2FGTAP_DRAGGING,
+                       TAP_STATE_3FGTAP_DRAGGING,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                break;
+       }
        case TAP_EVENT_BUTTON:
                tp->tap.state = TAP_STATE_DEAD;
                tp_tap_notify(tp,
                              tp->tap.saved_release_time,
-                             1,
+                             nfingers_tapped,
                              LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_THUMB:
                break;
-       case TAP_EVENT_PALM:
-               tp->tap.state = TAP_STATE_TAPPED;
+       case TAP_EVENT_PALM: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_TAPPED,
+                       TAP_STATE_2FGTAP_TAPPED,
+                       TAP_STATE_3FGTAP_TAPPED,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                break;
+       }
        case TAP_EVENT_PALM_UP:
                break;
        }
@@ -702,21 +772,35 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp,
 static void
 tp_tap_dragging_handle_event(struct tp_dispatch *tp,
                             struct tp_touch *t,
-                            enum tap_event event, uint64_t time)
+                            enum tap_event event, uint64_t time,
+                            int nfingers_tapped)
 {
 
        switch (event) {
-       case TAP_EVENT_TOUCH:
-               tp->tap.state = TAP_STATE_DRAGGING_2;
+       case TAP_EVENT_TOUCH: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING_2,
+                       TAP_STATE_2FGTAP_DRAGGING_2,
+                       TAP_STATE_3FGTAP_DRAGGING_2,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                break;
+       }
        case TAP_EVENT_RELEASE:
                if (tp->tap.drag_lock_enabled) {
-                       tp->tap.state = TAP_STATE_DRAGGING_WAIT;
+                       enum tp_tap_state dest[3] = {
+                               TAP_STATE_1FGTAP_DRAGGING_WAIT,
+                               TAP_STATE_2FGTAP_DRAGGING_WAIT,
+                               TAP_STATE_3FGTAP_DRAGGING_WAIT,
+                       };
+                       assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+                       tp->tap.state = dest[nfingers_tapped - 1];
                        tp_tap_set_drag_timer(tp, time);
                } else {
                        tp_tap_notify(tp,
                                      time,
-                                     1,
+                                     nfingers_tapped,
                                      LIBINPUT_BUTTON_STATE_RELEASED);
                        tp->tap.state = TAP_STATE_IDLE;
                }
@@ -727,14 +811,17 @@ tp_tap_dragging_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,
+                             time,
+                             nfingers_tapped,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_THUMB:
                break;
        case TAP_EVENT_PALM:
                tp_tap_notify(tp,
                              tp->tap.saved_release_time,
-                             1,
+                             nfingers_tapped,
                              LIBINPUT_BUTTON_STATE_RELEASED);
                tp->tap.state = TAP_STATE_IDLE;
                break;
@@ -746,24 +833,38 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp,
 static void
 tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
                                  struct tp_touch *t,
-                                 enum tap_event event, uint64_t time)
+                                 enum tap_event event, uint64_t time,
+                                 int nfingers_tapped)
 {
 
        switch (event) {
-       case TAP_EVENT_TOUCH:
-               tp->tap.state = TAP_STATE_DRAGGING_OR_TAP;
+       case TAP_EVENT_TOUCH: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING_OR_TAP,
+                       TAP_STATE_2FGTAP_DRAGGING_OR_TAP,
+                       TAP_STATE_3FGTAP_DRAGGING_OR_TAP,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                tp_tap_set_timer(tp, time);
                break;
+       }
        case TAP_EVENT_RELEASE:
        case TAP_EVENT_MOTION:
                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,
+                             time,
+                             nfingers_tapped,
+                             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,
+                             time,
+                             nfingers_tapped,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_THUMB:
        case TAP_EVENT_PALM:
@@ -776,35 +877,56 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp,
 static void
 tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp,
                                  struct tp_touch *t,
-                                 enum tap_event event, uint64_t time)
+                                 enum tap_event event, uint64_t time,
+                                 int nfingers_tapped)
 {
 
        switch (event) {
-       case TAP_EVENT_TOUCH:
-               tp->tap.state = TAP_STATE_DRAGGING_2;
-               tp_tap_clear_timer(tp);
+       case TAP_EVENT_TOUCH: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING_2,
+                       TAP_STATE_2FGTAP_DRAGGING_2,
+                       TAP_STATE_3FGTAP_DRAGGING_2,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                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,
+                             nfingers_tapped,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_MOTION:
-       case TAP_EVENT_TIMEOUT:
-               tp->tap.state = TAP_STATE_DRAGGING;
+       case TAP_EVENT_TIMEOUT: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING,
+                       TAP_STATE_2FGTAP_DRAGGING,
+                       TAP_STATE_3FGTAP_DRAGGING,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                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,
+                             time,
+                             nfingers_tapped,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_THUMB:
                break;
        case TAP_EVENT_PALM:
                tp_tap_notify(tp,
                              tp->tap.saved_release_time,
-                             1,
+                             nfingers_tapped,
                              LIBINPUT_BUTTON_STATE_RELEASED);
                tp->tap.state = TAP_STATE_IDLE;
                break;
+       }
        case TAP_EVENT_PALM_UP:
                break;
        }
@@ -813,16 +935,27 @@ tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp,
 static void
 tp_tap_dragging2_handle_event(struct tp_dispatch *tp,
                              struct tp_touch *t,
-                             enum tap_event event, uint64_t time)
+                             enum tap_event event, uint64_t time,
+                             int nfingers_tapped)
 {
 
        switch (event) {
-       case TAP_EVENT_RELEASE:
-               tp->tap.state = TAP_STATE_DRAGGING;
+       case TAP_EVENT_RELEASE: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING,
+                       TAP_STATE_2FGTAP_DRAGGING,
+                       TAP_STATE_3FGTAP_DRAGGING,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                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,
+                             time,
+                             nfingers_tapped,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_MOTION:
        case TAP_EVENT_TIMEOUT:
@@ -830,13 +963,23 @@ tp_tap_dragging2_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,
+                             time,
+                             nfingers_tapped,
+                             LIBINPUT_BUTTON_STATE_RELEASED);
                break;
        case TAP_EVENT_THUMB:
                break;
-       case TAP_EVENT_PALM:
-               tp->tap.state = TAP_STATE_DRAGGING_OR_DOUBLETAP;
+       case TAP_EVENT_PALM: {
+               enum tp_tap_state dest[3] = {
+                       TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
+                       TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
+                       TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
+               };
+               assert(nfingers_tapped >= 1 && nfingers_tapped <= 3);
+               tp->tap.state = dest[nfingers_tapped - 1];
                break;
+       }
        case TAP_EVENT_PALM_UP:
                break;
        }
@@ -889,8 +1032,14 @@ tp_tap_handle_event(struct tp_dispatch *tp,
        case TAP_STATE_HOLD:
                tp_tap_hold_handle_event(tp, t, event, time);
                break;
-       case TAP_STATE_TAPPED:
-               tp_tap_tapped_handle_event(tp, t, event, time);
+       case TAP_STATE_1FGTAP_TAPPED:
+               tp_tap_tapped_handle_event(tp, t, event, time, 1);
+               break;
+       case TAP_STATE_2FGTAP_TAPPED:
+               tp_tap_tapped_handle_event(tp, t, event, time, 2);
+               break;
+       case TAP_STATE_3FGTAP_TAPPED:
+               tp_tap_tapped_handle_event(tp, t, event, time, 3);
                break;
        case TAP_STATE_TOUCH_2:
                tp_tap_touch2_handle_event(tp, t, event, time);
@@ -913,20 +1062,53 @@ tp_tap_handle_event(struct tp_dispatch *tp,
        case TAP_STATE_TOUCH_3_RELEASE_2:
                tp_tap_touch3_release2_handle_event(tp, t, event, time);
                break;
-       case TAP_STATE_DRAGGING_OR_DOUBLETAP:
-               tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time);
+       case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP:
+               tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time,
+                                                         1);
+               break;
+       case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP:
+               tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time,
+                                                         2);
+               break;
+       case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP:
+               tp_tap_dragging_or_doubletap_handle_event(tp, t, event, time,
+                                                         3);
+               break;
+       case TAP_STATE_1FGTAP_DRAGGING:
+               tp_tap_dragging_handle_event(tp, t, event, time, 1);
+               break;
+       case TAP_STATE_2FGTAP_DRAGGING:
+               tp_tap_dragging_handle_event(tp, t, event, time, 2);
+               break;
+       case TAP_STATE_3FGTAP_DRAGGING:
+               tp_tap_dragging_handle_event(tp, t, event, time, 3);
+               break;
+       case TAP_STATE_1FGTAP_DRAGGING_WAIT:
+               tp_tap_dragging_wait_handle_event(tp, t, event, time, 1);
+               break;
+       case TAP_STATE_2FGTAP_DRAGGING_WAIT:
+               tp_tap_dragging_wait_handle_event(tp, t, event, time, 2);
+               break;
+       case TAP_STATE_3FGTAP_DRAGGING_WAIT:
+               tp_tap_dragging_wait_handle_event(tp, t, event, time, 3);
+               break;
+       case TAP_STATE_1FGTAP_DRAGGING_OR_TAP:
+               tp_tap_dragging_tap_handle_event(tp, t, event, time, 1);
+               break;
+       case TAP_STATE_2FGTAP_DRAGGING_OR_TAP:
+               tp_tap_dragging_tap_handle_event(tp, t, event, time, 2);
                break;
-       case TAP_STATE_DRAGGING:
-               tp_tap_dragging_handle_event(tp, t, event, time);
+       case TAP_STATE_3FGTAP_DRAGGING_OR_TAP:
+               tp_tap_dragging_tap_handle_event(tp, t, event, time, 3);
                break;
-       case TAP_STATE_DRAGGING_WAIT:
-               tp_tap_dragging_wait_handle_event(tp, t, event, time);
+       case TAP_STATE_1FGTAP_DRAGGING_2:
+               tp_tap_dragging2_handle_event(tp, t, event, time, 1);
                break;
-       case TAP_STATE_DRAGGING_OR_TAP:
-               tp_tap_dragging_tap_handle_event(tp, t, event, time);
+       case TAP_STATE_2FGTAP_DRAGGING_2:
+               tp_tap_dragging2_handle_event(tp, t, event, time, 2);
                break;
-       case TAP_STATE_DRAGGING_2:
-               tp_tap_dragging2_handle_event(tp, t, event, time);
+       case TAP_STATE_3FGTAP_DRAGGING_2:
+               tp_tap_dragging2_handle_event(tp, t, event, time, 3);
                break;
        case TAP_STATE_DEAD:
                tp_tap_dead_handle_event(tp, t, event, time);
@@ -1090,9 +1272,15 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
         */
        switch (tp->tap.state) {
        case TAP_STATE_TOUCH:
-       case TAP_STATE_TAPPED:
-       case TAP_STATE_DRAGGING_OR_DOUBLETAP:
-       case TAP_STATE_DRAGGING_OR_TAP:
+       case TAP_STATE_1FGTAP_TAPPED:
+       case TAP_STATE_2FGTAP_TAPPED:
+       case TAP_STATE_3FGTAP_TAPPED:
+       case TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP:
+       case TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP:
+       case TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP:
+       case TAP_STATE_1FGTAP_DRAGGING_OR_TAP:
+       case TAP_STATE_2FGTAP_DRAGGING_OR_TAP:
+       case TAP_STATE_3FGTAP_DRAGGING_OR_TAP:
        case TAP_STATE_TOUCH_2:
        case TAP_STATE_TOUCH_3:
                filter_motion = 1;
@@ -1421,10 +1609,18 @@ bool
 tp_tap_dragging(const struct tp_dispatch *tp)
 {
        switch (tp->tap.state) {
-       case TAP_STATE_DRAGGING:
-       case TAP_STATE_DRAGGING_2:
-       case TAP_STATE_DRAGGING_WAIT:
-       case TAP_STATE_DRAGGING_OR_TAP:
+       case TAP_STATE_1FGTAP_DRAGGING:
+       case TAP_STATE_2FGTAP_DRAGGING:
+       case TAP_STATE_3FGTAP_DRAGGING:
+       case TAP_STATE_1FGTAP_DRAGGING_2:
+       case TAP_STATE_2FGTAP_DRAGGING_2:
+       case TAP_STATE_3FGTAP_DRAGGING_2:
+       case TAP_STATE_1FGTAP_DRAGGING_WAIT:
+       case TAP_STATE_2FGTAP_DRAGGING_WAIT:
+       case TAP_STATE_3FGTAP_DRAGGING_WAIT:
+       case TAP_STATE_1FGTAP_DRAGGING_OR_TAP:
+       case TAP_STATE_2FGTAP_DRAGGING_OR_TAP:
+       case TAP_STATE_3FGTAP_DRAGGING_OR_TAP:
                return true;
        default:
                return false;
index db642966700ed58956a6b2b5e6555aa5cc221349..6e1e1e3af29db76c5babc36db70a56b87ff39443 100644 (file)
@@ -106,7 +106,9 @@ enum tp_tap_state {
        TAP_STATE_IDLE = 4,
        TAP_STATE_TOUCH,
        TAP_STATE_HOLD,
-       TAP_STATE_TAPPED,
+       TAP_STATE_1FGTAP_TAPPED,
+       TAP_STATE_2FGTAP_TAPPED,
+       TAP_STATE_3FGTAP_TAPPED,
        TAP_STATE_TOUCH_2,
        TAP_STATE_TOUCH_2_HOLD,
        TAP_STATE_TOUCH_2_RELEASE,
@@ -114,11 +116,21 @@ enum tp_tap_state {
        TAP_STATE_TOUCH_3_HOLD,
        TAP_STATE_TOUCH_3_RELEASE,
        TAP_STATE_TOUCH_3_RELEASE_2,
-       TAP_STATE_DRAGGING_OR_DOUBLETAP,
-       TAP_STATE_DRAGGING_OR_TAP,
-       TAP_STATE_DRAGGING,
-       TAP_STATE_DRAGGING_WAIT,
-       TAP_STATE_DRAGGING_2,
+       TAP_STATE_1FGTAP_DRAGGING_OR_DOUBLETAP,
+       TAP_STATE_2FGTAP_DRAGGING_OR_DOUBLETAP,
+       TAP_STATE_3FGTAP_DRAGGING_OR_DOUBLETAP,
+       TAP_STATE_1FGTAP_DRAGGING_OR_TAP,
+       TAP_STATE_2FGTAP_DRAGGING_OR_TAP,
+       TAP_STATE_3FGTAP_DRAGGING_OR_TAP,
+       TAP_STATE_1FGTAP_DRAGGING,
+       TAP_STATE_2FGTAP_DRAGGING,
+       TAP_STATE_3FGTAP_DRAGGING,
+       TAP_STATE_1FGTAP_DRAGGING_WAIT,
+       TAP_STATE_2FGTAP_DRAGGING_WAIT,
+       TAP_STATE_3FGTAP_DRAGGING_WAIT,
+       TAP_STATE_1FGTAP_DRAGGING_2,
+       TAP_STATE_2FGTAP_DRAGGING_2,
+       TAP_STATE_3FGTAP_DRAGGING_2,
        TAP_STATE_DEAD, /**< finger count exceeded */
 };
 
index 8ad644ee55d3d4eaf95b4ce4a8c6488b9fed1632..a15d62720581a5e0fea51bd94e9fa36547257b5c 100644 (file)
@@ -4560,10 +4560,9 @@ enum libinput_config_drag_state {
  * @ingroup config
  *
  * Enable or disable tap-and-drag on this device. When enabled, a
- * single-finger tap immediately followed by a finger down results in a
- * button down event, subsequent finger motion thus triggers a drag. The
- * button is released on finger up. See the libinput documentation for more
- * details.
+ * tap immediately followed by a finger down results in a button down event,
+ * subsequent finger motion thus triggers a drag. The button is released
+ * on finger up. See the libinput documentation for more details.
  *
  * @param device The device to configure
  * @param enable @ref LIBINPUT_CONFIG_DRAG_ENABLED to enable, @ref
index 74e03ccb634f9354947f68c300c06826892a031d..0b6aa3ead28eb54840db7158a0a9c6d9d2f528d0 100644 (file)
@@ -1048,6 +1048,8 @@ START_TEST(touchpad_2fg_tap)
        litest_touch_up(dev, 0);
        litest_touch_up(dev, 1);
 
+       libinput_dispatch(li);
+       litest_timeout_tap();
        libinput_dispatch(li);
 
        ev = libinput_get_event(li);
@@ -1100,6 +1102,8 @@ START_TEST(touchpad_2fg_tap_inverted)
        litest_touch_up(dev, 1);
        litest_touch_up(dev, 0);
 
+       libinput_dispatch(li);
+       litest_timeout_tap();
        libinput_dispatch(li);
 
        ev = libinput_get_event(li);
@@ -1557,6 +1561,8 @@ START_TEST(touchpad_3fg_tap)
                litest_touch_up(dev, (i + 1) % 3);
                litest_touch_up(dev, (i + 0) % 3);
 
+               libinput_dispatch(li);
+               litest_timeout_tap();
                libinput_dispatch(li);
 
                ev = libinput_get_event(li);
@@ -1609,6 +1615,8 @@ START_TEST(touchpad_3fg_tap_tap_again)
        litest_touch_up(dev, 1);
        litest_touch_up(dev, 2);
 
+       libinput_dispatch(li);
+       litest_timeout_tap();
        libinput_dispatch(li);
 
        for (i = 0; i < 2; i++) {