gestures: use a macro for debugging transition states
authorPeter Hutterer <peter.hutterer@who-t.net>
Fri, 20 Dec 2024 01:04:41 +0000 (11:04 +1000)
committerMarge Bot <emma+marge@anholt.net>
Fri, 20 Dec 2024 09:47:46 +0000 (09:47 +0000)
This avoids bugs where we forget to update a state but also provides
some bounds checking now to ensure our array is large enough to store
those transitions.

Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1106>

src/evdev-mt-touchpad-gestures.c

index 7aa55a404ebf5821630a663de2248ffe3d16baa9..4817b1ed4f8f39ed96b11ca8a79aaa60beda3ba6 100644 (file)
@@ -1460,74 +1460,72 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time,
 {
        enum tp_gesture_state oldstate = tp->gesture.state;
        enum tp_gesture_state transitions[16] = {0};
-       size_t idx = 0;
+       enum tp_gesture_state *transition_state = transitions;
+
+#define REMEMBER_TRANSITION(_ts, _state) { \
+               if (*(_ts) != (_state)) { \
+                       ++(_ts); \
+                       assert((_ts) < transitions + ARRAY_LENGTH(transitions)); \
+                       *(_ts) = _state; \
+               } \
+       }
 
-       transitions[idx++] = tp->gesture.state;
+       *transition_state = tp->gesture.state;
        if (tp->gesture.state == GESTURE_STATE_NONE) {
                tp_gesture_handle_state_none(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_UNKNOWN) {
                tp_gesture_handle_state_unknown(tp, time, ignore_motion);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_HOLD) {
                tp_gesture_handle_state_hold(tp, time, ignore_motion);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_POINTER_MOTION) {
                tp_gesture_handle_state_pointer_motion(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_HOLD_AND_MOTION) {
                tp_gesture_handle_state_hold_and_pointer_motion(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_SCROLL) {
                tp_gesture_handle_state_scroll(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_SCROLL_START) {
                tp_gesture_handle_state_scroll_start(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_SWIPE) {
                tp_gesture_handle_state_swipe(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_SWIPE_START) {
                tp_gesture_handle_state_swipe_start(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_PINCH) {
                tp_gesture_handle_state_pinch(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
        if (tp->gesture.state == GESTURE_STATE_PINCH_START) {
                tp_gesture_handle_state_pinch_start(tp, time);
-               if (transitions[idx - 1] != tp->gesture.state)
-                       transitions[idx++] = tp->gesture.state;
+               REMEMBER_TRANSITION(transition_state, tp->gesture.state);
        }
+
+#undef REMEMBER_TRANSITION
+
        if (oldstate != tp->gesture.state) {
                char buf[1024] = {0};
                size_t remaining = sizeof(buf);
                size_t slen = 0;
-               for (size_t i = 1; i < idx - 1; i++) {
-                       if (transitions[i] != transitions[i - 1]) {
-                               int n = snprintf(&buf[slen], remaining, " → %s", gesture_state_to_str(transitions[i]));
-                               slen += n;
-                               remaining -= n;
-                       }
+               for (enum tp_gesture_state *s = transitions + 1; s < transition_state; s++) {
+                       int n = snprintf(&buf[slen], remaining, " → %s", gesture_state_to_str(*s));
+                       slen += n;
+                       remaining -= n;
                }
                evdev_log_debug(tp->device,
                                "gesture: [%dfg] transitions %s%s → %s\n",