tablet: Improve forced prox out behavior.
authorJohn Chadwick <johnwchadwick@gmail.com>
Sun, 29 Sep 2019 23:35:09 +0000 (23:35 +0000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Sun, 29 Sep 2019 23:35:09 +0000 (23:35 +0000)
Some graphics tablets (most or all Wacom, for example) do not emit
proximity out events when the tablet pen goes out of range. To
compensate for this, libinput synthesizes proximity out events when no
events are received for a certain period of time. Unfortunately, on some
tablets, this is fairly failure prone when moving the pen slowly. As a
workaround, this patch causes libinput to avoid synthesizing proximity
out events when the pen is still in contact with the tablet pad, as
defined by the TABLET_TOOL_IN_CONTACT status.

src/evdev-tablet.c
test/test-tablet.c

index b000aba2920a1a27d25477c8d4d038233f9080d1..0e9c8e4642a3398bb82f33044a214dc00da4c0b9 100644 (file)
@@ -1943,6 +1943,11 @@ tablet_proximity_out_quirk_timer_func(uint64_t now, void *data)
        };
        struct input_event *e;
 
+       if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) {
+               tablet_proximity_out_quirk_set_timer(tablet, now);
+               return;
+       }
+
        if (tablet->quirks.last_event_time > now - FORCED_PROXOUT_TIMEOUT) {
                tablet_proximity_out_quirk_set_timer(tablet,
                                                     tablet->quirks.last_event_time);
index 90b81a7fb0aa80dd529745e1bc014c6d2e326e6a..f4915bc0228ac96ca33f72a1720c820de89aa8d3 100644 (file)
@@ -1534,6 +1534,42 @@ START_TEST(proximity_out_slow_event)
 }
 END_TEST
 
+START_TEST(proximity_out_not_during_contact)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct axis_replacement axes[] = {
+               { ABS_DISTANCE, 0 },
+               { ABS_PRESSURE, 10 },
+               { -1, -1 }
+       };
+
+       litest_tablet_proximity_in(dev, 10, 10, axes);
+       litest_tablet_motion(dev, 12, 12, axes);
+       litest_drain_events(li);
+
+       litest_timeout_tablet_proxout();
+       libinput_dispatch(li);
+
+       /* No forced proxout yet */
+       litest_assert_empty_queue(li);
+
+       litest_axis_set_value(axes, ABS_PRESSURE, 0);
+       litest_tablet_motion(dev, 14, 14, axes);
+       litest_drain_events(li);
+
+       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();
@@ -5756,6 +5792,7 @@ TEST_COLLECTION(tablet)
        litest_add("tablet:proximity", proximity_range_button_press, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
        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_for_device("tablet:proximity", proximity_out_no_timeout, LITEST_WACOM_ISDV4_4200_PEN);
 
        litest_add_no_device("tablet:proximity", proximity_out_on_delete);