Commit ffd8c71e authored by Peter Hutterer's avatar Peter Hutterer

tablet: fix double proximity out on slow proximity out pens

Where the proximity out event is delayed by the kernel, libinput would cause
an extra proxmity in-out after the forced proximity out event.

Event sequence is basically (k: kernel, l: libinput)

k: tablet axis events
l: tablet axis events
k: nothing for $proximity timer milliseconds
l: tablet proximity out
k: proximity out event
l: proximity in event
l: proximity out event

Fixes #306Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent ea5b764e
......@@ -806,6 +806,7 @@ tablet_process_key(struct tablet_dispatch *tablet,
case BTN_TOOL_MOUSE:
case BTN_TOOL_LENS:
type = tablet_evcode_to_tool(e->code);
tablet_set_status(tablet, TABLET_TOOL_UPDATED);
if (e->value)
tablet->tool_state |= bit(type);
else
......@@ -1721,13 +1722,22 @@ tablet_update_tool_state(struct tablet_dispatch *tablet,
* BTN_TOOL_PEN and the state for the tool was 0, this device will
* never send the event.
* We don't do this for pure button events because we discard those.
*
* But: on some devices the proximity out is delayed by the kernel,
* so we get it after our forced prox-out has triggered. In that
* case we need to just ignore the change.
*/
if (tablet_has_status(tablet, TABLET_AXES_UPDATED) &&
(tablet->quirks.proximity_out_forced ||
(tablet->tool_state == 0 &&
tablet->current_tool.type == LIBINPUT_TOOL_NONE))) {
tablet->tool_state = bit(LIBINPUT_TABLET_TOOL_TYPE_PEN);
tablet->quirks.proximity_out_forced = false;
if (tablet_has_status(tablet, TABLET_AXES_UPDATED)) {
if (tablet->quirks.proximity_out_forced) {
if (!tablet_has_status(tablet, TABLET_TOOL_UPDATED) ||
tablet->tool_state)
tablet->tool_state = bit(LIBINPUT_TABLET_TOOL_TYPE_PEN);
tablet->quirks.proximity_out_forced = false;
} else if (tablet->tool_state == 0 &&
tablet->current_tool.type == LIBINPUT_TOOL_NONE) {
tablet->tool_state = bit(LIBINPUT_TABLET_TOOL_TYPE_PEN);
tablet->quirks.proximity_out_forced = false;
}
}
if (tablet->tool_state == tablet->prev_tool_state)
......@@ -1886,6 +1896,7 @@ tablet_reset_state(struct tablet_dispatch *tablet)
memcpy(&tablet->prev_button_state,
&tablet->button_state,
sizeof(tablet->button_state));
tablet_unset_status(tablet, TABLET_TOOL_UPDATED);
}
static void
......
......@@ -38,13 +38,14 @@ enum tablet_status {
TABLET_AXES_UPDATED = bit(0),
TABLET_BUTTONS_PRESSED = bit(1),
TABLET_BUTTONS_RELEASED = bit(2),
TABLET_TOOL_IN_CONTACT = bit(3),
TABLET_TOOL_LEAVING_PROXIMITY = bit(4),
TABLET_TOOL_OUT_OF_PROXIMITY = bit(5),
TABLET_TOOL_ENTERING_PROXIMITY = bit(6),
TABLET_TOOL_ENTERING_CONTACT = bit(7),
TABLET_TOOL_LEAVING_CONTACT = bit(8),
TABLET_TOOL_OUT_OF_RANGE = bit(9),
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),
};
struct button_state {
......
......@@ -1506,6 +1506,32 @@ START_TEST(proximity_range_button_release)
}
END_TEST
START_TEST(proximity_out_slow_event)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
struct axis_replacement axes[] = {
{ ABS_DISTANCE, 90 },
{ -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);
/* The forced prox out */
litest_assert_tablet_proximity_event(li,
LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
litest_assert_empty_queue(li);
litest_tablet_proximity_out(dev);
litest_assert_empty_queue(li);
}
END_TEST
START_TEST(proximity_out_on_delete)
{
struct libinput *li = litest_create_context();
......@@ -5651,6 +5677,8 @@ TEST_COLLECTION(tablet)
litest_add("tablet:proximity", proximity_range_button_click, 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_out_slow_event, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
litest_add_no_device("tablet:proximity", proximity_out_on_delete);
litest_add("tablet:button", button_down_up, LITEST_TABLET, LITEST_ANY);
litest_add("tablet:button", button_seat_count, LITEST_TABLET, LITEST_ANY);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment