<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 20, 2017 at 3:40 AM, Peter Hutterer <span dir="ltr"><<a href="mailto:peter.hutterer@who-t.net" target="_blank">peter.hutterer@who-t.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">And instead disable it when we do get a proximity out.<br>
<br>
Signed-off-by: Peter Hutterer <<a href="mailto:peter.hutterer@who-t.net">peter.hutterer@who-t.net</a>><br>
---<br></blockquote><div><br></div><div>This looks good to me:</div><div>Reviewed-by: Benjamin Tissoires <<a href="mailto:benjamin.tissoires@gmail.com">benjamin.tissoires@gmail.com</a>></div><div><br></div><div>Cheers,</div><div>Benjamin<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Follow-up to<br>
<a href="https://lists.freedesktop.org/archives/wayland-devel/2017-September/035006.html" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>archives/wayland-devel/2017-<wbr>September/035006.html</a><br>
While writing some more documentation for it, I realised it's easier to just<br>
enable this on all HUION tablets and auto-disable it on those that support<br>
real proximity out. Much better than having the user drop a hwdb file and<br>
hope it works.<br>
<br>
 doc/device-configuration-via-<wbr>udev.dox  | 19 --------<br>
 src/evdev-tablet.c                     | 15 +++++-<br>
 src/evdev-tablet.h                     |  3 ++<br>
 test/test-tablet.c                     | 87 ++++++++++++++++++++++++++++++<wbr>++++<br>
 udev/90-libinput-model-quirks.<wbr>hwdb     | 13 ++---<br>
 udev/<a href="http://90-libinput-model-quirks.rules.in" rel="noreferrer" target="_blank">90-libinput-model-quirks.<wbr>rules.in</a> |  4 ++<br>
 udev/parse_hwdb.py                     |  2 +-<br>
 7 files changed, 112 insertions(+), 31 deletions(-)<br>
<br>
diff --git a/doc/device-configuration-<wbr>via-udev.dox b/doc/device-configuration-<wbr>via-udev.dox<br>
index 3050cd80..2ebfa321 100644<br>
--- a/doc/device-configuration-<wbr>via-udev.dox<br>
+++ b/doc/device-configuration-<wbr>via-udev.dox<br>
@@ -162,23 +162,4 @@ model quirks hwdb for instructions.<br>
 This property must not be used for any other purpose, no specific behavior<br>
 is guaranteed.<br>
<br>
-@subsection model_specific_configuration_<wbr>huion_tablets Graphics tablets without BTN_TOOL_PEN proximity events<br>
-<br>
-On graphics tablets, the <b>BTN_TOOL_PEN</b> bit signals that the pen is in<br>
-detectable range and will send events. When the pen leaves the sensor range,<br>
-the bit must be unset to signal that the tablet is out of proximity again.<br>
-Some HUION PenTablet devices are buggy and do not send this event. To a<br>
-caller, it thus looks like the pen is constantly in proximity. This causes<br>
-unexpected behavior in applications that rely on tablet device proximity.<br>
-<br>
-The property <b>LIBINPUT_MODEL_TABLET_NO_<wbr>PROXIMITY_OUT</b> may be set<br>
-by a user in a local hwdb file. This property designates the tablet<br>
-to be buggy and that libinput should work around this bug.<br>
-<br>
-Many of the affected tablets cannot be detected automatically by libinput<br>
-because HUION tablets reuse USB IDs.  Local configuration is required to set<br>
-this property. Refer to the libinput model quirks hwdb for instructions.<br>
-<br>
-This property must not be used for any other purpose, no specific behavior<br>
-is guaranteed.<br>
 */<br>
diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c<br>
index 7e9281d1..21501c2b 100644<br>
--- a/src/evdev-tablet.c<br>
+++ b/src/evdev-tablet.c<br>
@@ -1667,12 +1667,14 @@ tablet_proximity_out_quirk_<wbr>timer_func(uint64_t now, void *data)<br>
                return;<br>
        }<br>
<br>
+       tablet->quirks.proximity_out_<wbr>in_progress = true;<br>
        ARRAY_FOR_EACH(events, e) {<br>
                tablet->base.interface-><wbr>process(&tablet->base,<br>
                                                 tablet->device,<br>
                                                 e,<br>
                                                 now);<br>
        }<br>
+       tablet->quirks.proximity_out_<wbr>in_progress = false;<br>
<br>
        tablet->quirks.proximity_out_<wbr>forced = true;<br>
 }<br>
@@ -1721,10 +1723,19 @@ tablet_proximity_out_quirk_<wbr>update(struct tablet_dispatch *tablet,<br>
                }<br>
                tablet->quirks.last_event_time = time;<br>
        } else if (e->type == EV_KEY && e->code == BTN_TOOL_PEN) {<br>
-               if (e->value)<br>
+               if (e->value) {<br>
                        tablet_proximity_out_quirk_<wbr>set_timer(tablet, time);<br>
-               else<br>
+               } else {<br>
+                       /* If we get a BTN_TOOL_PEN 0 when *not* injecting<br>
+                        * events it means the tablet will give us the right<br>
+                        * events after all and we can disable our<br>
+                        * timer-based proximity out.<br>
+                        */<br>
+                       if (!tablet->quirks.proximity_<wbr>out_in_progress)<br>
+                               tablet->quirks.need_to_force_<wbr>prox_out = false;<br>
+<br>
                        libinput_timer_cancel(&tablet-<wbr>>quirks.prox_out_timer);<br>
+               }<br>
        }<br>
 }<br>
<br>
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h<br>
index ba05e88c..bf5a3dc1 100644<br>
--- a/src/evdev-tablet.h<br>
+++ b/src/evdev-tablet.h<br>
@@ -89,6 +89,9 @@ struct tablet_dispatch {<br>
                struct libinput_timer prox_out_timer;<br>
                bool proximity_out_forced;<br>
                uint64_t last_event_time;<br>
+<br>
+               /* true while injecting BTN_TOOL_PEN events */<br>
+               bool proximity_out_in_progress;<br>
        } quirks;<br>
 };<br>
<br>
diff --git a/test/test-tablet.c b/test/test-tablet.c<br>
index 66b4f79c..92fd45b9 100644<br>
--- a/test/test-tablet.c<br>
+++ b/test/test-tablet.c<br>
@@ -4445,9 +4445,95 @@ START_TEST(huion_static_btn_<wbr>tool_pen_no_timeout_during_<wbr>usage)<br>
 }<br>
 END_TEST<br>
<br>
+START_TEST(huion_static_btn_<wbr>tool_pen_disable_quirk_on_<wbr>prox_out)<br>
+{<br>
+       struct litest_device *dev = litest_current_device();<br>
+       struct libinput *li = dev->libinput;<br>
+       bool with_timeout = _i; /* ranged test */<br>
+       int i;<br>
+<br>
+       /* test is run twice, once where the real BTN_TOOL_PEN is triggered<br>
+        * during proximity out, one where the real BTN_TOOL_PEN is<br>
+        * triggered after we already triggered the quirk timeout<br>
+        */<br>
+<br>
+       litest_drain_events(li);<br>
+<br>
+       litest_event(dev, EV_ABS, ABS_X, 20000);<br>
+       litest_event(dev, EV_ABS, ABS_Y, 20000);<br>
+       litest_event(dev, EV_ABS, ABS_PRESSURE, 100);<br>
+       litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);<br>
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>
+       litest_drain_events(li);<br>
+<br>
+       for (i = 0; i < 10; i++) {<br>
+               litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);<br>
+               litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);<br>
+               litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>
+               libinput_dispatch(li);<br>
+       }<br>
+       litest_assert_only_typed_<wbr>events(li,<br>
+                                       LIBINPUT_EVENT_TABLET_TOOL_<wbr>AXIS);<br>
+<br>
+       /* Wait past the timeout to expect a proximity out */<br>
+       if (with_timeout) {<br>
+               litest_timeout_tablet_proxout(<wbr>);<br>
+               libinput_dispatch(li);<br>
+               litest_assert_tablet_<wbr>proximity_event(li,<br>
+                                                    LIBINPUT_TABLET_TOOL_<wbr>PROXIMITY_STATE_OUT);<br>
+       }<br>
+<br>
+       /* Send a real prox out, expect quirk to be disabled */<br>
+       litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);<br>
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>
+       libinput_dispatch(li);<br>
+<br>
+       if (with_timeout) {<br>
+               /* we got the proximity event above already */<br>
+               litest_assert_empty_queue(li);<br>
+       } else {<br>
+               litest_assert_tablet_<wbr>proximity_event(li,<br>
+                                                    LIBINPUT_TABLET_TOOL_<wbr>PROXIMITY_STATE_OUT);<br>
+       }<br>
+<br>
+       litest_push_event_frame(dev);<br>
+       litest_tablet_proximity_out(<wbr>dev);<br>
+       litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);<br>
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>
+       litest_pop_event_frame(dev);<br>
+<br>
+       litest_tablet_proximity_in(<wbr>dev, 50, 50, NULL);<br>
+       libinput_dispatch(li);<br>
+       litest_assert_tablet_<wbr>proximity_event(li,<br>
+                            LIBINPUT_TABLET_TOOL_<wbr>PROXIMITY_STATE_IN);<br>
+       libinput_dispatch(li);<br>
+<br>
+       for (i = 0; i < 10; i++) {<br>
+               litest_tablet_motion(dev, 50 + i, 50 + i, NULL);<br>
+               libinput_dispatch(li);<br>
+       }<br>
+<br>
+       litest_assert_only_typed_<wbr>events(li,<br>
+                                       LIBINPUT_EVENT_TABLET_TOOL_<wbr>AXIS);<br>
+<br>
+       litest_push_event_frame(dev);<br>
+       litest_tablet_proximity_out(<wbr>dev);<br>
+       litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);<br>
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);<br>
+       litest_pop_event_frame(dev);<br>
+       libinput_dispatch(li);<br>
+<br>
+       litest_assert_tablet_<wbr>proximity_event(li,<br>
+                            LIBINPUT_TABLET_TOOL_<wbr>PROXIMITY_STATE_OUT);<br>
+       litest_assert_empty_queue(li);<br>
+}<br>
+END_TEST<br>
+<br>
 void<br>
 litest_setup_tests_tablet(<wbr>void)<br>
 {<br>
+       struct range with_timeout = { 0, 2 };<br>
+<br>
        litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);<br>
        litest_add("tablet:tool", tool_user_data, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);<br>
        litest_add("tablet:tool", tool_capability, LITEST_TABLET, LITEST_ANY);<br>
@@ -4543,4 +4629,5 @@ litest_setup_tests_tablet(<wbr>void)<br>
<br>
        litest_add_for_device("tablet:<wbr>quirks", huion_static_btn_tool_pen, LITEST_HUION_TABLET);<br>
        litest_add_for_device("tablet:<wbr>quirks", huion_static_btn_tool_pen_no_<wbr>timeout_during_usage, LITEST_HUION_TABLET);<br>
+       litest_add_ranged_for_device("<wbr>tablet:quirks", huion_static_btn_tool_pen_<wbr>disable_quirk_on_prox_out, LITEST_HUION_TABLET, &with_timeout);<br>
 }<br>
diff --git a/udev/90-libinput-model-<wbr>quirks.hwdb b/udev/90-libinput-model-<wbr>quirks.hwdb<br>
index 867ffa53..6525b800 100644<br>
--- a/udev/90-libinput-model-<wbr>quirks.hwdb<br>
+++ b/udev/90-libinput-model-<wbr>quirks.hwdb<br>
@@ -171,15 +171,10 @@ libinput:name:AlpsPS/2 ALPS GlidePoint:dmi:*svnHP:<wbr>pnHPZBookStudioG3:*<br>
 # matching BTN_TOOL_PEN value 0 event. The device appears as if it was<br>
 # permanently in proximity.<br>
 #<br>
-# If the tablet is affected by this bug, copy the two lines below into a new<br>
-# file<br>
-# /etc/udev/hwdb.d/90-libinput-<wbr>huion-pentablet-proximity-<wbr>quirk.hwdb, then run<br>
-# sudo udevadm hwdb --update and reboot.<br>
-#<br>
-# Note that HUION re-uses USB IDs for its devices, not ever HUION tablet is<br>
-# affected by this bug.<br>
-#libinput:name:PenTablet Pen:dmi:*<br>
-# LIBINPUT_MODEL_TABLET_NO_<wbr>PROXIMITY_OUT=1<br>
+# HUION re-uses USB IDs for its devices, not every HUION tablet is<br>
+# affected by this bug, libinput will auto-disable this feature<br>
+libinput:tablet:input:<wbr>b0003v256Cp*<br>
+ LIBINPUT_MODEL_TABLET_NO_<wbr>PROXIMITY_OUT=1<br>
<br>
 ##############################<wbr>############<br>
 # LENOVO<br>
diff --git a/udev/<a href="http://90-libinput-model-quirks.rules.in" rel="noreferrer" target="_blank">90-libinput-model-<wbr>quirks.rules.in</a> b/udev/<a href="http://90-libinput-model-quirks.rules.in" rel="noreferrer" target="_blank">90-libinput-model-<wbr>quirks.rules.in</a><br>
index 08137812..5c2ff42e 100644<br>
--- a/udev/<a href="http://90-libinput-model-quirks.rules.in" rel="noreferrer" target="_blank">90-libinput-model-<wbr>quirks.rules.in</a><br>
+++ b/udev/<a href="http://90-libinput-model-quirks.rules.in" rel="noreferrer" target="_blank">90-libinput-model-<wbr>quirks.rules.in</a><br>
@@ -29,6 +29,10 @@ KERNELS=="*input*", \<br>
 ENV{ID_INPUT_TOUCHPAD}=="1", \<br>
   IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:<wbr>touchpad:"<br>
<br>
+# libinput:tablet:<modalias><br>
+ENV{ID_INPUT_TABLET}=="1", \<br>
+  IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:<wbr>TABLET:"<br>
+<br>
 # libinput:mouse:<modalias><br>
 ENV{ID_INPUT_MOUSE}=="1", \<br>
   IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=libinput:<wbr>mouse:"<br>
diff --git a/udev/parse_hwdb.py b/udev/parse_hwdb.py<br>
index f6b9ec0a..69eb65b0 100755<br>
--- a/udev/parse_hwdb.py<br>
+++ b/udev/parse_hwdb.py<br>
@@ -59,7 +59,7 @@ REAL = Combine((INTEGER + Optional('.' + Optional(INTEGER))) ^ ('.' + INTEGER))<br>
 UDEV_TAG = Word(string.ascii_uppercase, alphanums + '_')<br>
<br>
 TYPES = {<br>
-    'libinput': ('name', 'touchpad', 'mouse', 'keyboard'),<br>
+    'libinput': ('name', 'touchpad', 'mouse', 'keyboard', 'tablet'),<br>
 }<br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
--<br>
2.13.5<br>
<br>
</font></span></blockquote></div><br></div></div>