tablet: Improve forced prox out behavior.

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.

(cherry picked from commit 8568cf1b3a)
This commit is contained in:
John Chadwick 2019-09-29 23:35:09 +00:00 committed by Peter Hutterer
parent 68b471b31f
commit 65cfa032a0
2 changed files with 42 additions and 0 deletions

View file

@ -1944,6 +1944,11 @@ tablet_proximity_out_quirk_timer_func(uint64_t now, void *data)
}; };
struct input_event *e; 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) { if (tablet->quirks.last_event_time > now - FORCED_PROXOUT_TIMEOUT) {
tablet_proximity_out_quirk_set_timer(tablet, tablet_proximity_out_quirk_set_timer(tablet,
tablet->quirks.last_event_time); tablet->quirks.last_event_time);

View file

@ -1534,6 +1534,42 @@ START_TEST(proximity_out_slow_event)
} }
END_TEST 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) START_TEST(proximity_out_no_timeout)
{ {
struct litest_device *dev = litest_current_device(); 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_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_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_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_for_device("tablet:proximity", proximity_out_no_timeout, LITEST_WACOM_ISDV4_4200_PEN);
litest_add_no_device("tablet:proximity", proximity_out_on_delete); litest_add_no_device("tablet:proximity", proximity_out_on_delete);