touchpad: require a <45 degree movement for a palm to become a touch
authorPeter Hutterer <peter.hutterer@who-t.net>
Mon, 14 Jul 2014 06:38:46 +0000 (16:38 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Sun, 20 Jul 2014 22:56:12 +0000 (08:56 +1000)
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@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev-mt-touchpad.c
src/evdev-mt-touchpad.h
test/touchpad.c

index 830e9fe..2cf8b56 100644 (file)
@@ -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
index 8255a1c..4779120 100644 (file)
@@ -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;
 };
index 18427c1..1d95399 100644 (file)
@@ -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);