tablet: don't force a proximity out while buttons are down
authorPeter Hutterer <peter.hutterer@who-t.net>
Thu, 6 Feb 2020 09:09:14 +0000 (19:09 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 13 Feb 2020 04:53:27 +0000 (04:53 +0000)
While buttons are down, don't let a forced proximity out happen. If the tablet
goes out of proximity normally that's fine but we don't force a proximity out.

Remains to be seen if this causes stuck buttons now on devices that rely on
the forced proximity out...

Fixes #403

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

index e152065..cd07ae0 100644 (file)
@@ -1940,11 +1940,18 @@ tablet_toggle_touch_device(struct tablet_dispatch *tablet,
 static inline void
 tablet_reset_state(struct tablet_dispatch *tablet)
 {
+       struct button_state zero = {0};
+
        /* Update state */
        memcpy(&tablet->prev_button_state,
               &tablet->button_state,
               sizeof(tablet->button_state));
        tablet_unset_status(tablet, TABLET_TOOL_UPDATED);
+
+       if (memcmp(&tablet->button_state, &zero, sizeof(zero)) == 0)
+               tablet_unset_status(tablet, TABLET_BUTTONS_DOWN);
+       else
+               tablet_set_status(tablet, TABLET_BUTTONS_DOWN);
 }
 
 static void
@@ -1966,7 +1973,8 @@ tablet_proximity_out_quirk_timer_func(uint64_t now, void *data)
        };
        struct input_event *e;
 
-       if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) {
+       if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT) ||
+           tablet_has_status(tablet, TABLET_BUTTONS_DOWN)) {
                tablet_proximity_out_quirk_set_timer(tablet, now);
                return;
        }
index ab95b61..52806d4 100644 (file)
@@ -37,15 +37,16 @@ enum tablet_status {
        TABLET_NONE                     = 0,
        TABLET_AXES_UPDATED             = bit(0),
        TABLET_BUTTONS_PRESSED          = bit(1),
-       TABLET_BUTTONS_RELEASED         = bit(2),
-       TABLET_TOOL_UPDATED             = bit(3),
-       TABLET_TOOL_IN_CONTACT          = bit(4),
-       TABLET_TOOL_LEAVING_PROXIMITY   = bit(5),
-       TABLET_TOOL_OUT_OF_PROXIMITY    = bit(6),
-       TABLET_TOOL_ENTERING_PROXIMITY  = bit(7),
-       TABLET_TOOL_ENTERING_CONTACT    = bit(8),
-       TABLET_TOOL_LEAVING_CONTACT     = bit(9),
-       TABLET_TOOL_OUT_OF_RANGE        = bit(10),
+       TABLET_BUTTONS_DOWN             = bit(2),
+       TABLET_BUTTONS_RELEASED         = bit(3),
+       TABLET_TOOL_UPDATED             = bit(4),
+       TABLET_TOOL_IN_CONTACT          = bit(5),
+       TABLET_TOOL_LEAVING_PROXIMITY   = bit(6),
+       TABLET_TOOL_OUT_OF_PROXIMITY    = bit(7),
+       TABLET_TOOL_ENTERING_PROXIMITY  = bit(8),
+       TABLET_TOOL_ENTERING_CONTACT    = bit(9),
+       TABLET_TOOL_LEAVING_CONTACT     = bit(10),
+       TABLET_TOOL_OUT_OF_RANGE        = bit(11),
 };
 
 struct button_state {
index 999d1a4..e79dbae 100644 (file)
@@ -1098,9 +1098,6 @@ START_TEST(proximity_out_clear_buttons)
                litest_tablet_proximity_out(dev);
                libinput_dispatch(li);
 
-               litest_timeout_tablet_proxout();
-               libinput_dispatch(li);
-
                event = libinput_get_event(li);
                ck_assert_notnull(event);
                do {
@@ -1570,6 +1567,50 @@ START_TEST(proximity_out_not_during_contact)
 }
 END_TEST
 
+START_TEST(proximity_out_not_during_buttonpress)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct axis_replacement axes[] = {
+               { ABS_DISTANCE, 10 },
+               { ABS_PRESSURE, 0 },
+               { -1, -1 }
+       };
+
+       litest_tablet_proximity_in(dev, 10, 10, axes);
+       litest_tablet_motion(dev, 12, 12, axes);
+       litest_drain_events(li);
+
+       litest_event(dev, EV_KEY, BTN_STYLUS, 1);
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);
+       libinput_dispatch(li);
+
+       litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
+
+       litest_timeout_tablet_proxout();
+       libinput_dispatch(li);
+
+       /* No forced proxout yet */
+       litest_assert_empty_queue(li);
+
+       litest_event(dev, EV_KEY, BTN_STYLUS, 0);
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);
+       libinput_dispatch(li);
+
+       litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
+
+       litest_timeout_tablet_proxout();
+       libinput_dispatch(li);
+
+       /* The forced prox out */
+       litest_assert_tablet_proximity_event(li,
+                                            LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
+
+       litest_tablet_proximity_out(dev);
+       litest_assert_empty_queue(li);
+}
+END_TEST
+
 START_TEST(proximity_out_no_timeout)
 {
        struct litest_device *dev = litest_current_device();
@@ -5846,7 +5887,7 @@ TEST_COLLECTION(tablet)
        litest_add_no_device("tablet:tool_serial", tools_with_serials);
        litest_add_no_device("tablet:tool_serial", tools_without_serials);
        litest_add_for_device("tablet:tool_serial", tool_delayed_serial, LITEST_WACOM_HID4800_PEN);
-       litest_add("tablet:proximity", proximity_out_clear_buttons, LITEST_TABLET, LITEST_ANY);
+       litest_add("tablet:proximity", proximity_out_clear_buttons, LITEST_TABLET, LITEST_FORCED_PROXOUT);
        litest_add("tablet:proximity", proximity_in_out, LITEST_TABLET, LITEST_ANY);
        litest_add("tablet:proximity", proximity_in_button_down, LITEST_TABLET, LITEST_ANY);
        litest_add("tablet:proximity", proximity_out_button_up, LITEST_TABLET, LITEST_ANY);
@@ -5859,6 +5900,7 @@ TEST_COLLECTION(tablet)
        litest_add("tablet:proximity", proximity_range_button_release, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
        litest_add("tablet:proximity", proximity_out_slow_event, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
        litest_add("tablet:proximity", proximity_out_not_during_contact, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
+       litest_add("tablet:proximity", proximity_out_not_during_buttonpress, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
        litest_add_for_device("tablet:proximity", proximity_out_no_timeout, LITEST_WACOM_ISDV4_4200_PEN);
 
        litest_add_no_device("tablet:proximity", proximity_out_on_delete);