1/* 2 * Copyright © 2014 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include <config.h> 25 26#include <check.h> 27#include <errno.h> 28#include <fcntl.h> 29#include <libinput.h> 30#include <libinput-util.h> 31#include <unistd.h> 32#include <stdarg.h> 33 34#include "litest.h" 35#include "libinput-util.h" 36 37static int open_restricted(const char *path, int flags, void *data) 38{ 39 int fd = open(path, flags); 40 return fd < 0 ? -errno : fd; 41} 42static void close_restricted(int fd, void *data) 43{ 44 close(fd); 45} 46 47static const struct libinput_interface simple_interface = { 48 .open_restricted = open_restricted, 49 .close_restricted = close_restricted, 50}; 51 52static struct libevdev_uinput * 53create_simple_test_device(const char *name, ...) 54{ 55 va_list args; 56 struct libevdev_uinput *uinput; 57 struct libevdev *evdev; 58 unsigned int type, code; 59 int rc; 60 struct input_absinfo abs = { 61 .value = -1, 62 .minimum = 0, 63 .maximum = 100, 64 .fuzz = 0, 65 .flat = 0, 66 .resolution = 100, 67 }; 68 69 evdev = libevdev_new(); 70 litest_assert_notnull(evdev); 71 libevdev_set_name(evdev, name); 72 73 va_start(args, name); 74 75 while ((type = va_arg(args, unsigned int)) != (unsigned int)-1 && 76 (code = va_arg(args, unsigned int)) != (unsigned int)-1) { 77 const struct input_absinfo *a = NULL; 78 if (type == EV_ABS) 79 a = &abs; 80 libevdev_enable_event_code(evdev, type, code, a); 81 } 82 83 va_end(args); 84 85 rc = libevdev_uinput_create_from_device(evdev, 86 LIBEVDEV_UINPUT_OPEN_MANAGED, 87 &uinput); 88 litest_assert_int_eq(rc, 0); 89 libevdev_free(evdev); 90 91 return uinput; 92} 93 94START_TEST(event_conversion_device_notify) 95{ 96 struct libevdev_uinput *uinput; 97 struct libinput *li; 98 struct libinput_event *event; 99 int device_added = 0, device_removed = 0; 100 101 uinput = create_simple_test_device("litest test device", 102 EV_REL, REL_X, 103 EV_REL, REL_Y, 104 EV_KEY, BTN_LEFT, 105 EV_KEY, BTN_MIDDLE, 106 EV_KEY, BTN_LEFT, 107 -1, -1); 108 li = litest_create_context(); 109 litest_restore_log_handler(li); /* use the default litest handler */ 110 libinput_path_add_device(li, libevdev_uinput_get_devnode(uinput)); 111 112 libinput_dispatch(li); 113 libinput_suspend(li); 114 libinput_resume(li); 115 116 while ((event = libinput_get_event(li))) { 117 enum libinput_event_type type; 118 type = libinput_event_get_type(event); 119 120 if (type == LIBINPUT_EVENT_DEVICE_ADDED || 121 type == LIBINPUT_EVENT_DEVICE_REMOVED) { 122 struct libinput_event_device_notify *dn; 123 struct libinput_event *base; 124 dn = libinput_event_get_device_notify_event(event); 125 base = libinput_event_device_notify_get_base_event(dn); 126 ck_assert(event == base); 127 128 if (type == LIBINPUT_EVENT_DEVICE_ADDED) 129 device_added++; 130 else if (type == LIBINPUT_EVENT_DEVICE_REMOVED) 131 device_removed++; 132 133 litest_disable_log_handler(li); 134 ck_assert(libinput_event_get_pointer_event(event) == NULL); 135 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 136 ck_assert(libinput_event_get_touch_event(event) == NULL); 137 ck_assert(libinput_event_get_gesture_event(event) == NULL); 138 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); 139 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 140 ck_assert(libinput_event_get_switch_event(event) == NULL); 141 litest_restore_log_handler(li); 142 } 143 144 libinput_event_destroy(event); 145 } 146 147 litest_destroy_context(li); 148 libevdev_uinput_destroy(uinput); 149 150 ck_assert_int_gt(device_added, 0); 151 ck_assert_int_gt(device_removed, 0); 152} 153END_TEST 154 155START_TEST(event_conversion_pointer) 156{ 157 struct litest_device *dev = litest_current_device(); 158 struct libinput *li = dev->libinput; 159 struct libinput_event *event; 160 int motion = 0, button = 0; 161 162 /* Queue at least two relative motion events as the first one may 163 * be absorbed by the pointer acceleration filter. */ 164 litest_event(dev, EV_REL, REL_X, -1); 165 litest_event(dev, EV_REL, REL_Y, -1); 166 litest_event(dev, EV_SYN, SYN_REPORT, 0); 167 litest_event(dev, EV_REL, REL_X, -1); 168 litest_event(dev, EV_REL, REL_Y, -1); 169 litest_event(dev, EV_KEY, BTN_LEFT, 1); 170 litest_event(dev, EV_SYN, SYN_REPORT, 0); 171 172 libinput_dispatch(li); 173 174 while ((event = libinput_get_event(li))) { 175 enum libinput_event_type type; 176 type = libinput_event_get_type(event); 177 178 if (type == LIBINPUT_EVENT_POINTER_MOTION || 179 type == LIBINPUT_EVENT_POINTER_BUTTON) { 180 struct libinput_event_pointer *p; 181 struct libinput_event *base; 182 p = libinput_event_get_pointer_event(event); 183 base = libinput_event_pointer_get_base_event(p); 184 ck_assert(event == base); 185 186 if (type == LIBINPUT_EVENT_POINTER_MOTION) 187 motion++; 188 else if (type == LIBINPUT_EVENT_POINTER_BUTTON) 189 button++; 190 191 litest_disable_log_handler(li); 192 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 193 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 194 ck_assert(libinput_event_get_touch_event(event) == NULL); 195 ck_assert(libinput_event_get_gesture_event(event) == NULL); 196 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); 197 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 198 ck_assert(libinput_event_get_switch_event(event) == NULL); 199 litest_restore_log_handler(li); 200 } 201 libinput_event_destroy(event); 202 } 203 204 ck_assert_int_gt(motion, 0); 205 ck_assert_int_gt(button, 0); 206} 207END_TEST 208 209START_TEST(event_conversion_pointer_abs) 210{ 211 struct litest_device *dev = litest_current_device(); 212 struct libinput *li = dev->libinput; 213 struct libinput_event *event; 214 int motion = 0, button = 0; 215 216 litest_event(dev, EV_ABS, ABS_X, 10); 217 litest_event(dev, EV_ABS, ABS_Y, 50); 218 litest_event(dev, EV_KEY, BTN_LEFT, 1); 219 litest_event(dev, EV_SYN, SYN_REPORT, 0); 220 litest_event(dev, EV_ABS, ABS_X, 30); 221 litest_event(dev, EV_ABS, ABS_Y, 30); 222 litest_event(dev, EV_SYN, SYN_REPORT, 0); 223 224 libinput_dispatch(li); 225 226 while ((event = libinput_get_event(li))) { 227 enum libinput_event_type type; 228 type = libinput_event_get_type(event); 229 230 if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE || 231 type == LIBINPUT_EVENT_POINTER_BUTTON) { 232 struct libinput_event_pointer *p; 233 struct libinput_event *base; 234 p = libinput_event_get_pointer_event(event); 235 base = libinput_event_pointer_get_base_event(p); 236 ck_assert(event == base); 237 238 if (type == LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE) 239 motion++; 240 else if (type == LIBINPUT_EVENT_POINTER_BUTTON) 241 button++; 242 243 litest_disable_log_handler(li); 244 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 245 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 246 ck_assert(libinput_event_get_touch_event(event) == NULL); 247 ck_assert(libinput_event_get_gesture_event(event) == NULL); 248 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); 249 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 250 ck_assert(libinput_event_get_switch_event(event) == NULL); 251 litest_restore_log_handler(li); 252 } 253 libinput_event_destroy(event); 254 } 255 256 ck_assert_int_gt(motion, 0); 257 ck_assert_int_gt(button, 0); 258} 259END_TEST 260 261START_TEST(event_conversion_key) 262{ 263 struct litest_device *dev = litest_current_device(); 264 struct libinput *li = dev->libinput; 265 struct libinput_event *event; 266 int key = 0; 267 268 litest_event(dev, EV_KEY, KEY_A, 1); 269 litest_event(dev, EV_SYN, SYN_REPORT, 0); 270 litest_event(dev, EV_KEY, KEY_A, 0); 271 litest_event(dev, EV_SYN, SYN_REPORT, 0); 272 273 libinput_dispatch(li); 274 275 while ((event = libinput_get_event(li))) { 276 enum libinput_event_type type; 277 type = libinput_event_get_type(event); 278 279 if (type == LIBINPUT_EVENT_KEYBOARD_KEY) { 280 struct libinput_event_keyboard *k; 281 struct libinput_event *base; 282 k = libinput_event_get_keyboard_event(event); 283 base = libinput_event_keyboard_get_base_event(k); 284 ck_assert(event == base); 285 286 key++; 287 288 litest_disable_log_handler(li); 289 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 290 ck_assert(libinput_event_get_pointer_event(event) == NULL); 291 ck_assert(libinput_event_get_touch_event(event) == NULL); 292 ck_assert(libinput_event_get_gesture_event(event) == NULL); 293 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); 294 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 295 ck_assert(libinput_event_get_switch_event(event) == NULL); 296 litest_restore_log_handler(li); 297 } 298 libinput_event_destroy(event); 299 } 300 301 ck_assert_int_gt(key, 0); 302} 303END_TEST 304 305START_TEST(event_conversion_touch) 306{ 307 struct litest_device *dev = litest_current_device(); 308 struct libinput *li = dev->libinput; 309 struct libinput_event *event; 310 int touch = 0; 311 312 libinput_dispatch(li); 313 314 litest_event(dev, EV_KEY, BTN_TOOL_FINGER, 1); 315 litest_event(dev, EV_KEY, BTN_TOUCH, 1); 316 litest_event(dev, EV_ABS, ABS_X, 10); 317 litest_event(dev, EV_ABS, ABS_Y, 10); 318 litest_event(dev, EV_ABS, ABS_MT_SLOT, 0); 319 litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, 1); 320 litest_event(dev, EV_ABS, ABS_MT_POSITION_X, 10); 321 litest_event(dev, EV_ABS, ABS_MT_POSITION_Y, 10); 322 litest_event(dev, EV_SYN, SYN_REPORT, 0); 323 324 libinput_dispatch(li); 325 326 while ((event = libinput_get_event(li))) { 327 enum libinput_event_type type; 328 type = libinput_event_get_type(event); 329 330 if (type >= LIBINPUT_EVENT_TOUCH_DOWN && 331 type <= LIBINPUT_EVENT_TOUCH_FRAME) { 332 struct libinput_event_touch *t; 333 struct libinput_event *base; 334 t = libinput_event_get_touch_event(event); 335 base = libinput_event_touch_get_base_event(t); 336 ck_assert(event == base); 337 338 touch++; 339 340 litest_disable_log_handler(li); 341 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 342 ck_assert(libinput_event_get_pointer_event(event) == NULL); 343 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 344 ck_assert(libinput_event_get_gesture_event(event) == NULL); 345 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); 346 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 347 ck_assert(libinput_event_get_switch_event(event) == NULL); 348 litest_restore_log_handler(li); 349 } 350 libinput_event_destroy(event); 351 } 352 353 ck_assert_int_gt(touch, 0); 354} 355END_TEST 356 357START_TEST(event_conversion_gesture) 358{ 359 struct litest_device *dev = litest_current_device(); 360 struct libinput *li = dev->libinput; 361 struct libinput_event *event; 362 int gestures = 0; 363 int i; 364 365 libinput_dispatch(li); 366 367 litest_touch_down(dev, 0, 70, 30); 368 litest_touch_down(dev, 1, 30, 70); 369 libinput_dispatch(li); 370 litest_timeout_gesture_hold(); 371 372 for (i = 0; i < 8; i++) { 373 litest_push_event_frame(dev); 374 litest_touch_move(dev, 0, 70 - i * 5, 30 + i * 5); 375 litest_touch_move(dev, 1, 30 + i * 5, 70 - i * 5); 376 litest_pop_event_frame(dev); 377 libinput_dispatch(li); 378 } 379 380 while ((event = libinput_get_event(li))) { 381 enum libinput_event_type type; 382 type = libinput_event_get_type(event); 383 384 if (type >= LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN && 385 type <= LIBINPUT_EVENT_GESTURE_HOLD_END) { 386 struct libinput_event_gesture *g; 387 struct libinput_event *base; 388 g = libinput_event_get_gesture_event(event); 389 base = libinput_event_gesture_get_base_event(g); 390 ck_assert(event == base); 391 392 gestures++; 393 394 litest_disable_log_handler(li); 395 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 396 ck_assert(libinput_event_get_pointer_event(event) == NULL); 397 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 398 ck_assert(libinput_event_get_touch_event(event) == NULL); 399 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 400 ck_assert(libinput_event_get_switch_event(event) == NULL); 401 litest_restore_log_handler(li); 402 } 403 libinput_event_destroy(event); 404 } 405 406 ck_assert_int_gt(gestures, 0); 407} 408END_TEST 409 410START_TEST(event_conversion_tablet) 411{ 412 struct litest_device *dev = litest_current_device(); 413 struct libinput *li = dev->libinput; 414 struct libinput_event *event; 415 int events = 0; 416 struct axis_replacement axes[] = { 417 { ABS_DISTANCE, 10 }, 418 { -1, -1 } 419 }; 420 421 litest_tablet_proximity_in(dev, 50, 50, axes); 422 litest_tablet_motion(dev, 60, 50, axes); 423 litest_button_click(dev, BTN_STYLUS, true); 424 litest_button_click(dev, BTN_STYLUS, false); 425 426 libinput_dispatch(li); 427 428 while ((event = libinput_get_event(li))) { 429 enum libinput_event_type type; 430 type = libinput_event_get_type(event); 431 432 if (type >= LIBINPUT_EVENT_TABLET_TOOL_AXIS && 433 type <= LIBINPUT_EVENT_TABLET_TOOL_BUTTON) { 434 struct libinput_event_tablet_tool *t; 435 struct libinput_event *base; 436 t = libinput_event_get_tablet_tool_event(event); 437 base = libinput_event_tablet_tool_get_base_event(t); 438 ck_assert(event == base); 439 440 events++; 441 442 litest_disable_log_handler(li); 443 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 444 ck_assert(libinput_event_get_pointer_event(event) == NULL); 445 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 446 ck_assert(libinput_event_get_touch_event(event) == NULL); 447 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 448 ck_assert(libinput_event_get_switch_event(event) == NULL); 449 litest_restore_log_handler(li); 450 } 451 libinput_event_destroy(event); 452 } 453 454 ck_assert_int_gt(events, 0); 455} 456END_TEST 457 458START_TEST(event_conversion_tablet_pad) 459{ 460 struct litest_device *dev = litest_current_device(); 461 struct libinput *li = dev->libinput; 462 struct libinput_event *event; 463 int events = 0; 464 465 litest_button_click(dev, BTN_0, true); 466 litest_pad_ring_start(dev, 10); 467 litest_pad_ring_end(dev); 468 469 libinput_dispatch(li); 470 471 while ((event = libinput_get_event(li))) { 472 enum libinput_event_type type; 473 type = libinput_event_get_type(event); 474 475 if (type >= LIBINPUT_EVENT_TABLET_PAD_BUTTON && 476 type <= LIBINPUT_EVENT_TABLET_PAD_STRIP) { 477 struct libinput_event_tablet_pad *p; 478 struct libinput_event *base; 479 480 p = libinput_event_get_tablet_pad_event(event); 481 base = libinput_event_tablet_pad_get_base_event(p); 482 ck_assert(event == base); 483 484 events++; 485 486 litest_disable_log_handler(li); 487 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 488 ck_assert(libinput_event_get_pointer_event(event) == NULL); 489 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 490 ck_assert(libinput_event_get_touch_event(event) == NULL); 491 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); 492 ck_assert(libinput_event_get_switch_event(event) == NULL); 493 litest_restore_log_handler(li); 494 } 495 libinput_event_destroy(event); 496 } 497 498 ck_assert_int_gt(events, 0); 499} 500END_TEST 501 502START_TEST(event_conversion_switch) 503{ 504 struct litest_device *dev = litest_current_device(); 505 struct libinput *li = dev->libinput; 506 struct libinput_event *event; 507 int sw = 0; 508 509 litest_switch_action(dev, 510 LIBINPUT_SWITCH_LID, 511 LIBINPUT_SWITCH_STATE_ON); 512 litest_switch_action(dev, 513 LIBINPUT_SWITCH_LID, 514 LIBINPUT_SWITCH_STATE_OFF); 515 libinput_dispatch(li); 516 517 while ((event = libinput_get_event(li))) { 518 enum libinput_event_type type; 519 type = libinput_event_get_type(event); 520 521 if (type == LIBINPUT_EVENT_SWITCH_TOGGLE) { 522 struct libinput_event_switch *s; 523 struct libinput_event *base; 524 s = libinput_event_get_switch_event(event); 525 base = libinput_event_switch_get_base_event(s); 526 ck_assert(event == base); 527 528 sw++; 529 530 litest_disable_log_handler(li); 531 ck_assert(libinput_event_get_device_notify_event(event) == NULL); 532 ck_assert(libinput_event_get_keyboard_event(event) == NULL); 533 ck_assert(libinput_event_get_pointer_event(event) == NULL); 534 ck_assert(libinput_event_get_touch_event(event) == NULL); 535 ck_assert(libinput_event_get_gesture_event(event) == NULL); 536 ck_assert(libinput_event_get_tablet_tool_event(event) == NULL); 537 ck_assert(libinput_event_get_tablet_pad_event(event) == NULL); 538 litest_restore_log_handler(li); 539 } 540 libinput_event_destroy(event); 541 } 542 543 ck_assert_int_gt(sw, 0); 544} 545END_TEST 546 547START_TEST(context_ref_counting) 548{ 549 struct libinput *li; 550 551 /* These tests rely on valgrind to detect memory leak and use after 552 * free errors. */ 553 554 li = libinput_path_create_context(&simple_interface, NULL); 555 ck_assert_notnull(li); 556 ck_assert_ptr_eq(libinput_unref(li), NULL); 557 558 li = libinput_path_create_context(&simple_interface, NULL); 559 ck_assert_notnull(li); 560 ck_assert_ptr_eq(libinput_ref(li), li); 561 ck_assert_ptr_eq(libinput_unref(li), li); 562 ck_assert_ptr_eq(libinput_unref(li), NULL); 563} 564END_TEST 565 566START_TEST(config_status_string) 567{ 568 const char *strs[3]; 569 const char *invalid; 570 size_t i, j; 571 572 strs[0] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS); 573 strs[1] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_UNSUPPORTED); 574 strs[2] = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID); 575 576 for (i = 0; i < ARRAY_LENGTH(strs) - 1; i++) 577 for (j = i + 1; j < ARRAY_LENGTH(strs); j++) 578 ck_assert_str_ne(strs[i], strs[j]); 579 580 invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_INVALID + 1); 581 ck_assert(invalid == NULL); 582 invalid = libinput_config_status_to_str(LIBINPUT_CONFIG_STATUS_SUCCESS - 1); 583 ck_assert(invalid == NULL); 584} 585END_TEST 586 587static int open_restricted_leak(const char *path, int flags, void *data) 588{ 589 return *(int*)data; 590} 591 592static void close_restricted_leak(int fd, void *data) 593{ 594 /* noop */ 595} 596 597const struct libinput_interface leak_interface = { 598 .open_restricted = open_restricted_leak, 599 .close_restricted = close_restricted_leak, 600}; 601 602START_TEST(fd_no_event_leak) 603{ 604 struct libevdev_uinput *uinput; 605 struct libinput *li; 606 struct libinput_device *device; 607 int fd = -1; 608 const char *path; 609 struct libinput_event *event; 610 611 uinput = create_simple_test_device("litest test device", 612 EV_REL, REL_X, 613 EV_REL, REL_Y, 614 EV_KEY, BTN_LEFT, 615 EV_KEY, BTN_MIDDLE, 616 EV_KEY, BTN_LEFT, 617 -1, -1); 618 path = libevdev_uinput_get_devnode(uinput); 619 620 fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC); 621 ck_assert_int_gt(fd, -1); 622 623 li = libinput_path_create_context(&leak_interface, &fd); 624 litest_restore_log_handler(li); /* use the default litest handler */ 625 626 /* Add the device, trigger an event, then remove it again. 627 * Without it, we get a SYN_DROPPED immediately and no events. 628 */ 629 device = libinput_path_add_device(li, path); 630 libevdev_uinput_write_event(uinput, EV_REL, REL_X, 1); 631 libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); 632 libinput_path_remove_device(device); 633 libinput_dispatch(li); 634 litest_drain_events(li); 635 636 /* Device is removed, but fd is still open. Queue an event, add a 637 * new device with the same fd, the queued event must be discarded 638 * by libinput */ 639 libevdev_uinput_write_event(uinput, EV_REL, REL_Y, 1); 640 libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0); 641 libinput_dispatch(li); 642 643 libinput_path_add_device(li, path); 644 libinput_dispatch(li); 645 event = libinput_get_event(li); 646 ck_assert_int_eq(libinput_event_get_type(event), 647 LIBINPUT_EVENT_DEVICE_ADDED); 648 libinput_event_destroy(event); 649 650 litest_assert_empty_queue(li); 651 652 close(fd); 653 libinput_unref(li); 654 libevdev_uinput_destroy(uinput); 655} 656END_TEST 657 658static void timer_offset_warning(struct libinput *libinput, 659 enum libinput_log_priority priority, 660 const char *format, 661 va_list args) 662{ 663 struct litest_user_data *user_data = libinput_get_user_data(libinput); 664 int *warning_triggered = user_data->private; 665 666 if (priority == LIBINPUT_LOG_PRIORITY_ERROR && 667 strstr(format, "scheduled expiry is in the past")) 668 (*warning_triggered)++; 669} 670 671START_TEST(timer_offset_bug_warning) 672{ 673 struct litest_device *dev = litest_current_device(); 674 struct libinput *li = dev->libinput; 675 int warning_triggered = 0; 676 struct litest_user_data *user_data = libinput_get_user_data(li); 677 678 litest_enable_tap(dev->libinput_device); 679 litest_drain_events(li); 680 681 litest_touch_down(dev, 0, 50, 50); 682 litest_touch_up(dev, 0); 683 684 litest_timeout_tap(); 685 686 user_data->private = &warning_triggered; 687 libinput_log_set_handler(li, timer_offset_warning); 688 libinput_dispatch(li); 689 690 /* triggered for touch down and touch up */ 691 ck_assert_int_eq(warning_triggered, 2); 692 litest_restore_log_handler(li); 693} 694END_TEST 695 696static void timer_delay_warning(struct libinput *libinput, 697 enum libinput_log_priority priority, 698 const char *format, 699 va_list args) 700{ 701 struct litest_user_data *user_data = libinput_get_user_data(libinput); 702 int *warning_triggered = user_data->private; 703 704 if (priority == LIBINPUT_LOG_PRIORITY_ERROR && 705 strstr(format, "event processing lagging behind by")) 706 (*warning_triggered)++; 707} 708 709START_TEST(timer_delay_bug_warning) 710{ 711 struct litest_device *dev = litest_current_device(); 712 struct libinput *li = dev->libinput; 713 int warning_triggered = 0; 714 struct litest_user_data *user_data = libinput_get_user_data(li); 715 716 litest_drain_events(li); 717 718 user_data->private = &warning_triggered; 719 libinput_log_set_handler(li, timer_delay_warning); 720 721 for (int i = 0; i < 20; i++) { 722 litest_event(dev, EV_REL, REL_X, -1); 723 litest_event(dev, EV_SYN, SYN_REPORT, 0); 724 msleep(21); 725 libinput_dispatch(li); 726 } 727 728 ck_assert_int_ge(warning_triggered, 1); 729 litest_restore_log_handler(li); 730} 731END_TEST 732 733START_TEST(timer_flush) 734{ 735 struct libinput *li; 736 struct litest_device *keyboard, *touchpad; 737 738 li = litest_create_context(); 739 740 touchpad = litest_add_device(li, LITEST_SYNAPTICS_TOUCHPAD); 741 litest_enable_tap(touchpad->libinput_device); 742 libinput_dispatch(li); 743 keyboard = litest_add_device(li, LITEST_KEYBOARD); 744 libinput_dispatch(li); 745 litest_drain_events(li); 746 747 /* make sure tapping works */ 748 litest_touch_down(touchpad, 0, 50, 50); 749 litest_touch_up(touchpad, 0); 750 libinput_dispatch(li); 751 litest_timeout_tap(); 752 libinput_dispatch(li); 753 754 litest_assert_button_event(li, BTN_LEFT, 755 LIBINPUT_BUTTON_STATE_PRESSED); 756 litest_assert_button_event(li, BTN_LEFT, 757 LIBINPUT_BUTTON_STATE_RELEASED); 758 litest_assert_empty_queue(li); 759 760 /* make sure dwt-tap is ignored */ 761 litest_keyboard_key(keyboard, KEY_A, true); 762 litest_keyboard_key(keyboard, KEY_A, false); 763 libinput_dispatch(li); 764 litest_touch_down(touchpad, 0, 50, 50); 765 litest_touch_up(touchpad, 0); 766 libinput_dispatch(li); 767 litest_timeout_tap(); 768 libinput_dispatch(li); 769 litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); 770 771 /* Ignore 'timer offset negative' warnings */ 772 litest_disable_log_handler(li); 773 774 /* now mess with the timing 775 - send a key event 776 - expire dwt 777 - send a tap 778 and then call libinput_dispatch(). libinput should notice that 779 the tap event came in after the timeout and thus acknowledge the 780 tap. 781 */ 782 litest_keyboard_key(keyboard, KEY_A, true); 783 litest_keyboard_key(keyboard, KEY_A, false); 784 litest_timeout_dwt_long(); 785 litest_touch_down(touchpad, 0, 50, 50); 786 litest_touch_up(touchpad, 0); 787 libinput_dispatch(li); 788 litest_timeout_tap(); 789 libinput_dispatch(li); 790 litest_restore_log_handler(li); 791 792 litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED); 793 litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED); 794 litest_assert_button_event(li, BTN_LEFT, 795 LIBINPUT_BUTTON_STATE_PRESSED); 796 litest_assert_button_event(li, BTN_LEFT, 797 LIBINPUT_BUTTON_STATE_RELEASED); 798 799 litest_delete_device(keyboard); 800 litest_delete_device(touchpad); 801 802 litest_destroy_context(li); 803} 804END_TEST 805 806START_TEST(udev_absinfo_override) 807{ 808 struct litest_device *dev = litest_current_device(); 809 struct libevdev *evdev = dev->evdev; 810 const struct input_absinfo *abs; 811 struct udev_device *ud; 812 struct udev_list_entry *entry; 813 bool found_x = false, found_y = false, 814 found_mt_x = false, found_mt_y = false; 815 816 ud = libinput_device_get_udev_device(dev->libinput_device); 817 ck_assert_notnull(ud); 818 819 /* Custom checks for this special litest device only */ 820 821 entry = udev_device_get_properties_list_entry(ud); 822 while (entry) { 823 const char *key, *value; 824 825 key = udev_list_entry_get_name(entry); 826 value = udev_list_entry_get_value(entry); 827 828 if (streq(key, "EVDEV_ABS_00")) { 829 found_x = true; 830 ck_assert(streq(value, "1:1000:100:10")); 831 } 832 if (streq(key, "EVDEV_ABS_01")) { 833 found_y = true; 834 ck_assert(streq(value, "2:2000:200:20")); 835 } 836 if (streq(key, "EVDEV_ABS_35")) { 837 found_mt_x = true; 838 ck_assert(streq(value, "3:3000:300:30")); 839 } 840 if (streq(key, "EVDEV_ABS_36")) { 841 found_mt_y = true; 842 ck_assert(streq(value, "4:4000:400:40")); 843 } 844 845 entry = udev_list_entry_get_next(entry); 846 } 847 udev_device_unref(ud); 848 849 ck_assert(found_x); 850 ck_assert(found_y); 851 ck_assert(found_mt_x); 852 ck_assert(found_mt_y); 853 854 abs = libevdev_get_abs_info(evdev, ABS_X); 855 ck_assert_int_eq(abs->minimum, 1); 856 ck_assert_int_eq(abs->maximum, 1000); 857 ck_assert_int_eq(abs->resolution, 100); 858 /* if everything goes well, we override the fuzz to 0 */ 859 ck_assert_int_eq(abs->fuzz, 0); 860 861 abs = libevdev_get_abs_info(evdev, ABS_Y); 862 ck_assert_int_eq(abs->minimum, 2); 863 ck_assert_int_eq(abs->maximum, 2000); 864 ck_assert_int_eq(abs->resolution, 200); 865 /* if everything goes well, we override the fuzz to 0 */ 866 ck_assert_int_eq(abs->fuzz, 0); 867 868 abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); 869 ck_assert_int_eq(abs->minimum, 3); 870 ck_assert_int_eq(abs->maximum, 3000); 871 ck_assert_int_eq(abs->resolution, 300); 872 /* if everything goes well, we override the fuzz to 0 */ 873 ck_assert_int_eq(abs->fuzz, 0); 874 875 abs = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); 876 ck_assert_int_eq(abs->minimum, 4); 877 ck_assert_int_eq(abs->maximum, 4000); 878 ck_assert_int_eq(abs->resolution, 400); 879 /* if everything goes well, we override the fuzz to 0 */ 880 ck_assert_int_eq(abs->fuzz, 0); 881} 882END_TEST 883 884TEST_COLLECTION(misc) 885{ 886 litest_add_no_device(event_conversion_device_notify); 887 litest_add_for_device(event_conversion_pointer, LITEST_MOUSE); 888 litest_add_for_device(event_conversion_pointer_abs, LITEST_XEN_VIRTUAL_POINTER); 889 litest_add_for_device(event_conversion_key, LITEST_KEYBOARD); 890 litest_add_for_device(event_conversion_touch, LITEST_WACOM_TOUCH); 891 litest_add_for_device(event_conversion_gesture, LITEST_BCM5974); 892 litest_add_for_device(event_conversion_tablet, LITEST_WACOM_CINTIQ); 893 litest_add_for_device(event_conversion_tablet_pad, LITEST_WACOM_INTUOS5_PAD); 894 litest_add_for_device(event_conversion_switch, LITEST_LID_SWITCH); 895 896 litest_add_deviceless(context_ref_counting); 897 litest_add_deviceless(config_status_string); 898 899 litest_add_for_device(timer_offset_bug_warning, LITEST_SYNAPTICS_TOUCHPAD); 900 litest_add_for_device(timer_delay_bug_warning, LITEST_MOUSE); 901 litest_add_no_device(timer_flush); 902 903 litest_add_no_device(fd_no_event_leak); 904 905 litest_add_for_device(udev_absinfo_override, LITEST_ABSINFO_OVERRIDE); 906} 907