touchpad: allow BTN_LEFT in clickfinger mode without touches
authorPeter Hutterer <peter.hutterer@who-t.net>
Fri, 24 Apr 2015 02:25:50 +0000 (12:25 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Sun, 26 Apr 2015 23:04:27 +0000 (09:04 +1000)
On the Logitech T650 it's quite easy to trigger a click without touching the
surface. For software buttons we discard those clicks because we can't tell
where the finger is to decide on left vs right click.

It takes effort to trigger a click with two fingers without triggering a touch
though, so in clickfinger mode post a click without touches as single-finger
click.

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

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev-mt-touchpad-buttons.c
test/touchpad.c

index c907ecc56e89c3cbc7d6ab7f175917bf61edde35..7f60a53ab6452550f5a3240ac91820bdb092278b 100644 (file)
@@ -804,6 +804,7 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp,
        if (tp->buttons.click_method == LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER &&
            state == LIBINPUT_BUTTON_STATE_PRESSED) {
                switch (tp->nfingers_down) {
+               case 0:
                case 1: button = BTN_LEFT; break;
                case 2: button = BTN_RIGHT; break;
                case 3: button = BTN_MIDDLE; break;
@@ -865,7 +866,8 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
                        }
                }
 
-               if (area == 0) {
+               if (area == 0 &&
+                   tp->buttons.click_method != LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) {
                        /* No touches, wait for a touch before processing */
                        tp->buttons.click_pending = true;
                        return 0;
@@ -877,7 +879,7 @@ tp_post_clickpadbutton_buttons(struct tp_dispatch *tp, uint64_t time)
                        button = evdev_to_left_handed(tp->device, BTN_RIGHT);
                else if (area & LEFT)
                        button = evdev_to_left_handed(tp->device, BTN_LEFT);
-               else /* main area is always BTN_LEFT */
+               else /* main or no area (for clickfinger) is always BTN_LEFT */
                        button = BTN_LEFT;
 
                tp->buttons.active = button;
index c04ef115ec53d0b0f90eb76327e5b52e0109d85d..db981dcba22343baf2fdb4033cfda6d069d00a80 100644 (file)
@@ -1506,6 +1506,32 @@ START_TEST(touchpad_1fg_clickfinger)
 }
 END_TEST
 
+START_TEST(touchpad_1fg_clickfinger_no_touch)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       enum libinput_config_status status;
+
+       status = libinput_device_config_click_set_method(dev->libinput_device,
+                                                        LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER);
+       ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
+
+       litest_drain_events(li);
+
+       litest_event(dev, EV_KEY, BTN_LEFT, 1);
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);
+       litest_event(dev, EV_KEY, BTN_LEFT, 0);
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);
+
+       libinput_dispatch(li);
+
+       litest_assert_button_event(li, BTN_LEFT,
+                                  LIBINPUT_BUTTON_STATE_PRESSED);
+       litest_assert_button_event(li, BTN_LEFT,
+                                  LIBINPUT_BUTTON_STATE_RELEASED);
+}
+END_TEST
+
 START_TEST(touchpad_2fg_clickfinger)
 {
        struct litest_device *dev = litest_current_device();
@@ -1785,6 +1811,9 @@ START_TEST(clickpad_btn_left)
        struct litest_device *dev = litest_current_device();
        struct libinput *li = dev->libinput;
 
+       libinput_device_config_click_set_method(dev->libinput_device,
+                                               LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS);
+
        litest_drain_events(li);
 
        /* A clickpad always needs a finger down to tell where the
@@ -4119,6 +4148,7 @@ int main(int argc, char **argv) {
        litest_add("touchpad:tap", clickpad_2fg_tap_click, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH|LITEST_APPLE_CLICKPAD);
 
        litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY);
+       litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger_no_touch, LITEST_CLICKPAD, LITEST_ANY);
        litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY);
        litest_add("touchpad:clickfinger", touchpad_clickfinger_to_area_method, LITEST_CLICKPAD, LITEST_ANY);
        litest_add("touchpad:clickfinger",