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 830e9feec242ce9ba8ff0d010ed07b2abc52e292..2cf8b567eccc8d4092a6dc6b723123407e30d8e6 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 8255a1cd266f33040df1d785c01d49b6724e57e9..47791201d55dae8ff0c31d2e27b1274c5e3decd0 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 18427c1aa1eeacf6690b48c8daed3a8a3f678ef8..1d95399c6c7f8412672d0786b0519d5a14f2aa0e 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);