xref: /third_party/libinput/test/test-pad.c (revision a46c0ec8)
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