mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-25 14:00:06 +01:00
Send an extra ABS_MT_SLOT event to sync the client up with the current slot
If multiple slots have changed during the sync handling, the client must be re-set to the current slot before continuing with normal events. Signed-off-by: Benjamin Tissoires <btissoir@redhat.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
parent
12ff51b871
commit
d3ae3da90f
2 changed files with 116 additions and 2 deletions
|
|
@ -551,9 +551,12 @@ out:
|
|||
static int
|
||||
sync_mt_state(struct libevdev *dev, int create_events)
|
||||
{
|
||||
struct input_event *ev;
|
||||
struct input_absinfo abs_info;
|
||||
int rc;
|
||||
int axis, slot;
|
||||
int ioctl_success = 0;
|
||||
int last_reported_slot = 0;
|
||||
struct mt_state {
|
||||
int code;
|
||||
int val[MAX_SLOTS];
|
||||
|
|
@ -599,14 +602,18 @@ sync_mt_state(struct libevdev *dev, int create_events)
|
|||
}
|
||||
}
|
||||
|
||||
for (slot = 0; create_events && slot < min(dev->num_slots, MAX_SLOTS); slot++) {
|
||||
struct input_event *ev;
|
||||
if (!create_events) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (slot = 0; slot < min(dev->num_slots, MAX_SLOTS); slot++) {
|
||||
if (!bit_is_set(slot_update, AXISBIT(slot, ABS_MT_SLOT)))
|
||||
continue;
|
||||
|
||||
ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_ABS, ABS_MT_SLOT, slot);
|
||||
last_reported_slot = slot;
|
||||
|
||||
for (axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
|
||||
if (axis == ABS_MT_SLOT ||
|
||||
|
|
@ -620,6 +627,20 @@ sync_mt_state(struct libevdev *dev, int create_events)
|
|||
}
|
||||
}
|
||||
|
||||
/* add one last slot event to make sure the client is on the same
|
||||
slot as the kernel */
|
||||
|
||||
rc = ioctl(dev->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
dev->current_slot = abs_info.value;
|
||||
|
||||
if (dev->current_slot != last_reported_slot) {
|
||||
ev = queue_push(dev);
|
||||
init_event(dev, ev, EV_ABS, ABS_MT_SLOT, dev->current_slot);
|
||||
}
|
||||
|
||||
#undef AXISBIT
|
||||
|
||||
rc = 0;
|
||||
|
|
|
|||
|
|
@ -585,6 +585,93 @@ START_TEST(test_syn_delta_mt)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_syn_delta_mt_reset_slot)
|
||||
{
|
||||
struct uinput_device* uidev;
|
||||
struct libevdev *dev;
|
||||
int rc;
|
||||
struct input_event ev,
|
||||
last_slot_event = { .type = 0};
|
||||
struct input_absinfo abs[6];
|
||||
|
||||
memset(abs, 0, sizeof(abs));
|
||||
abs[0].value = ABS_X;
|
||||
abs[0].maximum = 1000;
|
||||
abs[1].value = ABS_MT_POSITION_X;
|
||||
abs[1].maximum = 1000;
|
||||
|
||||
abs[2].value = ABS_Y;
|
||||
abs[2].maximum = 1000;
|
||||
abs[3].value = ABS_MT_POSITION_Y;
|
||||
abs[3].maximum = 1000;
|
||||
|
||||
|
||||
abs[4].value = ABS_MT_SLOT;
|
||||
abs[4].maximum = 1;
|
||||
abs[5].value = ABS_MT_TRACKING_ID;
|
||||
abs[5].minimum = -1;
|
||||
abs[5].maximum = 2;
|
||||
|
||||
rc = test_create_abs_device(&uidev, &dev,
|
||||
6, abs,
|
||||
EV_SYN, SYN_REPORT,
|
||||
-1);
|
||||
ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
|
||||
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 1);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 100);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 500);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 0);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 1);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 5);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 2);
|
||||
uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
|
||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC);
|
||||
|
||||
do {
|
||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
|
||||
if (libevdev_event_is_code(&ev, EV_ABS, ABS_MT_SLOT))
|
||||
last_slot_event = ev;
|
||||
} while (rc != -EAGAIN);
|
||||
|
||||
ck_assert(libevdev_event_is_code(&last_slot_event, EV_ABS, ABS_MT_SLOT));
|
||||
ck_assert_int_eq(last_slot_event.value, 0);
|
||||
ck_assert_int_eq(libevdev_get_current_slot(dev), 0);
|
||||
|
||||
last_slot_event.type = 0;
|
||||
|
||||
/* same thing again, this time swap the numbers */
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 0);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 100);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 500);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 1);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT, 1);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 1);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 5);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_TRACKING_ID, 2);
|
||||
uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_FORCE_SYNC, &ev);
|
||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC);
|
||||
|
||||
do {
|
||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
|
||||
if (libevdev_event_is_code(&ev, EV_ABS, ABS_MT_SLOT))
|
||||
last_slot_event = ev;
|
||||
} while (rc != -EAGAIN);
|
||||
|
||||
ck_assert(libevdev_event_is_code(&last_slot_event, EV_ABS, ABS_MT_SLOT));
|
||||
ck_assert_int_eq(last_slot_event.value, 1);
|
||||
ck_assert_int_eq(libevdev_get_current_slot(dev), 1);
|
||||
|
||||
uinput_device_free(uidev);
|
||||
libevdev_free(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_syn_delta_mt_too_many)
|
||||
{
|
||||
struct uinput_device* uidev;
|
||||
|
|
@ -656,6 +743,11 @@ START_TEST(test_syn_delta_mt_too_many)
|
|||
ck_assert_int_lt(slot, MAX_SLOTS);
|
||||
|
||||
rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev);
|
||||
|
||||
/* last MT_SLOT event is on its own */
|
||||
if (libevdev_event_is_code(&ev, EV_SYN, SYN_REPORT))
|
||||
break;
|
||||
|
||||
ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SYNC);
|
||||
ck_assert_int_eq(ev.type, EV_ABS);
|
||||
ck_assert_int_eq(ev.code, ABS_MT_POSITION_X);
|
||||
|
|
@ -1590,6 +1682,7 @@ libevdev_events(void)
|
|||
tcase_add_test(tc, test_syn_delta_abs);
|
||||
tcase_add_test(tc, test_syn_delta_mt);
|
||||
tcase_add_test(tc, test_syn_delta_mt_too_many);
|
||||
tcase_add_test(tc, test_syn_delta_mt_reset_slot);
|
||||
tcase_add_test(tc, test_syn_delta_led);
|
||||
tcase_add_test(tc, test_syn_delta_sw);
|
||||
tcase_add_test(tc, test_syn_delta_fake_mt);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue