gestures: if two fingers are in definitive pinch position, pinch
authorPeter Hutterer <peter.hutterer@who-t.net>
Thu, 26 Apr 2018 01:18:58 +0000 (11:18 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 26 Apr 2018 03:59:03 +0000 (13:59 +1000)
Two fingers on the touchpad, they're 40x40mm apart, that's a pinch. But only
after a timeout because we don't want to start a 2fg gesture if the user puts
down the third/fourth finger within the next few ms.

Related to: https://bugs.freedesktop.org/show_bug.cgi?id=99830

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
src/evdev-mt-touchpad-gestures.c
src/evdev.h

index 37682fb4f412ac17b8c68993ea26262801b79d0f..8f2dda7f13056cd9da61bebf63ab215abaae1b3e 100644 (file)
@@ -31,6 +31,7 @@
 
 #define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100)
 #define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(150)
+#define DEFAULT_GESTURE_2FG_PINCH_TIMEOUT ms2us(75)
 
 static inline const char*
 gesture_state_to_str(enum tp_gesture_state state)
@@ -328,8 +329,11 @@ tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
        struct tp_touch *first = tp->gesture.touches[0],
                        *second = tp->gesture.touches[1];
        uint32_t dir1, dir2;
-       int yres = tp->device->abs.absinfo_y->resolution;
-       int vert_distance;
+       struct phys_coords mm;
+       int vert_distance, horiz_distance;
+
+       vert_distance = abs(first->point.y - second->point.y);
+       horiz_distance = abs(first->point.x - second->point.x);
 
        if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
                /* for two-finger gestures, if the fingers stay unmoving for a
@@ -345,9 +349,10 @@ tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
 
                /* for 3+ finger gestures, check if one finger is > 20mm
                   below the others */
-               vert_distance = abs(first->point.y - second->point.y);
-               if (vert_distance > 20 * yres &&
-                   tp->gesture.enabled) {
+               mm = evdev_convert_xy_to_mm(tp->device,
+                                           horiz_distance,
+                                           vert_distance);
+               if (mm.y > 20 && tp->gesture.enabled) {
                        tp_gesture_init_pinch(tp);
                        return GESTURE_STATE_PINCH;
                } else {
@@ -355,6 +360,12 @@ tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time)
                }
        }
 
+       if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) {
+               mm = evdev_convert_xy_to_mm(tp->device, horiz_distance, vert_distance);
+               if (tp->gesture.finger_count == 2 && mm.x > 40 && mm.y > 40)
+                       return GESTURE_STATE_PINCH;
+       }
+
        /* Else wait for both fingers to have moved */
        dir1 = tp_gesture_get_direction(tp, first, tp->gesture.finger_count);
        dir2 = tp_gesture_get_direction(tp, second, tp->gesture.finger_count);
index 42d71a054a55892205d0333fa0275056b8f19550..0c602ea0b2b884e6df4e8d8549e8fb09d0e49f5f 100644 (file)
@@ -586,6 +586,17 @@ evdev_convert_to_mm(const struct input_absinfo *absinfo, double v)
        return value/absinfo->resolution;
 }
 
+static inline struct phys_coords
+evdev_convert_xy_to_mm(const struct evdev_device *device, int x, int y)
+{
+       struct phys_coords mm;
+
+       mm.x = evdev_convert_to_mm(device->abs.absinfo_x, x);
+       mm.y = evdev_convert_to_mm(device->abs.absinfo_y, y);
+
+       return mm;
+}
+
 void
 evdev_init_left_handed(struct evdev_device *device,
                       void (*change_to_left_handed)(struct evdev_device *));