xref: /third_party/libinput/test/test-switch.c (revision a46c0ec8)
1/*
2 * Copyright © 2017 James Ye <jye836@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 <fcntl.h>
28#include <libinput.h>
29
30#include "libinput-util.h"
31#include "litest.h"
32
33static inline bool
34switch_has_lid(struct litest_device *dev)
35{
36	return libinput_device_switch_has_switch(dev->libinput_device,
37						 LIBINPUT_SWITCH_LID) > 0;
38}
39
40static inline bool
41switch_has_tablet_mode(struct litest_device *dev)
42{
43	return libinput_device_switch_has_switch(dev->libinput_device,
44						 LIBINPUT_SWITCH_TABLET_MODE) > 0;
45}
46
47START_TEST(switch_has_cap)
48{
49	struct litest_device *dev = litest_current_device();
50
51	/* Need to check for this specific device here because the
52	 * unreliable tablet mode switch removes the capability too */
53	if (dev->which == LITEST_TABLET_MODE_UNRELIABLE) {
54		ck_assert(!libinput_device_has_capability(dev->libinput_device,
55							  LIBINPUT_DEVICE_CAP_SWITCH));
56		return;
57	}
58
59	ck_assert(libinput_device_has_capability(dev->libinput_device,
60						 LIBINPUT_DEVICE_CAP_SWITCH));
61
62}
63END_TEST
64
65START_TEST(switch_has_lid_switch)
66{
67	struct litest_device *dev = litest_current_device();
68
69	if (!libevdev_has_event_code(dev->evdev, EV_SW, SW_LID))
70		return;
71
72	ck_assert_int_eq(libinput_device_switch_has_switch(dev->libinput_device,
73							   LIBINPUT_SWITCH_LID),
74			 1);
75}
76END_TEST
77
78static bool
79tablet_mode_switch_is_reliable(struct litest_device *dev)
80{
81	bool is_unreliable = false;
82
83       quirks_get_bool(dev->quirks,
84		QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE,
85		&is_unreliable);
86
87	return !is_unreliable;
88}
89
90START_TEST(switch_has_tablet_mode_switch)
91{
92	struct litest_device *dev = litest_current_device();
93	int has_switch;
94
95	if (!libevdev_has_event_code(dev->evdev, EV_SW, SW_TABLET_MODE))
96		return;
97
98	has_switch = libinput_device_switch_has_switch(dev->libinput_device,
99						       LIBINPUT_SWITCH_TABLET_MODE);
100
101	if (!tablet_mode_switch_is_reliable(dev))
102		ck_assert_int_ne(has_switch, 1);
103	else
104		ck_assert_int_eq(has_switch, 1);
105}
106END_TEST
107
108START_TEST(switch_toggle)
109{
110	struct litest_device *dev = litest_current_device();
111	struct libinput *li = dev->libinput;
112	struct libinput_event *event;
113	enum libinput_switch sw = _i; /* ranged test */
114
115	litest_drain_events(li);
116
117	litest_grab_device(dev);
118	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
119	libinput_dispatch(li);
120
121	if (libinput_device_switch_has_switch(dev->libinput_device, sw) > 0) {
122		event = libinput_get_event(li);
123		litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON);
124		libinput_event_destroy(event);
125	} else {
126		litest_assert_empty_queue(li);
127	}
128
129	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_OFF);
130	libinput_dispatch(li);
131
132	if (libinput_device_switch_has_switch(dev->libinput_device, sw) > 0) {
133		event = libinput_get_event(li);
134		litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_OFF);
135		libinput_event_destroy(event);
136	}
137
138	litest_assert_empty_queue(li);
139	litest_ungrab_device(dev);
140}
141END_TEST
142
143START_TEST(switch_toggle_double)
144{
145	struct litest_device *dev = litest_current_device();
146	struct libinput *li = dev->libinput;
147	struct libinput_event *event;
148	enum libinput_switch sw = _i; /* ranged test */
149
150	if (libinput_device_switch_has_switch(dev->libinput_device, sw) <= 0)
151		return;
152
153	litest_drain_events(li);
154
155	litest_grab_device(dev);
156	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
157	libinput_dispatch(li);
158
159	event = libinput_get_event(li);
160	litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON);
161	libinput_event_destroy(event);
162
163	/* This will be filtered by the kernel, so this test is a bit
164	 * useless */
165	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
166	libinput_dispatch(li);
167
168	litest_assert_empty_queue(li);
169	litest_ungrab_device(dev);
170}
171END_TEST
172
173static bool
174lid_switch_is_reliable(struct litest_device *dev)
175{
176	char *prop;
177	bool is_reliable = false;
178
179	if (quirks_get_string(dev->quirks,
180			      QUIRK_ATTR_LID_SWITCH_RELIABILITY,
181			      &prop)) {
182		is_reliable = streq(prop, "reliable");
183	}
184
185
186	return is_reliable;
187}
188
189START_TEST(switch_down_on_init)
190{
191	struct litest_device *dev = litest_current_device();
192	struct libinput *li;
193	struct libinput_event *event;
194	enum libinput_switch sw = _i; /* ranged test */
195
196	if (libinput_device_switch_has_switch(dev->libinput_device, sw) <= 0)
197		return;
198
199	if (sw == LIBINPUT_SWITCH_LID && !lid_switch_is_reliable(dev))
200		return;
201
202	litest_grab_device(dev);
203	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
204	litest_ungrab_device(dev);
205
206	/* need separate context to test */
207	li = litest_create_context();
208	libinput_path_add_device(li,
209				 libevdev_uinput_get_devnode(dev->uinput));
210	libinput_dispatch(li);
211
212	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_SWITCH_TOGGLE, -1);
213	event = libinput_get_event(li);
214	litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON);
215	libinput_event_destroy(event);
216
217	while ((event = libinput_get_event(li))) {
218		ck_assert_int_ne(libinput_event_get_type(event),
219				 LIBINPUT_EVENT_SWITCH_TOGGLE);
220		libinput_event_destroy(event);
221	}
222
223	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_OFF);
224	libinput_dispatch(li);
225	event = libinput_get_event(li);
226	litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_OFF);
227	libinput_event_destroy(event);
228	litest_assert_empty_queue(li);
229
230	litest_destroy_context(li);
231}
232END_TEST
233
234START_TEST(switch_not_down_on_init)
235{
236	struct litest_device *dev = litest_current_device();
237	struct libinput *li;
238	struct libinput_event *event;
239	enum libinput_switch sw = LIBINPUT_SWITCH_LID;
240
241	if (libinput_device_switch_has_switch(dev->libinput_device, sw) <= 0)
242		return;
243
244	if (sw == LIBINPUT_SWITCH_LID && lid_switch_is_reliable(dev))
245		return;
246
247	litest_grab_device(dev);
248	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON);
249	litest_ungrab_device(dev);
250
251	/* need separate context to test */
252	li = litest_create_context();
253	libinput_path_add_device(li,
254				 libevdev_uinput_get_devnode(dev->uinput));
255	libinput_dispatch(li);
256
257	while ((event = libinput_get_event(li)) != NULL) {
258		ck_assert_int_ne(libinput_event_get_type(event),
259				 LIBINPUT_EVENT_SWITCH_TOGGLE);
260		libinput_event_destroy(event);
261	}
262
263	litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_OFF);
264	litest_assert_empty_queue(li);
265	litest_destroy_context(li);
266}
267END_TEST
268
269static inline struct litest_device *
270switch_init_paired_touchpad(struct libinput *li)
271{
272	enum litest_device_type which = LITEST_SYNAPTICS_I2C;
273
274	return litest_add_device(li, which);
275}
276
277START_TEST(switch_disable_touchpad)
278{
279	struct litest_device *sw = litest_current_device();
280	struct litest_device *touchpad;
281	struct libinput *li = sw->libinput;
282	enum libinput_switch which = _i; /* ranged test */
283
284	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
285		return;
286
287	touchpad = switch_init_paired_touchpad(li);
288	litest_disable_tap(touchpad->libinput_device);
289	litest_disable_hold_gestures(touchpad->libinput_device);
290	litest_drain_events(li);
291
292	litest_grab_device(sw);
293
294	/* switch is on - no events */
295	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
296	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
297
298	litest_touch_down(touchpad, 0, 50, 50);
299	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
300	litest_touch_up(touchpad, 0);
301	litest_assert_empty_queue(li);
302
303	/* switch is off - motion events */
304	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
305	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
306
307	litest_touch_down(touchpad, 0, 50, 50);
308	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
309	litest_touch_up(touchpad, 0);
310	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
311
312	litest_delete_device(touchpad);
313	litest_ungrab_device(sw);
314}
315END_TEST
316
317START_TEST(switch_disable_touchpad_during_touch)
318{
319	struct litest_device *sw = litest_current_device();
320	struct litest_device *touchpad;
321	struct libinput *li = sw->libinput;
322	enum libinput_switch which = _i; /* ranged test */
323
324	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
325		return;
326
327	touchpad = switch_init_paired_touchpad(li);
328	litest_disable_tap(touchpad->libinput_device);
329	litest_disable_hold_gestures(touchpad->libinput_device);
330	litest_drain_events(li);
331
332	litest_touch_down(touchpad, 0, 50, 50);
333	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 5);
334	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
335
336	litest_grab_device(sw);
337	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
338	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
339	litest_ungrab_device(sw);
340
341	litest_touch_move_to(touchpad, 0, 70, 50, 50, 50, 5);
342	litest_touch_up(touchpad, 0);
343	litest_assert_empty_queue(li);
344
345	litest_delete_device(touchpad);
346}
347END_TEST
348
349START_TEST(switch_disable_touchpad_edge_scroll)
350{
351	struct litest_device *sw = litest_current_device();
352	struct litest_device *touchpad;
353	struct libinput *li = sw->libinput;
354	enum libinput_switch which = _i; /* ranged test */
355
356	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
357		return;
358
359	touchpad = switch_init_paired_touchpad(li);
360	litest_enable_edge_scroll(touchpad);
361
362	litest_drain_events(li);
363
364	litest_grab_device(sw);
365	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
366	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
367	litest_ungrab_device(sw);
368
369	litest_touch_down(touchpad, 0, 99, 20);
370	libinput_dispatch(li);
371	litest_timeout_edgescroll();
372	libinput_dispatch(li);
373	litest_assert_empty_queue(li);
374
375	litest_touch_move_to(touchpad, 0, 99, 20, 99, 80, 60);
376	libinput_dispatch(li);
377	litest_assert_empty_queue(li);
378
379	litest_touch_move_to(touchpad, 0, 99, 80, 99, 20, 60);
380	litest_touch_up(touchpad, 0);
381	libinput_dispatch(li);
382	litest_assert_empty_queue(li);
383
384	litest_delete_device(touchpad);
385}
386END_TEST
387
388START_TEST(switch_disable_touchpad_edge_scroll_interrupt)
389{
390	struct litest_device *sw = litest_current_device();
391	struct litest_device *touchpad;
392	struct libinput *li = sw->libinput;
393	struct libinput_event *event;
394	enum libinput_switch which = _i; /* ranged test */
395
396	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
397		return;
398
399	touchpad = switch_init_paired_touchpad(li);
400	litest_enable_edge_scroll(touchpad);
401
402	litest_drain_events(li);
403
404	litest_touch_down(touchpad, 0, 99, 20);
405	libinput_dispatch(li);
406	litest_timeout_edgescroll();
407	litest_touch_move_to(touchpad, 0, 99, 20, 99, 30, 10);
408	libinput_dispatch(li);
409	litest_assert_only_axis_events(li, LIBINPUT_EVENT_POINTER_SCROLL_FINGER);
410
411	litest_grab_device(sw);
412	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
413	litest_ungrab_device(sw);
414	libinput_dispatch(li);
415
416	litest_assert_axis_end_sequence(li,
417					LIBINPUT_EVENT_POINTER_SCROLL_FINGER,
418					LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
419					LIBINPUT_POINTER_AXIS_SOURCE_FINGER);
420
421	event = libinput_get_event(li);
422	litest_is_switch_event(event, which, LIBINPUT_SWITCH_STATE_ON);
423	libinput_event_destroy(event);
424
425	litest_delete_device(touchpad);
426}
427END_TEST
428
429START_TEST(switch_disable_touchpad_already_open)
430{
431	struct litest_device *sw = litest_current_device();
432	struct litest_device *touchpad;
433	struct libinput *li = sw->libinput;
434	enum libinput_switch which = _i; /* ranged test */
435
436	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
437		return;
438
439	touchpad = switch_init_paired_touchpad(li);
440
441	litest_disable_tap(touchpad->libinput_device);
442	litest_disable_hold_gestures(touchpad->libinput_device);
443	litest_drain_events(li);
444
445	/* default: switch is off - motion events */
446	litest_touch_down(touchpad, 0, 50, 50);
447	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
448	litest_touch_up(touchpad, 0);
449	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
450
451	/* disable switch - motion events */
452	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
453	litest_assert_empty_queue(li);
454
455	litest_touch_down(touchpad, 0, 50, 50);
456	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
457	litest_touch_up(touchpad, 0);
458	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
459
460	litest_delete_device(touchpad);
461}
462END_TEST
463
464START_TEST(switch_dont_resume_disabled_touchpad)
465{
466	struct litest_device *sw = litest_current_device();
467	struct litest_device *touchpad;
468	struct libinput *li = sw->libinput;
469	enum libinput_switch which = _i; /* ranged test */
470
471	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
472		return;
473
474	touchpad = switch_init_paired_touchpad(li);
475	litest_disable_tap(touchpad->libinput_device);
476	litest_disable_hold_gestures(touchpad->libinput_device);
477	libinput_device_config_send_events_set_mode(touchpad->libinput_device,
478						    LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
479	litest_drain_events(li);
480
481	/* switch is on - no events */
482	litest_grab_device(sw);
483	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
484	litest_ungrab_device(sw);
485	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
486
487	litest_touch_down(touchpad, 0, 50, 50);
488	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
489	litest_touch_up(touchpad, 0);
490	litest_assert_empty_queue(li);
491
492	/* switch is off but but tp is still disabled */
493	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
494	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
495
496	litest_touch_down(touchpad, 0, 50, 50);
497	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
498	litest_touch_up(touchpad, 0);
499	litest_assert_empty_queue(li);
500
501	litest_delete_device(touchpad);
502}
503END_TEST
504
505START_TEST(switch_dont_resume_disabled_touchpad_external_mouse)
506{
507	struct litest_device *sw = litest_current_device();
508	struct litest_device *touchpad, *mouse;
509	struct libinput *li = sw->libinput;
510	enum libinput_switch which = _i; /* ranged test */
511
512	if (libinput_device_switch_has_switch(sw->libinput_device, which) <= 0)
513		return;
514
515	touchpad = switch_init_paired_touchpad(li);
516	mouse = litest_add_device(li, LITEST_MOUSE);
517	litest_disable_tap(touchpad->libinput_device);
518	litest_disable_hold_gestures(touchpad->libinput_device);
519	libinput_device_config_send_events_set_mode(touchpad->libinput_device,
520						    LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE);
521	litest_drain_events(li);
522
523	litest_touch_down(touchpad, 0, 50, 50);
524	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
525	litest_touch_up(touchpad, 0);
526	litest_assert_empty_queue(li);
527
528	/* switch is on - no events */
529	litest_grab_device(sw);
530	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
531	litest_ungrab_device(sw);
532	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
533
534	litest_touch_down(touchpad, 0, 50, 50);
535	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
536	litest_touch_up(touchpad, 0);
537	litest_assert_empty_queue(li);
538
539	/* switch is off but but tp is still disabled */
540	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
541	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
542
543	litest_touch_down(touchpad, 0, 50, 50);
544	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
545	litest_touch_up(touchpad, 0);
546	litest_assert_empty_queue(li);
547
548	litest_delete_device(touchpad);
549	litest_delete_device(mouse);
550}
551END_TEST
552
553START_TEST(lid_open_on_key)
554{
555	struct litest_device *sw = litest_current_device();
556	struct litest_device *keyboard;
557	struct libinput *li = sw->libinput;
558	struct libinput_event *event;
559
560	if (!switch_has_lid(sw))
561		return;
562
563	keyboard = litest_add_device(li, LITEST_KEYBOARD);
564
565	litest_grab_device(sw);
566	for (int i = 0; i < 3; i++) {
567		litest_switch_action(sw,
568				     LIBINPUT_SWITCH_LID,
569				     LIBINPUT_SWITCH_STATE_ON);
570		litest_drain_events(li);
571
572		litest_event(keyboard, EV_KEY, KEY_A, 1);
573		litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
574		litest_event(keyboard, EV_KEY, KEY_A, 0);
575		litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
576		libinput_dispatch(li);
577
578		event = libinput_get_event(li);
579		litest_is_switch_event(event,
580				       LIBINPUT_SWITCH_LID,
581				       LIBINPUT_SWITCH_STATE_OFF);
582		libinput_event_destroy(event);
583
584		litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
585
586		litest_switch_action(sw,
587				     LIBINPUT_SWITCH_LID,
588				     LIBINPUT_SWITCH_STATE_OFF);
589		litest_assert_empty_queue(li);
590	}
591	litest_ungrab_device(sw);
592
593	litest_delete_device(keyboard);
594}
595END_TEST
596
597START_TEST(lid_open_on_key_touchpad_enabled)
598{
599	struct litest_device *sw = litest_current_device();
600	struct litest_device *keyboard, *touchpad;
601	struct libinput *li = sw->libinput;
602
603	if (!switch_has_lid(sw))
604		return;
605
606	keyboard = litest_add_device(li, LITEST_KEYBOARD);
607	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
608
609	litest_disable_hold_gestures(touchpad->libinput_device);
610
611	litest_grab_device(sw);
612	litest_switch_action(sw,
613			     LIBINPUT_SWITCH_LID,
614			     LIBINPUT_SWITCH_STATE_ON);
615	litest_ungrab_device(sw);
616	litest_drain_events(li);
617
618	litest_event(keyboard, EV_KEY, KEY_A, 1);
619	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
620	litest_event(keyboard, EV_KEY, KEY_A, 0);
621	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
622	litest_drain_events(li);
623	litest_timeout_dwt_long();
624
625	litest_touch_down(touchpad, 0, 50, 50);
626	litest_touch_move_to(touchpad, 0, 50, 50, 70, 70, 10);
627	litest_touch_up(touchpad, 0);
628	libinput_dispatch(li);
629
630	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
631
632	litest_delete_device(keyboard);
633	litest_delete_device(touchpad);
634}
635END_TEST
636
637START_TEST(switch_suspend_with_keyboard)
638{
639	struct libinput *li;
640	struct litest_device *keyboard;
641	struct litest_device *sw;
642	enum libinput_switch which = _i; /* ranged test */
643
644	li = litest_create_context();
645
646	switch(which) {
647	case LIBINPUT_SWITCH_LID:
648		sw = litest_add_device(li, LITEST_LID_SWITCH);
649		break;
650	case LIBINPUT_SWITCH_TABLET_MODE:
651		sw = litest_add_device(li, LITEST_THINKPAD_EXTRABUTTONS);
652		break;
653	default:
654		abort();
655	}
656
657	libinput_dispatch(li);
658
659	keyboard = litest_add_device(li, LITEST_KEYBOARD);
660	libinput_dispatch(li);
661
662	litest_grab_device(sw);
663	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
664	litest_drain_events(li);
665	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
666	litest_drain_events(li);
667	litest_ungrab_device(sw);
668
669	litest_delete_device(keyboard);
670	litest_drain_events(li);
671
672	litest_delete_device(sw);
673	libinput_dispatch(li);
674
675	litest_destroy_context(li);
676}
677END_TEST
678
679START_TEST(switch_suspend_with_touchpad)
680{
681	struct libinput *li;
682	struct litest_device *touchpad, *sw;
683	enum libinput_switch which = _i; /* ranged test */
684
685	li = litest_create_context();
686
687	switch(which) {
688	case LIBINPUT_SWITCH_LID:
689		sw = litest_add_device(li, LITEST_LID_SWITCH);
690		break;
691	case LIBINPUT_SWITCH_TABLET_MODE:
692		sw = litest_add_device(li, LITEST_THINKPAD_EXTRABUTTONS);
693		break;
694	default:
695		abort();
696	}
697
698	litest_drain_events(li);
699
700	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
701	litest_drain_events(li);
702
703	litest_grab_device(sw);
704	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_ON);
705	litest_drain_events(li);
706	litest_switch_action(sw, which, LIBINPUT_SWITCH_STATE_OFF);
707	litest_drain_events(li);
708	litest_ungrab_device(sw);
709
710	litest_delete_device(sw);
711	litest_drain_events(li);
712	litest_delete_device(touchpad);
713	litest_drain_events(li);
714
715	litest_destroy_context(li);
716}
717END_TEST
718
719START_TEST(lid_update_hw_on_key)
720{
721	struct litest_device *sw = litest_current_device();
722	struct libinput *li = sw->libinput;
723	struct litest_device *keyboard;
724	struct libevdev *evdev;
725	struct input_event event;
726	int fd;
727	int rc;
728
729	if (!switch_has_lid(sw))
730		return;
731
732	keyboard = litest_add_device(li, LITEST_KEYBOARD);
733
734	litest_grab_device(sw);
735	litest_switch_action(sw,
736			     LIBINPUT_SWITCH_LID,
737			     LIBINPUT_SWITCH_STATE_ON);
738	litest_drain_events(li);
739	litest_ungrab_device(sw);
740
741	/* Separate direct libevdev context to check if the HW event goes
742	 * through */
743	fd = open(libevdev_uinput_get_devnode(sw->uinput), O_RDONLY|O_NONBLOCK);
744	ck_assert_int_ge(fd, 0);
745	ck_assert_int_eq(libevdev_new_from_fd(fd, &evdev), 0);
746	ck_assert_int_eq(libevdev_get_event_value(evdev, EV_SW, SW_LID), 1);
747
748	/* Typing on the keyboard should trigger a lid open event */
749	litest_event(keyboard, EV_KEY, KEY_A, 1);
750	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
751	litest_event(keyboard, EV_KEY, KEY_A, 0);
752	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
753	litest_drain_events(li);
754
755	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
756	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
757	ck_assert_int_eq(event.type, EV_SW);
758	ck_assert_int_eq(event.code, SW_LID);
759	ck_assert_int_eq(event.value, 0);
760	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
761	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
762	ck_assert_int_eq(event.type, EV_SYN);
763	ck_assert_int_eq(event.code, SYN_REPORT);
764	ck_assert_int_eq(event.value, 0);
765	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
766	ck_assert_int_eq(rc, -EAGAIN);
767
768	litest_delete_device(keyboard);
769	close(fd);
770	libevdev_free(evdev);
771}
772END_TEST
773
774START_TEST(lid_update_hw_on_key_closed_on_init)
775{
776	struct litest_device *sw = litest_current_device();
777	struct libinput *li;
778	struct litest_device *keyboard;
779	struct libevdev *evdev = sw->evdev;
780	struct input_event event;
781	int fd;
782	int rc;
783
784	litest_grab_device(sw);
785	litest_switch_action(sw,
786			     LIBINPUT_SWITCH_LID,
787			     LIBINPUT_SWITCH_STATE_ON);
788	litest_ungrab_device(sw);
789
790	/* Separate direct libevdev context to check if the HW event goes
791	 * through */
792	fd = open(libevdev_uinput_get_devnode(sw->uinput), O_RDONLY|O_NONBLOCK);
793	ck_assert_int_ge(fd, 0);
794	ck_assert_int_eq(libevdev_new_from_fd(fd, &evdev), 0);
795	ck_assert_int_eq(libevdev_get_event_value(evdev, EV_SW, SW_LID), 1);
796
797	keyboard = litest_add_device(sw->libinput, LITEST_KEYBOARD);
798
799	/* separate context for the right state on init */
800	li = litest_create_context();
801	libinput_path_add_device(li,
802				 libevdev_uinput_get_devnode(sw->uinput));
803	libinput_path_add_device(li,
804				 libevdev_uinput_get_devnode(keyboard->uinput));
805
806	/* don't expect a switch waiting for us, this is run for an
807	 * unreliable device */
808	while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
809		ck_assert_int_ne(libinput_next_event_type(li),
810				 LIBINPUT_EVENT_SWITCH_TOGGLE);
811		libinput_event_destroy(libinput_get_event(li));
812	}
813
814	litest_event(keyboard, EV_KEY, KEY_A, 1);
815	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
816	litest_event(keyboard, EV_KEY, KEY_A, 0);
817	litest_event(keyboard, EV_SYN, SYN_REPORT, 0);
818	/* No switch event, we're still in vanilla (open) state */
819	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
820
821	/* Make sure kernel state has updated */
822	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
823	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
824	ck_assert_int_eq(event.type, EV_SW);
825	ck_assert_int_eq(event.code, SW_LID);
826	ck_assert_int_eq(event.value, 0);
827	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
828	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
829	ck_assert_int_eq(event.type, EV_SYN);
830	ck_assert_int_eq(event.code, SYN_REPORT);
831	ck_assert_int_eq(event.value, 0);
832	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
833	ck_assert_int_eq(rc, -EAGAIN);
834
835	litest_destroy_context(li);
836	litest_delete_device(keyboard);
837	close(fd);
838	libevdev_free(evdev);
839}
840END_TEST
841
842START_TEST(lid_update_hw_on_key_multiple_keyboards)
843{
844	struct litest_device *sw = litest_current_device();
845	struct libinput *li = sw->libinput;
846	struct litest_device *keyboard1, *keyboard2;
847	struct libevdev *evdev = sw->evdev;
848	struct input_event event;
849	int fd;
850	int rc;
851
852	if (!switch_has_lid(sw))
853		return;
854
855	keyboard1 = litest_add_device(li,
856				LITEST_KEYBOARD_BLADE_STEALTH_VIDEOSWITCH);
857	libinput_dispatch(li);
858
859	keyboard2 = litest_add_device(li, LITEST_KEYBOARD_BLADE_STEALTH);
860	libinput_dispatch(li);
861
862	litest_grab_device(sw);
863	litest_switch_action(sw,
864			     LIBINPUT_SWITCH_LID,
865			     LIBINPUT_SWITCH_STATE_ON);
866	litest_drain_events(li);
867	litest_ungrab_device(sw);
868
869	/* Separate direct libevdev context to check if the HW event goes
870	 * through */
871	fd = open(libevdev_uinput_get_devnode(sw->uinput), O_RDONLY|O_NONBLOCK);
872	ck_assert_int_ge(fd, 0);
873	ck_assert_int_eq(libevdev_new_from_fd(fd, &evdev), 0);
874	ck_assert_int_eq(libevdev_get_event_value(evdev, EV_SW, SW_LID), 1);
875
876	/* Typing on the second keyboard should trigger a lid open event */
877	litest_event(keyboard2, EV_KEY, KEY_A, 1);
878	litest_event(keyboard2, EV_SYN, SYN_REPORT, 0);
879	litest_event(keyboard2, EV_KEY, KEY_A, 0);
880	litest_event(keyboard2, EV_SYN, SYN_REPORT, 0);
881	litest_drain_events(li);
882
883	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
884	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
885	ck_assert_int_eq(event.type, EV_SW);
886	ck_assert_int_eq(event.code, SW_LID);
887	ck_assert_int_eq(event.value, 0);
888	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
889	ck_assert_int_eq(rc, LIBEVDEV_READ_STATUS_SUCCESS);
890	ck_assert_int_eq(event.type, EV_SYN);
891	ck_assert_int_eq(event.code, SYN_REPORT);
892	ck_assert_int_eq(event.value, 0);
893	rc = libevdev_next_event(evdev, LIBEVDEV_READ_FLAG_NORMAL, &event);
894	ck_assert_int_eq(rc, -EAGAIN);
895
896	litest_delete_device(keyboard1);
897	litest_delete_device(keyboard2);
898	close(fd);
899	libevdev_free(evdev);
900}
901END_TEST
902
903START_TEST(lid_key_press)
904{
905	struct litest_device *sw = litest_current_device();
906	struct libinput *li = sw->libinput;
907
908	litest_drain_events(li);
909
910	litest_keyboard_key(sw, KEY_VOLUMEUP, true);
911	litest_keyboard_key(sw, KEY_VOLUMEUP, false);
912	libinput_dispatch(li);
913
914	/* Check that we're routing key events from a lid device too */
915	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
916}
917END_TEST
918
919START_TEST(tablet_mode_disable_touchpad_on_init)
920{
921	struct litest_device *sw = litest_current_device();
922	struct litest_device *touchpad;
923	struct libinput *li = sw->libinput;
924
925	if (!switch_has_tablet_mode(sw))
926		return;
927
928	litest_grab_device(sw);
929	litest_switch_action(sw,
930			     LIBINPUT_SWITCH_TABLET_MODE,
931			     LIBINPUT_SWITCH_STATE_ON);
932	litest_drain_events(li);
933
934	/* touchpad comes with switch already on - no events */
935	touchpad = switch_init_paired_touchpad(li);
936	litest_disable_tap(touchpad->libinput_device);
937	litest_disable_hold_gestures(touchpad->libinput_device);
938	litest_drain_events(li);
939
940	litest_touch_down(touchpad, 0, 50, 50);
941	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
942	litest_touch_up(touchpad, 0);
943	litest_assert_empty_queue(li);
944
945	litest_switch_action(sw,
946			     LIBINPUT_SWITCH_TABLET_MODE,
947			     LIBINPUT_SWITCH_STATE_OFF);
948	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
949
950	litest_touch_down(touchpad, 0, 50, 50);
951	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
952	litest_touch_up(touchpad, 0);
953	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
954	litest_ungrab_device(sw);
955
956	litest_delete_device(touchpad);
957}
958END_TEST
959
960START_TEST(tablet_mode_disable_touchpad_on_resume)
961{
962	struct litest_device *sw = litest_current_device();
963	struct litest_device *touchpad;
964	struct libinput *li = sw->libinput;
965	struct libinput_event *event;
966	bool have_switch_toggle = false;
967
968	if (!switch_has_tablet_mode(sw))
969		return;
970
971	touchpad = switch_init_paired_touchpad(li);
972	litest_disable_tap(touchpad->libinput_device);
973	litest_disable_hold_gestures(touchpad->libinput_device);
974	litest_drain_events(li);
975
976	libinput_suspend(li);
977	litest_switch_action(sw,
978			     LIBINPUT_SWITCH_TABLET_MODE,
979			     LIBINPUT_SWITCH_STATE_ON);
980	litest_drain_events(li);
981	libinput_resume(li);
982	libinput_dispatch(li);
983
984	while ((event = libinput_get_event(li))) {
985		enum libinput_event_type type;
986
987		type = libinput_event_get_type(event);
988		switch (type) {
989		case LIBINPUT_EVENT_DEVICE_ADDED:
990			break;
991		case LIBINPUT_EVENT_SWITCH_TOGGLE:
992			litest_is_switch_event(event,
993					       LIBINPUT_SWITCH_TABLET_MODE,
994					       LIBINPUT_SWITCH_STATE_ON);
995			have_switch_toggle = true;
996			break;
997		default:
998			ck_abort();
999		}
1000		libinput_event_destroy(event);
1001	}
1002
1003	ck_assert(have_switch_toggle);
1004
1005	litest_touch_down(touchpad, 0, 50, 50);
1006	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
1007	litest_touch_up(touchpad, 0);
1008	litest_assert_empty_queue(li);
1009
1010	litest_switch_action(sw,
1011			     LIBINPUT_SWITCH_TABLET_MODE,
1012			     LIBINPUT_SWITCH_STATE_OFF);
1013	libinput_dispatch(li);
1014	event = libinput_get_event(li);
1015	litest_is_switch_event(event,
1016			       LIBINPUT_SWITCH_TABLET_MODE,
1017			       LIBINPUT_SWITCH_STATE_OFF);
1018	libinput_event_destroy(event);
1019
1020	litest_touch_down(touchpad, 0, 50, 50);
1021	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
1022	litest_touch_up(touchpad, 0);
1023	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1024
1025	litest_delete_device(touchpad);
1026}
1027END_TEST
1028
1029START_TEST(tablet_mode_enable_touchpad_on_resume)
1030{
1031	struct litest_device *sw = litest_current_device();
1032	struct litest_device *touchpad;
1033	struct libinput *li = sw->libinput;
1034	struct libinput_event *event;
1035
1036	if (!switch_has_tablet_mode(sw))
1037		return;
1038
1039	touchpad = switch_init_paired_touchpad(li);
1040	litest_disable_tap(touchpad->libinput_device);
1041	litest_drain_events(li);
1042
1043	litest_switch_action(sw,
1044			     LIBINPUT_SWITCH_TABLET_MODE,
1045			     LIBINPUT_SWITCH_STATE_ON);
1046	libinput_suspend(li);
1047	litest_drain_events(li);
1048
1049	litest_switch_action(sw,
1050			     LIBINPUT_SWITCH_TABLET_MODE,
1051			     LIBINPUT_SWITCH_STATE_OFF);
1052
1053	libinput_resume(li);
1054	libinput_dispatch(li);
1055
1056	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_ADDED);
1057
1058	litest_touch_down(touchpad, 0, 50, 50);
1059	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
1060	litest_touch_up(touchpad, 0);
1061	litest_drain_events_of_type(li,
1062				    LIBINPUT_EVENT_GESTURE_HOLD_BEGIN,
1063				    LIBINPUT_EVENT_GESTURE_HOLD_END,
1064				    -1);
1065	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1066
1067	litest_switch_action(sw,
1068			     LIBINPUT_SWITCH_TABLET_MODE,
1069			     LIBINPUT_SWITCH_STATE_ON);
1070	libinput_dispatch(li);
1071	event = libinput_get_event(li);
1072	litest_is_switch_event(event,
1073			       LIBINPUT_SWITCH_TABLET_MODE,
1074			       LIBINPUT_SWITCH_STATE_ON);
1075	libinput_event_destroy(event);
1076
1077	litest_touch_down(touchpad, 0, 50, 50);
1078	litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10);
1079	litest_touch_up(touchpad, 0);
1080	litest_assert_empty_queue(li);
1081
1082	litest_delete_device(touchpad);
1083}
1084END_TEST
1085
1086START_TEST(tablet_mode_disable_keyboard)
1087{
1088	struct litest_device *sw = litest_current_device();
1089	struct litest_device *keyboard;
1090	struct libinput *li = sw->libinput;
1091
1092	if (!switch_has_tablet_mode(sw))
1093		return;
1094
1095	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1096	litest_drain_events(li);
1097
1098	litest_keyboard_key(keyboard, KEY_A, true);
1099	litest_keyboard_key(keyboard, KEY_A, false);
1100	litest_keyboard_key(keyboard, KEY_B, true); /* KEY_B down but not up */
1101	libinput_dispatch(li);
1102
1103	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
1104	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
1105	litest_assert_key_event(li, KEY_B, LIBINPUT_KEY_STATE_PRESSED); /* KEY_B down but not up */
1106
1107	litest_switch_action(sw,
1108			     LIBINPUT_SWITCH_TABLET_MODE,
1109			     LIBINPUT_SWITCH_STATE_ON);
1110
1111	/* The key currently down must be released */
1112	litest_assert_key_event(li, KEY_B, LIBINPUT_KEY_STATE_RELEASED);
1113	litest_assert_switch_event(li, LIBINPUT_SWITCH_TABLET_MODE, LIBINPUT_SWITCH_STATE_ON);
1114	litest_assert_empty_queue(li);
1115
1116	litest_keyboard_key(keyboard, KEY_B, false); /* release the kernel device */
1117	litest_keyboard_key(keyboard, KEY_A, true);
1118	litest_keyboard_key(keyboard, KEY_A, false);
1119	litest_assert_empty_queue(li);
1120
1121	litest_switch_action(sw,
1122			     LIBINPUT_SWITCH_TABLET_MODE,
1123			     LIBINPUT_SWITCH_STATE_OFF);
1124	litest_assert_switch_event(li, LIBINPUT_SWITCH_TABLET_MODE, LIBINPUT_SWITCH_STATE_OFF);
1125
1126	litest_keyboard_key(keyboard, KEY_A, true);
1127	litest_keyboard_key(keyboard, KEY_A, false);
1128	litest_keyboard_key(keyboard, KEY_B, true);
1129	litest_keyboard_key(keyboard, KEY_B, false);
1130	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_PRESSED);
1131	litest_assert_key_event(li, KEY_A, LIBINPUT_KEY_STATE_RELEASED);
1132	litest_assert_key_event(li, KEY_B, LIBINPUT_KEY_STATE_PRESSED);
1133	litest_assert_key_event(li, KEY_B, LIBINPUT_KEY_STATE_RELEASED);
1134
1135	litest_delete_device(keyboard);
1136}
1137END_TEST
1138
1139START_TEST(tablet_mode_disable_keyboard_on_init)
1140{
1141	struct litest_device *sw = litest_current_device();
1142	struct litest_device *keyboard;
1143	struct libinput *li = sw->libinput;
1144
1145	if (!switch_has_tablet_mode(sw))
1146		return;
1147
1148	litest_switch_action(sw,
1149			     LIBINPUT_SWITCH_TABLET_MODE,
1150			     LIBINPUT_SWITCH_STATE_ON);
1151	litest_drain_events(li);
1152
1153	/* keyboard comes with switch already on - no events */
1154	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1155	litest_drain_events(li);
1156
1157	litest_keyboard_key(keyboard, KEY_A, true);
1158	litest_keyboard_key(keyboard, KEY_A, false);
1159	litest_assert_empty_queue(li);
1160
1161	litest_switch_action(sw,
1162			     LIBINPUT_SWITCH_TABLET_MODE,
1163			     LIBINPUT_SWITCH_STATE_OFF);
1164	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1165
1166	litest_keyboard_key(keyboard, KEY_A, true);
1167	litest_keyboard_key(keyboard, KEY_A, false);
1168	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1169
1170	litest_delete_device(keyboard);
1171}
1172END_TEST
1173
1174START_TEST(tablet_mode_disable_keyboard_on_resume)
1175{
1176	struct litest_device *sw = litest_current_device();
1177	struct litest_device *keyboard;
1178	struct libinput *li = sw->libinput;
1179	struct libinput_event *event;
1180	bool have_switch_toggle = false;
1181
1182	if (!switch_has_tablet_mode(sw))
1183		return;
1184
1185	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1186	litest_drain_events(li);
1187	libinput_suspend(li);
1188
1189	/* We cannot grab this device because libinput doesn't have an open
1190	 * fd to this device, we need an independent grab.
1191	 */
1192	libevdev_grab(sw->evdev, LIBEVDEV_GRAB);
1193	litest_switch_action(sw,
1194			     LIBINPUT_SWITCH_TABLET_MODE,
1195			     LIBINPUT_SWITCH_STATE_ON);
1196	libevdev_grab(sw->evdev, LIBEVDEV_UNGRAB);
1197	litest_drain_events(li);
1198
1199	libinput_resume(li);
1200	libinput_dispatch(li);
1201
1202	while ((event = libinput_get_event(li))) {
1203		enum libinput_event_type type;
1204
1205		type = libinput_event_get_type(event);
1206		switch (type) {
1207		case LIBINPUT_EVENT_DEVICE_ADDED:
1208			break;
1209		case LIBINPUT_EVENT_SWITCH_TOGGLE:
1210			litest_is_switch_event(event,
1211					       LIBINPUT_SWITCH_TABLET_MODE,
1212					       LIBINPUT_SWITCH_STATE_ON);
1213			have_switch_toggle = true;
1214			break;
1215		default:
1216			ck_abort();
1217		}
1218		libinput_event_destroy(event);
1219	}
1220
1221	ck_assert(have_switch_toggle);
1222
1223	litest_keyboard_key(keyboard, KEY_A, true);
1224	litest_keyboard_key(keyboard, KEY_A, false);
1225	litest_assert_empty_queue(li);
1226
1227	litest_grab_device(sw);
1228	litest_switch_action(sw,
1229			     LIBINPUT_SWITCH_TABLET_MODE,
1230			     LIBINPUT_SWITCH_STATE_OFF);
1231	litest_ungrab_device(sw);
1232	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1233
1234	litest_keyboard_key(keyboard, KEY_A, true);
1235	litest_keyboard_key(keyboard, KEY_A, false);
1236	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1237
1238	litest_delete_device(keyboard);
1239}
1240END_TEST
1241
1242START_TEST(tablet_mode_enable_keyboard_on_resume)
1243{
1244	struct litest_device *sw = litest_current_device();
1245	struct litest_device *keyboard;
1246	struct libinput *li = sw->libinput;
1247
1248	if (!switch_has_tablet_mode(sw))
1249		return;
1250
1251	keyboard = litest_add_device(li, LITEST_KEYBOARD);
1252	litest_grab_device(sw);
1253	litest_switch_action(sw,
1254			     LIBINPUT_SWITCH_TABLET_MODE,
1255			     LIBINPUT_SWITCH_STATE_ON);
1256	litest_drain_events(li);
1257	litest_ungrab_device(sw);
1258	libinput_suspend(li);
1259	litest_drain_events(li);
1260
1261	litest_switch_action(sw,
1262			     LIBINPUT_SWITCH_TABLET_MODE,
1263			     LIBINPUT_SWITCH_STATE_OFF);
1264
1265	libinput_resume(li);
1266	libinput_dispatch(li);
1267	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_ADDED);
1268
1269	litest_keyboard_key(keyboard, KEY_A, true);
1270	litest_keyboard_key(keyboard, KEY_A, false);
1271	litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY);
1272
1273	litest_switch_action(sw,
1274			     LIBINPUT_SWITCH_TABLET_MODE,
1275			     LIBINPUT_SWITCH_STATE_ON);
1276	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1277
1278	litest_keyboard_key(keyboard, KEY_A, true);
1279	litest_keyboard_key(keyboard, KEY_A, false);
1280	litest_assert_empty_queue(li);
1281
1282	litest_delete_device(keyboard);
1283}
1284END_TEST
1285
1286START_TEST(tablet_mode_disable_trackpoint)
1287{
1288	struct litest_device *sw = litest_current_device();
1289	struct litest_device *trackpoint;
1290	struct libinput *li = sw->libinput;
1291
1292	if (!switch_has_tablet_mode(sw))
1293		return;
1294
1295	trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
1296	litest_drain_events(li);
1297
1298	litest_event(trackpoint, EV_REL, REL_Y, -1);
1299	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1300	litest_event(trackpoint, EV_REL, REL_Y, -1);
1301	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1302	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1303
1304	litest_grab_device(sw);
1305	litest_switch_action(sw,
1306			     LIBINPUT_SWITCH_TABLET_MODE,
1307			     LIBINPUT_SWITCH_STATE_ON);
1308	litest_drain_events(li);
1309
1310	litest_event(trackpoint, EV_REL, REL_Y, -1);
1311	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1312	litest_event(trackpoint, EV_REL, REL_Y, -1);
1313	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1314	litest_assert_empty_queue(li);
1315
1316	litest_switch_action(sw,
1317			     LIBINPUT_SWITCH_TABLET_MODE,
1318			     LIBINPUT_SWITCH_STATE_OFF);
1319	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1320
1321	litest_event(trackpoint, EV_REL, REL_Y, -1);
1322	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1323	litest_event(trackpoint, EV_REL, REL_Y, -1);
1324	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1325	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1326	litest_ungrab_device(sw);
1327
1328	litest_delete_device(trackpoint);
1329}
1330END_TEST
1331
1332START_TEST(tablet_mode_disable_trackpoint_on_init)
1333{
1334	struct litest_device *sw = litest_current_device();
1335	struct litest_device *trackpoint;
1336	struct libinput *li = sw->libinput;
1337
1338	if (!switch_has_tablet_mode(sw))
1339		return;
1340
1341	litest_grab_device(sw);
1342	litest_switch_action(sw,
1343			     LIBINPUT_SWITCH_TABLET_MODE,
1344			     LIBINPUT_SWITCH_STATE_ON);
1345	litest_drain_events(li);
1346
1347	/* trackpoint comes with switch already on - no events */
1348	trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
1349	litest_drain_events(li);
1350
1351	litest_event(trackpoint, EV_REL, REL_Y, -1);
1352	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1353	litest_event(trackpoint, EV_REL, REL_Y, -1);
1354	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1355	litest_assert_empty_queue(li);
1356
1357	litest_switch_action(sw,
1358			     LIBINPUT_SWITCH_TABLET_MODE,
1359			     LIBINPUT_SWITCH_STATE_OFF);
1360	litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE);
1361
1362	litest_event(trackpoint, EV_REL, REL_Y, -1);
1363	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1364	litest_event(trackpoint, EV_REL, REL_Y, -1);
1365	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
1366	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
1367	litest_ungrab_device(sw);
1368
1369	litest_delete_device(trackpoint);
1370}
1371END_TEST
1372
1373START_TEST(dock_toggle)
1374{
1375	struct litest_device *sw = litest_current_device();
1376	struct libinput *li = sw->libinput;
1377
1378	if (!libevdev_has_event_code(sw->evdev, EV_SW, SW_DOCK))
1379		return;
1380
1381	litest_drain_events(li);
1382
1383	litest_grab_device(sw);
1384	litest_event(sw, EV_SW, SW_DOCK, 1);
1385	libinput_dispatch(li);
1386
1387	litest_event(sw, EV_SW, SW_DOCK, 0);
1388	libinput_dispatch(li);
1389	litest_ungrab_device(sw);
1390
1391	litest_assert_empty_queue(li);
1392}
1393END_TEST
1394
1395TEST_COLLECTION(switch)
1396{
1397	struct range switches = { LIBINPUT_SWITCH_LID,
1398				  LIBINPUT_SWITCH_TABLET_MODE + 1};
1399
1400	litest_add(switch_has_cap, LITEST_SWITCH, LITEST_ANY);
1401	litest_add(switch_has_lid_switch, LITEST_SWITCH, LITEST_ANY);
1402	litest_add(switch_has_tablet_mode_switch, LITEST_SWITCH, LITEST_ANY);
1403	litest_add_ranged(switch_toggle, LITEST_SWITCH, LITEST_ANY, &switches);
1404	litest_add_ranged(switch_toggle_double, LITEST_SWITCH, LITEST_ANY, &switches);
1405	litest_add_ranged(switch_down_on_init, LITEST_SWITCH, LITEST_ANY, &switches);
1406	litest_add(switch_not_down_on_init, LITEST_SWITCH, LITEST_ANY);
1407	litest_add_ranged(switch_disable_touchpad, LITEST_SWITCH, LITEST_ANY, &switches);
1408	litest_add_ranged(switch_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY, &switches);
1409	litest_add_ranged(switch_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY, &switches);
1410	litest_add_ranged(switch_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY, &switches);
1411	litest_add_ranged(switch_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY, &switches);
1412	litest_add_ranged(switch_dont_resume_disabled_touchpad, LITEST_SWITCH, LITEST_ANY, &switches);
1413	litest_add_ranged(switch_dont_resume_disabled_touchpad_external_mouse, LITEST_SWITCH, LITEST_ANY, &switches);
1414
1415	litest_add_ranged_no_device(switch_suspend_with_keyboard, &switches);
1416	litest_add_ranged_no_device(switch_suspend_with_touchpad, &switches);
1417
1418	litest_add(lid_open_on_key, LITEST_SWITCH, LITEST_ANY);
1419	litest_add(lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY);
1420	litest_add_for_device(lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3);
1421	litest_add_for_device(lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3);
1422	litest_add_for_device(lid_update_hw_on_key_multiple_keyboards, LITEST_LID_SWITCH_SURFACE3);
1423	litest_add_for_device(lid_key_press, LITEST_GPIO_KEYS);
1424
1425	litest_add(tablet_mode_disable_touchpad_on_init, LITEST_SWITCH, LITEST_ANY);
1426	litest_add(tablet_mode_disable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY);
1427	litest_add(tablet_mode_enable_touchpad_on_resume, LITEST_SWITCH, LITEST_ANY);
1428	litest_add(tablet_mode_disable_keyboard, LITEST_SWITCH, LITEST_ANY);
1429	litest_add(tablet_mode_disable_keyboard_on_init, LITEST_SWITCH, LITEST_ANY);
1430	litest_add(tablet_mode_disable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY);
1431	litest_add(tablet_mode_enable_keyboard_on_resume, LITEST_SWITCH, LITEST_ANY);
1432	litest_add(tablet_mode_disable_trackpoint, LITEST_SWITCH, LITEST_ANY);
1433	litest_add(tablet_mode_disable_trackpoint_on_init, LITEST_SWITCH, LITEST_ANY);
1434
1435	litest_add(dock_toggle, LITEST_SWITCH, LITEST_ANY);
1436}
1437