touchpad: add support for clickfingers
authorPeter Hutterer <peter.hutterer@who-t.net>
Mon, 17 Feb 2014 01:14:29 +0000 (11:14 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Mon, 24 Mar 2014 06:39:12 +0000 (16:39 +1000)
On touchpads without physical buttons, the number of fingers on the touchpad
at the time the physical click happens decides the button type. 1/2/3 fingers
is handled left/right/middle.

We also swallow the motion event on the actual click event, this reduces
erroneous motion events by a bit. More processing is needed here though.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
src/evdev-mt-touchpad.c
src/evdev-mt-touchpad.h
test/pointer.c

index e8e7731bc5b95304c9ab0d12d80ae9f322c5e0e7..93349870c6f9f68b723caea2a2ebab61d36eb56e 100644 (file)
@@ -461,14 +461,42 @@ tp_post_scroll_events(struct tp_dispatch *tp, uint32_t time)
        return 0;
 }
 
-static void
-tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
+static int
+tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint32_t time)
 {
        uint32_t current, old, button;
+       enum libinput_pointer_button_state state;
 
-       if ((tp->queued &
-               (TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 0)
-                               return;
+       current = tp->buttons.state;
+       old = tp->buttons.old_state;
+
+       if (current == old)
+               return 0;
+
+       switch (tp->nfingers_down) {
+               case 1: button = BTN_LEFT; break;
+               case 2: button = BTN_RIGHT; break;
+               case 3: button = BTN_MIDDLE; break;
+               default:
+                       return 0;
+       }
+
+       if (current)
+               state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
+       else
+               state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+
+       pointer_notify_button(&tp->device->base,
+                             time,
+                             button,
+                             state);
+       return 1;
+}
+
+static int
+tp_post_physical_buttons(struct tp_dispatch *tp, uint32_t time)
+{
+       uint32_t current, old, button;
 
        current = tp->buttons.state;
        old = tp->buttons.old_state;
@@ -493,6 +521,25 @@ tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
                current >>= 1;
                old >>= 1;
        }
+
+       return 0;
+}
+
+static int
+tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
+{
+       int rc;
+
+       if ((tp->queued &
+               (TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 0)
+                               return 0;
+
+       if (tp->buttons.has_buttons)
+               rc = tp_post_physical_buttons(tp, time);
+       else
+               rc = tp_post_clickfinger_buttons(tp, time);
+
+       return rc;
 }
 
 static void
@@ -501,6 +548,9 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
        struct tp_touch *t = tp_current_touch(tp);
        double dx, dy;
 
+       if (tp_post_button_events(tp, time) != 0)
+               return;
+
        if (tp_tap_handle_state(tp, time) != 0)
                return;
 
@@ -519,8 +569,6 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
                                li_fixed_from_double(dx),
                                li_fixed_from_double(dy));
        }
-
-       tp_post_button_events(tp, time);
 }
 
 static void
@@ -639,6 +687,10 @@ tp_init(struct tp_dispatch *tp,
        tp->hysteresis.margin_y =
                diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
 
+       if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT) ||
+           libevdev_has_event_code(device->evdev, EV_KEY, BTN_RIGHT))
+               tp->buttons.has_buttons = true;
+
        if (tp_init_scroll(tp) != 0)
                return -1;
 
index 84d8cec7b710074ecc5c740fd8be779b7b200c07..327ce11592ab279851c741b3072ac61818b1e380 100644 (file)
@@ -117,6 +117,7 @@ struct tp_dispatch {
        } accel;
 
        struct {
+               bool has_buttons;               /* true for physical LMR buttons */
                uint32_t state;
                uint32_t old_state;
        } buttons;                              /* physical buttons */
index e864169c683b58fadaf11eda1bf2ad0278e62b3c..59fe8183af7fd18f6db9b008ffff7eb95eb1f653 100644 (file)
@@ -186,7 +186,7 @@ END_TEST
 int main (int argc, char **argv) {
 
        litest_add("pointer:motion", pointer_motion_relative, LITEST_POINTER, LITEST_ANY);
-       litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_ANY);
+       litest_add("pointer:button", pointer_button, LITEST_BUTTON, LITEST_CLICKPAD);
        litest_add("pointer:scroll", pointer_scroll_wheel, LITEST_WHEEL, LITEST_ANY);
 
        return litest_run(argc, argv);