With a thumb on the touchpad, a two-finger click was always treated as
a middle-click. This patch takes the thumb into account and treats the
click as a right-click, if the touchpad supports tracking of at least
three fingers.
---
 src/evdev-mt-touchpad-buttons.c | 90 +++++++++++++++++++++++++++++------------
 1 file changed, 65 insertions(+), 25 deletions(-)

diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index 895cf0e..30c2948 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -978,54 +978,94 @@ out:
        return within_distance;
 }
 
+static inline bool
+tp_clickfinger_within_distance_3(struct tp_dispatch *tp,
+                                struct tp_touch *t1,
+                                struct tp_touch *t2,
+                                struct tp_touch *t3)
+{
+       if (!t1 || !t2 || !t3)
+               return false;
+
+       double d12 =
+               (t1->point.x - t2->point.x) * (t1->point.x - t2->point.x) +
+               (t1->point.y - t2->point.y) * (t1->point.y - t2->point.y);
+       double d23 =
+               (t2->point.x - t3->point.x) * (t2->point.x - t3->point.x) +
+               (t2->point.y - t3->point.y) * (t2->point.y - t3->point.y);
+       double d31 =
+               (t3->point.x - t1->point.x) * (t3->point.x - t1->point.x) +
+               (t3->point.y - t1->point.y) * (t3->point.y - t1->point.y);
+
+       if (d12 > d23 && d12 > d31) {
+               return tp_clickfinger_within_distance(tp, t2, t3) &&
+                      tp_clickfinger_within_distance(tp, t3, t1);
+       }
+
+       if (d23 > d31 && d23 > d12) {
+               return tp_clickfinger_within_distance(tp, t3, t1) &&
+                      tp_clickfinger_within_distance(tp, t1, t2);
+       }
+
+       return tp_clickfinger_within_distance(tp, t1, t2) &&
+              tp_clickfinger_within_distance(tp, t2, t3);
+}
+
 static uint32_t
 tp_clickfinger_set_button(struct tp_dispatch *tp)
 {
-       uint32_t button;
+       bool thumb_detected = false;
        unsigned int nfingers = tp->nfingers_down;
        struct tp_touch *t;
        struct tp_touch *first = NULL,
-                       *second = NULL;
+                       *second = NULL,
+                       *third = NULL;
 
-       if (nfingers != 2)
-               goto out;
+       if (nfingers < 2)
+               return BTN_LEFT;
+       if (nfingers > 3)
+               return BTN_MIDDLE;
+
+       /* Thumb detection is unreliable if the number of fingers on the
+        * touchpad is greater than the number of touches that can be
+        * tracked. */
+       if (nfingers == 3 && tp->num_slots < 3)
+               return BTN_MIDDLE;
 
-       /* two fingers down on the touchpad. Check for distance
-        * between the fingers. */
        tp_for_each_touch(tp, t) {
                if (t->state != TOUCH_BEGIN && t->state != TOUCH_UPDATE)
                        continue;
 
-               if (t->thumb.state == THUMB_STATE_YES)
+               if (t->thumb.state == THUMB_STATE_YES) {
+                       thumb_detected = true;
                        continue;
+               }
 
                if (!first)
                        first = t;
                else if (!second)
                        second = t;
+               else if (!third)
+                       third = t;
        }
 
-       if (!first || !second) {
-               nfingers = 1;
-               goto out;
-       }
+       if (nfingers == 2) {
+               if (thumb_detected)
+                       return BTN_LEFT;
 
-       if (tp_clickfinger_within_distance(tp, first, second))
-               nfingers = 2;
-       else
-               nfingers = 1;
+               if (tp_clickfinger_within_distance(tp, first, second))
+                       return BTN_RIGHT;
+               else
+                       return BTN_LEFT;
+       } else {
+               if (thumb_detected)
+                       return BTN_RIGHT;
 
-out:
-       switch (nfingers) {
-       case 0:
-       case 1: button = BTN_LEFT; break;
-       case 2: button = BTN_RIGHT; break;
-       default:
-               button = BTN_MIDDLE; break;
-               break;
+               if (tp_clickfinger_within_distance_3(tp, first, second, third))
+                       return BTN_MIDDLE;
+               else
+                       return BTN_RIGHT;
        }
-
-       return button;
 }
 
 static int
-- 
2.9.4

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to