| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921 |
- /*
- * Copyright © 2014 Red Hat, Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- #include <config.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <libinput-util.h>
- #include <libinput.h>
- #include <stdarg.h>
- #include <unistd.h>
- #include "libinput-util.h"
- #include "litest.h"
- static int
- open_restricted(const char *path, int flags, void *data)
- {
- int fd = open(path, flags);
- return fd < 0 ? -errno : fd;
- }
- static void
- close_restricted(int fd, void *data)
- {
- close(fd);
- }
- static const struct libinput_interface simple_interface = {
- .open_restricted = open_restricted,
- .close_restricted = close_restricted,
- };
- static struct libevdev_uinput *
- create_simple_test_device(const char *name, ...)
- {
- va_list args;
- struct libevdev_uinput *uinput;
- struct libevdev *evdev;
- unsigned int type, code;
- int rc;
- struct input_absinfo abs = {
- .value = -1,
- .minimum = 0,
- .maximum = 100,
- .fuzz = 0,
- .flat = 0,
- .resolution = 100,
- };
- evdev = libevdev_new();
- litest_assert_notnull(evdev);
- libevdev_set_name(evdev, name);
- va_start(args, name);
- while ((type = va_arg(args, unsigned int)) != (unsigned int)-1 &&
- (code = va_arg(args, unsigned int)) != (unsigned int)-1) {
- const struct input_absinfo *a = NULL;
- if (type == EV_ABS)
- a = &abs;
- libevdev_enable_event_code(evdev, type, code, a);
- }
- va_end(args);
- rc = libevdev_uinput_create_from_device(evdev,
- LIBEVDEV_UINPUT_OPEN_MANAGED,
- &uinput);
- litest_assert_neg_errno_success(rc);
- libevdev_free(evdev);
- return uinput;
- }
- START_TEST(event_conversion_device_notify)
- {
- struct libevdev_uinput *uinput;
- struct libinput_event *event;
- int device_added = 0, device_removed = 0;
- /* clang-format off */
- uinput = create_simple_test_device("litest test device",
- EV_REL, REL_X,
- EV_REL, REL_Y,
- EV_KEY, BTN_LEFT,
- EV_KEY, BTN_MIDDLE,
- EV_KEY, BTN_LEFT,
- -1, -1);
- /* clang-format on */
- _litest_context_destroy_ struct libinput *li = litest_create_context();
- litest_restore_log_handler(li); /* use the default litest handler */
- libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput));
- litest_dispatch(li);
- libinput_suspend(li);
- libinput_resume(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type == LIBINPUT_EVENT_DEVICE_ADDED ||
- type == LIBINPUT_EVENT_DEVICE_REMOVED) {
- struct libinput_event_device_notify *dn;
- struct libinput_event *base;
- dn = libinput_event_get_device_notify_event(event);
- base = libinput_event_device_notify_get_base_event(dn);
- litest_assert(event == base);
- if (type == LIBINPUT_EVENT_DEVICE_ADDED)
- device_added++;
- else if (type == LIBINPUT_EVENT_DEVICE_REMOVED)
- device_removed++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_pointer_event(event) == NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_gesture_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_tool_event(event) ==
- NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- libevdev_uinput_destroy(uinput);
- litest_assert_int_gt(device_added, 0);
- litest_assert_int_gt(device_removed, 0);
- }
- END_TEST
- START_TEST(event_conversion_pointer)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int motion = 0, button = 0;
- /* Queue at least two relative motion events as the first one may
- * be absorbed by the pointer acceleration filter. */
- litest_event(dev, EV_REL, REL_X, -1);
- litest_event(dev, EV_REL, REL_Y, -1);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- litest_event(dev, EV_REL, REL_X, -1);
- litest_event(dev, EV_REL, REL_Y, -1);
- litest_event(dev, EV_KEY, BTN_LEFT, 1);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- litest_dispatch(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type == LIBINPUT_EVENT_POINTER_MOTION ||
- type == LIBINPUT_EVENT_POINTER_BUTTON) {
- struct libinput_event_pointer *p;
- struct libinput_event *base;
- p = libinput_event_get_pointer_event(event);
- base = libinput_event_pointer_get_base_event(p);
- litest_assert(event == base);
- if (type == LIBINPUT_EVENT_POINTER_MOTION)
- motion++;
- else if (type == LIBINPUT_EVENT_POINTER_BUTTON)
- button++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_gesture_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_tool_event(event) ==
- NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(motion, 0);
- litest_assert_int_gt(button, 0);
- }
- END_TEST
- START_TEST(event_conversion_pointer_abs)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int motion = 0, button = 0;
- litest_event(dev, EV_ABS, ABS_X, 10);
- litest_event(dev, EV_ABS, ABS_Y, 50);
- litest_event(dev, EV_KEY, BTN_LEFT, 1);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- litest_event(dev, EV_ABS, ABS_X, 30);
- litest_event(dev, EV_ABS, ABS_Y, 30);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- litest_dispatch(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE ||
- type == LIBINPUT_EVENT_POINTER_BUTTON) {
- struct libinput_event_pointer *p;
- struct libinput_event *base;
- p = libinput_event_get_pointer_event(event);
- base = libinput_event_pointer_get_base_event(p);
- litest_assert(event == base);
- if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE)
- motion++;
- else if (type == LIBINPUT_EVENT_POINTER_BUTTON)
- button++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_gesture_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_tool_event(event) ==
- NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(motion, 0);
- litest_assert_int_gt(button, 0);
- }
- END_TEST
- START_TEST(event_conversion_key)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int key = 0;
- litest_event(dev, EV_KEY, KEY_A, 1);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- litest_event(dev, EV_KEY, KEY_A, 0);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- litest_dispatch(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type == LIBINPUT_EVENT_KEYBOARD_KEY) {
- struct libinput_event_keyboard *k;
- struct libinput_event *base;
- k = libinput_event_get_keyboard_event(event);
- base = libinput_event_keyboard_get_base_event(k);
- litest_assert(event == base);
- key++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_pointer_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_gesture_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_tool_event(event) ==
- NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(key, 0);
- }
- END_TEST
- START_TEST(event_conversion_touch)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int touch = 0;
- litest_dispatch(li);
- litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1);
- litest_event(dev, EV_KEY, BTN_TOUCH, 1);
- litest_event(dev, EV_ABS, ABS_X, 10);
- litest_event(dev, EV_ABS, ABS_Y, 10);
- litest_event(dev, EV_ABS, ABS_MT_SLOT, 0);
- litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1);
- litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 10);
- litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 10);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- litest_dispatch(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type >= LIBINPUT_EVENT_TOUCH_DOWN &&
- type <= LIBINPUT_EVENT_TOUCH_FRAME) {
- struct libinput_event_touch *t;
- struct libinput_event *base;
- t = libinput_event_get_touch_event(event);
- base = libinput_event_touch_get_base_event(t);
- litest_assert(event == base);
- touch++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_pointer_event(event) == NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_gesture_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_tool_event(event) ==
- NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(touch, 0);
- }
- END_TEST
- START_TEST(event_conversion_gesture)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int gestures = 0;
- int i;
- litest_dispatch(li);
- litest_touch_down(dev, 0, 70, 30);
- litest_touch_down(dev, 1, 30, 70);
- litest_timeout_gesture_hold(li);
- for (i = 0; i < 8; i++) {
- litest_push_event_frame(dev);
- litest_touch_move(dev, 0, 70 - i * 5, 30 + i * 5);
- litest_touch_move(dev, 1, 30 + i * 5, 70 - i * 5);
- litest_pop_event_frame(dev);
- litest_dispatch(li);
- }
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type >= LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN &&
- type <= LIBINPUT_EVENT_GESTURE_HOLD_END) {
- struct libinput_event_gesture *g;
- struct libinput_event *base;
- g = libinput_event_get_gesture_event(event);
- base = libinput_event_gesture_get_base_event(g);
- litest_assert(event == base);
- gestures++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_pointer_event(event) == NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(gestures, 0);
- }
- END_TEST
- START_TEST(event_conversion_tablet)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int events = 0;
- struct axis_replacement axes[] = {
- { ABS_DISTANCE, 10 },
- { -1, -1 },
- };
- litest_tablet_proximity_in(dev, 50, 50, axes);
- litest_tablet_motion(dev, 60, 50, axes);
- litest_button_click(dev, BTN_STYLUS, true);
- litest_button_click(dev, BTN_STYLUS, false);
- litest_dispatch(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type >= LIBINPUT_EVENT_TABLET_TOOL_AXIS &&
- type <= LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
- struct libinput_event_tablet_tool *t;
- struct libinput_event *base;
- t = libinput_event_get_tablet_tool_event(event);
- base = libinput_event_tablet_tool_get_base_event(t);
- litest_assert(event == base);
- events++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_pointer_event(event) == NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(events, 0);
- }
- END_TEST
- START_TEST(event_conversion_tablet_pad)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int events = 0;
- litest_button_click(dev, BTN_0, true);
- litest_pad_ring_start(dev, 10);
- litest_pad_ring_end(dev);
- litest_dispatch(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type >= LIBINPUT_EVENT_TABLET_PAD_BUTTON &&
- type <= LIBINPUT_EVENT_TABLET_PAD_STRIP) {
- struct libinput_event_tablet_pad *p;
- struct libinput_event *base;
- p = libinput_event_get_tablet_pad_event(event);
- base = libinput_event_tablet_pad_get_base_event(p);
- litest_assert(event == base);
- events++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_pointer_event(event) == NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_tool_event(event) ==
- NULL);
- litest_assert(libinput_event_get_switch_event(event) == NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(events, 0);
- }
- END_TEST
- START_TEST(event_conversion_switch)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- struct libinput_event *event;
- int sw = 0;
- litest_switch_action(dev, LIBINPUT_SWITCH_LID, LIBINPUT_SWITCH_STATE_ON);
- litest_switch_action(dev, LIBINPUT_SWITCH_LID, LIBINPUT_SWITCH_STATE_OFF);
- litest_switch_action(dev,
- LIBINPUT_SWITCH_KEYPAD_SLIDE,
- LIBINPUT_SWITCH_STATE_ON);
- litest_switch_action(dev,
- LIBINPUT_SWITCH_KEYPAD_SLIDE,
- LIBINPUT_SWITCH_STATE_OFF);
- litest_dispatch(li);
- while ((event = libinput_get_event(li))) {
- enum libinput_event_type type;
- type = libinput_event_get_type(event);
- if (type == LIBINPUT_EVENT_SWITCH_TOGGLE) {
- struct libinput_event_switch *s;
- struct libinput_event *base;
- s = libinput_event_get_switch_event(event);
- base = libinput_event_switch_get_base_event(s);
- litest_assert(event == base);
- sw++;
- litest_disable_log_handler(li);
- litest_assert(libinput_event_get_device_notify_event(event) ==
- NULL);
- litest_assert(libinput_event_get_keyboard_event(event) == NULL);
- litest_assert(libinput_event_get_pointer_event(event) == NULL);
- litest_assert(libinput_event_get_touch_event(event) == NULL);
- litest_assert(libinput_event_get_gesture_event(event) == NULL);
- litest_assert(libinput_event_get_tablet_tool_event(event) ==
- NULL);
- litest_assert(libinput_event_get_tablet_pad_event(event) ==
- NULL);
- litest_restore_log_handler(li);
- }
- libinput_event_destroy(event);
- }
- litest_assert_int_gt(sw, 0);
- }
- END_TEST
- START_TEST(context_ref_counting)
- {
- struct libinput *li;
- /* These tests rely on valgrind to detect memory leak and use after
- * free errors. */
- li = libinput_path_create_context(&simple_interface, NULL);
- litest_assert_notnull(li);
- litest_assert_ptr_eq(libinput_unref(li), NULL);
- li = libinput_path_create_context(&simple_interface, NULL);
- litest_assert_notnull(li);
- litest_assert_ptr_eq(libinput_ref(li), li);
- litest_assert_ptr_eq(libinput_unref(li), li);
- litest_assert_ptr_eq(libinput_unref(li), NULL);
- }
- END_TEST
- START_TEST(config_status_string)
- {
- const char *strs[3];
- const char *invalid;
- size_t i, j;
- strs[0] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS);
- strs[1] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
- strs[2] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID);
- for (i = 0; i < ARRAY_LENGTH(strs) - 1; i++)
- for (j = i + 1; j < ARRAY_LENGTH(strs); j++)
- litest_assert_str_ne(strs[i], strs[j]);
- invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID + 1);
- litest_assert(invalid == NULL);
- invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS - 1);
- litest_assert(invalid == NULL);
- }
- END_TEST
- static int
- open_restricted_leak(const char *path, int flags, void *data)
- {
- return *(int *)data;
- }
- static void
- close_restricted_leak(int fd, void *data)
- {
- /* noop */
- }
- static const struct libinput_interface leak_interface = {
- .open_restricted = open_restricted_leak,
- .close_restricted = close_restricted_leak,
- };
- START_TEST(fd_no_event_leak)
- {
- struct libevdev_uinput *uinput;
- struct libinput *li;
- struct libinput_device *device;
- int fd = -1;
- const char *path;
- struct libinput_event *event;
- /* clang-format off */
- uinput = create_simple_test_device("litest test device",
- EV_REL, REL_X,
- EV_REL, REL_Y,
- EV_KEY, BTN_LEFT,
- EV_KEY, BTN_MIDDLE,
- EV_KEY, BTN_LEFT,
- -1, -1);
- /* clang-format on */
- path = libevdev_uinput_get_devnode(uinput);
- fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC);
- litest_assert_int_gt(fd, -1);
- li = libinput_path_create_context(&leak_interface, &fd);
- litest_restore_log_handler(li); /* use the default litest handler */
- /* Add the device, trigger an event, then remove it again.
- * Without it, we get a SYN_DROPPED immediately and no events.
- */
- device = libinput_path_add_device(li, path);
- libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1);
- libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
- libinput_path_remove_device(device);
- litest_dispatch(li);
- litest_drain_events(li);
- /* Device is removed, but fd is still open. Queue an event, add a
- * new device with the same fd, the queued event must be discarded
- * by libinput */
- libevdev_uinput_write_event(uinput, EV_REL, REL_Y, 1);
- libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
- litest_dispatch(li);
- libinput_path_add_device(li, path);
- litest_dispatch(li);
- event = libinput_get_event(li);
- litest_assert_event_type(event, LIBINPUT_EVENT_DEVICE_ADDED);
- libinput_event_destroy(event);
- litest_assert_empty_queue(li);
- close(fd);
- libinput_unref(li);
- libevdev_uinput_destroy(uinput);
- }
- END_TEST
- static void
- timer_offset_warning(struct libinput *libinput,
- enum libinput_log_priority priority,
- const char *format,
- va_list args)
- {
- struct litest_user_data *user_data = libinput_get_user_data(libinput);
- int *warning_triggered = user_data->private;
- if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
- strstr(format, "scheduled expiry is in the past"))
- (*warning_triggered)++;
- }
- START_TEST(timer_offset_bug_warning)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- int warning_triggered = 0;
- struct litest_user_data *user_data = libinput_get_user_data(li);
- litest_enable_tap(dev->libinput_device);
- litest_drain_events(li);
- litest_touch_down(dev, 0, 50, 50);
- litest_touch_up(dev, 0);
- litest_timeout_tap(NULL);
- user_data->private = &warning_triggered;
- libinput_log_set_handler(li, timer_offset_warning);
- litest_dispatch(li);
- /* triggered for touch down and touch up */
- litest_assert_int_eq(warning_triggered, 2);
- litest_restore_log_handler(li);
- }
- END_TEST
- static void
- timer_delay_warning(struct libinput *libinput,
- enum libinput_log_priority priority,
- const char *format,
- va_list args)
- {
- struct litest_user_data *user_data = libinput_get_user_data(libinput);
- int *warning_triggered = user_data->private;
- if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
- strstr(format, "event processing lagging behind by"))
- (*warning_triggered)++;
- }
- START_TEST(timer_delay_bug_warning)
- {
- struct litest_device *dev = litest_current_device();
- struct libinput *li = dev->libinput;
- int warning_triggered = 0;
- struct litest_user_data *user_data = libinput_get_user_data(li);
- litest_drain_events(li);
- user_data->private = &warning_triggered;
- libinput_log_set_handler(li, timer_delay_warning);
- for (int i = 0; i < 20; i++) {
- litest_event(dev, EV_REL, REL_X, -1);
- litest_event(dev, EV_SYN, SYN_REPORT, 0);
- msleep(21);
- litest_dispatch(li);
- }
- litest_assert_int_ge(warning_triggered, 1);
- litest_restore_log_handler(li);
- }
- END_TEST
- START_TEST(timer_flush)
- {
- _litest_context_destroy_ struct libinput *li = litest_create_context();
- _destroy_(litest_device) *touchpad =
- litest_add_device(li, LITEST_SYNAPTICS_TOUCHPAD);
- litest_enable_tap(touchpad->libinput_device);
- litest_dispatch(li);
- _destroy_(litest_device) *keyboard = litest_add_device(li, LITEST_KEYBOARD);
- litest_dispatch(li);
- litest_drain_events(li);
- /* make sure tapping works */
- litest_touch_down(touchpad, 0, 50, 50);
- litest_touch_up(touchpad, 0);
- litest_timeout_tap(li);
- litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
- litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED);
- litest_assert_empty_queue(li);
- /* make sure dwt-tap is ignored */
- litest_keyboard_key(keyboard, KEY_A, true);
- litest_keyboard_key(keyboard, KEY_A, false);
- litest_dispatch(li);
- litest_touch_down(touchpad, 0, 50, 50);
- litest_touch_up(touchpad, 0);
- litest_timeout_tap(li);
- litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
- /* Ignore 'timer offset negative' warnings */
- litest_disable_log_handler(li);
- /* now mess with the timing
- - send a key event
- - expire dwt
- - send a tap
- and then call litest_dispatch(). libinput should notice that
- the tap event came in after the timeout and thus acknowledge the
- tap.
- */
- litest_keyboard_key(keyboard, KEY_A, true);
- litest_keyboard_key(keyboard, KEY_A, false);
- litest_timeout_dwt_long(li);
- litest_touch_down(touchpad, 0, 50, 50);
- litest_touch_up(touchpad, 0);
- litest_timeout_tap(li);
- litest_restore_log_handler(li);
- litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
- litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
- litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
- litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED);
- }
- END_TEST
- START_TEST(udev_absinfo_override)
- {
- struct litest_device *dev = litest_current_device();
- struct libevdev *evdev = dev->evdev;
- const struct input_absinfo *abs;
- struct udev_device *ud;
- struct udev_list_entry *entry;
- bool found_x = false, found_y = false, found_mt_x = false, found_mt_y = false;
- ud = libinput_device_get_udev_device(dev->libinput_device);
- litest_assert_notnull(ud);
- /* Custom checks for this special litest device only */
- entry = udev_device_get_properties_list_entry(ud);
- while (entry) {
- const char *key, *value;
- key = udev_list_entry_get_name(entry);
- value = udev_list_entry_get_value(entry);
- if (streq(key, "EVDEV_ABS_00")) {
- found_x = true;
- litest_assert(streq(value, "1:1000:100:10"));
- }
- if (streq(key, "EVDEV_ABS_01")) {
- found_y = true;
- litest_assert(streq(value, "2:2000:200:20"));
- }
- if (streq(key, "EVDEV_ABS_35")) {
- found_mt_x = true;
- litest_assert(streq(value, "3:3000:300:30"));
- }
- if (streq(key, "EVDEV_ABS_36")) {
- found_mt_y = true;
- litest_assert(streq(value, "4:4000:400:40"));
- }
- entry = udev_list_entry_get_next(entry);
- }
- udev_device_unref(ud);
- litest_assert(found_x);
- litest_assert(found_y);
- litest_assert(found_mt_x);
- litest_assert(found_mt_y);
- abs = libevdev_get_abs_info(evdev, ABS_X);
- litest_assert_int_eq(abs->minimum, 1);
- litest_assert_int_eq(abs->maximum, 1000);
- litest_assert_int_eq(abs->resolution, 100);
- /* if everything goes well, we override the fuzz to 0 */
- litest_assert_int_eq(abs->fuzz, 0);
- abs = libevdev_get_abs_info(evdev, ABS_Y);
- litest_assert_int_eq(abs->minimum, 2);
- litest_assert_int_eq(abs->maximum, 2000);
- litest_assert_int_eq(abs->resolution, 200);
- /* if everything goes well, we override the fuzz to 0 */
- litest_assert_int_eq(abs->fuzz, 0);
- abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X);
- litest_assert_int_eq(abs->minimum, 3);
- litest_assert_int_eq(abs->maximum, 3000);
- litest_assert_int_eq(abs->resolution, 300);
- /* if everything goes well, we override the fuzz to 0 */
- litest_assert_int_eq(abs->fuzz, 0);
- abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y);
- litest_assert_int_eq(abs->minimum, 4);
- litest_assert_int_eq(abs->maximum, 4000);
- litest_assert_int_eq(abs->resolution, 400);
- /* if everything goes well, we override the fuzz to 0 */
- litest_assert_int_eq(abs->fuzz, 0);
- }
- END_TEST
- TEST_COLLECTION(misc)
- {
- /* clang-format off */
- litest_add_no_device(event_conversion_device_notify);
- litest_add_for_device(event_conversion_pointer, LITEST_MOUSE);
- litest_add_for_device(event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER);
- litest_add_for_device(event_conversion_key, LITEST_KEYBOARD);
- litest_add_for_device(event_conversion_touch, LITEST_WACOM_ISDV4_E6_FINGER);
- litest_add_for_device(event_conversion_gesture, LITEST_BCM5974);
- litest_add_for_device(event_conversion_tablet, LITEST_WACOM_CINTIQ_12WX_PEN);
- litest_add_for_device(event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD);
- litest_add_for_device(event_conversion_switch, LITEST_LID_SWITCH);
- litest_add_for_device(event_conversion_switch, LITEST_KEYPAD_SLIDE_SWITCH);
- litest_add_deviceless(context_ref_counting);
- litest_add_deviceless(config_status_string);
- litest_add_for_device(timer_offset_bug_warning, LITEST_SYNAPTICS_TOUCHPAD);
- litest_add_for_device(timer_delay_bug_warning, LITEST_MOUSE);
- litest_add_no_device(timer_flush);
- litest_add_no_device(fd_no_event_leak);
- litest_add_for_device(udev_absinfo_override, LITEST_ABSINFO_OVERRIDE);
- /* clang-format on */
- }
|