1/* 2 * Copyright © 2016 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 <unistd.h> 31#include <stdbool.h> 32 33#if HAVE_LIBWACOM 34#include <libwacom/libwacom.h> 35#endif 36 37#include "libinput-util.h" 38#include "litest.h" 39 40START_TEST(pad_cap) 41{ 42 struct litest_device *dev = litest_current_device(); 43 struct libinput_device *device = dev->libinput_device; 44 45 ck_assert(libinput_device_has_capability(device, 46 LIBINPUT_DEVICE_CAP_TABLET_PAD)); 47 48} 49END_TEST 50 51START_TEST(pad_no_cap) 52{ 53 struct litest_device *dev = litest_current_device(); 54 struct libinput_device *device = dev->libinput_device; 55 56 ck_assert(!libinput_device_has_capability(device, 57 LIBINPUT_DEVICE_CAP_TABLET_PAD)); 58} 59END_TEST 60 61START_TEST(pad_time) 62{ 63 struct litest_device *dev = litest_current_device(); 64 struct libinput *li = dev->libinput; 65 struct libinput_event *ev; 66 struct libinput_event_tablet_pad *pev; 67 unsigned int code; 68 uint64_t time, time_usec, oldtime; 69 bool has_buttons = false; 70 71 litest_drain_events(li); 72 73 for (code = BTN_0; code < BTN_DIGI; code++) { 74 if (!libevdev_has_event_code(dev->evdev, EV_KEY, code)) 75 continue; 76 77 has_buttons = true; 78 79 litest_button_click(dev, code, 1); 80 litest_button_click(dev, code, 0); 81 libinput_dispatch(li); 82 83 break; 84 } 85 86 if (!has_buttons) 87 return; 88 89 ev = libinput_get_event(li); 90 ck_assert_notnull(ev); 91 ck_assert_int_eq(libinput_event_get_type(ev), 92 LIBINPUT_EVENT_TABLET_PAD_BUTTON); 93 pev = libinput_event_get_tablet_pad_event(ev); 94 time = libinput_event_tablet_pad_get_time(pev); 95 time_usec = libinput_event_tablet_pad_get_time_usec(pev); 96 97 ck_assert(time != 0); 98 ck_assert(time == time_usec/1000); 99 100 libinput_event_destroy(ev); 101 102 litest_drain_events(li); 103 msleep(10); 104 105 litest_button_click(dev, code, 1); 106 litest_button_click(dev, code, 0); 107 libinput_dispatch(li); 108 109 ev = libinput_get_event(li); 110 ck_assert_int_eq(libinput_event_get_type(ev), 111 LIBINPUT_EVENT_TABLET_PAD_BUTTON); 112 pev = libinput_event_get_tablet_pad_event(ev); 113 114 oldtime = time; 115 time = libinput_event_tablet_pad_get_time(pev); 116 time_usec = libinput_event_tablet_pad_get_time_usec(pev); 117 118 ck_assert(time > oldtime); 119 ck_assert(time != 0); 120 ck_assert(time == time_usec/1000); 121 122 libinput_event_destroy(ev); 123} 124END_TEST 125 126START_TEST(pad_num_buttons_libwacom) 127{ 128#if HAVE_LIBWACOM 129 struct litest_device *dev = litest_current_device(); 130 struct libinput_device *device = dev->libinput_device; 131 WacomDeviceDatabase *db = NULL; 132 WacomDevice *wacom = NULL; 133 unsigned int nb_lw, nb; 134 135 db = libwacom_database_new(); 136 ck_assert_notnull(db); 137 138 wacom = libwacom_new_from_usbid(db, 139 libevdev_get_id_vendor(dev->evdev), 140 libevdev_get_id_product(dev->evdev), 141 NULL); 142 ck_assert_notnull(wacom); 143 144 nb_lw = libwacom_get_num_buttons(wacom); 145 nb = libinput_device_tablet_pad_get_num_buttons(device); 146 147 ck_assert_int_eq(nb, nb_lw); 148 149 libwacom_destroy(wacom); 150 libwacom_database_destroy(db); 151#endif 152} 153END_TEST 154 155START_TEST(pad_num_buttons) 156{ 157 struct litest_device *dev = litest_current_device(); 158 struct libinput_device *device = dev->libinput_device; 159 unsigned int code; 160 unsigned int nbuttons = 0; 161 162 for (code = BTN_0; code < KEY_OK; code++) { 163 /* BTN_STYLUS is set for compatibility reasons but not 164 * actually hooked up */ 165 if (code == BTN_STYLUS) 166 continue; 167 168 if (libevdev_has_event_code(dev->evdev, EV_KEY, code)) 169 nbuttons++; 170 } 171 172 ck_assert_int_eq(libinput_device_tablet_pad_get_num_buttons(device), 173 nbuttons); 174} 175END_TEST 176 177START_TEST(pad_button_intuos) 178{ 179#if !HAVE_LIBWACOM 180 struct litest_device *dev = litest_current_device(); 181 struct libinput *li = dev->libinput; 182 unsigned int code; 183 unsigned int expected_number = 0; 184 struct libinput_event *ev; 185 struct libinput_event_tablet_pad *pev; 186 unsigned int count = 0; 187 188 /* Intuos button mapping is sequential up from BTN_0 and continues 189 * with BTN_A */ 190 if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_0)) 191 return; 192 193 litest_drain_events(li); 194 195 for (code = BTN_0; code < BTN_DIGI; code++) { 196 /* Skip over the BTN_MOUSE and BTN_JOYSTICK range */ 197 if ((code >= BTN_MOUSE && code < BTN_JOYSTICK) || 198 (code >= BTN_DIGI)) { 199 ck_assert(!libevdev_has_event_code(dev->evdev, 200 EV_KEY, code)); 201 continue; 202 } 203 204 if (!libevdev_has_event_code(dev->evdev, EV_KEY, code)) 205 continue; 206 207 litest_button_click(dev, code, 1); 208 litest_button_click(dev, code, 0); 209 libinput_dispatch(li); 210 211 count++; 212 213 ev = libinput_get_event(li); 214 pev = litest_is_pad_button_event(ev, 215 expected_number, 216 LIBINPUT_BUTTON_STATE_PRESSED); 217 ev = libinput_event_tablet_pad_get_base_event(pev); 218 libinput_event_destroy(ev); 219 220 ev = libinput_get_event(li); 221 pev = litest_is_pad_button_event(ev, 222 expected_number, 223 LIBINPUT_BUTTON_STATE_RELEASED); 224 ev = libinput_event_tablet_pad_get_base_event(pev); 225 libinput_event_destroy(ev); 226 227 expected_number++; 228 } 229 230 litest_assert_empty_queue(li); 231 232 ck_assert_int_gt(count, 3); 233#endif 234} 235END_TEST 236 237START_TEST(pad_button_bamboo) 238{ 239#if !HAVE_LIBWACOM 240 struct litest_device *dev = litest_current_device(); 241 struct libinput *li = dev->libinput; 242 unsigned int code; 243 unsigned int expected_number = 0; 244 struct libinput_event *ev; 245 struct libinput_event_tablet_pad *pev; 246 unsigned int count = 0; 247 248 if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_LEFT)) 249 return; 250 251 litest_drain_events(li); 252 253 for (code = BTN_LEFT; code < BTN_JOYSTICK; code++) { 254 if (!libevdev_has_event_code(dev->evdev, EV_KEY, code)) 255 continue; 256 257 litest_button_click(dev, code, 1); 258 litest_button_click(dev, code, 0); 259 libinput_dispatch(li); 260 261 count++; 262 263 ev = libinput_get_event(li); 264 pev = litest_is_pad_button_event(ev, 265 expected_number, 266 LIBINPUT_BUTTON_STATE_PRESSED); 267 ev = libinput_event_tablet_pad_get_base_event(pev); 268 libinput_event_destroy(ev); 269 270 ev = libinput_get_event(li); 271 pev = litest_is_pad_button_event(ev, 272 expected_number, 273 LIBINPUT_BUTTON_STATE_RELEASED); 274 ev = libinput_event_tablet_pad_get_base_event(pev); 275 libinput_event_destroy(ev); 276 277 expected_number++; 278 } 279 280 litest_assert_empty_queue(li); 281 282 ck_assert_int_gt(count, 3); 283#endif 284} 285END_TEST 286 287START_TEST(pad_button_libwacom) 288{ 289#if HAVE_LIBWACOM 290 struct litest_device *dev = litest_current_device(); 291 struct libinput *li = dev->libinput; 292 WacomDeviceDatabase *db = NULL; 293 WacomDevice *wacom = NULL; 294 295 db = libwacom_database_new(); 296 assert(db); 297 298 wacom = libwacom_new_from_usbid(db, 299 libevdev_get_id_vendor(dev->evdev), 300 libevdev_get_id_product(dev->evdev), 301 NULL); 302 assert(wacom); 303 304 litest_drain_events(li); 305 306 for (int i = 0; i < libwacom_get_num_buttons(wacom); i++) { 307 unsigned int code; 308 309 code = libwacom_get_button_evdev_code(wacom, 'A' + i); 310 311 litest_button_click(dev, code, 1); 312 litest_button_click(dev, code, 0); 313 libinput_dispatch(li); 314 315 litest_assert_pad_button_event(li, 316 i, 317 LIBINPUT_BUTTON_STATE_PRESSED); 318 litest_assert_pad_button_event(li, 319 i, 320 LIBINPUT_BUTTON_STATE_RELEASED); 321 } 322 323 libwacom_destroy(wacom); 324 libwacom_database_destroy(db); 325#endif 326} 327END_TEST 328 329START_TEST(pad_button_mode_groups) 330{ 331 struct litest_device *dev = litest_current_device(); 332 struct libinput *li = dev->libinput; 333 unsigned int code; 334 struct libinput_event *ev; 335 struct libinput_event_tablet_pad *pev; 336 337 litest_drain_events(li); 338 339 for (code = BTN_0; code < KEY_OK; code++) { 340 unsigned int mode, index; 341 struct libinput_tablet_pad_mode_group *group; 342 343 if (!libevdev_has_event_code(dev->evdev, EV_KEY, code)) 344 continue; 345 346 litest_button_click(dev, code, 1); 347 litest_button_click(dev, code, 0); 348 libinput_dispatch(li); 349 350 switch (code) { 351 case BTN_STYLUS: 352 litest_assert_empty_queue(li); 353 continue; 354 default: 355 break; 356 } 357 358 ev = libinput_get_event(li); 359 ck_assert_int_eq(libinput_event_get_type(ev), 360 LIBINPUT_EVENT_TABLET_PAD_BUTTON); 361 pev = libinput_event_get_tablet_pad_event(ev); 362 363 /* litest virtual devices don't have modes */ 364 mode = libinput_event_tablet_pad_get_mode(pev); 365 ck_assert_int_eq(mode, 0); 366 group = libinput_event_tablet_pad_get_mode_group(pev); 367 index = libinput_tablet_pad_mode_group_get_index(group); 368 ck_assert_int_eq(index, 0); 369 370 libinput_event_destroy(ev); 371 372 ev = libinput_get_event(li); 373 ck_assert_int_eq(libinput_event_get_type(ev), 374 LIBINPUT_EVENT_TABLET_PAD_BUTTON); 375 pev = libinput_event_get_tablet_pad_event(ev); 376 377 mode = libinput_event_tablet_pad_get_mode(pev); 378 ck_assert_int_eq(mode, 0); 379 group = libinput_event_tablet_pad_get_mode_group(pev); 380 index = libinput_tablet_pad_mode_group_get_index(group); 381 ck_assert_int_eq(index, 0); 382 libinput_event_destroy(ev); 383 } 384 385 litest_assert_empty_queue(li); 386} 387END_TEST 388 389START_TEST(pad_has_ring) 390{ 391 struct litest_device *dev = litest_current_device(); 392 struct libinput_device *device = dev->libinput_device; 393 int nrings; 394 395 nrings = libinput_device_tablet_pad_get_num_rings(device); 396 ck_assert_int_ge(nrings, 1); 397} 398END_TEST 399 400START_TEST(pad_ring) 401{ 402 struct litest_device *dev = litest_current_device(); 403 struct libinput *li = dev->libinput; 404 struct libinput_event *ev; 405 struct libinput_event_tablet_pad *pev; 406 int val; 407 double degrees, expected; 408 int min, max; 409 int step_size; 410 int nevents = 0; 411 412 litest_pad_ring_start(dev, 10); 413 414 litest_drain_events(li); 415 416 /* Wacom's 0 value is at 275 degrees */ 417 expected = 270; 418 419 min = libevdev_get_abs_minimum(dev->evdev, ABS_WHEEL); 420 max = libevdev_get_abs_maximum(dev->evdev, ABS_WHEEL); 421 step_size = 360/(max - min + 1); 422 423 /* This is a bit strange because we rely on kernel filtering here. 424 The litest_*() functions take a percentage, but mapping this to 425 the pads 72 or 36 range pad ranges is lossy and a bit 426 unpredictable. So instead we increase by a small percentage, 427 expecting *most* events to be filtered by the kernel because they 428 resolve to the same integer value as the previous event. Whenever 429 an event gets through, we expect that to be the next integer 430 value in the range and thus the next step on the circle. 431 */ 432 for (val = 0; val < 100.0; val += 1) { 433 litest_pad_ring_change(dev, val); 434 libinput_dispatch(li); 435 436 ev = libinput_get_event(li); 437 if (!ev) 438 continue; 439 440 nevents++; 441 pev = litest_is_pad_ring_event(ev, 442 0, 443 LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); 444 445 degrees = libinput_event_tablet_pad_get_ring_position(pev); 446 ck_assert_double_ge(degrees, 0.0); 447 ck_assert_double_lt(degrees, 360.0); 448 449 ck_assert_double_eq(degrees, expected); 450 451 libinput_event_destroy(ev); 452 expected = fmod(degrees + step_size, 360); 453 } 454 455 ck_assert_int_eq(nevents, 360/step_size - 1); 456 457 litest_pad_ring_end(dev); 458} 459END_TEST 460 461START_TEST(pad_ring_finger_up) 462{ 463 struct litest_device *dev = litest_current_device(); 464 struct libinput *li = dev->libinput; 465 struct libinput_event *ev; 466 struct libinput_event_tablet_pad *pev; 467 double degrees; 468 469 litest_pad_ring_start(dev, 10); 470 471 litest_drain_events(li); 472 473 litest_pad_ring_end(dev); 474 libinput_dispatch(li); 475 476 ev = libinput_get_event(li); 477 pev = litest_is_pad_ring_event(ev, 478 0, 479 LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); 480 481 degrees = libinput_event_tablet_pad_get_ring_position(pev); 482 ck_assert_double_eq(degrees, -1.0); 483 libinput_event_destroy(ev); 484 485 litest_assert_empty_queue(li); 486} 487END_TEST 488 489START_TEST(pad_has_strip) 490{ 491 struct litest_device *dev = litest_current_device(); 492 struct libinput_device *device = dev->libinput_device; 493 int nstrips; 494 495 nstrips = libinput_device_tablet_pad_get_num_strips(device); 496 ck_assert_int_ge(nstrips, 1); 497} 498END_TEST 499 500START_TEST(pad_strip) 501{ 502 struct litest_device *dev = litest_current_device(); 503 struct libinput *li = dev->libinput; 504 struct libinput_event *ev; 505 struct libinput_event_tablet_pad *pev; 506 int val; 507 double pos, expected; 508 509 litest_pad_strip_start(dev, 10); 510 511 litest_drain_events(li); 512 513 expected = 0; 514 515 /* 9.5 works with the generic axis scaling without jumping over a 516 * value. */ 517 for (val = 0; val < 100; val += 9.5) { 518 litest_pad_strip_change(dev, val); 519 libinput_dispatch(li); 520 521 ev = libinput_get_event(li); 522 pev = litest_is_pad_strip_event(ev, 523 0, 524 LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); 525 526 pos = libinput_event_tablet_pad_get_strip_position(pev); 527 ck_assert_double_ge(pos, 0.0); 528 ck_assert_double_lt(pos, 1.0); 529 530 /* rounding errors, mostly caused by small physical range */ 531 ck_assert_double_ge(pos, expected - 0.02); 532 ck_assert_double_le(pos, expected + 0.02); 533 534 libinput_event_destroy(ev); 535 536 expected = pos + 0.08; 537 } 538 539 litest_pad_strip_change(dev, 100); 540 libinput_dispatch(li); 541 542 ev = libinput_get_event(li); 543 pev = litest_is_pad_strip_event(ev, 544 0, 545 LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); 546 pos = libinput_event_tablet_pad_get_strip_position(pev); 547 ck_assert_double_eq(pos, 1.0); 548 libinput_event_destroy(ev); 549 550 litest_pad_strip_end(dev); 551} 552END_TEST 553 554START_TEST(pad_strip_finger_up) 555{ 556 struct litest_device *dev = litest_current_device(); 557 struct libinput *li = dev->libinput; 558 struct libinput_event *ev; 559 struct libinput_event_tablet_pad *pev; 560 double pos; 561 562 litest_pad_strip_start(dev, 10); 563 litest_drain_events(li); 564 565 litest_pad_strip_end(dev); 566 libinput_dispatch(li); 567 568 ev = libinput_get_event(li); 569 pev = litest_is_pad_strip_event(ev, 570 0, 571 LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER); 572 573 pos = libinput_event_tablet_pad_get_strip_position(pev); 574 ck_assert_double_eq(pos, -1.0); 575 libinput_event_destroy(ev); 576 577 litest_assert_empty_queue(li); 578} 579END_TEST 580 581START_TEST(pad_left_handed_default) 582{ 583#if HAVE_LIBWACOM 584 struct litest_device *dev = litest_current_device(); 585 struct libinput_device *device = dev->libinput_device; 586 enum libinput_config_status status; 587 588 ck_assert(libinput_device_config_left_handed_is_available(device)); 589 590 ck_assert_int_eq(libinput_device_config_left_handed_get_default(device), 591 0); 592 ck_assert_int_eq(libinput_device_config_left_handed_get(device), 593 0); 594 595 status = libinput_device_config_left_handed_set(dev->libinput_device, 1); 596 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); 597 598 ck_assert_int_eq(libinput_device_config_left_handed_get(device), 599 1); 600 ck_assert_int_eq(libinput_device_config_left_handed_get_default(device), 601 0); 602 603 status = libinput_device_config_left_handed_set(dev->libinput_device, 0); 604 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); 605 606 ck_assert_int_eq(libinput_device_config_left_handed_get(device), 607 0); 608 ck_assert_int_eq(libinput_device_config_left_handed_get_default(device), 609 0); 610 611#endif 612} 613END_TEST 614 615START_TEST(pad_no_left_handed) 616{ 617 struct litest_device *dev = litest_current_device(); 618 struct libinput_device *device = dev->libinput_device; 619 enum libinput_config_status status; 620 621 /* Without libwacom we default to left-handed being available */ 622#if HAVE_LIBWACOM 623 ck_assert(!libinput_device_config_left_handed_is_available(device)); 624#else 625 ck_assert(libinput_device_config_left_handed_is_available(device)); 626#endif 627 628 ck_assert_int_eq(libinput_device_config_left_handed_get_default(device), 629 0); 630 ck_assert_int_eq(libinput_device_config_left_handed_get(device), 631 0); 632 633#if HAVE_LIBWACOM 634 status = libinput_device_config_left_handed_set(dev->libinput_device, 1); 635 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED); 636 637 ck_assert_int_eq(libinput_device_config_left_handed_get(device), 638 0); 639 ck_assert_int_eq(libinput_device_config_left_handed_get_default(device), 640 0); 641 642 status = libinput_device_config_left_handed_set(dev->libinput_device, 0); 643 ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED); 644 645 ck_assert_int_eq(libinput_device_config_left_handed_get(device), 646 0); 647 ck_assert_int_eq(libinput_device_config_left_handed_get_default(device), 648 0); 649#endif 650} 651END_TEST 652 653START_TEST(pad_left_handed_ring) 654{ 655#if HAVE_LIBWACOM 656 struct litest_device *dev = litest_current_device(); 657 struct libinput *li = dev->libinput; 658 struct libinput_event *ev; 659 struct libinput_event_tablet_pad *pev; 660 int val; 661 double degrees, expected; 662 663 libinput_device_config_left_handed_set(dev->libinput_device, 1); 664 665 litest_pad_ring_start(dev, 10); 666 667 litest_drain_events(li); 668 669 /* Wacom's 0 value is at 275 degrees -> 90 in left-handed mode*/ 670 expected = 90; 671 672 for (val = 0; val < 100; val += 10) { 673 litest_pad_ring_change(dev, val); 674 libinput_dispatch(li); 675 676 ev = libinput_get_event(li); 677 pev = litest_is_pad_ring_event(ev, 678 0, 679 LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER); 680 681 degrees = libinput_event_tablet_pad_get_ring_position(pev); 682 ck_assert_double_ge(degrees, 0.0); 683 ck_assert_double_lt(degrees, 360.0); 684 685 /* rounding errors, mostly caused by small physical range */ 686 ck_assert_double_ge(degrees, expected - 2); 687 ck_assert_double_le(degrees, expected + 2); 688 689 libinput_event_destroy(ev); 690 691 expected = fmod(degrees + 36, 360); 692 } 693 694 litest_pad_ring_end(dev); 695#endif 696} 697END_TEST 698 699START_TEST(pad_mode_groups) 700{ 701 struct litest_device *dev = litest_current_device(); 702 struct libinput_device *device = dev->libinput_device; 703 struct libinput_tablet_pad_mode_group *group; 704 int ngroups; 705 int i; 706 707 ngroups = libinput_device_tablet_pad_get_num_mode_groups(device); 708 ck_assert_int_eq(ngroups, 1); 709 710 for (i = 0; i < ngroups; i++) { 711 group = libinput_device_tablet_pad_get_mode_group(device, i); 712 ck_assert_notnull(group); 713 ck_assert_int_eq(libinput_tablet_pad_mode_group_get_index(group), 714 i); 715 } 716 717 group = libinput_device_tablet_pad_get_mode_group(device, ngroups); 718 ck_assert(group == NULL); 719 group = libinput_device_tablet_pad_get_mode_group(device, ngroups + 1); 720 ck_assert(group == NULL); 721} 722END_TEST 723 724START_TEST(pad_mode_groups_userdata) 725{ 726 struct litest_device *dev = litest_current_device(); 727 struct libinput_device *device = dev->libinput_device; 728 struct libinput_tablet_pad_mode_group *group; 729 int rc; 730 void *userdata = &rc; 731 732 group = libinput_device_tablet_pad_get_mode_group(device, 0); 733 ck_assert(libinput_tablet_pad_mode_group_get_user_data(group) == 734 NULL); 735 libinput_tablet_pad_mode_group_set_user_data(group, userdata); 736 ck_assert(libinput_tablet_pad_mode_group_get_user_data(group) == 737 &rc); 738 739 libinput_tablet_pad_mode_group_set_user_data(group, NULL); 740 ck_assert(libinput_tablet_pad_mode_group_get_user_data(group) == 741 NULL); 742} 743END_TEST 744 745START_TEST(pad_mode_groups_ref) 746{ 747 struct litest_device *dev = litest_current_device(); 748 struct libinput_device *device = dev->libinput_device; 749 struct libinput_tablet_pad_mode_group *group, *g; 750 751 group = libinput_device_tablet_pad_get_mode_group(device, 0); 752 g = libinput_tablet_pad_mode_group_ref(group); 753 ck_assert_ptr_eq(g, group); 754 755 /* We don't expect this to be freed. Any leaks should be caught by 756 * valgrind. */ 757 g = libinput_tablet_pad_mode_group_unref(group); 758 ck_assert_ptr_eq(g, group); 759} 760END_TEST 761 762START_TEST(pad_mode_group_mode) 763{ 764 struct litest_device *dev = litest_current_device(); 765 struct libinput_device *device = dev->libinput_device; 766 struct libinput_tablet_pad_mode_group *group; 767 int ngroups; 768 unsigned int nmodes, mode; 769 770 ngroups = libinput_device_tablet_pad_get_num_mode_groups(device); 771 ck_assert_int_ge(ngroups, 1); 772 773 group = libinput_device_tablet_pad_get_mode_group(device, 0); 774 775 nmodes = libinput_tablet_pad_mode_group_get_num_modes(group); 776 ck_assert_int_eq(nmodes, 1); 777 778 mode = libinput_tablet_pad_mode_group_get_mode(group); 779 ck_assert_int_lt(mode, nmodes); 780} 781END_TEST 782 783START_TEST(pad_mode_group_has) 784{ 785 struct litest_device *dev = litest_current_device(); 786 struct libinput_device *device = dev->libinput_device; 787 struct libinput_tablet_pad_mode_group *group; 788 int ngroups, nbuttons, nrings, nstrips; 789 int i, b, r, s; 790 791 ngroups = libinput_device_tablet_pad_get_num_mode_groups(device); 792 ck_assert_int_ge(ngroups, 1); 793 794 nbuttons = libinput_device_tablet_pad_get_num_buttons(device); 795 nrings = libinput_device_tablet_pad_get_num_rings(device); 796 nstrips = libinput_device_tablet_pad_get_num_strips(device); 797 798 for (b = 0; b < nbuttons; b++) { 799 bool found = false; 800 for (i = 0; i < ngroups; i++) { 801 group = libinput_device_tablet_pad_get_mode_group(device, 802 i); 803 if (libinput_tablet_pad_mode_group_has_button(group, 804 b)) { 805 ck_assert(!found); 806 found = true; 807 } 808 } 809 ck_assert(found); 810 } 811 812 for (s = 0; s < nstrips; s++) { 813 bool found = false; 814 for (i = 0; i < ngroups; i++) { 815 group = libinput_device_tablet_pad_get_mode_group(device, 816 i); 817 if (libinput_tablet_pad_mode_group_has_strip(group, 818 s)) { 819 ck_assert(!found); 820 found = true; 821 } 822 } 823 ck_assert(found); 824 } 825 826 for (r = 0; r < nrings; r++) { 827 bool found = false; 828 for (i = 0; i < ngroups; i++) { 829 group = libinput_device_tablet_pad_get_mode_group(device, 830 i); 831 if (libinput_tablet_pad_mode_group_has_ring(group, 832 r)) { 833 ck_assert(!found); 834 found = true; 835 } 836 } 837 ck_assert(found); 838 } 839} 840END_TEST 841 842START_TEST(pad_mode_group_has_invalid) 843{ 844 struct litest_device *dev = litest_current_device(); 845 struct libinput_device *device = dev->libinput_device; 846 struct libinput_tablet_pad_mode_group* group; 847 int ngroups, nbuttons, nrings, nstrips; 848 int i; 849 int rc; 850 851 ngroups = libinput_device_tablet_pad_get_num_mode_groups(device); 852 ck_assert_int_ge(ngroups, 1); 853 854 nbuttons = libinput_device_tablet_pad_get_num_buttons(device); 855 nrings = libinput_device_tablet_pad_get_num_rings(device); 856 nstrips = libinput_device_tablet_pad_get_num_strips(device); 857 858 for (i = 0; i < ngroups; i++) { 859 group = libinput_device_tablet_pad_get_mode_group(device, i); 860 rc = libinput_tablet_pad_mode_group_has_button(group, 861 nbuttons); 862 ck_assert_int_eq(rc, 0); 863 rc = libinput_tablet_pad_mode_group_has_button(group, 864 nbuttons + 1); 865 ck_assert_int_eq(rc, 0); 866 rc = libinput_tablet_pad_mode_group_has_button(group, 867 0x1000000); 868 ck_assert_int_eq(rc, 0); 869 } 870 871 for (i = 0; i < ngroups; i++) { 872 group = libinput_device_tablet_pad_get_mode_group(device, i); 873 rc = libinput_tablet_pad_mode_group_has_strip(group, 874 nstrips); 875 ck_assert_int_eq(rc, 0); 876 rc = libinput_tablet_pad_mode_group_has_strip(group, 877 nstrips + 1); 878 ck_assert_int_eq(rc, 0); 879 rc = libinput_tablet_pad_mode_group_has_strip(group, 880 0x1000000); 881 ck_assert_int_eq(rc, 0); 882 } 883 884 for (i = 0; i < ngroups; i++) { 885 group = libinput_device_tablet_pad_get_mode_group(device, i); 886 rc = libinput_tablet_pad_mode_group_has_ring(group, 887 nrings); 888 ck_assert_int_eq(rc, 0); 889 rc = libinput_tablet_pad_mode_group_has_ring(group, 890 nrings + 1); 891 ck_assert_int_eq(rc, 0); 892 rc = libinput_tablet_pad_mode_group_has_ring(group, 893 0x1000000); 894 ck_assert_int_eq(rc, 0); 895 } 896} 897END_TEST 898 899START_TEST(pad_mode_group_has_no_toggle) 900{ 901 struct litest_device *dev = litest_current_device(); 902 struct libinput_device *device = dev->libinput_device; 903 struct libinput_tablet_pad_mode_group* group; 904 int ngroups, nbuttons; 905 int i, b; 906 907 ngroups = libinput_device_tablet_pad_get_num_mode_groups(device); 908 ck_assert_int_ge(ngroups, 1); 909 910 /* Button must not be toggle buttons */ 911 nbuttons = libinput_device_tablet_pad_get_num_buttons(device); 912 for (i = 0; i < ngroups; i++) { 913 group = libinput_device_tablet_pad_get_mode_group(device, i); 914 for (b = 0; b < nbuttons; b++) { 915 ck_assert(!libinput_tablet_pad_mode_group_button_is_toggle( 916 group, 917 b)); 918 } 919 } 920} 921END_TEST 922 923static bool 924pad_has_keys(struct litest_device *dev) 925{ 926 struct libevdev *evdev = dev->evdev; 927 928 return (libevdev_has_event_code(evdev, EV_KEY, KEY_BUTTONCONFIG) || 929 libevdev_has_event_code(evdev, EV_KEY, KEY_ONSCREEN_KEYBOARD) || 930 libevdev_has_event_code(evdev, EV_KEY, KEY_CONTROLPANEL)); 931} 932 933static void 934pad_key_down(struct litest_device *dev, unsigned int which) 935{ 936 litest_event(dev, EV_ABS, ABS_MISC, 15); 937 litest_event(dev, EV_KEY, which, 1); 938 litest_event(dev, EV_SYN, SYN_REPORT, 0); 939} 940 941static void 942pad_key_up(struct litest_device *dev, unsigned int which) 943{ 944 litest_event(dev, EV_ABS, ABS_MISC, 0); 945 litest_event(dev, EV_KEY, which, 0); 946 litest_event(dev, EV_SYN, SYN_REPORT, 0); 947} 948 949START_TEST(pad_keys) 950{ 951 struct litest_device *dev = litest_current_device(); 952 struct libinput *li = dev->libinput; 953 unsigned int key; 954 955 if (!pad_has_keys(dev)) 956 return; 957 958 litest_drain_events(li); 959 960 key = KEY_BUTTONCONFIG; 961 pad_key_down(dev, key); 962 libinput_dispatch(li); 963 litest_assert_pad_key_event(li, key, LIBINPUT_KEY_STATE_PRESSED); 964 965 pad_key_up(dev, key); 966 libinput_dispatch(li); 967 litest_assert_pad_key_event(li, key, LIBINPUT_KEY_STATE_RELEASED); 968 969 key = KEY_ONSCREEN_KEYBOARD; 970 pad_key_down(dev, key); 971 libinput_dispatch(li); 972 litest_assert_pad_key_event(li, key, LIBINPUT_KEY_STATE_PRESSED); 973 974 pad_key_up(dev, key); 975 libinput_dispatch(li); 976 litest_assert_pad_key_event(li, key, LIBINPUT_KEY_STATE_RELEASED); 977 978 key = KEY_CONTROLPANEL; 979 pad_key_down(dev, key); 980 libinput_dispatch(li); 981 litest_assert_pad_key_event(li, key, LIBINPUT_KEY_STATE_PRESSED); 982 983 pad_key_up(dev, key); 984 libinput_dispatch(li); 985 litest_assert_pad_key_event(li, key, LIBINPUT_KEY_STATE_RELEASED); 986} 987END_TEST 988 989TEST_COLLECTION(tablet_pad) 990{ 991 litest_add(pad_cap, LITEST_TABLET_PAD, LITEST_ANY); 992 litest_add(pad_no_cap, LITEST_ANY, LITEST_TABLET_PAD); 993 994 litest_add(pad_time, LITEST_TABLET_PAD, LITEST_ANY); 995 996 litest_add(pad_num_buttons, LITEST_TABLET_PAD, LITEST_ANY); 997 litest_add(pad_num_buttons_libwacom, LITEST_TABLET_PAD, LITEST_ANY); 998 litest_add(pad_button_intuos, LITEST_TABLET_PAD, LITEST_ANY); 999 litest_add(pad_button_bamboo, LITEST_TABLET_PAD, LITEST_ANY); 1000 litest_add(pad_button_libwacom, LITEST_TABLET_PAD, LITEST_ANY); 1001 litest_add(pad_button_mode_groups, LITEST_TABLET_PAD, LITEST_ANY); 1002 1003 litest_add(pad_has_ring, LITEST_RING, LITEST_ANY); 1004 litest_add(pad_ring, LITEST_RING, LITEST_ANY); 1005 litest_add(pad_ring_finger_up, LITEST_RING, LITEST_ANY); 1006 1007 litest_add(pad_has_strip, LITEST_STRIP, LITEST_ANY); 1008 litest_add(pad_strip, LITEST_STRIP, LITEST_ANY); 1009 litest_add(pad_strip_finger_up, LITEST_STRIP, LITEST_ANY); 1010 1011 litest_add_for_device(pad_left_handed_default, LITEST_WACOM_INTUOS5_PAD); 1012 litest_add_for_device(pad_no_left_handed, LITEST_WACOM_INTUOS3_PAD); 1013 litest_add_for_device(pad_left_handed_ring, LITEST_WACOM_INTUOS5_PAD); 1014 /* None of the current strip tablets are left-handed */ 1015 1016 litest_add(pad_mode_groups, LITEST_TABLET_PAD, LITEST_ANY); 1017 litest_add(pad_mode_groups_userdata, LITEST_TABLET_PAD, LITEST_ANY); 1018 litest_add(pad_mode_groups_ref, LITEST_TABLET_PAD, LITEST_ANY); 1019 litest_add(pad_mode_group_mode, LITEST_TABLET_PAD, LITEST_ANY); 1020 litest_add(pad_mode_group_has, LITEST_TABLET_PAD, LITEST_ANY); 1021 litest_add(pad_mode_group_has_invalid, LITEST_TABLET_PAD, LITEST_ANY); 1022 litest_add(pad_mode_group_has_no_toggle, LITEST_TABLET_PAD, LITEST_ANY); 1023 1024 litest_add(pad_keys, LITEST_TABLET_PAD, LITEST_ANY); 1025} 1026