[PATCH libinput 6/7] touchpad: require a <45 degree movement for a palm to become a touch

Peter Hutterer peter.hutterer at who-t.net
Tue Jul 15 22:18:45 PDT 2014


Any legitimate finger movement that starts in the palm area is expected to
move out of the palm area at an angle roughly orthogonal to the edge of the
touchpad. Check for the direction of the movement vector, and if it is within
the accepted cardinal/ordinal directions then proceed.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Thought this was an interesting-enough idea. The palmdata on the edges tends
to move around a bit but it does so mostly vertically. A pure movement
threshold is not enough as the palm moves whenever the top or bottom row of
the keys are accessed.

Adding the directional component should filter palm events. But tbh, this is
all just based on one touchpad so far.

 src/evdev-mt-touchpad.c | 13 ++++++++++---
 src/evdev-mt-touchpad.h |  1 +
 test/touchpad.c         | 15 +++++++++++++++
 3 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 830e9fe..2cf8b56 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -363,15 +363,20 @@ static void
 tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
 {
 	const int PALM_TIMEOUT = 200; /* ms */
+	const int DIRECTIONS = NE|E|SE|SW|W|NW;
 
 	/* If labelled a touch as palm, we unlabel as palm when
-	   we move out of the palm edge zone within the timeout.
+	   we move out of the palm edge zone within the timeout, provided
+	   the direction is within 45 degrees of the horizontal.
 	 */
 	if (t->palm.is_palm) {
 		if (time < t->palm.time + PALM_TIMEOUT &&
 		    (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) {
-			t->palm.is_palm = false;
-			tp_set_pointer(tp, t);
+			int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y);
+			if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) {
+				t->palm.is_palm = false;
+				tp_set_pointer(tp, t);
+			}
 		}
 		return;
 	}
@@ -391,6 +396,8 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
 
 	t->palm.is_palm = true;
 	t->palm.time = time;
+	t->palm.x = t->x;
+	t->palm.y = t->y;
 }
 
 static void
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 8255a1c..4779120 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -142,6 +142,7 @@ struct tp_touch {
 
 	struct {
 		bool is_palm;
+		int32_t x, y;  /* first coordinates if is_palm == true */
 		uint32_t time; /* first timestamp if is_palm == true */
 	} palm;
 };
diff --git a/test/touchpad.c b/test/touchpad.c
index 5bb8d9b..259b227 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -1302,6 +1302,20 @@ START_TEST(touchpad_palm_detect_at_top_corners)
 }
 END_TEST
 
+START_TEST(touchpad_palm_detect_palm_stays_palm)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+
+	litest_drain_events(li);
+
+	litest_touch_down(dev, 0, 99, 20);
+	litest_touch_move_to(dev, 0, 99, 20, 75, 99, 5);
+	litest_touch_up(dev, 0);
+	litest_assert_empty_queue(li);
+}
+END_TEST
+
 START_TEST(touchpad_palm_detect_palm_becomes_pointer)
 {
 	struct litest_device *dev = litest_current_device();
@@ -1419,6 +1433,7 @@ int main(int argc, char **argv) {
 	litest_add("touchpad:palm", touchpad_palm_detect_at_bottom_corners, LITEST_TOUCHPAD, LITEST_CLICKPAD);
 	litest_add("touchpad:palm", touchpad_palm_detect_at_top_corners, LITEST_TOUCHPAD, LITEST_TOPBUTTONPAD);
 	litest_add("touchpad:palm", touchpad_palm_detect_palm_becomes_pointer, LITEST_TOUCHPAD, LITEST_ANY);
+	litest_add("touchpad:palm", touchpad_palm_detect_palm_stays_palm, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:palm", touchpad_palm_detect_no_palm_moving_into_edges, LITEST_TOUCHPAD, LITEST_ANY);
 
 	return litest_run(argc, argv);
-- 
1.9.3



More information about the wayland-devel mailing list