This property must not be used for any other purpose, no specific behavior
is guaranteed.
-@subsection model_specific_configuration_huion_tablets Graphics tablets without BTN_TOOL_PEN proximity events
-
-On graphics tablets, the <b>BTN_TOOL_PEN</b> bit signals that the pen is in
-detectable range and will send events. When the pen leaves the sensor range,
-the bit must be unset to signal that the tablet is out of proximity again.
-Some HUION PenTablet devices are buggy and do not send this event. To a
-caller, it thus looks like the pen is constantly in proximity. This causes
-unexpected behavior in applications that rely on tablet device proximity.
-
-The property <b>LIBINPUT_MODEL_TABLET_NO_PROXIMITY_OUT</b> may be set
-by a user in a local hwdb file. This property designates the tablet
-to be buggy and that libinput should work around this bug.
-
-Many of the affected tablets cannot be detected automatically by libinput
-because HUION tablets reuse USB IDs. Local configuration is required to set
-this property. Refer to the libinput model quirks hwdb for instructions.
-
-This property must not be used for any other purpose, no specific behavior
-is guaranteed.
*/
}
END_TEST
+START_TEST(huion_static_btn_tool_pen_disable_quirk_on_prox_out)
+{
+ struct litest_device *dev = litest_current_device();
+ struct libinput *li = dev->libinput;
+ bool with_timeout = _i; /* ranged test */
+ int i;
+
+ /* test is run twice, once where the real BTN_TOOL_PEN is triggered
+ * during proximity out, one where the real BTN_TOOL_PEN is
+ * triggered after we already triggered the quirk timeout
+ */
+
+ litest_drain_events(li);
+
+ litest_event(dev, EV_ABS, ABS_X, 20000);
+ litest_event(dev, EV_ABS, ABS_Y, 20000);
+ litest_event(dev, EV_ABS, ABS_PRESSURE, 100);
+ litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ litest_drain_events(li);
+
+ for (i = 0; i < 10; i++) {
+ litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
+ litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ libinput_dispatch(li);
+ }
+ litest_assert_only_typed_events(li,
+ LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+
+ /* Wait past the timeout to expect a proximity out */
+ if (with_timeout) {
+ litest_timeout_tablet_proxout();
+ libinput_dispatch(li);
+ litest_assert_tablet_proximity_event(li,
+ LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
+ }
+
+ /* Send a real prox out, expect quirk to be disabled */
+ litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ libinput_dispatch(li);
+
+ if (with_timeout) {
+ /* we got the proximity event above already */
+ litest_assert_empty_queue(li);
+ } else {
+ litest_assert_tablet_proximity_event(li,
+ LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
+ }
+
+ litest_push_event_frame(dev);
+ litest_tablet_proximity_out(dev);
+ litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ litest_pop_event_frame(dev);
+
+ litest_tablet_proximity_in(dev, 50, 50, NULL);
+ libinput_dispatch(li);
+ litest_assert_tablet_proximity_event(li,
+ LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
+ libinput_dispatch(li);
+
+ for (i = 0; i < 10; i++) {
+ litest_tablet_motion(dev, 50 + i, 50 + i, NULL);
+ libinput_dispatch(li);
+ }
+
+ litest_assert_only_typed_events(li,
+ LIBINPUT_EVENT_TABLET_TOOL_AXIS);
+
+ litest_push_event_frame(dev);
+ litest_tablet_proximity_out(dev);
+ litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
+ litest_event(dev, EV_SYN, SYN_REPORT, 0);
+ litest_pop_event_frame(dev);
+ libinput_dispatch(li);
+
+ litest_assert_tablet_proximity_event(li,
+ LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
+ litest_assert_empty_queue(li);
+}
+END_TEST
+
void
litest_setup_tests_tablet(void)
{
+ struct range with_timeout = { 0, 2 };
+
litest_add("tablet:tool", tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
litest_add("tablet:tool", tool_user_data, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
litest_add("tablet:tool", tool_capability, LITEST_TABLET, LITEST_ANY);
litest_add_for_device("tablet:quirks", huion_static_btn_tool_pen, LITEST_HUION_TABLET);
litest_add_for_device("tablet:quirks", huion_static_btn_tool_pen_no_timeout_during_usage, LITEST_HUION_TABLET);
+ litest_add_ranged_for_device("tablet:quirks", huion_static_btn_tool_pen_disable_quirk_on_prox_out, LITEST_HUION_TABLET, &with_timeout);
}