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
START_TEST(pad_cap)40 START_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 }
49 END_TEST
50
START_TEST(pad_no_cap)51 START_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 }
59 END_TEST
60
START_TEST(pad_time)61 START_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 }
124 END_TEST
125
START_TEST(pad_num_buttons_libwacom)126 START_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 }
153 END_TEST
154
START_TEST(pad_num_buttons)155 START_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 }
175 END_TEST
176
START_TEST(pad_button_intuos)177 START_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 }
235 END_TEST
236
START_TEST(pad_button_bamboo)237 START_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 }
285 END_TEST
286
START_TEST(pad_button_libwacom)287 START_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 }
327 END_TEST
328
START_TEST(pad_button_mode_groups)329 START_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 }
387 END_TEST
388
START_TEST(pad_has_ring)389 START_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 }
398 END_TEST
399
START_TEST(pad_ring)400 START_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 }
459 END_TEST
460
START_TEST(pad_ring_finger_up)461 START_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 }
487 END_TEST
488
START_TEST(pad_has_strip)489 START_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 }
498 END_TEST
499
START_TEST(pad_strip)500 START_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 }
552 END_TEST
553
START_TEST(pad_strip_finger_up)554 START_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 }
579 END_TEST
580
START_TEST(pad_left_handed_default)581 START_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 }
613 END_TEST
614
START_TEST(pad_no_left_handed)615 START_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 }
651 END_TEST
652
START_TEST(pad_left_handed_ring)653 START_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 }
697 END_TEST
698
START_TEST(pad_mode_groups)699 START_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 }
722 END_TEST
723
START_TEST(pad_mode_groups_userdata)724 START_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 }
743 END_TEST
744
START_TEST(pad_mode_groups_ref)745 START_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 }
760 END_TEST
761
START_TEST(pad_mode_group_mode)762 START_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 }
781 END_TEST
782
START_TEST(pad_mode_group_has)783 START_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 }
840 END_TEST
841
START_TEST(pad_mode_group_has_invalid)842 START_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 }
897 END_TEST
898
START_TEST(pad_mode_group_has_no_toggle)899 START_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 }
921 END_TEST
922
923 static bool
pad_has_keys(struct litest_device * dev)924 pad_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
933 static void
pad_key_down(struct litest_device * dev,unsigned int which)934 pad_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
941 static void
pad_key_up(struct litest_device * dev,unsigned int which)942 pad_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
START_TEST(pad_keys)949 START_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 }
987 END_TEST
988
TEST_COLLECTION(tablet_pad)989 TEST_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