gestures: get rid of tp_gestures_start
authorPeter Hutterer <peter.hutterer@who-t.net>
Fri, 13 Sep 2024 02:34:41 +0000 (12:34 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Fri, 4 Oct 2024 05:13:23 +0000 (15:13 +1000)
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1049>

src/evdev-mt-touchpad-gestures.c
src/evdev-mt-touchpad.h

index 161b1210a2825d8fb833695e979cb333a46e0802..ff2348e24c3d0164395c53ce2ae4fdb05b059a60 100644 (file)
@@ -69,8 +69,11 @@ gesture_state_to_str(enum tp_gesture_state state)
        CASE_RETURN_STRING(GESTURE_STATE_HOLD);
        CASE_RETURN_STRING(GESTURE_STATE_HOLD_AND_MOTION);
        CASE_RETURN_STRING(GESTURE_STATE_POINTER_MOTION);
+       CASE_RETURN_STRING(GESTURE_STATE_SCROLL_START);
        CASE_RETURN_STRING(GESTURE_STATE_SCROLL);
+       CASE_RETURN_STRING(GESTURE_STATE_PINCH_START);
        CASE_RETURN_STRING(GESTURE_STATE_PINCH);
+       CASE_RETURN_STRING(GESTURE_STATE_SWIPE_START);
        CASE_RETURN_STRING(GESTURE_STATE_SWIPE);
        }
        return NULL;
@@ -153,47 +156,6 @@ tp_get_average_touches_delta(struct tp_dispatch *tp)
        return tp_get_touches_delta(tp, true);
 }
 
-static void
-tp_gesture_start(struct tp_dispatch *tp, uint64_t time)
-{
-       const struct normalized_coords zero = { 0.0, 0.0 };
-
-       if (tp->gesture.started)
-               return;
-
-       switch (tp->gesture.state) {
-       case GESTURE_STATE_NONE:
-       case GESTURE_STATE_UNKNOWN:
-               evdev_log_bug_libinput(tp->device,
-                                      "%s in unknown gesture state %s\n",
-                                      __func__,
-                                      gesture_state_to_str(tp->gesture.state));
-               break;
-       case GESTURE_STATE_HOLD:
-       case GESTURE_STATE_HOLD_AND_MOTION:
-               break;
-       case GESTURE_STATE_SCROLL:
-               tp_gesture_init_scroll(tp);
-               break;
-       case GESTURE_STATE_PINCH:
-               gesture_notify_pinch(&tp->device->base, time,
-                                   LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
-                                   tp->gesture.finger_count,
-                                   &zero, &zero, 1.0, 0.0);
-               break;
-       case GESTURE_STATE_SWIPE:
-               gesture_notify_swipe(&tp->device->base, time,
-                                    LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
-                                    tp->gesture.finger_count,
-                                    &zero, &zero);
-               break;
-       case GESTURE_STATE_POINTER_MOTION:
-               break;
-       }
-
-       tp->gesture.started = true;
-}
-
 static struct device_float_coords
 tp_get_raw_pointer_motion(struct tp_dispatch *tp)
 {
@@ -580,7 +542,7 @@ tp_gesture_handle_event_on_state_none(struct tp_dispatch *tp,
                tp->gesture.state = GESTURE_STATE_POINTER_MOTION;
                break;
        case GESTURE_EVENT_SCROLL_START:
-               tp->gesture.state = GESTURE_STATE_SCROLL;
+               tp->gesture.state = GESTURE_STATE_SCROLL_START;
                break;
        case GESTURE_EVENT_FINGER_SWITCH_TIMEOUT:
        case GESTURE_EVENT_HOLD_AND_MOTION_START:
@@ -609,7 +571,6 @@ tp_gesture_handle_event_on_state_unknown(struct tp_dispatch *tp,
                tp->gesture.state = GESTURE_STATE_HOLD;
                gesture_notify_hold_begin(&tp->device->base, time,
                                          tp->gesture.finger_count);
-               tp_gesture_start(tp, time);
                break;
        case GESTURE_EVENT_POINTER_MOTION_START:
                /* Don't cancel the hold timer. This pointer motion can end up
@@ -619,16 +580,16 @@ tp_gesture_handle_event_on_state_unknown(struct tp_dispatch *tp,
        case GESTURE_EVENT_SCROLL_START:
                libinput_timer_cancel(&tp->gesture.hold_timer);
                tp_gesture_set_scroll_buildup(tp);
-               tp->gesture.state = GESTURE_STATE_SCROLL;
+               tp->gesture.state = GESTURE_STATE_SCROLL_START;
                break;
        case GESTURE_EVENT_SWIPE_START:
                libinput_timer_cancel(&tp->gesture.hold_timer);
-               tp->gesture.state = GESTURE_STATE_SWIPE;
+               tp->gesture.state = GESTURE_STATE_SWIPE_START;
                break;
        case GESTURE_EVENT_PINCH_START:
                libinput_timer_cancel(&tp->gesture.hold_timer);
                tp_gesture_init_pinch(tp);
-               tp->gesture.state = GESTURE_STATE_PINCH;
+               tp->gesture.state = GESTURE_STATE_PINCH_START;
                break;
        case GESTURE_EVENT_HOLD_AND_MOTION_START:
        case GESTURE_EVENT_FINGER_DETECTED:
@@ -668,16 +629,16 @@ tp_gesture_handle_event_on_state_hold(struct tp_dispatch *tp,
        case GESTURE_EVENT_SCROLL_START:
                tp_gesture_set_scroll_buildup(tp);
                tp_gesture_cancel(tp, time);
-               tp->gesture.state = GESTURE_STATE_SCROLL;
+               tp->gesture.state = GESTURE_STATE_SCROLL_START;
                break;
        case GESTURE_EVENT_SWIPE_START:
                tp_gesture_cancel(tp, time);
-               tp->gesture.state = GESTURE_STATE_SWIPE;
+               tp->gesture.state = GESTURE_STATE_SWIPE_START;
                break;
        case GESTURE_EVENT_PINCH_START:
                tp_gesture_cancel(tp, time);
                tp_gesture_init_pinch(tp);
-               tp->gesture.state = GESTURE_STATE_PINCH;
+               tp->gesture.state = GESTURE_STATE_PINCH_START;
                break;
        case GESTURE_EVENT_HOLD_TIMEOUT:
        case GESTURE_EVENT_FINGER_DETECTED:
@@ -750,7 +711,6 @@ tp_gesture_handle_event_on_state_pointer_motion(struct tp_dispatch *tp,
                        tp->gesture.state = GESTURE_STATE_HOLD_AND_MOTION;
                        gesture_notify_hold_begin(&tp->device->base, time,
                                                  tp->gesture.finger_count);
-                       tp_gesture_start(tp, time);
                }
                break;
        case GESTURE_EVENT_FINGER_SWITCH_TIMEOUT:
@@ -765,6 +725,36 @@ tp_gesture_handle_event_on_state_pointer_motion(struct tp_dispatch *tp,
        }
 }
 
+static void
+tp_gesture_handle_event_on_state_scroll_start(struct tp_dispatch *tp,
+                                             enum gesture_event event,
+                                             uint64_t time)
+{
+       switch(event) {
+       case GESTURE_EVENT_RESET:
+       case GESTURE_EVENT_END:
+       case GESTURE_EVENT_CANCEL:
+               libinput_timer_cancel(&tp->gesture.hold_timer);
+               tp->gesture.state = GESTURE_STATE_NONE;
+               break;
+       case GESTURE_EVENT_FINGER_SWITCH_TIMEOUT:
+               break;
+       case GESTURE_EVENT_PINCH_START:
+               tp_gesture_init_pinch(tp);
+               tp_gesture_cancel(tp, time);
+               tp->gesture.state = GESTURE_STATE_PINCH;
+               break;
+       case GESTURE_EVENT_HOLD_AND_MOTION_START:
+       case GESTURE_EVENT_FINGER_DETECTED:
+       case GESTURE_EVENT_HOLD_TIMEOUT:
+       case GESTURE_EVENT_POINTER_MOTION_START:
+       case GESTURE_EVENT_SCROLL_START:
+       case GESTURE_EVENT_SWIPE_START:
+               log_gesture_bug(tp, event);
+               break;
+       }
+}
+
 static void
 tp_gesture_handle_event_on_state_scroll(struct tp_dispatch *tp,
                                        enum gesture_event event,
@@ -797,6 +787,31 @@ tp_gesture_handle_event_on_state_scroll(struct tp_dispatch *tp,
        }
 }
 
+static void
+tp_gesture_handle_event_on_state_pinch_start(struct tp_dispatch *tp,
+                                            enum gesture_event event,
+                                            uint64_t time)
+{
+       switch(event) {
+       case GESTURE_EVENT_RESET:
+       case GESTURE_EVENT_END:
+       case GESTURE_EVENT_CANCEL:
+               libinput_timer_cancel(&tp->gesture.hold_timer);
+               break;
+       case GESTURE_EVENT_FINGER_SWITCH_TIMEOUT:
+               break;
+       case GESTURE_EVENT_HOLD_AND_MOTION_START:
+       case GESTURE_EVENT_FINGER_DETECTED:
+       case GESTURE_EVENT_HOLD_TIMEOUT:
+       case GESTURE_EVENT_POINTER_MOTION_START:
+       case GESTURE_EVENT_SCROLL_START:
+       case GESTURE_EVENT_SWIPE_START:
+       case GESTURE_EVENT_PINCH_START:
+               log_gesture_bug(tp, event);
+               break;
+       }
+}
+
 static void
 tp_gesture_handle_event_on_state_pinch(struct tp_dispatch *tp,
                                       enum gesture_event event,
@@ -832,6 +847,32 @@ tp_gesture_handle_event_on_state_pinch(struct tp_dispatch *tp,
        }
 }
 
+static void
+tp_gesture_handle_event_on_state_swipe_start(struct tp_dispatch *tp,
+                                            enum gesture_event event,
+                                            uint64_t time)
+{
+       switch(event) {
+       case GESTURE_EVENT_RESET:
+       case GESTURE_EVENT_END:
+       case GESTURE_EVENT_CANCEL:
+               libinput_timer_cancel(&tp->gesture.hold_timer);
+               tp->gesture.state = GESTURE_STATE_NONE;
+               break;
+       case GESTURE_EVENT_FINGER_SWITCH_TIMEOUT:
+               break;
+       case GESTURE_EVENT_HOLD_AND_MOTION_START:
+       case GESTURE_EVENT_FINGER_DETECTED:
+       case GESTURE_EVENT_HOLD_TIMEOUT:
+       case GESTURE_EVENT_POINTER_MOTION_START:
+       case GESTURE_EVENT_SCROLL_START:
+       case GESTURE_EVENT_SWIPE_START:
+       case GESTURE_EVENT_PINCH_START:
+               log_gesture_bug(tp, event);
+               break;
+       }
+}
+
 static void
 tp_gesture_handle_event_on_state_swipe(struct tp_dispatch *tp,
                                       enum gesture_event event,
@@ -892,12 +933,21 @@ tp_gesture_handle_event(struct tp_dispatch *tp,
        case GESTURE_STATE_POINTER_MOTION:
                tp_gesture_handle_event_on_state_pointer_motion(tp, event, time);
                break;
+       case GESTURE_STATE_SCROLL_START:
+               tp_gesture_handle_event_on_state_scroll_start(tp, event, time);
+               break;
        case GESTURE_STATE_SCROLL:
                tp_gesture_handle_event_on_state_scroll(tp, event, time);
                break;
+       case GESTURE_STATE_PINCH_START:
+               tp_gesture_handle_event_on_state_pinch_start(tp, event, time);
+               break;
        case GESTURE_STATE_PINCH:
                tp_gesture_handle_event_on_state_pinch(tp, event, time);
                break;
+       case GESTURE_STATE_SWIPE_START:
+               tp_gesture_handle_event_on_state_swipe_start(tp, event, time);
+               break;
        case GESTURE_STATE_SWIPE:
                tp_gesture_handle_event_on_state_swipe(tp, event, time);
                break;
@@ -1206,8 +1256,6 @@ static void
 tp_gesture_handle_state_hold(struct tp_dispatch *tp, uint64_t time,
                             bool ignore_motion)
 {
-       tp_gesture_start(tp, time);
-
        if (!ignore_motion)
                tp_gesture_detect_motion_gestures(tp, time);
 }
@@ -1228,6 +1276,36 @@ tp_gesture_handle_state_pointer_motion(struct tp_dispatch *tp, uint64_t time)
                tp_gesture_post_pointer_motion(tp, time);
 }
 
+static void
+tp_gesture_handle_state_scroll_start(struct tp_dispatch *tp, uint64_t time)
+{
+       struct device_float_coords raw;
+       struct normalized_coords delta;
+
+       if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
+               return;
+
+       /* We may confuse a pinch for a scroll initially,
+        * allow ourselves to correct our guess.
+        */
+       if (time < (tp->gesture.initial_time + DEFAULT_GESTURE_PINCH_TIMEOUT) &&
+           tp_gesture_is_pinch(tp)) {
+               tp_gesture_handle_event(tp, GESTURE_EVENT_PINCH_START, time);
+               return;
+       }
+
+       raw = tp_get_average_touches_delta(tp);
+
+       /* scroll is not accelerated by default */
+       delta = tp_filter_scroll(tp, &raw, time);
+
+       if (normalized_is_zero(delta))
+               return;
+
+       tp_gesture_init_scroll(tp);
+       tp->gesture.state = GESTURE_STATE_SCROLL;
+}
+
 static void
 tp_gesture_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
 {
@@ -1254,7 +1332,6 @@ tp_gesture_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
        if (normalized_is_zero(delta))
                return;
 
-       tp_gesture_start(tp, time);
        tp_gesture_apply_scroll_constraints(tp, &raw, &delta, time);
        evdev_post_scroll(tp->device,
                          time,
@@ -1262,6 +1339,25 @@ tp_gesture_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
                          &delta);
 }
 
+static void
+tp_gesture_handle_state_swipe_start(struct tp_dispatch *tp, uint64_t time)
+{
+       struct device_float_coords raw;
+       struct normalized_coords delta;
+
+       raw = tp_get_average_touches_delta(tp);
+       delta = tp_filter_motion(tp, &raw, time);
+
+       if (!normalized_is_zero(delta) || !device_float_is_zero(raw)) {
+               const struct normalized_coords zero = { 0.0, 0.0 };
+               gesture_notify_swipe(&tp->device->base, time,
+                                    LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN,
+                                    tp->gesture.finger_count,
+                                    &zero, &zero);
+               tp->gesture.state = GESTURE_STATE_SWIPE;
+       }
+}
+
 static void
 tp_gesture_handle_state_swipe(struct tp_dispatch *tp, uint64_t time)
 {
@@ -1273,7 +1369,6 @@ tp_gesture_handle_state_swipe(struct tp_dispatch *tp, uint64_t time)
 
        if (!normalized_is_zero(delta) || !device_float_is_zero(raw)) {
                unaccel = tp_filter_motion_unaccelerated(tp, &raw, time);
-               tp_gesture_start(tp, time);
                gesture_notify_swipe(&tp->device->base, time,
                                     LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE,
                                     tp->gesture.finger_count,
@@ -1281,6 +1376,43 @@ tp_gesture_handle_state_swipe(struct tp_dispatch *tp, uint64_t time)
        }
 }
 
+static void
+tp_gesture_handle_state_pinch_start(struct tp_dispatch *tp, uint64_t time)
+{
+       const struct normalized_coords zero = { 0.0, 0.0 };
+       double angle, angle_delta, distance, scale;
+       struct device_float_coords center, fdelta;
+       struct normalized_coords delta;
+
+       tp_gesture_get_pinch_info(tp, &distance, &angle, &center);
+
+       scale = distance / tp->gesture.initial_distance;
+
+       angle_delta = angle - tp->gesture.angle;
+       tp->gesture.angle = angle;
+       if (angle_delta > 180.0)
+               angle_delta -= 360.0;
+       else if (angle_delta < -180.0)
+               angle_delta += 360.0;
+
+       fdelta = device_float_delta(center, tp->gesture.center);
+       tp->gesture.center = center;
+
+       delta = tp_filter_motion(tp, &fdelta, time);
+
+       if (normalized_is_zero(delta) && device_float_is_zero(fdelta) &&
+           scale == tp->gesture.prev_scale && angle_delta == 0.0)
+               return;
+
+        gesture_notify_pinch(&tp->device->base, time,
+                             LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
+                             tp->gesture.finger_count,
+                             &zero, &zero, 1.0, 0.0);
+
+       tp->gesture.prev_scale = scale;
+       tp->gesture.state = GESTURE_STATE_PINCH;
+}
+
 static void
 tp_gesture_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
 {
@@ -1309,7 +1441,6 @@ tp_gesture_handle_state_pinch(struct tp_dispatch *tp, uint64_t time)
                return;
 
        unaccel = tp_filter_motion_unaccelerated(tp, &fdelta, time);
-       tp_gesture_start(tp, time);
        gesture_notify_pinch(&tp->device->base, time,
                             LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
                             tp->gesture.finger_count,
@@ -1337,12 +1468,21 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time,
        if (tp->gesture.state == GESTURE_STATE_HOLD_AND_MOTION)
                tp_gesture_handle_state_hold_and_pointer_motion(tp, time);
 
+       if (tp->gesture.state == GESTURE_STATE_SCROLL_START)
+               tp_gesture_handle_state_scroll_start(tp, time);
+
        if (tp->gesture.state == GESTURE_STATE_SCROLL)
                tp_gesture_handle_state_scroll(tp, time);
 
+       if (tp->gesture.state == GESTURE_STATE_SWIPE_START)
+               tp_gesture_handle_state_swipe_start(tp, time);
+
        if (tp->gesture.state == GESTURE_STATE_SWIPE)
                tp_gesture_handle_state_swipe(tp, time);
 
+       if (tp->gesture.state == GESTURE_STATE_PINCH_START)
+               tp_gesture_handle_state_pinch_start(tp, time);
+
        if (tp->gesture.state == GESTURE_STATE_PINCH)
                tp_gesture_handle_state_pinch(tp, time);
 }
@@ -1419,13 +1559,23 @@ tp_gesture_stop_twofinger_scroll(struct tp_dispatch *tp, uint64_t time)
 static void
 tp_gesture_end(struct tp_dispatch *tp, uint64_t time, bool cancelled)
 {
-       if (!tp->gesture.started) {
+       switch (tp->gesture.state) {
+       case GESTURE_STATE_NONE:
+       case GESTURE_STATE_UNKNOWN:
+       case GESTURE_STATE_SCROLL_START:
+       case GESTURE_STATE_PINCH_START:
+       case GESTURE_STATE_SWIPE_START:
                tp_gesture_handle_event(tp, GESTURE_EVENT_RESET, time);
-               return;
+               break;
+       case GESTURE_STATE_HOLD:
+       case GESTURE_STATE_HOLD_AND_MOTION:
+       case GESTURE_STATE_POINTER_MOTION:
+       case GESTURE_STATE_SCROLL:
+       case GESTURE_STATE_PINCH:
+       case GESTURE_STATE_SWIPE:
+               tp_gesture_handle_event(tp, cancelled ? GESTURE_EVENT_CANCEL : GESTURE_EVENT_END, time);
+               break;
        }
-
-       tp->gesture.started = false;
-       tp_gesture_handle_event(tp, cancelled ? GESTURE_EVENT_CANCEL : GESTURE_EVENT_END, time);
 }
 
 void
@@ -1437,8 +1587,23 @@ tp_gesture_cancel(struct tp_dispatch *tp, uint64_t time)
 void
 tp_gesture_cancel_motion_gestures(struct tp_dispatch *tp, uint64_t time)
 {
-       if (tp->gesture.started && tp->gesture.state != GESTURE_STATE_HOLD)
+       switch (tp->gesture.state) {
+       case GESTURE_STATE_NONE:
+       case GESTURE_STATE_UNKNOWN:
+       case GESTURE_STATE_SCROLL_START:
+       case GESTURE_STATE_PINCH_START:
+       case GESTURE_STATE_SWIPE_START:
+               break;
+       case GESTURE_STATE_HOLD:
+               break;
+       case GESTURE_STATE_HOLD_AND_MOTION:
+       case GESTURE_STATE_POINTER_MOTION:
+       case GESTURE_STATE_SCROLL:
+       case GESTURE_STATE_PINCH:
+       case GESTURE_STATE_SWIPE:
                tp_gesture_end(tp, time, true);
+               break;
+       }
 }
 
 void
@@ -1460,6 +1625,28 @@ tp_gesture_finger_count_switch_timeout(uint64_t now, void *data)
        tp->gesture.finger_count_pending = 0;
 }
 
+static bool
+tp_gesture_has_started(struct tp_dispatch *tp)
+{
+       switch (tp->gesture.state) {
+       case GESTURE_STATE_NONE:
+       case GESTURE_STATE_UNKNOWN:
+       case GESTURE_STATE_SCROLL_START:
+       case GESTURE_STATE_PINCH_START:
+       case GESTURE_STATE_SWIPE_START:
+       case GESTURE_STATE_POINTER_MOTION:
+               return false;
+       case GESTURE_STATE_HOLD:
+       case GESTURE_STATE_HOLD_AND_MOTION:
+       case GESTURE_STATE_SCROLL:
+       case GESTURE_STATE_PINCH:
+       case GESTURE_STATE_SWIPE:
+               return true;
+       }
+
+       abort();
+}
+
 void
 tp_gesture_update_finger_state(struct tp_dispatch *tp, uint64_t time)
 {
@@ -1478,7 +1665,7 @@ tp_gesture_update_finger_state(struct tp_dispatch *tp, uint64_t time)
                        tp->gesture.finger_count = 0;
                        tp->gesture.finger_count_pending = 0;
                /* Immediately switch to new mode to avoid initial latency */
-               } else if (!tp->gesture.started) {
+               } else if (!tp_gesture_has_started(tp)) {
                        tp->gesture.finger_count = active_touches;
                        tp->gesture.finger_count_pending = 0;
                        /* If in UNKNOWN or POINTER_MOTION state, go back to
index d2842651b70dcd80798d980c91e27dd546b0acff..48d1b11323fc0a96ae1551b25d23f6aa80759c9f 100644 (file)
@@ -160,8 +160,11 @@ enum tp_gesture_state {
        GESTURE_STATE_HOLD,
        GESTURE_STATE_HOLD_AND_MOTION,
        GESTURE_STATE_POINTER_MOTION,
+       GESTURE_STATE_SCROLL_START,
        GESTURE_STATE_SCROLL,
+       GESTURE_STATE_PINCH_START,
        GESTURE_STATE_PINCH,
+       GESTURE_STATE_SWIPE_START,
        GESTURE_STATE_SWIPE,
 };
 
@@ -350,7 +353,6 @@ struct tp_dispatch {
        struct {
                struct libinput_device_config_gesture config;
                bool enabled;
-               bool started;
                unsigned int finger_count;
                unsigned int finger_count_pending;
                struct libinput_timer finger_count_switch_timer;