[PATCH libinput] touchpad: detect fake finger overflow after BTN_TOOL_QUINTTAB

Peter Hutterer peter.hutterer at who-t.net
Wed Apr 8 21:23:16 PDT 2015


Up to QUINTTAP, we count fake fingers through the BTN_TOOL_*TAP kernel defines.
Once we exceed QUINTTAP, the nfake_finger count returns to 0 and
tp_unhover_touches terminates all touch sequences. The most visible effect of
this was stopped in 591a41f but the problem remained.

Since we're not using 5 fingers for anything, use that to set the
overflow flag. The kernel gives us either a BTN_TOUCH 0 (all
released) or a lower BTN_TOOL_*TAP to unset the flag when we go below 5
fingers again.

And if we overflow, we can skip the unhovering of touch points since we a)
have a decent touchpad that gives us real touchpoints and b) hovering isn't
supported for 5 touches anyway.

https://bugs.freedesktop.org/show_bug.cgi?id=89800

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c | 29 +++++++++++++++++++++++++----
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 724fd32..19ec99e 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -34,6 +34,7 @@
 #define DEFAULT_ACCEL_NUMERATOR 3000.0
 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
 #define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */
+#define FAKE_FINGER_OVERFLOW (1 << 7)
 
 static inline int
 tp_hysteresis(int in, int center, int margin)
@@ -127,8 +128,10 @@ tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
 static inline unsigned int
 tp_fake_finger_count(struct tp_dispatch *tp)
 {
-	/* don't count BTN_TOUCH */
-	return ffs(tp->fake_touches >> 1);
+	if (tp->fake_touches & FAKE_FINGER_OVERFLOW)
+		return FAKE_FINGER_OVERFLOW;
+	else /* don't count BTN_TOUCH */
+		return ffs(tp->fake_touches >> 1);
 }
 
 static inline bool
@@ -146,6 +149,8 @@ tp_fake_finger_set(struct tp_dispatch *tp,
 
 	switch (code) {
 	case BTN_TOUCH:
+		if (!is_press)
+			tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
 		shift = 0;
 		break;
 	case BTN_TOOL_FINGER:
@@ -156,14 +161,24 @@ tp_fake_finger_set(struct tp_dispatch *tp,
 	case BTN_TOOL_QUADTAP:
 		shift = code - BTN_TOOL_DOUBLETAP + 2;
 		break;
+	/* when QUINTTAP is released we're either switching to 6 fingers
+	   (flag stays in place until BTN_TOUCH is released) or
+	   one of DOUBLE/TRIPLE/QUADTAP (will clear the flag on press) */
+	case BTN_TOOL_QUINTTAP:
+		if (is_press)
+			tp->fake_touches |= FAKE_FINGER_OVERFLOW;
+		return;
 	default:
 		return;
 	}
 
-	if (is_press)
+	if (is_press) {
+		tp->fake_touches &= ~FAKE_FINGER_OVERFLOW;
 		tp->fake_touches |= 1 << shift;
-	else
+
+	} else {
 		tp->fake_touches &= ~(0x1 << shift);
+	}
 }
 
 static inline void
@@ -325,6 +340,8 @@ tp_process_fake_touches(struct tp_dispatch *tp,
 	unsigned int i, start;
 
 	nfake_touches = tp_fake_finger_count(tp);
+	if (nfake_touches == FAKE_FINGER_OVERFLOW)
+		return;
 
 	start = tp->has_mt ? tp->real_touches : 0;
 	for (i = start; i < tp->ntouches; i++) {
@@ -387,6 +404,7 @@ tp_process_key(struct tp_dispatch *tp,
 		case BTN_TOOL_DOUBLETAP:
 		case BTN_TOOL_TRIPLETAP:
 		case BTN_TOOL_QUADTAP:
+		case BTN_TOOL_QUINTTAP:
 			tp_fake_finger_set(tp, e->code, !!e->value);
 			break;
 		case BTN_0:
@@ -494,6 +512,9 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
 		return;
 
 	nfake_touches = tp_fake_finger_count(tp);
+	if (nfake_touches == FAKE_FINGER_OVERFLOW)
+		return;
+
 	if (tp->nfingers_down == nfake_touches &&
 	    ((tp->nfingers_down == 0 && !tp_fake_finger_is_touching(tp)) ||
 	     (tp->nfingers_down > 0 && tp_fake_finger_is_touching(tp))))
-- 
2.3.4



More information about the wayland-devel mailing list