mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-24 21:40:05 +01:00
Don't sync the MT state for fake MT devices
Devices with ABS_MT_SLOT-1 are fake MT devices, they merely overlap the axis range but don't actually provide slots. The EVIOCGABS ioctl won't work to retrieve the current value - the kernel does not store values for those axes and the return value is always 0. Thus, simply ignore those axes for fake MT devices and instead rely on the next event to update the caller with the correct state for each axis. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
This commit is contained in:
parent
68a297577a
commit
12ff51b871
3 changed files with 91 additions and 2 deletions
|
|
@ -662,8 +662,9 @@ sync_state(struct libevdev *dev)
|
|||
rc = sync_sw_state(dev);
|
||||
if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
|
||||
rc = sync_abs_state(dev);
|
||||
if (rc == 0 && libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
|
||||
rc = sync_mt_state(dev, 1);
|
||||
if (rc == 0 && dev->num_slots > -1 &&
|
||||
libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
|
||||
rc = sync_mt_state(dev, 1);
|
||||
|
||||
dev->queue_nsync = queue_num_elements(dev);
|
||||
|
||||
|
|
|
|||
|
|
@ -377,6 +377,12 @@ extern "C" {
|
|||
* device is not treated as multitouch device. No slot information is
|
||||
* available and the ABS_MT axis range for these devices is treated as all
|
||||
* other EV_ABS axes.
|
||||
*
|
||||
* Note that because of limitations in the kernel API, such fake multitouch
|
||||
* devices can not be reliably synched after a SYN_DROPPED event. libevdev
|
||||
* ignores all ABS_MT axis values during the sync process and instead
|
||||
* relies on the device to send the current axis value with the first event
|
||||
* after SYN_DROPPED.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <libevdev-util.h>
|
||||
|
||||
#include "test-common.h"
|
||||
|
||||
|
|
@ -791,6 +792,86 @@ START_TEST(test_syn_delta_sw)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_syn_delta_fake_mt)
|
||||
{
|
||||
struct uinput_device* uidev;
|
||||
struct libevdev *dev;
|
||||
int rc;
|
||||
struct input_event ev;
|
||||
struct input_absinfo abs[] = { { ABS_X, 0, 1000 },
|
||||
{ ABS_Y, 0, 1000 },
|
||||
{ ABS_MT_POSITION_X, 0, 1000 },
|
||||
{ ABS_MT_POSITION_Y, 0, 1000 },
|
||||
{ ABS_MT_SLOT - 1, 0, 2 }};
|
||||
/* don't set ABS_MT_SLOT here, otherwise uinput will init
|
||||
* slots and the behavior is different to real devices with
|
||||
* such events */
|
||||
unsigned long received[NLONGS(ABS_CNT)] = {0};
|
||||
|
||||
rc = test_create_abs_device(&uidev, &dev, 5, abs,
|
||||
-1);
|
||||
ck_assert_msg(rc == 0, "Failed to uinput device: %s", strerror(-rc));
|
||||
|
||||
/* first set of events */
|
||||
uinput_device_event(uidev, EV_ABS, ABS_X, 200);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_Y, 400);
|
||||
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_SLOT - 1, 1);
|
||||
uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
|
||||
|
||||
/* second set of events */
|
||||
uinput_device_event(uidev, EV_ABS, ABS_X, 201);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_Y, 401);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_X, 101);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_POSITION_Y, 501);
|
||||
uinput_device_event(uidev, EV_ABS, ABS_MT_SLOT - 1, 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);
|
||||
|
||||
while ((rc = libevdev_next_event(dev, LIBEVDEV_READ_STATUS_SYNC, &ev)) != -EAGAIN) {
|
||||
if (ev.type != EV_ABS)
|
||||
continue;
|
||||
|
||||
ck_assert(!bit_is_set(received, ev.code));
|
||||
|
||||
switch(ev.code) {
|
||||
/* see comment below for ABS_MT_POSITION_X
|
||||
* and ABS_MT_POSITION_Y */
|
||||
case ABS_MT_POSITION_X:
|
||||
case ABS_MT_POSITION_Y:
|
||||
ck_abort();
|
||||
break;
|
||||
|
||||
case ABS_MT_SLOT - 1: ck_assert_int_eq(ev.value, 2); break;
|
||||
case ABS_X: ck_assert_int_eq(ev.value, 201); break;
|
||||
case ABS_Y: ck_assert_int_eq(ev.value, 401); break;
|
||||
default:
|
||||
ck_abort();
|
||||
}
|
||||
|
||||
set_bit(received, ev.code);
|
||||
}
|
||||
|
||||
/* Dont' expect ABS_MT values, they are ignored during the sync
|
||||
* process */
|
||||
ck_assert(!bit_is_set(received, ABS_MT_POSITION_X));
|
||||
ck_assert(!bit_is_set(received, ABS_MT_POSITION_Y));
|
||||
ck_assert(bit_is_set(received, ABS_MT_SLOT - 1));
|
||||
ck_assert(bit_is_set(received, ABS_X));
|
||||
ck_assert(bit_is_set(received, ABS_Y));
|
||||
|
||||
ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 201);
|
||||
ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 401);
|
||||
ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_SLOT - 1), 2);
|
||||
|
||||
uinput_device_free(uidev);
|
||||
libevdev_free(dev);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_skipped_sync)
|
||||
{
|
||||
struct uinput_device* uidev;
|
||||
|
|
@ -1511,6 +1592,7 @@ libevdev_events(void)
|
|||
tcase_add_test(tc, test_syn_delta_mt_too_many);
|
||||
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);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("skipped syncs");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue