[PATCH libinput] gestures: if two fingers are in definitive pinch position, pinch

Peter Hutterer peter.hutterer at who-t.net
Thu Apr 26 04:09:04 UTC 2018


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 at who-t.net>
---
 src/evdev-mt-touchpad-gestures.c | 21 ++++++++++++++++-----
 src/evdev.h                      | 11 +++++++++++
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c
index 37682fb4..8f2dda7f 100644
--- a/src/evdev-mt-touchpad-gestures.c
+++ b/src/evdev-mt-touchpad-gestures.c
@@ -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);
diff --git a/src/evdev.h b/src/evdev.h
index 42d71a05..0c602ea0 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -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 *));
-- 
2.14.3



More information about the wayland-devel mailing list