evdev: restart debouncing timers after every event

Signed-off-by: satrmb <10471-satrmb@users.noreply.gitlab.freedesktop.org>
This commit is contained in:
satrmb 2021-05-19 10:13:06 +02:00
parent c4ea48eda6
commit 0cb570addd
3 changed files with 141 additions and 2 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 97 KiB

View file

@ -57,7 +57,9 @@
7 and 8 are cases where the first event happens within the first timeout
but the second event is outside that timeout (but within the timeout of
the second event). These cases are currently unhandled.
the second event). These cases are handled by restarting the timer on every
event that could be part of a bouncing sequence, which makes these cases
indistinguishable from 5 and 6.
*/
enum debounce_event {
@ -236,6 +238,7 @@ debounce_is_down_waiting_handle_event(struct fallback_dispatch *fallback, enum d
log_debounce_bug(fallback, event);
break;
case DEBOUNCE_EVENT_RELEASE:
debounce_set_timer(fallback, time);
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_DELAYING);
/* Note: In the debouncing RPR case, we use the last
* release's time stamp */
@ -258,6 +261,7 @@ debounce_is_up_delaying_handle_event(struct fallback_dispatch *fallback, enum de
{
switch (event) {
case DEBOUNCE_EVENT_PRESS:
debounce_set_timer(fallback, time);
debounce_set_state(fallback, DEBOUNCE_STATE_IS_DOWN_WAITING);
break;
case DEBOUNCE_EVENT_RELEASE:
@ -304,6 +308,8 @@ debounce_is_up_detecting_spurious_handle_event(struct fallback_dispatch *fallbac
{
switch (event) {
case DEBOUNCE_EVENT_PRESS:
debounce_set_timer(fallback, time);
debounce_set_timer_short(fallback, time);
/* Note: in a bouncing PRP case, we use the last press
* event time */
fallback->debounce.button_time = time;
@ -332,6 +338,8 @@ debounce_is_down_detecting_spurious_handle_event(struct fallback_dispatch *fallb
log_debounce_bug(fallback, event);
break;
case DEBOUNCE_EVENT_RELEASE:
debounce_set_timer(fallback, time);
debounce_set_timer_short(fallback, time);
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_DETECTING_SPURIOUS);
break;
case DEBOUNCE_EVENT_TIMEOUT_SHORT:
@ -355,6 +363,7 @@ debounce_is_up_waiting_handle_event(struct fallback_dispatch *fallback, enum deb
{
switch (event) {
case DEBOUNCE_EVENT_PRESS:
debounce_set_timer(fallback, time);
/* Note: in a debouncing PRP case, we use the last press'
* time */
fallback->debounce.button_time = time;
@ -379,6 +388,7 @@ debounce_is_down_delaying_handle_event(struct fallback_dispatch *fallback, enum
log_debounce_bug(fallback, event);
break;
case DEBOUNCE_EVENT_RELEASE:
debounce_set_timer(fallback, time);
debounce_set_state(fallback, DEBOUNCE_STATE_IS_UP_WAITING);
break;
case DEBOUNCE_EVENT_TIMEOUT_SHORT:

View file

@ -2719,6 +2719,64 @@ START_TEST(debounce_bounce)
}
END_TEST
START_TEST(debounce_bounce_high_delay)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
unsigned int button = _i; /* ranged test */
if (!libinput_device_pointer_has_button(dev->libinput_device,
button))
return;
litest_disable_middleemu(dev);
disable_button_scrolling(dev);
litest_drain_events(li);
/* Debouncing timeout is 25ms after a button down or up. Make sure we go
* over 25ms for the total bouncing duration, but stay under 25ms for
* each single event. */
litest_event(dev, EV_KEY, button, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
msleep(15);
litest_event(dev, EV_KEY, button, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
msleep(15);
litest_event(dev, EV_KEY, button, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_timeout_debounce();
libinput_dispatch(li);
litest_assert_button_event(li,
button,
LIBINPUT_BUTTON_STATE_PRESSED);
litest_assert_empty_queue(li);
litest_event(dev, EV_KEY, button, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
msleep(15);
litest_event(dev, EV_KEY, button, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
msleep(15);
litest_event(dev, EV_KEY, button, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_timeout_debounce();
libinput_dispatch(li);
litest_assert_button_event(li,
button,
LIBINPUT_BUTTON_STATE_RELEASED);
litest_assert_empty_queue(li);
}
END_TEST
START_TEST(debounce_bounce_check_immediate)
{
struct litest_device *dev = litest_current_device();
@ -2908,6 +2966,75 @@ START_TEST(debounce_spurious_multibounce)
}
END_TEST
START_TEST(debounce_spurious_trigger_high_delay)
{
struct litest_device *dev = litest_current_device();
struct libinput *li = dev->libinput;
litest_disable_middleemu(dev);
litest_drain_events(li);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_timeout_debounce();
libinput_dispatch(li);
litest_assert_button_event(li,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
/* Spurious timeout is 12ms after a button down or up. Make sure we go
* over 12ms for the total bouncing duration, but stay under 12ms for
* each single event. */
litest_event(dev, EV_KEY, BTN_LEFT, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
msleep(5);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
msleep(5);
litest_event(dev, EV_KEY, BTN_LEFT, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
msleep(5);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_timeout_debounce();
libinput_dispatch(li);
litest_assert_button_event(li,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
litest_assert_button_event(li,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_PRESSED);
/* gets filtered now */
litest_event(dev, EV_KEY, BTN_LEFT, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_event(dev, EV_KEY, BTN_LEFT, 1);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_timeout_debounce();
litest_assert_empty_queue(li);
litest_event(dev, EV_KEY, BTN_LEFT, 0);
litest_event(dev, EV_SYN, SYN_REPORT, 0);
libinput_dispatch(li);
litest_timeout_debounce();
libinput_dispatch(li);
litest_assert_button_event(li,
BTN_LEFT,
LIBINPUT_BUTTON_STATE_RELEASED);
litest_assert_empty_queue(li);
}
END_TEST
START_TEST(debounce_spurious_dont_enable_on_otherbutton)
{
struct litest_device *dev = litest_current_device();
@ -3231,9 +3358,11 @@ TEST_COLLECTION(pointer)
litest_add(pointer_time_usec, LITEST_RELATIVE, LITEST_ANY);
litest_add_ranged(debounce_bounce, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE, &buttons);
litest_add_ranged(debounce_bounce_high_delay, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE, &buttons);
litest_add(debounce_bounce_check_immediate, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE);
litest_add_ranged(debounce_spurious, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE, &buttons);
litest_add(debounce_spurious_multibounce, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE);
litest_add(debounce_spurious_trigger_high_delay, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE);
litest_add(debounce_spurious_dont_enable_on_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE);
litest_add(debounce_spurious_cancel_debounce_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE);
litest_add(debounce_spurious_switch_to_otherbutton, LITEST_BUTTON, LITEST_TOUCHPAD|LITEST_NO_DEBOUNCE);