From a1c4ffe95209555a8f0dfda62552e60483ae619a Mon Sep 17 00:00:00 2001
From: Ming-Yang Lu <op8867555@gmail.com>
Date: Sun, 2 Jul 2017 18:07:20 +0800
Subject: [PATCH libinput] touchpad: add upper edge into exclusion zone

This reduces unexpected cursor moves when placing thumb finger near border of
trackpoint buttons and upper edge of touchpad.

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

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
---
 src/evdev-mt-touchpad.c | 50 ++++++++++++++++++++++++++++++++++++++-----------
 src/evdev-mt-touchpad.h |  1 +
 2 files changed, 40 insertions(+), 11 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 4d0cff97..d40d4c78 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -550,14 +550,32 @@ tp_touch_active(const struct tp_dispatch *tp, const struct tp_touch *t)
 		tp_edge_scroll_touch_active(tp, t);
 }
 
+static inline bool
+tp_palm_in_side_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
+{
+	return t->point.x < tp->palm.left_edge ||
+	       t->point.x > tp->palm.right_edge;
+}
+
+static inline bool
+tp_palm_in_top_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
+{
+	return t->point.y < tp->palm.upper_edge;
+}
+
+static inline bool
+tp_palm_in_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
+{
+	return tp_palm_in_side_edge(tp, t) || tp_palm_in_top_edge(tp, t);
+}
+
 bool
 tp_palm_tap_is_palm(const struct tp_dispatch *tp, const struct tp_touch *t)
 {
 	if (t->state != TOUCH_BEGIN)
 		return false;
 
-	if (t->point.x > tp->palm.left_edge &&
-	    t->point.x < tp->palm.right_edge)
+	if (!tp_palm_in_edge(tp, t))
 		return false;
 
 	evdev_log_debug(tp->device, "palm: palm-tap detected\n");
@@ -654,16 +672,22 @@ tp_palm_detect_move_out_of_edge(struct tp_dispatch *tp,
 				uint64_t time)
 {
 	const int PALM_TIMEOUT = ms2us(200);
-	const int DIRECTIONS = NE|E|SE|SW|W|NW;
+	int directions = 0;
 	struct device_float_coords delta;
 	int dirs;
 
-	if (time < t->palm.time + PALM_TIMEOUT &&
-	    (t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge)) {
-		delta = device_delta(t->point, t->palm.first);
-		dirs = phys_get_direction(tp_phys_delta(tp, delta));
-		if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS))
-			return true;
+	if (time < t->palm.time + PALM_TIMEOUT) {
+		if (tp_palm_in_side_edge(tp, t))
+			directions = NE|E|SE|SW|W|NW;
+		else if (tp_palm_in_top_edge(tp, t))
+			directions = S|SE|SW;
+
+		if (directions) {
+			delta = device_delta(t->point, t->palm.first);
+			dirs = phys_get_direction(tp_phys_delta(tp, delta));
+			if ((dirs & directions) && !(dirs & ~directions))
+				return true;
+		}
 	}
 
 	return false;
@@ -725,8 +749,7 @@ tp_palm_detect_edge(struct tp_dispatch *tp,
 
 	/* palm must start in exclusion zone, it's ok to move into
 	   the zone without being a palm */
-	if (t->state != TOUCH_BEGIN ||
-	    (t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge))
+	if (t->state != TOUCH_BEGIN || tp_palm_in_edge(tp, t))
 		return false;
 
 	/* don't detect palm in software button areas, it's
@@ -2320,6 +2343,10 @@ tp_init_palmdetect_edge(struct tp_dispatch *tp,
 	mm.x = width * 0.92;
 	edges = evdev_device_mm_to_units(device, &mm);
 	tp->palm.right_edge = edges.x;
+
+	mm.y = height * 0.05;
+	edges = evdev_device_mm_to_units(device, &mm);
+	tp->palm.upper_edge = edges.y;
 }
 
 static int
@@ -2365,6 +2392,7 @@ tp_init_palmdetect(struct tp_dispatch *tp,
 
 	tp->palm.right_edge = INT_MAX;
 	tp->palm.left_edge = INT_MIN;
+	tp->palm.upper_edge = INT_MIN;
 
 	if (device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD &&
 	    !tp_is_tpkb_combo_below(device))
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 6d014607..d601f7e5 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -335,6 +335,7 @@ struct tp_dispatch {
 	struct {
 		int32_t right_edge;		/* in device coordinates */
 		int32_t left_edge;		/* in device coordinates */
+		int32_t upper_edge;		/* in device coordinates */
 
 		bool trackpoint_active;
 		struct libinput_event_listener trackpoint_listener;
-- 
2.13.0