• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014 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 
32 #include "libinput-util.h"
33 #include "litest.h"
34 
35 static inline bool
has_disable_while_trackpointing(struct litest_device * device)36 has_disable_while_trackpointing(struct litest_device *device)
37 {
38 	return libinput_device_config_dwtp_is_available(device->libinput_device);
39 }
40 
START_TEST(trackpoint_middlebutton)41 START_TEST(trackpoint_middlebutton)
42 {
43 	struct litest_device *dev = litest_current_device();
44 	struct libinput *li = dev->libinput;
45 	struct libinput_event *event;
46 	struct libinput_event_pointer *ptrev;
47 	uint64_t ptime, rtime;
48 
49 	litest_drain_events(li);
50 
51 	/* A quick middle button click should get reported normally */
52 	litest_button_click_debounced(dev, li, BTN_MIDDLE, 1);
53 	msleep(2);
54 	litest_button_click_debounced(dev, li, BTN_MIDDLE, 0);
55 
56 	litest_wait_for_event(li);
57 
58 	event = libinput_get_event(li);
59 	ptrev = litest_is_button_event(event,
60 				       BTN_MIDDLE,
61 				       LIBINPUT_BUTTON_STATE_PRESSED);
62 	ptime = libinput_event_pointer_get_time(ptrev);
63 	libinput_event_destroy(event);
64 
65 	event = libinput_get_event(li);
66 	ptrev = litest_is_button_event(event,
67 				       BTN_MIDDLE,
68 				       LIBINPUT_BUTTON_STATE_RELEASED);
69 	rtime = libinput_event_pointer_get_time(ptrev);
70 	libinput_event_destroy(event);
71 
72 	ck_assert_int_lt(ptime, rtime);
73 
74 	litest_assert_empty_queue(li);
75 }
76 END_TEST
77 
START_TEST(trackpoint_scroll)78 START_TEST(trackpoint_scroll)
79 {
80 	struct litest_device *dev = litest_current_device();
81 	struct libinput *li = dev->libinput;
82 
83 	litest_drain_events(li);
84 
85 	litest_button_scroll(dev, BTN_MIDDLE, 1, 6);
86 	litest_assert_scroll(li,
87 			     LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
88 			     LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
89 			     6);
90 	litest_button_scroll(dev, BTN_MIDDLE, 1, -7);
91 	litest_assert_scroll(li,
92 			     LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
93 			     LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
94 			     -7);
95 	litest_button_scroll(dev, BTN_MIDDLE, 8, 1);
96 	litest_assert_scroll(li,
97 			     LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
98 			     LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
99 			     8);
100 	litest_button_scroll(dev, BTN_MIDDLE, -9, 1);
101 	litest_assert_scroll(li,
102 			     LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS,
103 			     LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
104 			     -9);
105 
106 	/* scroll smaller than the threshold should not generate axis events */
107 	litest_button_scroll(dev, BTN_MIDDLE, 1, 1);
108 
109 	litest_button_scroll(dev, BTN_MIDDLE, 0, 0);
110 	litest_assert_button_event(li, BTN_MIDDLE,
111 				   LIBINPUT_BUTTON_STATE_PRESSED);
112 	litest_assert_button_event(li,
113 				   BTN_MIDDLE,
114 				   LIBINPUT_BUTTON_STATE_RELEASED);
115 
116 	litest_assert_empty_queue(li);
117 }
118 END_TEST
119 
START_TEST(trackpoint_middlebutton_noscroll)120 START_TEST(trackpoint_middlebutton_noscroll)
121 {
122 	struct litest_device *dev = litest_current_device();
123 	struct libinput *li = dev->libinput;
124 	struct libinput_event *event;
125 
126 	/* Disable middle button scrolling */
127 	libinput_device_config_scroll_set_method(dev->libinput_device,
128 					LIBINPUT_CONFIG_SCROLL_NO_SCROLL);
129 
130 	litest_drain_events(li);
131 
132 	/* A long middle button click + motion should get reported normally now */
133 	litest_button_scroll(dev, BTN_MIDDLE, 0, 10);
134 
135 	litest_assert_button_event(li, BTN_MIDDLE, 1);
136 
137 	event = libinput_get_event(li);
138 	ck_assert_notnull(event);
139 	ck_assert_int_eq(libinput_event_get_type(event), LIBINPUT_EVENT_POINTER_MOTION);
140 	libinput_event_destroy(event);
141 
142 	litest_assert_button_event(li, BTN_MIDDLE, 0);
143 
144 	litest_assert_empty_queue(li);
145 
146 	/* Restore default scroll behavior */
147 	libinput_device_config_scroll_set_method(dev->libinput_device,
148 		libinput_device_config_scroll_get_default_method(
149 			dev->libinput_device));
150 }
151 END_TEST
152 
START_TEST(trackpoint_scroll_source)153 START_TEST(trackpoint_scroll_source)
154 {
155 	struct litest_device *dev = litest_current_device();
156 	struct libinput *li = dev->libinput;
157 	struct libinput_event *event;
158 	struct libinput_event_pointer *ptrev;
159 
160 	litest_drain_events(li);
161 
162 	litest_button_scroll(dev, BTN_MIDDLE, 0, 6);
163 	litest_wait_for_event_of_type(li, LIBINPUT_EVENT_POINTER_AXIS, -1);
164 
165 	while ((event = libinput_get_event(li))) {
166 		ptrev = libinput_event_get_pointer_event(event);
167 
168 		ck_assert_int_eq(litest_event_pointer_get_axis_source(ptrev),
169 				 LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS);
170 
171 		libinput_event_destroy(event);
172 	}
173 }
174 END_TEST
175 
START_TEST(trackpoint_topsoftbuttons_left_handed_trackpoint)176 START_TEST(trackpoint_topsoftbuttons_left_handed_trackpoint)
177 {
178 	struct litest_device *touchpad = litest_current_device();
179 	struct litest_device *trackpoint;
180 	struct libinput *li = touchpad->libinput;
181 	enum libinput_config_status status;
182 	struct libinput_event *event;
183 	struct libinput_device *device;
184 
185 	litest_disable_hold_gestures(touchpad->libinput_device);
186 
187 	trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
188 	litest_drain_events(li);
189 	/* touchpad right-handed, trackpoint left-handed */
190 	status = libinput_device_config_left_handed_set(
191 					trackpoint->libinput_device, 1);
192 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
193 
194 	litest_touch_down(touchpad, 0, 5, 5);
195 	libinput_dispatch(li);
196 	litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
197 	libinput_dispatch(li);
198 
199 	event = libinput_get_event(li);
200 	litest_is_button_event(event,
201 			       BTN_RIGHT,
202 			       LIBINPUT_BUTTON_STATE_PRESSED);
203 	device = libinput_event_get_device(event);
204 	ck_assert(device == trackpoint->libinput_device);
205 	libinput_event_destroy(event);
206 
207 	litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
208 	libinput_dispatch(li);
209 	event = libinput_get_event(li);
210 	litest_is_button_event(event,
211 			       BTN_RIGHT,
212 			       LIBINPUT_BUTTON_STATE_RELEASED);
213 	device = libinput_event_get_device(event);
214 	ck_assert(device == trackpoint->libinput_device);
215 	libinput_event_destroy(event);
216 
217 	litest_delete_device(trackpoint);
218 }
219 END_TEST
220 
START_TEST(trackpoint_topsoftbuttons_left_handed_touchpad)221 START_TEST(trackpoint_topsoftbuttons_left_handed_touchpad)
222 {
223 	struct litest_device *touchpad = litest_current_device();
224 	struct litest_device *trackpoint;
225 	struct libinput *li = touchpad->libinput;
226 	enum libinput_config_status status;
227 	struct libinput_event *event;
228 	struct libinput_device *device;
229 
230 	litest_disable_hold_gestures(touchpad->libinput_device);
231 
232 	trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
233 	litest_drain_events(li);
234 	/* touchpad left-handed, trackpoint right-handed */
235 	status = libinput_device_config_left_handed_set(
236 					touchpad->libinput_device, 1);
237 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
238 
239 	litest_touch_down(touchpad, 0, 5, 5);
240 	libinput_dispatch(li);
241 	litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
242 	libinput_dispatch(li);
243 
244 	event = libinput_get_event(li);
245 	litest_is_button_event(event, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED);
246 	device = libinput_event_get_device(event);
247 	ck_assert(device == trackpoint->libinput_device);
248 	libinput_event_destroy(event);
249 
250 	litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
251 	libinput_dispatch(li);
252 	event = libinput_get_event(li);
253 	litest_is_button_event(event,
254 			       BTN_LEFT,
255 			       LIBINPUT_BUTTON_STATE_RELEASED);
256 	device = libinput_event_get_device(event);
257 	ck_assert(device == trackpoint->libinput_device);
258 	libinput_event_destroy(event);
259 
260 	litest_delete_device(trackpoint);
261 }
262 END_TEST
263 
START_TEST(trackpoint_topsoftbuttons_left_handed_both)264 START_TEST(trackpoint_topsoftbuttons_left_handed_both)
265 {
266 	struct litest_device *touchpad = litest_current_device();
267 	struct litest_device *trackpoint;
268 	struct libinput *li = touchpad->libinput;
269 	enum libinput_config_status status;
270 	struct libinput_event *event;
271 	struct libinput_device *device;
272 
273 	litest_disable_hold_gestures(touchpad->libinput_device);
274 
275 	trackpoint = litest_add_device(li, LITEST_TRACKPOINT);
276 	litest_drain_events(li);
277 	/* touchpad left-handed, trackpoint left-handed */
278 	status = libinput_device_config_left_handed_set(
279 					touchpad->libinput_device, 1);
280 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
281 	status = libinput_device_config_left_handed_set(
282 					trackpoint->libinput_device, 1);
283 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
284 
285 	litest_touch_down(touchpad, 0, 5, 5);
286 	libinput_dispatch(li);
287 	litest_button_click_debounced(touchpad, li, BTN_LEFT, true);
288 	libinput_dispatch(li);
289 
290 	event = libinput_get_event(li);
291 	litest_is_button_event(event,
292 			       BTN_RIGHT,
293 			       LIBINPUT_BUTTON_STATE_PRESSED);
294 	device = libinput_event_get_device(event);
295 	ck_assert(device == trackpoint->libinput_device);
296 	libinput_event_destroy(event);
297 
298 	litest_button_click_debounced(touchpad, li, BTN_LEFT, false);
299 	libinput_dispatch(li);
300 	event = libinput_get_event(li);
301 	litest_is_button_event(event,
302 			       BTN_RIGHT,
303 			       LIBINPUT_BUTTON_STATE_RELEASED);
304 	device = libinput_event_get_device(event);
305 	ck_assert(device == trackpoint->libinput_device);
306 	libinput_event_destroy(event);
307 
308 	litest_delete_device(trackpoint);
309 }
310 END_TEST
311 
312 static inline void
enable_dwtp(struct litest_device * dev)313 enable_dwtp(struct litest_device *dev)
314 {
315 	enum libinput_config_status status,
316 				    expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
317 	status = libinput_device_config_dwtp_set_enabled(dev->libinput_device,
318 						LIBINPUT_CONFIG_DWTP_ENABLED);
319 	litest_assert_int_eq(status, expected);
320 }
321 
322 static inline void
disable_dwtp(struct litest_device * dev)323 disable_dwtp(struct litest_device *dev)
324 {
325 	enum libinput_config_status status,
326 				    expected = LIBINPUT_CONFIG_STATUS_SUCCESS;
327 	status = libinput_device_config_dwtp_set_enabled(dev->libinput_device,
328 						LIBINPUT_CONFIG_DWTP_DISABLED);
329 	litest_assert_int_eq(status, expected);
330 }
331 
332 
START_TEST(trackpoint_palmdetect)333 START_TEST(trackpoint_palmdetect)
334 {
335 	struct litest_device *trackpoint = litest_current_device();
336 	struct litest_device *touchpad;
337 	struct libinput *li = trackpoint->libinput;
338 	int i;
339 
340 	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
341 	if (has_disable_while_trackpointing(touchpad))
342 		enable_dwtp(touchpad);
343 
344 	litest_disable_hold_gestures(touchpad->libinput_device);
345 	litest_drain_events(li);
346 
347 	for (i = 0; i < 10; i++) {
348 		litest_event(trackpoint, EV_REL, REL_X, 1);
349 		litest_event(trackpoint, EV_REL, REL_Y, 1);
350 		litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
351 		libinput_dispatch(li);
352 	}
353 	litest_drain_events(li);
354 
355 	litest_touch_down(touchpad, 0, 30, 30);
356 	litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10);
357 	litest_touch_up(touchpad, 0);
358 	litest_assert_empty_queue(li);
359 
360 	litest_timeout_trackpoint();
361 	libinput_dispatch(li);
362 
363 	litest_touch_down(touchpad, 0, 30, 30);
364 	litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10);
365 	litest_touch_up(touchpad, 0);
366 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
367 
368 	litest_delete_device(touchpad);
369 }
370 END_TEST
371 
START_TEST(trackpoint_palmdetect_dwtp_disabled)372 START_TEST(trackpoint_palmdetect_dwtp_disabled)
373 {
374 	struct litest_device *trackpoint = litest_current_device();
375 	struct litest_device *touchpad;
376 	struct libinput *li = trackpoint->libinput;
377 	int i;
378 
379 	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
380 	if (has_disable_while_trackpointing(touchpad))
381 		disable_dwtp(touchpad);
382 
383 	litest_disable_hold_gestures(touchpad->libinput_device);
384 	litest_drain_events(li);
385 
386 	for (i = 0; i < 10; i++) {
387 		litest_event(trackpoint, EV_REL, REL_X, 1);
388 		litest_event(trackpoint, EV_REL, REL_Y, 1);
389 		litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
390 		libinput_dispatch(li);
391 	}
392 	litest_drain_events(li);
393 
394 	litest_touch_down(touchpad, 0, 30, 30);
395 	litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10);
396 	litest_touch_up(touchpad, 0);
397 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
398 
399 	litest_delete_device(touchpad);
400 }
401 END_TEST
402 
START_TEST(trackpoint_palmdetect_resume_touch)403 START_TEST(trackpoint_palmdetect_resume_touch)
404 {
405 	struct litest_device *trackpoint = litest_current_device();
406 	struct litest_device *touchpad;
407 	struct libinput *li = trackpoint->libinput;
408 	int i;
409 
410 	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
411 
412 	if (has_disable_while_trackpointing(touchpad))
413 		enable_dwtp(touchpad);
414 
415 	litest_disable_hold_gestures(touchpad->libinput_device);
416 	litest_drain_events(li);
417 
418 	for (i = 0; i < 10; i++) {
419 		litest_event(trackpoint, EV_REL, REL_X, 1);
420 		litest_event(trackpoint, EV_REL, REL_Y, 1);
421 		litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
422 		libinput_dispatch(li);
423 	}
424 	litest_drain_events(li);
425 
426 	litest_touch_down(touchpad, 0, 30, 30);
427 	litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10);
428 	litest_assert_empty_queue(li);
429 
430 	litest_timeout_trackpoint();
431 	libinput_dispatch(li);
432 
433 	/* touch started after last tp event, expect resume */
434 	litest_touch_move_to(touchpad, 0, 80, 80, 30, 30, 10);
435 	litest_touch_up(touchpad, 0);
436 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
437 
438 	litest_delete_device(touchpad);
439 }
440 END_TEST
441 
START_TEST(trackpoint_palmdetect_require_min_events)442 START_TEST(trackpoint_palmdetect_require_min_events)
443 {
444 	struct litest_device *trackpoint = litest_current_device();
445 	struct litest_device *touchpad;
446 	struct libinput *li = trackpoint->libinput;
447 
448 	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
449 
450 	if (has_disable_while_trackpointing(touchpad))
451 		enable_dwtp(touchpad);
452 
453 	litest_disable_hold_gestures(touchpad->libinput_device);
454 	litest_drain_events(li);
455 
456 	/* A single event does not trigger palm detection */
457 	litest_event(trackpoint, EV_REL, REL_X, 1);
458 	litest_event(trackpoint, EV_REL, REL_Y, 1);
459 	litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
460 	libinput_dispatch(li);
461 	litest_drain_events(li);
462 
463 	litest_touch_down(touchpad, 0, 30, 30);
464 	litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10);
465 	litest_touch_up(touchpad, 0);
466 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
467 
468 	litest_delete_device(touchpad);
469 }
470 END_TEST
471 
START_TEST(trackpoint_palmdetect_require_min_events_timeout)472 START_TEST(trackpoint_palmdetect_require_min_events_timeout)
473 {
474 	struct litest_device *trackpoint = litest_current_device();
475 	struct litest_device *touchpad;
476 	struct libinput *li = trackpoint->libinput;
477 
478 	touchpad = litest_add_device(li, LITEST_SYNAPTICS_I2C);
479 
480 	if (has_disable_while_trackpointing(touchpad))
481 		enable_dwtp(touchpad);
482 
483 	litest_disable_hold_gestures(touchpad->libinput_device);
484 	litest_drain_events(li);
485 
486 	for (int i = 0; i < 10; i++) {
487 		/* A single event does not trigger palm detection */
488 		litest_event(trackpoint, EV_REL, REL_X, 1);
489 		litest_event(trackpoint, EV_REL, REL_Y, 1);
490 		litest_event(trackpoint, EV_SYN, SYN_REPORT, 0);
491 		libinput_dispatch(li);
492 		litest_drain_events(li);
493 
494 		litest_touch_down(touchpad, 0, 30, 30);
495 		litest_touch_move_to(touchpad, 0, 30, 30, 80, 80, 10);
496 		litest_touch_up(touchpad, 0);
497 		litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
498 
499 		litest_timeout_trackpoint();
500 	}
501 
502 	litest_delete_device(touchpad);
503 }
504 END_TEST
505 
TEST_COLLECTION(trackpoint)506 TEST_COLLECTION(trackpoint)
507 {
508 	litest_add(trackpoint_middlebutton, LITEST_POINTINGSTICK, LITEST_ANY);
509 	litest_add(trackpoint_middlebutton_noscroll, LITEST_POINTINGSTICK, LITEST_ANY);
510 	litest_add(trackpoint_scroll, LITEST_POINTINGSTICK, LITEST_ANY);
511 	litest_add(trackpoint_scroll_source, LITEST_POINTINGSTICK, LITEST_ANY);
512 	litest_add(trackpoint_topsoftbuttons_left_handed_trackpoint, LITEST_TOPBUTTONPAD, LITEST_ANY);
513 	litest_add(trackpoint_topsoftbuttons_left_handed_touchpad, LITEST_TOPBUTTONPAD, LITEST_ANY);
514 	litest_add(trackpoint_topsoftbuttons_left_handed_both, LITEST_TOPBUTTONPAD, LITEST_ANY);
515 
516 	litest_add(trackpoint_palmdetect, LITEST_POINTINGSTICK, LITEST_ANY);
517 	litest_add(trackpoint_palmdetect_dwtp_disabled, LITEST_POINTINGSTICK, LITEST_ANY);
518 	litest_add(trackpoint_palmdetect_resume_touch, LITEST_POINTINGSTICK, LITEST_ANY);
519 	litest_add(trackpoint_palmdetect_require_min_events, LITEST_POINTINGSTICK, LITEST_ANY);
520 	litest_add(trackpoint_palmdetect_require_min_events_timeout, LITEST_POINTINGSTICK, LITEST_ANY);
521 }
522