From 1f3f681fa70a04b80a87011a24cb6e2b827ab231 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 29 Jun 2018 13:43:15 +1000 Subject: [PATCH] fallback: cancel the debounce timers during device remove, not destroy destroy isn't called until the last libinput_device_unref(), so we may trigger a debounce timer after the device was removed. The same fix is neded for the touchpad interface. Fixes https://gitlab.freedesktop.org/libinput/libinput/issues/72 Signed-off-by: Peter Hutterer --- src/evdev-fallback.c | 6 +++-- src/evdev-mt-touchpad.c | 3 ++- test/test-pointer.c | 54 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/evdev-fallback.c b/src/evdev-fallback.c index 7dad0fce..22dfb1b6 100644 --- a/src/evdev-fallback.c +++ b/src/evdev-fallback.c @@ -1012,6 +1012,9 @@ fallback_interface_remove(struct evdev_dispatch *evdev_dispatch) struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); struct evdev_paired_keyboard *kbd, *tmp; + libinput_timer_cancel(&dispatch->debounce.timer); + libinput_timer_cancel(&dispatch->debounce.timer_short); + libinput_device_remove_event_listener(&dispatch->tablet_mode.other.listener); list_for_each_safe(kbd, @@ -1081,10 +1084,9 @@ fallback_interface_destroy(struct evdev_dispatch *evdev_dispatch) { struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); - libinput_timer_cancel(&dispatch->debounce.timer); libinput_timer_destroy(&dispatch->debounce.timer); - libinput_timer_cancel(&dispatch->debounce.timer_short); libinput_timer_destroy(&dispatch->debounce.timer_short); + free(dispatch->mt.slots); free(dispatch); } diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 03ea9b38..5554c0bd 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1782,6 +1782,8 @@ tp_interface_remove(struct evdev_dispatch *dispatch) { struct tp_dispatch *tp = tp_dispatch(dispatch); + libinput_timer_cancel(&tp->arbitration.arbitration_timer); + tp_remove_tap(tp); tp_remove_buttons(tp); tp_remove_sendevents(tp); @@ -1794,7 +1796,6 @@ tp_interface_destroy(struct evdev_dispatch *dispatch) { struct tp_dispatch *tp = tp_dispatch(dispatch); - libinput_timer_cancel(&tp->arbitration.arbitration_timer); libinput_timer_destroy(&tp->arbitration.arbitration_timer); libinput_timer_destroy(&tp->palm.trackpoint_timer); libinput_timer_destroy(&tp->dwt.keyboard_timer); diff --git a/test/test-pointer.c b/test/test-pointer.c index d6ff4ffe..ff0b3c61 100644 --- a/test/test-pointer.c +++ b/test/test-pointer.c @@ -2533,6 +2533,58 @@ START_TEST(debounce_spurious_switch_to_otherbutton) } END_TEST +START_TEST(debounce_remove_device_button_up) +{ + struct libinput *li; + struct litest_device *dev; + + li = litest_create_context(); + + dev = litest_add_device(li, LITEST_MOUSE); + litest_drain_events(li); + + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + /* delete the device while the timer is still active */ + litest_delete_device(dev); + libinput_dispatch(li); + + litest_timeout_debounce(); + libinput_dispatch(li); + + libinput_unref(li); +} +END_TEST + +START_TEST(debounce_remove_device_button_down) +{ + struct libinput *li; + struct litest_device *dev; + + li = litest_create_context(); + + dev = litest_add_device(li, LITEST_MOUSE); + litest_drain_events(li); + + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + /* delete the device the timer is still active */ + litest_delete_device(dev); + libinput_dispatch(li); + + litest_timeout_debounce(); + libinput_dispatch(li); + + libinput_unref(li); +} +END_TEST + TEST_COLLECTION(pointer) { struct range axis_range = {ABS_X, ABS_Y + 1}; @@ -2607,4 +2659,6 @@ TEST_COLLECTION(pointer) litest_add("pointer:debounce_otherbutton", debounce_spurious_dont_enable_on_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); litest_add("pointer:debounce_otherbutton", debounce_spurious_cancel_debounce_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); litest_add("pointer:debounce_otherbutton", debounce_spurious_switch_to_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE); + litest_add_no_device("pointer:debounce", debounce_remove_device_button_down); + litest_add_no_device("pointer:debounce", debounce_remove_device_button_up); }