summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2014-07-14 16:06:51 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2014-07-21 08:56:12 +1000
commit9ecce8e2f73e9115f680755745d9c0d8c4e50a00 (patch)
tree6f9432421ab6ea7568d5e244429efafbd689f1f8
parentec7fc30ae2176c7361c1eb26c4c53e98382cbb6d (diff)
downloadlibinput-9ecce8e2f73e9115f680755745d9c0d8c4e50a00.tar.gz
touchpad: if a palm touch moves out of the edge zone within a timeout, unpalm
On small touchpads a touch that is intended to traverse much of the screen width may start at the very edge, i.e. in the palm zone. In that case, and if the touch moves out of the palm zone quickly enough, drop the palm label and make it a normal touchpoint. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--src/evdev-mt-touchpad.c25
-rw-r--r--src/evdev-mt-touchpad.h6
-rw-r--r--test/touchpad.c20
3 files changed, 40 insertions, 11 deletions
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 1325355c..830e9fee 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -148,7 +148,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
t->dirty = true;
t->is_pointer = false;
- t->is_palm = false;
+ t->palm.is_palm = false;
t->state = TOUCH_END;
t->pinned.is_pinned = false;
assert(tp->nfingers_down >= 1);
@@ -340,7 +340,7 @@ static int
tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t)
{
return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) &&
- !t->is_palm &&
+ !t->palm.is_palm &&
!t->pinned.is_pinned && tp_button_touch_active(tp, t);
}
@@ -360,11 +360,21 @@ tp_set_pointer(struct tp_dispatch *tp, struct tp_touch *t)
}
static void
-tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t)
+tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
{
- /* once a palm, always a palm */
- if (t->is_palm)
+ const int PALM_TIMEOUT = 200; /* ms */
+
+ /* If labelled a touch as palm, we unlabel as palm when
+ we move out of the palm edge zone within the timeout.
+ */
+ 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);
+ }
return;
+ }
/* palm must start in exclusion zone, it's ok to move into
the zone without being a palm */
@@ -379,7 +389,8 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t)
tp_button_is_inside_softbutton_area(tp, t))
return;
- t->is_palm = true;
+ t->palm.is_palm = true;
+ t->palm.time = time;
}
static void
@@ -398,7 +409,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
continue;
}
- tp_palm_detect(tp, t);
+ tp_palm_detect(tp, t, time);
tp_motion_hysteresis(tp, t);
tp_motion_history_push(t);
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 689687ee..8255a1cd 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -103,7 +103,6 @@ struct tp_touch {
bool dirty;
bool fake; /* a fake touch */
bool is_pointer; /* the pointer-controlling touch */
- bool is_palm;
int32_t x;
int32_t y;
uint64_t millis;
@@ -140,6 +139,11 @@ struct tp_touch {
struct {
enum tp_tap_touch_state state;
} tap;
+
+ struct {
+ bool is_palm;
+ uint32_t time; /* first timestamp if is_palm == true */
+ } palm;
};
struct tp_dispatch {
diff --git a/test/touchpad.c b/test/touchpad.c
index 672cbf9b..18427c1a 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -1302,17 +1302,31 @@ START_TEST(touchpad_palm_detect_at_top_corners)
}
END_TEST
-START_TEST(touchpad_palm_detect_palm_stays_palm)
+START_TEST(touchpad_palm_detect_palm_becomes_pointer)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
+ struct libinput_event *ev;
+ enum libinput_event_type type;
litest_drain_events(li);
litest_touch_down(dev, 0, 99, 50);
- litest_touch_move_to(dev, 0, 99, 50, 0, 70, 5);
+ litest_touch_move_to(dev, 0, 99, 70, 0, 70, 5);
litest_touch_up(dev, 0);
+ libinput_dispatch(li);
+
+ ev = libinput_get_event(li);
+ ck_assert_notnull(ev);
+ do {
+ type = libinput_event_get_type(ev);
+ ck_assert_int_eq(type, LIBINPUT_EVENT_POINTER_MOTION);
+
+ libinput_event_destroy(ev);
+ ev = libinput_get_event(li);
+ } while (ev);
+
litest_assert_empty_queue(li);
}
END_TEST
@@ -1404,7 +1418,7 @@ int main(int argc, char **argv) {
litest_add("touchpad:palm", touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY);
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_stays_palm, LITEST_TOUCHPAD, LITEST_ANY);
+ litest_add("touchpad:palm", touchpad_palm_detect_palm_becomes_pointer, 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);