mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-05 19:18:03 +02:00
touchpad: improve finger counting for synaptics serial touchpads
A three-finger touch may cause slot N to end, in a frame after the BTN_TOOL_TRIPLETAP. This causes tp->nfinger_down to be decremented to 2 as the touch switches to MAYBE_END - which happens to be our num_slots. We exit early and never restore the touch correctly. Fix this by checking that the number of fake touches is equal to the slots, if it is higher then we need to check for recovery. Fixes https://gitlab.freedesktop.org/libinput/libinput/issues/99 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
da0fbb580f
commit
ba603ea192
3 changed files with 202 additions and 1 deletions
|
|
@ -554,7 +554,7 @@ tp_restore_synaptics_touches(struct tp_dispatch *tp,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (tp->nfingers_down >= nfake_touches ||
|
if (tp->nfingers_down >= nfake_touches ||
|
||||||
tp->nfingers_down == tp->num_slots)
|
(tp->nfingers_down == tp->num_slots && nfake_touches == tp->num_slots))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Synaptics devices may end touch 2 on BTN_TOOL_TRIPLETAP
|
/* Synaptics devices may end touch 2 on BTN_TOOL_TRIPLETAP
|
||||||
|
|
|
||||||
|
|
@ -1886,6 +1886,96 @@ START_TEST(touchpad_3fg_tap_btntool_pointerjump)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_3fg_tap_slot_release_btntool)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput *li = dev->libinput;
|
||||||
|
|
||||||
|
/* Synaptics touchpads sometimes end one touch point after
|
||||||
|
* setting BTN_TOOL_TRIPLETAP.
|
||||||
|
* https://gitlab.freedesktop.org/libinput/libinput/issues/99
|
||||||
|
*/
|
||||||
|
litest_drain_events(li);
|
||||||
|
litest_enable_tap(dev->libinput_device);
|
||||||
|
|
||||||
|
/* touch 1 down */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 2200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_ABS, ABS_X, 2200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_Y, 3200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
msleep(2);
|
||||||
|
|
||||||
|
/* touch 2 and TRIPLETAP down */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 2500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3800);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 73);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
msleep(2);
|
||||||
|
|
||||||
|
/* touch 2 up, coordinate jump + ends slot 1, TRIPLETAP stays */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 2500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3800);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_X, 2500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_Y, 3800);
|
||||||
|
litest_event(dev, EV_ABS, ABS_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
msleep(2);
|
||||||
|
|
||||||
|
/* slot 2 reactivated
|
||||||
|
*/
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 2500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3800);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 3);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 3500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 73);
|
||||||
|
litest_event(dev, EV_ABS, ABS_X, 2200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_Y, 3200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
|
||||||
|
/* now end all three */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
litest_timeout_tap();
|
||||||
|
libinput_dispatch(li);
|
||||||
|
|
||||||
|
litest_assert_button_event(li, BTN_MIDDLE,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
litest_assert_button_event(li, BTN_MIDDLE,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
|
||||||
|
litest_assert_empty_queue(li);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(touchpad_4fg_tap)
|
START_TEST(touchpad_4fg_tap)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
|
@ -3454,6 +3544,8 @@ TEST_COLLECTION(touchpad_tap)
|
||||||
litest_add("tap-3fg:3fg", touchpad_3fg_tap_hover_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("tap-3fg:3fg", touchpad_3fg_tap_hover_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
litest_add("tap-3fg:3fg", touchpad_3fg_tap_pressure_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
litest_add("tap-3fg:3fg", touchpad_3fg_tap_pressure_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
|
||||||
litest_add_for_device("tap-3fg:3fg", touchpad_3fg_tap_btntool_pointerjump, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
litest_add_for_device("tap-3fg:3fg", touchpad_3fg_tap_btntool_pointerjump, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||||
|
litest_add_for_device("tap-3fg:3fg", touchpad_3fg_tap_slot_release_btntool, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||||
|
|
||||||
litest_add("tap-4fg:4fg", touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
litest_add("tap-4fg:4fg", touchpad_4fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
||||||
litest_add("tap-4fg:4fg", touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
litest_add("tap-4fg:4fg", touchpad_4fg_tap_quickrelease, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
||||||
litest_add("tap-5fg:5fg", touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
litest_add("tap-5fg:5fg", touchpad_5fg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
|
||||||
|
|
|
||||||
|
|
@ -5165,6 +5165,114 @@ START_TEST(touchpad_tool_tripletap_touch_count)
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(touchpad_tool_tripletap_touch_count_late)
|
||||||
|
{
|
||||||
|
struct litest_device *dev = litest_current_device();
|
||||||
|
struct libinput *li = dev->libinput;
|
||||||
|
struct libinput_event *event;
|
||||||
|
|
||||||
|
/* Synaptics touchpads sometimes end one touch point after
|
||||||
|
* setting BTN_TOOL_TRIPLETAP.
|
||||||
|
* https://gitlab.freedesktop.org/libinput/libinput/issues/99
|
||||||
|
*/
|
||||||
|
litest_drain_events(li);
|
||||||
|
litest_enable_clickfinger(dev);
|
||||||
|
|
||||||
|
/* touch 1 down */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 1200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_ABS, ABS_X, 1200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_Y, 3200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOUCH, 1);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
msleep(2);
|
||||||
|
|
||||||
|
/* touch 2 and TRIPLETAP down */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 2200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3200);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 73);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
msleep(2);
|
||||||
|
|
||||||
|
/* touch 2 up, coordinate jump + ends slot 1, TRIPLETAP stays */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_X, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_Y, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
msleep(2);
|
||||||
|
|
||||||
|
/* slot 2 reactivated:
|
||||||
|
* Note, slot is activated close enough that we don't accidentally
|
||||||
|
* trigger the clickfinger distance check, remains to be seen if
|
||||||
|
* that is true for real-world interaction.
|
||||||
|
*/
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 3);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 3500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 3500);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 73);
|
||||||
|
litest_event(dev, EV_ABS, ABS_X, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_Y, 4000);
|
||||||
|
litest_event(dev, EV_ABS, ABS_PRESSURE, 78);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
msleep(2);
|
||||||
|
|
||||||
|
/* now a click should trigger middle click */
|
||||||
|
litest_event(dev, EV_KEY, BTN_LEFT, 1);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
litest_event(dev, EV_KEY, BTN_LEFT, 0);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
libinput_dispatch(li);
|
||||||
|
|
||||||
|
litest_wait_for_event(li);
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
litest_is_button_event(event,
|
||||||
|
BTN_MIDDLE,
|
||||||
|
LIBINPUT_BUTTON_STATE_PRESSED);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
event = libinput_get_event(li);
|
||||||
|
litest_is_button_event(event,
|
||||||
|
BTN_MIDDLE,
|
||||||
|
LIBINPUT_BUTTON_STATE_RELEASED);
|
||||||
|
libinput_event_destroy(event);
|
||||||
|
|
||||||
|
/* release everything */
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
|
||||||
|
litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 0);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0);
|
||||||
|
litest_event(dev, EV_KEY, BTN_TOUCH, 0);
|
||||||
|
litest_event(dev, EV_SYN, SYN_REPORT, 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(touchpad_slot_swap)
|
START_TEST(touchpad_slot_swap)
|
||||||
{
|
{
|
||||||
struct litest_device *dev = litest_current_device();
|
struct litest_device *dev = litest_current_device();
|
||||||
|
|
@ -6482,6 +6590,7 @@ TEST_COLLECTION(touchpad)
|
||||||
litest_add("touchpad:thumb", touchpad_thumb_move_and_tap, LITEST_CLICKPAD, LITEST_ANY);
|
litest_add("touchpad:thumb", touchpad_thumb_move_and_tap, LITEST_CLICKPAD, LITEST_ANY);
|
||||||
|
|
||||||
litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||||
|
litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count_late, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||||
litest_add_for_device("touchpad:bugs", touchpad_slot_swap, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
litest_add_for_device("touchpad:bugs", touchpad_slot_swap, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||||
litest_add_for_device("touchpad:bugs", touchpad_finger_always_down, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
litest_add_for_device("touchpad:bugs", touchpad_finger_always_down, LITEST_SYNAPTICS_TOPBUTTONPAD);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue