From edc31cf12ef9f99e22aacdc93f12dc1511cd6ad0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 15 Aug 2013 11:10:17 +1000 Subject: [PATCH] Store the abs value after handling mt events This way any ABS_MT_ event value that comes in will also be stored in abs_info. That always corresponds to "current slot", so if a user calls libevdev_set_event_value() or libevdev_get_event_value() they're actually modifying the current slot value. When the current slot changes, sync the state back into the absinfo values. Signed-off-by: Peter Hutterer --- libevdev/libevdev.c | 9 ++++++- libevdev/libevdev.h | 8 ++++++ test/test-libevdev-events.c | 54 +++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c index ba5b17f..e59d795 100644 --- a/libevdev/libevdev.c +++ b/libevdev/libevdev.c @@ -507,7 +507,14 @@ static int update_mt_state(struct libevdev *dev, const struct input_event *e) { if (e->code == ABS_MT_SLOT) { + int i; dev->current_slot = e->value; + /* sync abs_info with the current slot values */ + for (i = ABS_MT_SLOT + 1; i <= ABS_MT_MAX; i++) { + if (libevdev_has_event_code(dev, EV_ABS, i)) + dev->abs_info[i].value = dev->mt_slot_vals[dev->current_slot][i - ABS_MT_MIN]; + } + return 0; } else if (dev->current_slot == -1) return 1; @@ -527,7 +534,7 @@ update_abs_state(struct libevdev *dev, const struct input_event *e) return 1; if (e->code >= ABS_MT_MIN && e->code <= ABS_MT_MAX) - return update_mt_state(dev, e); + update_mt_state(dev, e); dev->abs_info[e->code].value = e->value; diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h index db6a2ec..61553cc 100644 --- a/libevdev/libevdev.h +++ b/libevdev/libevdev.h @@ -799,6 +799,10 @@ const struct input_absinfo* libevdev_get_abs_info(const struct libevdev *dev, un * Behaviour of this function is undefined if the device does not provide * the event. * + * If the device supports ABS_MT_SLOT, the value returned for any ABS_MT_* + * event code is the value of the currently active slot. You should use + * libevdev_get_slot_value() instead. + * * @param dev The evdev device, already initialized with libevdev_set_fd() * @param type The event type for the code to query (EV_SYN, EV_REL, etc.) * @param code The event code to query for, one of ABS_X, REL_X, etc. @@ -823,6 +827,10 @@ int libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsi * this device. A future call to libevdev_get_event_value() will return this * value, unless the value was overwritten by an event. * + * If the device supports ABS_MT_SLOT, the value set for any ABS_MT_* + * event code is the value of the currently active slot. You should use + * libevdev_set_slot_value() instead. + * * @param dev The evdev device, already initialized with libevdev_set_fd() * @param type The event type for the code to query (EV_SYN, EV_REL, etc.) * @param code The event code to set the value for, one of ABS_X, LED_NUML, etc. diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c index afa426d..669de12 100644 --- a/test/test-libevdev-events.c +++ b/test/test-libevdev-events.c @@ -1033,6 +1033,59 @@ START_TEST(test_event_mt_value_setters_invalid) } END_TEST +START_TEST(test_event_mt_value_setters_current_slot) +{ + struct uinput_device* uidev; + struct libevdev *dev; + int rc; + struct input_absinfo abs[5]; + + 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 = 2; + + rc = test_create_abs_device(&uidev, &dev, + 5, abs, + EV_SYN, SYN_REPORT, + -1); + ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc)); + + /* set_event_value/get_event_value works on the current slot */ + + ck_assert_int_eq(libevdev_get_current_slot(dev), 0); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_POSITION_X, 1), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 1); + ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_X), 1); + + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_SLOT, 1), 0); + ck_assert_int_eq(libevdev_get_current_slot(dev), 1); + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_POSITION_X, 2), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 2); + ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_X), 2); + + /* set slot 0, but current is still slot 1 */ + ck_assert_int_eq(libevdev_set_slot_value(dev, 0, ABS_MT_POSITION_X, 3), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 2); + + ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_MT_SLOT, 0), 0); + ck_assert_int_eq(libevdev_get_current_slot(dev), 0); + ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_MT_POSITION_X), 3); + + uinput_device_free(uidev); + libevdev_free(dev); +} +END_TEST + Suite * libevdev_events(void) { @@ -1071,6 +1124,7 @@ libevdev_events(void) tcase_add_test(tc, test_event_value_setters_invalid); tcase_add_test(tc, test_event_mt_value_setters); tcase_add_test(tc, test_event_mt_value_setters_invalid); + tcase_add_test(tc, test_event_mt_value_setters_current_slot); suite_add_tcase(s, tc); return s; -- 2.34.1