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