xref: /third_party/libinput/test/test-keyboard.c (revision a46c0ec8)
1/*
2 * Copyright © 2014 Jonas Ådahl <jadahl@gmail.com>
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 <stdio.h>
28
29#include "libinput-util.h"
30#include "litest.h"
31
32START_TEST(keyboard_seat_key_count)
33{
34	struct litest_device *devices[4];
35	const int num_devices = ARRAY_LENGTH(devices);
36	struct libinput *libinput;
37	struct libinput_event *ev;
38	struct libinput_event_keyboard *kev;
39	int i;
40	int seat_key_count = 0;
41	int expected_key_button_count = 0;
42	char device_name[255];
43
44	libinput = litest_create_context();
45	for (i = 0; i < num_devices; ++i) {
46		sprintf(device_name, "litest Generic keyboard (%d)", i);
47		devices[i] = litest_add_device_with_overrides(libinput,
48							      LITEST_KEYBOARD,
49							      device_name,
50							      NULL, NULL, NULL);
51	}
52
53	litest_drain_events(libinput);
54
55	for (i = 0; i < num_devices; ++i)
56		litest_keyboard_key(devices[i], KEY_A, true);
57
58	libinput_dispatch(libinput);
59	while ((ev = libinput_get_event(libinput))) {
60		kev = litest_is_keyboard_event(ev,
61					       KEY_A,
62					       LIBINPUT_KEY_STATE_PRESSED);
63
64		++expected_key_button_count;
65		seat_key_count =
66			libinput_event_keyboard_get_seat_key_count(kev);
67		ck_assert_int_eq(expected_key_button_count, seat_key_count);
68
69		libinput_event_destroy(ev);
70		libinput_dispatch(libinput);
71	}
72
73	ck_assert_int_eq(seat_key_count, num_devices);
74
75	for (i = 0; i < num_devices; ++i)
76		litest_keyboard_key(devices[i], KEY_A, false);
77
78	libinput_dispatch(libinput);
79	while ((ev = libinput_get_event(libinput))) {
80		kev = libinput_event_get_keyboard_event(ev);
81		ck_assert_notnull(kev);
82		ck_assert_int_eq(libinput_event_keyboard_get_key(kev), KEY_A);
83		ck_assert_int_eq(libinput_event_keyboard_get_key_state(kev),
84				 LIBINPUT_KEY_STATE_RELEASED);
85
86		--expected_key_button_count;
87		seat_key_count =
88			libinput_event_keyboard_get_seat_key_count(kev);
89		ck_assert_int_eq(expected_key_button_count, seat_key_count);
90
91		libinput_event_destroy(ev);
92		libinput_dispatch(libinput);
93	}
94
95	ck_assert_int_eq(seat_key_count, 0);
96
97	for (i = 0; i < num_devices; ++i)
98		litest_delete_device(devices[i]);
99	litest_destroy_context(libinput);
100}
101END_TEST
102
103START_TEST(keyboard_ignore_no_pressed_release)
104{
105	struct litest_device *dev;
106	struct libinput *unused_libinput;
107	struct libinput *libinput;
108	struct libinput_event *event;
109	struct libinput_event_keyboard *kevent;
110	int events[] = {
111		EV_KEY, KEY_A,
112		-1, -1,
113	};
114	enum libinput_key_state expected_states[] = {
115		LIBINPUT_KEY_STATE_PRESSED,
116		LIBINPUT_KEY_STATE_RELEASED,
117	};
118
119	/* We can't send pressed -> released -> pressed events using uinput
120	 * as such non-symmetric events are dropped. Work-around this by first
121	 * adding the test device to the tested context after having sent an
122	 * initial pressed event. */
123	unused_libinput = litest_create_context();
124	dev = litest_add_device_with_overrides(unused_libinput,
125					       LITEST_KEYBOARD,
126					       "Generic keyboard",
127					       NULL, NULL, events);
128
129	litest_keyboard_key(dev, KEY_A, true);
130	litest_drain_events(unused_libinput);
131
132	libinput = litest_create_context();
133	libinput_path_add_device(libinput,
134				 libevdev_uinput_get_devnode(dev->uinput));
135	litest_drain_events(libinput);
136
137	litest_keyboard_key(dev, KEY_A, false);
138	litest_keyboard_key(dev, KEY_A, true);
139	litest_keyboard_key(dev, KEY_A, false);
140
141	libinput_dispatch(libinput);
142
143	ARRAY_FOR_EACH(expected_states, state) {
144		event = libinput_get_event(libinput);
145		ck_assert_notnull(event);
146		ck_assert_int_eq(libinput_event_get_type(event),
147				 LIBINPUT_EVENT_KEYBOARD_KEY);
148		kevent = libinput_event_get_keyboard_event(event);
149		ck_assert_int_eq(libinput_event_keyboard_get_key(kevent),
150				 KEY_A);
151		ck_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
152				 *state);
153		libinput_event_destroy(event);
154		libinput_dispatch(libinput);
155	}
156
157	litest_assert_empty_queue(libinput);
158	litest_delete_device(dev);
159	litest_destroy_context(libinput);
160	litest_destroy_context(unused_libinput);
161}
162END_TEST
163
164START_TEST(keyboard_key_auto_release)
165{
166	struct libinput *libinput;
167	struct litest_device *dev;
168	struct libinput_event *event;
169	enum libinput_event_type type;
170	struct libinput_event_keyboard *kevent;
171	struct {
172		int code;
173		int released;
174	} keys[] = {
175		{ .code = KEY_A, },
176		{ .code = KEY_S, },
177		{ .code = KEY_D, },
178		{ .code = KEY_G, },
179		{ .code = KEY_Z, },
180		{ .code = KEY_DELETE, },
181		{ .code = KEY_F24, },
182	};
183	int events[2 * (ARRAY_LENGTH(keys) + 1)];
184	unsigned i;
185	int key;
186	int valid_code;
187
188	/* Enable all tested keys on the device */
189	i = 0;
190	while (i < 2 * ARRAY_LENGTH(keys)) {
191		key = keys[i / 2].code;
192		events[i++] = EV_KEY;
193		events[i++] = key;
194	}
195	events[i++] = -1;
196	events[i++] = -1;
197
198	libinput = litest_create_context();
199	dev = litest_add_device_with_overrides(libinput,
200					       LITEST_KEYBOARD,
201					       "Generic keyboard",
202					       NULL, NULL, events);
203
204	litest_drain_events(libinput);
205
206	/* Send pressed events, without releasing */
207	for (i = 0; i < ARRAY_LENGTH(keys); ++i) {
208		key = keys[i].code;
209		litest_event(dev, EV_KEY, key, 1);
210		litest_event(dev, EV_SYN, SYN_REPORT, 0);
211
212		libinput_dispatch(libinput);
213
214		event = libinput_get_event(libinput);
215		litest_is_keyboard_event(event,
216					 key,
217					 LIBINPUT_KEY_STATE_PRESSED);
218		libinput_event_destroy(event);
219	}
220
221	litest_drain_events(libinput);
222
223	/* "Disconnect" device */
224	litest_delete_device(dev);
225
226	/* Mark all released keys until device is removed */
227	while (1) {
228		event = libinput_get_event(libinput);
229		ck_assert_notnull(event);
230		type = libinput_event_get_type(event);
231
232		if (type == LIBINPUT_EVENT_DEVICE_REMOVED) {
233			libinput_event_destroy(event);
234			break;
235		}
236
237		ck_assert_int_eq(type, LIBINPUT_EVENT_KEYBOARD_KEY);
238		kevent = libinput_event_get_keyboard_event(event);
239		ck_assert_int_eq(libinput_event_keyboard_get_key_state(kevent),
240				 LIBINPUT_KEY_STATE_RELEASED);
241		key = libinput_event_keyboard_get_key(kevent);
242
243		valid_code = 0;
244		for (i = 0; i < ARRAY_LENGTH(keys); ++i) {
245			if (keys[i].code == key) {
246				ck_assert_int_eq(keys[i].released, 0);
247				keys[i].released = 1;
248				valid_code = 1;
249			}
250		}
251		ck_assert_int_eq(valid_code, 1);
252		libinput_event_destroy(event);
253	}
254
255	/* Check that all pressed keys has been released. */
256	for (i = 0; i < ARRAY_LENGTH(keys); ++i) {
257		ck_assert_int_eq(keys[i].released, 1);
258	}
259
260	litest_destroy_context(libinput);
261}
262END_TEST
263
264START_TEST(keyboard_has_key)
265{
266	struct litest_device *dev = litest_current_device();
267	struct libinput_device *device = dev->libinput_device;
268	unsigned int code;
269	int evdev_has, libinput_has;
270
271	ck_assert(libinput_device_has_capability(
272					 device,
273					 LIBINPUT_DEVICE_CAP_KEYBOARD));
274
275	for (code = 0; code < KEY_CNT; code++) {
276		evdev_has = libevdev_has_event_code(dev->evdev, EV_KEY, code);
277		libinput_has = libinput_device_keyboard_has_key(device, code);
278		ck_assert_int_eq(evdev_has, libinput_has);
279	}
280}
281END_TEST
282
283START_TEST(keyboard_keys_bad_device)
284{
285	struct litest_device *dev = litest_current_device();
286	struct libinput_device *device = dev->libinput_device;
287	unsigned int code;
288	int has_key;
289
290	if (libinput_device_has_capability(device,
291					   LIBINPUT_DEVICE_CAP_KEYBOARD))
292		return;
293
294	for (code = 0; code < KEY_CNT; code++) {
295		has_key = libinput_device_keyboard_has_key(device, code);
296		ck_assert_int_eq(has_key, -1);
297	}
298}
299END_TEST
300
301START_TEST(keyboard_time_usec)
302{
303	struct litest_device *dev = litest_current_device();
304	struct libinput *li = dev->libinput;
305	struct libinput_event_keyboard *kev;
306	struct libinput_event *event;
307	uint64_t time_usec;
308
309	if (!libevdev_has_event_code(dev->evdev, EV_KEY, KEY_A))
310		return;
311
312	litest_drain_events(dev->libinput);
313
314	litest_keyboard_key(dev, KEY_A, true);
315	libinput_dispatch(li);
316
317	event = libinput_get_event(li);
318	kev = litest_is_keyboard_event(event,
319				       KEY_A,
320				       LIBINPUT_KEY_STATE_PRESSED);
321
322	time_usec = libinput_event_keyboard_get_time_usec(kev);
323	ck_assert_int_eq(libinput_event_keyboard_get_time(kev),
324			 (uint32_t) (time_usec / 1000));
325
326	libinput_event_destroy(event);
327	litest_drain_events(dev->libinput);
328}
329END_TEST
330
331START_TEST(keyboard_no_buttons)
332{
333	struct litest_device *dev = litest_current_device();
334	struct libinput *li = dev->libinput;
335	struct libinput_event *event;
336	int code;
337	const char *name;
338
339	litest_drain_events(dev->libinput);
340
341	for (code = 0; code < KEY_MAX; code++) {
342		if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
343			continue;
344
345		name = libevdev_event_code_get_name(EV_KEY, code);
346		if (!name || !strneq(name, "KEY_", 4))
347			continue;
348
349		litest_keyboard_key(dev, code, true);
350		litest_keyboard_key(dev, code, false);
351		libinput_dispatch(li);
352
353		event = libinput_get_event(li);
354		litest_is_keyboard_event(event,
355					 code,
356					 LIBINPUT_KEY_STATE_PRESSED);
357		libinput_event_destroy(event);
358		event = libinput_get_event(li);
359		litest_is_keyboard_event(event,
360					 code,
361					 LIBINPUT_KEY_STATE_RELEASED);
362		libinput_event_destroy(event);
363	}
364}
365END_TEST
366
367START_TEST(keyboard_frame_order)
368{
369	struct litest_device *dev = litest_current_device();
370	struct libinput *li = dev->libinput;
371
372	if (!libevdev_has_event_code(dev->evdev, EV_KEY, KEY_A) ||
373	    !libevdev_has_event_code(dev->evdev, EV_KEY, KEY_LEFTSHIFT))
374		return;
375
376	litest_drain_events(li);
377
378	litest_event(dev, EV_KEY, KEY_LEFTSHIFT, 1);
379	litest_event(dev, EV_KEY, KEY_A, 1);
380	litest_event(dev, EV_SYN, SYN_REPORT, 0);
381	libinput_dispatch(li);
382
383	litest_assert_key_event(li,
384				KEY_LEFTSHIFT,
385				LIBINPUT_KEY_STATE_PRESSED);
386	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
387
388	litest_event(dev, EV_KEY, KEY_LEFTSHIFT, 0);
389	litest_event(dev, EV_KEY, KEY_A, 0);
390	litest_event(dev, EV_SYN, SYN_REPORT, 0);
391	libinput_dispatch(li);
392
393	litest_assert_key_event(li,
394				KEY_LEFTSHIFT,
395				LIBINPUT_KEY_STATE_RELEASED);
396	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
397
398	litest_event(dev, EV_KEY, KEY_A, 1);
399	litest_event(dev, EV_KEY, KEY_LEFTSHIFT, 1);
400	litest_event(dev, EV_SYN, SYN_REPORT, 0);
401	libinput_dispatch(li);
402
403	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
404	litest_assert_key_event(li,
405				KEY_LEFTSHIFT,
406				LIBINPUT_KEY_STATE_PRESSED);
407
408	litest_event(dev, EV_KEY, KEY_A, 0);
409	litest_event(dev, EV_KEY, KEY_LEFTSHIFT, 0);
410	litest_event(dev, EV_SYN, SYN_REPORT, 0);
411	libinput_dispatch(li);
412
413	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
414	litest_assert_key_event(li,
415				KEY_LEFTSHIFT,
416				LIBINPUT_KEY_STATE_RELEASED);
417
418	libinput_dispatch(li);
419}
420END_TEST
421
422START_TEST(keyboard_leds)
423{
424	struct litest_device *dev = litest_current_device();
425	struct libinput_device *device = dev->libinput_device;
426
427	/* we can't actually test the results here without physically
428	 * looking at the LEDs. So all we do is trigger the code for devices
429	 * with and without LEDs and check that it doesn't go boom
430	 */
431
432	libinput_device_led_update(device,
433				   LIBINPUT_LED_NUM_LOCK);
434	libinput_device_led_update(device,
435				   LIBINPUT_LED_CAPS_LOCK);
436	libinput_device_led_update(device,
437				   LIBINPUT_LED_SCROLL_LOCK);
438
439	libinput_device_led_update(device,
440				   LIBINPUT_LED_NUM_LOCK|
441				   LIBINPUT_LED_CAPS_LOCK);
442	libinput_device_led_update(device,
443				   LIBINPUT_LED_NUM_LOCK|
444				   LIBINPUT_LED_CAPS_LOCK |
445				   LIBINPUT_LED_SCROLL_LOCK);
446	libinput_device_led_update(device, 0);
447	libinput_device_led_update(device, -1);
448}
449END_TEST
450
451START_TEST(keyboard_no_scroll)
452{
453	struct litest_device *dev = litest_current_device();
454	struct libinput_device *device = dev->libinput_device;
455	enum libinput_config_scroll_method method;
456	enum libinput_config_status status;
457
458	method = libinput_device_config_scroll_get_method(device);
459	ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
460	method = libinput_device_config_scroll_get_default_method(device);
461	ck_assert_int_eq(method, LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
462
463	status = libinput_device_config_scroll_set_method(device,
464				 LIBINPUT_CONFIG_SCROLL_2FG);
465	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
466	status = libinput_device_config_scroll_set_method(device,
467				 LIBINPUT_CONFIG_SCROLL_EDGE);
468	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
469	status = libinput_device_config_scroll_set_method(device,
470				 LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN);
471	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
472	status = libinput_device_config_scroll_set_method(device,
473				 LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
474	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
475}
476END_TEST
477
478TEST_COLLECTION(keyboard)
479{
480	litest_add_no_device(keyboard_seat_key_count);
481	litest_add_no_device(keyboard_ignore_no_pressed_release);
482	litest_add_no_device(keyboard_key_auto_release);
483	litest_add(keyboard_has_key, LITEST_KEYS, LITEST_ANY);
484	litest_add(keyboard_keys_bad_device, LITEST_ANY, LITEST_ANY);
485	litest_add(keyboard_time_usec, LITEST_KEYS, LITEST_ANY);
486
487	litest_add(keyboard_no_buttons, LITEST_KEYS, LITEST_ANY);
488	litest_add(keyboard_frame_order, LITEST_KEYS, LITEST_ANY);
489
490	litest_add(keyboard_leds, LITEST_ANY, LITEST_ANY);
491
492	litest_add(keyboard_no_scroll, LITEST_KEYS, LITEST_WHEEL);
493}
494