mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 15:50:29 +01:00
evdev: discard any frame with EV_SYN SYN_REPORT 1
When the kernel inserts a repeat frame it does that with EV_KEY code value of 2 and the frame itself is a SYN_REPORT with value 1. Nothing in libinput wants those repeat values, so let's discard them here before anything tries to process them. This inserted frame causes bugs on touchpads with EV_REP (rare enough) because while the key event itself is dropped, the timestamp of the frame still causes the next real frame's delta time to shorten, resulting in wrong acceleration values. Closes #1149 Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1255>
This commit is contained in:
parent
06d8750504
commit
9a9466b6a9
2 changed files with 45 additions and 1 deletions
10
src/evdev.c
10
src/evdev.c
|
|
@ -1084,7 +1084,15 @@ evdev_device_dispatch(void *data)
|
|||
"event frame overflow, discarding events.\n");
|
||||
}
|
||||
if (ev.type == EV_SYN && ev.code == SYN_REPORT) {
|
||||
evdev_device_dispatch_frame(libinput, device, frame);
|
||||
/* A SYN_REPORT 1 event is a kernel-inserted
|
||||
* auto-repeat. Nothing in libinput cares about kernel
|
||||
* repeats and the inserted frame causes issues with
|
||||
* timestamp deltas (see e.g. #1145)
|
||||
*/
|
||||
if (ev.value != 1)
|
||||
evdev_device_dispatch_frame(libinput,
|
||||
device,
|
||||
frame);
|
||||
evdev_frame_reset(frame);
|
||||
}
|
||||
} else if (rc == -ENODEV) {
|
||||
|
|
|
|||
|
|
@ -1656,6 +1656,36 @@ START_TEST(device_button_down_remove)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(device_ignore_repeat_frames)
|
||||
{
|
||||
struct litest_device *dev = litest_current_device();
|
||||
struct libinput *li = dev->libinput;
|
||||
|
||||
unsigned int code = BTN_LEFT;
|
||||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
code = BTN_0;
|
||||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
code = KEY_A;
|
||||
if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
|
||||
return LITEST_NOT_APPLICABLE;
|
||||
|
||||
litest_drain_events(li);
|
||||
|
||||
/* Send a button/key press event with a repeat frame
|
||||
* (SYN_REPORT value 1). Notably, the actual event in this frame is
|
||||
* *not* a repeat (value 2), the whole event frame is a repeat frame
|
||||
* though. */
|
||||
litest_event(dev, EV_KEY, code, 1);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||
litest_dispatch(li);
|
||||
litest_event(dev, EV_KEY, code, 0);
|
||||
litest_event(dev, EV_SYN, SYN_REPORT, 1);
|
||||
litest_dispatch(li);
|
||||
|
||||
litest_assert_empty_queue(li);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
TEST_COLLECTION(device)
|
||||
{
|
||||
/* clang-format off */
|
||||
|
|
@ -1743,5 +1773,11 @@ TEST_COLLECTION(device)
|
|||
litest_add(device_seat_phys_name, LITEST_ANY, LITEST_ANY);
|
||||
|
||||
litest_add(device_button_down_remove, LITEST_BUTTON, LITEST_ANY);
|
||||
|
||||
/* Run for various combinations of devices to hopefully cover most backends */
|
||||
litest_add(device_ignore_repeat_frames, LITEST_BUTTON, LITEST_ANY);
|
||||
litest_add(device_ignore_repeat_frames, LITEST_KEYS, LITEST_ANY);
|
||||
litest_add(device_ignore_repeat_frames, LITEST_TABLET, LITEST_ANY);
|
||||
litest_add(device_ignore_repeat_frames, LITEST_TABLET_PAD, LITEST_ANY);
|
||||
/* clang-format off */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue