• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2014-2015 Red Hat, Inc.
3  * Copyright © 2014 Lyude Paul
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <config.h>
26 
27 #include <check.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <libinput.h>
31 #include <unistd.h>
32 #include <stdbool.h>
33 #include <stdarg.h>
34 
35 #include "libinput-util.h"
36 #include "evdev-tablet.h"
37 #include "litest.h"
38 #include "util-input-event.h"
39 
40 static inline unsigned int
pick_stylus_or_btn0(struct litest_device * dev)41 pick_stylus_or_btn0(struct litest_device *dev)
42 {
43 	if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_STYLUS))
44 		return BTN_STYLUS;
45 
46 	if (libevdev_has_event_code(dev->evdev, EV_KEY, BTN_0))
47 		return BTN_0; /* totem */
48 
49 	abort();
50 }
51 
START_TEST(button_down_up)52 START_TEST(button_down_up)
53 {
54 	struct litest_device *dev = litest_current_device();
55 	struct libinput *li = dev->libinput;
56 	struct libinput_event *event;
57 	struct libinput_event_tablet_tool *tev;
58 	struct axis_replacement axes[] = {
59 		{ ABS_DISTANCE, 10 },
60 		{ ABS_PRESSURE, 0 },
61 		{ -1, -1 }
62 	};
63 	unsigned int button = pick_stylus_or_btn0(dev);
64 
65 	litest_tablet_proximity_in(dev, 10, 10, axes);
66 	litest_drain_events(li);
67 
68 	litest_button_click(dev, button, true);
69 	libinput_dispatch(li);
70 
71 	event = libinput_get_event(li);
72 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
73 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
74 			 button);
75 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
76 			 LIBINPUT_BUTTON_STATE_PRESSED);
77 	libinput_event_destroy(event);
78 	litest_assert_empty_queue(li);
79 
80 	litest_button_click(dev, button, false);
81 	libinput_dispatch(li);
82 
83 	event = libinput_get_event(li);
84 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
85 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tev),
86 			 button);
87 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
88 			 LIBINPUT_BUTTON_STATE_RELEASED);
89 	libinput_event_destroy(event);
90 	litest_assert_empty_queue(li);
91 }
92 END_TEST
93 
START_TEST(button_seat_count)94 START_TEST(button_seat_count)
95 {
96 	struct litest_device *dev = litest_current_device();
97 	struct libinput *li = dev->libinput;
98 	struct libinput_event *event;
99 	struct libinput_event_tablet_tool *tev;
100 	struct litest_device *dev2;
101 	struct axis_replacement axes[] = {
102 		{ ABS_DISTANCE, 10 },
103 		{ ABS_PRESSURE, 0 },
104 		{ -1, -1 }
105 	};
106 	unsigned int button = pick_stylus_or_btn0(dev);
107 
108 	switch (button) {
109 	case BTN_STYLUS:
110 		dev2 = litest_add_device(li, LITEST_WACOM_CINTIQ_13HDT_PEN);
111 		break;
112 	case BTN_0:
113 		dev2 = litest_add_device(li, LITEST_DELL_CANVAS_TOTEM);
114 		break;
115 	default:
116 		ck_abort();
117 	}
118 
119 	litest_tablet_proximity_in(dev, 10, 10, axes);
120 	litest_tablet_proximity_in(dev2, 10, 10, axes);
121 	litest_drain_events(li);
122 
123 	litest_button_click(dev, button, true);
124 	litest_button_click(dev2, button, true);
125 	libinput_dispatch(li);
126 
127 	event = libinput_get_event(li);
128 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
129 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
130 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
131 			 LIBINPUT_BUTTON_STATE_PRESSED);
132 	ck_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 1);
133 	libinput_event_destroy(event);
134 
135 	event = libinput_get_event(li);
136 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
137 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
138 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
139 			 LIBINPUT_BUTTON_STATE_PRESSED);
140 	ck_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 2);
141 	libinput_event_destroy(event);
142 
143 	litest_assert_empty_queue(li);
144 
145 	litest_button_click(dev2, button, false);
146 	litest_button_click(dev, button, false);
147 	libinput_dispatch(li);
148 
149 	event = libinput_get_event(li);
150 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
151 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
152 			 LIBINPUT_BUTTON_STATE_RELEASED);
153 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
154 	ck_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 1);
155 	libinput_event_destroy(event);
156 
157 	event = libinput_get_event(li);
158 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
159 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tev),
160 			 LIBINPUT_BUTTON_STATE_RELEASED);
161 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tev), button);
162 	ck_assert_int_eq(libinput_event_tablet_tool_get_seat_button_count(tev), 0);
163 	libinput_event_destroy(event);
164 	litest_assert_empty_queue(li);
165 
166 	litest_delete_device(dev2);
167 }
168 END_TEST
169 
START_TEST(button_up_on_delete)170 START_TEST(button_up_on_delete)
171 {
172 	struct libinput *li = litest_create_context();
173 	struct litest_device *dev = litest_add_device(li, LITEST_WACOM_INTUOS);
174 	struct libevdev *evdev = libevdev_new();
175 	unsigned int code;
176 
177 	litest_tablet_proximity_in(dev, 10, 10, NULL);
178 	litest_drain_events(li);
179 
180 	for (code = BTN_LEFT; code <= BTN_TASK; code++) {
181 		if (!libevdev_has_event_code(dev->evdev, EV_KEY, code))
182 			continue;
183 
184 		libevdev_enable_event_code(evdev, EV_KEY, code, NULL);
185 		litest_event(dev, EV_KEY, code, 1);
186 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
187 		libinput_dispatch(li);
188 	}
189 
190 	litest_drain_events(li);
191 	litest_delete_device(dev);
192 	libinput_dispatch(li);
193 
194 	for (code = BTN_LEFT; code <= BTN_TASK; code++) {
195 		if (!libevdev_has_event_code(evdev, EV_KEY, code))
196 			continue;
197 
198 		litest_assert_tablet_button_event(li,
199 					  code,
200 					  LIBINPUT_BUTTON_STATE_RELEASED);
201 	}
202 
203 	litest_assert_tablet_proximity_event(li,
204 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
205 	libevdev_free(evdev);
206 	litest_destroy_context(li);
207 }
208 END_TEST
209 
START_TEST(tip_down_up)210 START_TEST(tip_down_up)
211 {
212 	struct litest_device *dev = litest_current_device();
213 	struct libinput *li = dev->libinput;
214 	struct libinput_event *event;
215 	struct libinput_event_tablet_tool *tablet_event;
216 	struct axis_replacement axes[] = {
217 		{ ABS_DISTANCE, 10 },
218 		{ ABS_PRESSURE, 0 },
219 		{ -1, -1 }
220 	};
221 
222 	litest_tablet_proximity_in(dev, 10, 10, axes);
223 	litest_drain_events(li);
224 
225 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
226 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
227 	litest_tablet_tip_down(dev, 10, 10, axes);
228 
229 	libinput_dispatch(li);
230 
231 	event = libinput_get_event(li);
232 	tablet_event = litest_is_tablet_event(event,
233 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
234 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
235 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
236 	libinput_event_destroy(event);
237 	litest_assert_empty_queue(li);
238 
239 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
240 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
241 	litest_tablet_tip_up(dev, 10, 10, axes);
242 
243 	libinput_dispatch(li);
244 	event = libinput_get_event(li);
245 	tablet_event = litest_is_tablet_event(event,
246 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
247 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
248 			 LIBINPUT_TABLET_TOOL_TIP_UP);
249 	libinput_event_destroy(event);
250 
251 	litest_assert_empty_queue(li);
252 
253 }
254 END_TEST
255 
START_TEST(tip_down_up_eraser)256 START_TEST(tip_down_up_eraser)
257 {
258 	struct litest_device *dev = litest_current_device();
259 	struct libinput *li = dev->libinput;
260 	struct libinput_event *event;
261 	struct libinput_event_tablet_tool *tablet_event;
262 	struct libinput_tablet_tool *tool;
263 	struct axis_replacement axes[] = {
264 		{ ABS_DISTANCE, 10 },
265 		{ ABS_PRESSURE, 0 },
266 		{ -1, -1 }
267 	};
268 
269 	if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
270 		return;
271 
272 	litest_tablet_set_tool_type(dev, BTN_TOOL_RUBBER);
273 
274 	litest_tablet_proximity_in(dev, 10, 10, axes);
275 	litest_drain_events(li);
276 
277 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
278 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
279 	litest_tablet_tip_down(dev, 10, 10, axes);
280 
281 	libinput_dispatch(li);
282 
283 	event = libinput_get_event(li);
284 	tablet_event = litest_is_tablet_event(event,
285 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
286 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
287 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
288 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
289 	ck_assert_int_eq(libinput_tablet_tool_get_type(tool), LIBINPUT_TABLET_TOOL_TYPE_ERASER);
290 	libinput_event_destroy(event);
291 	litest_assert_empty_queue(li);
292 
293 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
294 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
295 	litest_tablet_tip_up(dev, 10, 10, axes);
296 
297 	libinput_dispatch(li);
298 	event = libinput_get_event(li);
299 	tablet_event = litest_is_tablet_event(event,
300 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
301 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
302 			 LIBINPUT_TABLET_TOOL_TIP_UP);
303 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
304 	ck_assert_int_eq(libinput_tablet_tool_get_type(tool), LIBINPUT_TABLET_TOOL_TYPE_ERASER);
305 	libinput_event_destroy(event);
306 
307 	litest_assert_empty_queue(li);
308 
309 }
310 END_TEST
311 
START_TEST(tip_down_prox_in)312 START_TEST(tip_down_prox_in)
313 {
314 	struct litest_device *dev = litest_current_device();
315 	struct libinput *li = dev->libinput;
316 	struct libinput_event *event;
317 	struct libinput_event_tablet_tool *tablet_event;
318 	struct axis_replacement axes[] = {
319 		{ ABS_DISTANCE, 0 },
320 		{ ABS_PRESSURE, 30 },
321 		{ -1, -1 }
322 	};
323 
324 	litest_drain_events(li);
325 
326 	litest_push_event_frame(dev);
327 	litest_tablet_proximity_in(dev, 10, 10, axes);
328 	litest_tablet_tip_down(dev, 10, 10, axes);
329 	litest_pop_event_frame(dev);
330 
331 	libinput_dispatch(li);
332 	event = libinput_get_event(li);
333 	tablet_event = litest_is_tablet_event(event,
334 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
335 	ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tablet_event),
336 			 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
337 	libinput_event_destroy(event);
338 
339 	event = libinput_get_event(li);
340 	tablet_event = litest_is_tablet_event(event,
341 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
342 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
343 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
344 	libinput_event_destroy(event);
345 
346 	litest_assert_empty_queue(li);
347 
348 }
349 END_TEST
350 
START_TEST(tip_up_prox_out)351 START_TEST(tip_up_prox_out)
352 {
353 	struct litest_device *dev = litest_current_device();
354 	struct libinput *li = dev->libinput;
355 	struct libinput_event *event;
356 	struct libinput_event_tablet_tool *tablet_event;
357 	struct axis_replacement axes[] = {
358 		{ ABS_DISTANCE, 0 },
359 		{ ABS_PRESSURE, 30 },
360 		{ -1, -1 }
361 	};
362 
363 	litest_tablet_proximity_in(dev, 10, 10, axes);
364 	litest_tablet_tip_down(dev, 10, 10, axes);
365 	litest_drain_events(li);
366 
367 	litest_axis_set_value(axes, ABS_DISTANCE, 30);
368 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
369 	litest_push_event_frame(dev);
370 	litest_tablet_tip_up(dev, 10, 10, axes);
371 	litest_tablet_proximity_out(dev);
372 	litest_pop_event_frame(dev);
373 
374 	libinput_dispatch(li);
375 	event = libinput_get_event(li);
376 	tablet_event = litest_is_tablet_event(event,
377 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
378 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
379 			 LIBINPUT_TABLET_TOOL_TIP_UP);
380 	libinput_event_destroy(event);
381 
382 	litest_timeout_tablet_proxout();
383 	libinput_dispatch(li);
384 	event = libinput_get_event(li);
385 	tablet_event = litest_is_tablet_event(event,
386 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
387 	ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tablet_event),
388 			 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
389 	libinput_event_destroy(event);
390 
391 	litest_assert_empty_queue(li);
392 
393 }
394 END_TEST
395 
START_TEST(tip_up_btn_change)396 START_TEST(tip_up_btn_change)
397 {
398 	struct litest_device *dev = litest_current_device();
399 	struct libinput *li = dev->libinput;
400 	struct libinput_event *event;
401 	struct libinput_event_tablet_tool *tablet_event;
402 	struct axis_replacement axes[] = {
403 		{ ABS_DISTANCE, 0 },
404 		{ ABS_PRESSURE, 30 },
405 		{ -1, -1 }
406 	};
407 
408 	litest_tablet_proximity_in(dev, 10, 10, axes);
409 	litest_tablet_tip_down(dev, 10, 10, axes);
410 	litest_drain_events(li);
411 
412 	litest_axis_set_value(axes, ABS_DISTANCE, 30);
413 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
414 	litest_push_event_frame(dev);
415 	litest_tablet_tip_up(dev, 10, 20, axes);
416 	litest_event(dev, EV_KEY, BTN_STYLUS, 1);
417 	litest_pop_event_frame(dev);
418 
419 	libinput_dispatch(li);
420 
421 	event = libinput_get_event(li);
422 	tablet_event = litest_is_tablet_event(event,
423 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
424 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
425 			 LIBINPUT_TABLET_TOOL_TIP_UP);
426 	libinput_event_destroy(event);
427 
428 	event = libinput_get_event(li);
429 	tablet_event = litest_is_tablet_event(event,
430 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
431 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
432 			 BTN_STYLUS);
433 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
434 			 LIBINPUT_BUTTON_STATE_PRESSED);
435 	libinput_event_destroy(event);
436 
437 	litest_assert_empty_queue(li);
438 
439 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
440 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
441 	litest_tablet_tip_down(dev, 10, 10, axes);
442 	litest_drain_events(li);
443 
444 	/* same thing with a release at tip-up */
445 	litest_axis_set_value(axes, ABS_DISTANCE, 30);
446 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
447 	litest_push_event_frame(dev);
448 	litest_tablet_tip_up(dev, 10, 10, axes);
449 	litest_event(dev, EV_KEY, BTN_STYLUS, 0);
450 	litest_pop_event_frame(dev);
451 
452 	libinput_dispatch(li);
453 
454 	event = libinput_get_event(li);
455 	tablet_event = litest_is_tablet_event(event,
456 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
457 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
458 			 LIBINPUT_TABLET_TOOL_TIP_UP);
459 	libinput_event_destroy(event);
460 
461 	event = libinput_get_event(li);
462 	tablet_event = litest_is_tablet_event(event,
463 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
464 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
465 			 BTN_STYLUS);
466 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
467 			 LIBINPUT_BUTTON_STATE_RELEASED);
468 	libinput_event_destroy(event);
469 
470 	litest_assert_empty_queue(li);
471 }
472 END_TEST
473 
START_TEST(tip_down_btn_change)474 START_TEST(tip_down_btn_change)
475 {
476 	struct litest_device *dev = litest_current_device();
477 	struct libinput *li = dev->libinput;
478 	struct libinput_event *event;
479 	struct libinput_event_tablet_tool *tablet_event;
480 	struct axis_replacement axes[] = {
481 		{ ABS_DISTANCE, 10 },
482 		{ ABS_PRESSURE, 0 },
483 		{ -1, -1 }
484 	};
485 
486 	litest_tablet_proximity_in(dev, 10, 10, axes);
487 	litest_drain_events(li);
488 
489 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
490 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
491 	litest_push_event_frame(dev);
492 	litest_tablet_tip_down(dev, 10, 20, axes);
493 	litest_event(dev, EV_KEY, BTN_STYLUS, 1);
494 	litest_pop_event_frame(dev);
495 
496 	libinput_dispatch(li);
497 
498 	event = libinput_get_event(li);
499 	tablet_event = litest_is_tablet_event(event,
500 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
501 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
502 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
503 	libinput_event_destroy(event);
504 
505 	libinput_dispatch(li);
506 	event = libinput_get_event(li);
507 	tablet_event = litest_is_tablet_event(event,
508 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
509 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
510 			 BTN_STYLUS);
511 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
512 			 LIBINPUT_BUTTON_STATE_PRESSED);
513 	libinput_event_destroy(event);
514 
515 	litest_assert_empty_queue(li);
516 
517 	litest_axis_set_value(axes, ABS_DISTANCE, 30);
518 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
519 	litest_tablet_tip_up(dev, 10, 20, axes);
520 	litest_drain_events(li);
521 
522 	/* same thing with a release at tip-down */
523 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
524 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
525 	litest_push_event_frame(dev);
526 	litest_tablet_tip_down(dev, 10, 20, axes);
527 	litest_event(dev, EV_KEY, BTN_STYLUS, 0);
528 	litest_pop_event_frame(dev);
529 
530 	libinput_dispatch(li);
531 
532 	event = libinput_get_event(li);
533 	tablet_event = litest_is_tablet_event(event,
534 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
535 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
536 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
537 	libinput_event_destroy(event);
538 
539 	libinput_dispatch(li);
540 	event = libinput_get_event(li);
541 	tablet_event = litest_is_tablet_event(event,
542 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
543 	ck_assert_int_eq(libinput_event_tablet_tool_get_button(tablet_event),
544 			 BTN_STYLUS);
545 	ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(tablet_event),
546 			 LIBINPUT_BUTTON_STATE_RELEASED);
547 	libinput_event_destroy(event);
548 
549 	litest_assert_empty_queue(li);
550 }
551 END_TEST
552 
START_TEST(tip_down_motion)553 START_TEST(tip_down_motion)
554 {
555 	struct litest_device *dev = litest_current_device();
556 	struct libinput *li = dev->libinput;
557 	struct libinput_event *event;
558 	struct libinput_event_tablet_tool *tablet_event;
559 	struct axis_replacement axes[] = {
560 		{ ABS_DISTANCE, 10 },
561 		{ ABS_PRESSURE, 0 },
562 		{ -1, -1 }
563 	};
564 	double x, y, last_x, last_y;
565 
566 	litest_drain_events(li);
567 
568 	litest_tablet_proximity_in(dev, 10, 10, axes);
569 	libinput_dispatch(li);
570 	event = libinput_get_event(li);
571 	tablet_event = litest_is_tablet_event(event,
572 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
573 	last_x = libinput_event_tablet_tool_get_x(tablet_event);
574 	last_y = libinput_event_tablet_tool_get_y(tablet_event);
575 	libinput_event_destroy(event);
576 
577 	/* move x/y on tip down, make sure x/y changed */
578 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
579 	litest_axis_set_value(axes, ABS_PRESSURE, 20);
580 	litest_tablet_tip_down(dev, 70, 70, axes);
581 
582 	libinput_dispatch(li);
583 	event = libinput_get_event(li);
584 	tablet_event = litest_is_tablet_event(event,
585 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
586 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
587 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
588 	ck_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
589 	ck_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
590 	x = libinput_event_tablet_tool_get_x(tablet_event);
591 	y = libinput_event_tablet_tool_get_y(tablet_event);
592 	ck_assert_double_lt(last_x, x);
593 	ck_assert_double_lt(last_y, y);
594 	libinput_event_destroy(event);
595 
596 	litest_assert_empty_queue(li);
597 }
598 END_TEST
599 
START_TEST(tip_up_motion)600 START_TEST(tip_up_motion)
601 {
602 	struct litest_device *dev = litest_current_device();
603 	struct libinput *li = dev->libinput;
604 	struct libinput_event *event;
605 	struct libinput_event_tablet_tool *tablet_event;
606 	struct axis_replacement axes[] = {
607 		{ ABS_DISTANCE, 0 },
608 		{ ABS_PRESSURE, 0 },
609 		{ -1, -1 }
610 	};
611 	double x, y, last_x, last_y;
612 
613 	litest_tablet_proximity_in(dev, 10, 10, axes);
614 	litest_drain_events(li);
615 
616 	litest_axis_set_value(axes, ABS_PRESSURE, 20);
617 	litest_tablet_tip_down(dev, 70, 70, axes);
618 
619 	libinput_dispatch(li);
620 	event = libinput_get_event(li);
621 	tablet_event = litest_is_tablet_event(event,
622 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
623 	last_x = libinput_event_tablet_tool_get_x(tablet_event);
624 	last_y = libinput_event_tablet_tool_get_y(tablet_event);
625 	libinput_event_destroy(event);
626 
627 	/* move x/y on tip up, make sure x/y changed */
628 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
629 	litest_tablet_tip_up(dev, 40, 40, axes);
630 
631 	libinput_dispatch(li);
632 	event = libinput_get_event(li);
633 	tablet_event = litest_is_tablet_event(event,
634 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
635 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
636 			 LIBINPUT_TABLET_TOOL_TIP_UP);
637 	ck_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
638 	ck_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
639 	x = libinput_event_tablet_tool_get_x(tablet_event);
640 	y = libinput_event_tablet_tool_get_y(tablet_event);
641 	ck_assert_double_ne(last_x, x);
642 	ck_assert_double_ne(last_y, y);
643 	libinput_event_destroy(event);
644 
645 	litest_assert_empty_queue(li);
646 }
647 END_TEST
648 
START_TEST(tip_up_motion_one_axis)649 START_TEST(tip_up_motion_one_axis)
650 {
651 	struct litest_device *dev = litest_current_device();
652 	struct libinput *li = dev->libinput;
653 	struct libinput_event *event;
654 	struct libinput_event_tablet_tool *tablet_event;
655 	struct axis_replacement axes[] = {
656 		{ ABS_DISTANCE, 0 },
657 		{ ABS_PRESSURE, 0 },
658 		{ -1, -1 }
659 	};
660 	unsigned int axis = _i; /* ranged test */
661 	double x, y, last_x, last_y;
662 	double start_x = 20,
663 	       start_y = 20;
664 
665 	switch (axis) {
666 	case ABS_X:
667 		start_x = 15;
668 		start_y = 20;
669 		break;
670 	case ABS_Y:
671 		start_x = 20;
672 		start_y = 15;
673 		break;
674 	default:
675 		abort();
676 	}
677 
678 	/* generate enough events to fill the history and move alonge the
679 	 * current axis to avoid axis smoothing interference */
680 	litest_tablet_proximity_in(dev, start_x, start_y, axes);
681 	litest_axis_set_value(axes, ABS_PRESSURE, 20);
682 	for (int i = 0; i < 5; i++) {
683 		litest_tablet_tip_down(dev, start_x, start_y, axes);
684 
685 		switch (axis) {
686 		case ABS_X:
687 			start_x++;
688 			break;
689 		case ABS_Y:
690 			start_y++;
691 			break;
692 		}
693 
694 	}
695 	litest_drain_events(li);
696 
697 	litest_tablet_motion(dev, 20, 20, axes);
698 	libinput_dispatch(li);
699 	event = libinput_get_event(li);
700 	tablet_event = litest_is_tablet_event(event,
701 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
702 	last_x = libinput_event_tablet_tool_get_x(tablet_event);
703 	last_y = libinput_event_tablet_tool_get_y(tablet_event);
704 	libinput_event_destroy(event);
705 
706 	/* move x on tip up, make sure x/y changed */
707 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
708 	switch (axis) {
709 	case ABS_X:
710 		litest_tablet_tip_up(dev, 40, 20, axes);
711 		break;
712 	case ABS_Y:
713 		litest_tablet_tip_up(dev, 20, 40, axes);
714 		break;
715 	}
716 
717 	libinput_dispatch(li);
718 	event = libinput_get_event(li);
719 	tablet_event = litest_is_tablet_event(event,
720 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
721 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
722 			 LIBINPUT_TABLET_TOOL_TIP_UP);
723 	x = libinput_event_tablet_tool_get_x(tablet_event);
724 	y = libinput_event_tablet_tool_get_y(tablet_event);
725 
726 	switch(axis) {
727 	case ABS_X:
728 		ck_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
729 		ck_assert(!libinput_event_tablet_tool_y_has_changed(tablet_event));
730 		ck_assert_double_ne(last_x, x);
731 		ck_assert_double_eq(last_y, y);
732 		break;
733 	case ABS_Y:
734 		ck_assert(!libinput_event_tablet_tool_x_has_changed(tablet_event));
735 		ck_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
736 		ck_assert_double_eq(last_x, x);
737 		ck_assert_double_ne(last_y, y);
738 		break;
739 	}
740 
741 	libinput_event_destroy(event);
742 
743 	litest_assert_empty_queue(li);
744 }
745 END_TEST
746 
START_TEST(tip_state_proximity)747 START_TEST(tip_state_proximity)
748 {
749 	struct litest_device *dev = litest_current_device();
750 	struct libinput *li = dev->libinput;
751 	struct libinput_event *event;
752 	struct libinput_event_tablet_tool *tablet_event;
753 	struct axis_replacement axes[] = {
754 		{ ABS_DISTANCE, 10 },
755 		{ ABS_PRESSURE, 0 },
756 		{ -1, -1 }
757 	};
758 
759 	litest_drain_events(li);
760 
761 	litest_tablet_proximity_in(dev, 10, 10, axes);
762 	libinput_dispatch(li);
763 
764 	event = libinput_get_event(li);
765 	tablet_event = litest_is_tablet_event(event,
766 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
767 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
768 			 LIBINPUT_TABLET_TOOL_TIP_UP);
769 	libinput_event_destroy(event);
770 
771 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
772 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
773 	litest_tablet_tip_down(dev, 10, 10, axes);
774 
775 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
776 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
777 	litest_tablet_tip_up(dev, 10, 10, axes);
778 
779 	litest_drain_events(li);
780 
781 	litest_tablet_proximity_out(dev);
782 	libinput_dispatch(li);
783 
784 	litest_timeout_tablet_proxout();
785 	libinput_dispatch(li);
786 
787 	event = libinput_get_event(li);
788 	tablet_event = litest_is_tablet_event(event,
789 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
790 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
791 			 LIBINPUT_TABLET_TOOL_TIP_UP);
792 	libinput_event_destroy(event);
793 }
794 END_TEST
795 
START_TEST(tip_state_axis)796 START_TEST(tip_state_axis)
797 {
798 	struct litest_device *dev = litest_current_device();
799 	struct libinput *li = dev->libinput;
800 	struct libinput_event *event;
801 	struct libinput_event_tablet_tool *tablet_event;
802 	struct axis_replacement axes[] = {
803 		{ ABS_DISTANCE, 10 },
804 		{ ABS_PRESSURE, 0 },
805 		{ -1, -1 }
806 	};
807 
808 	litest_tablet_proximity_in(dev, 10, 10, axes);
809 	litest_drain_events(li);
810 
811 	litest_tablet_motion(dev, 70, 70, axes);
812 	libinput_dispatch(li);
813 
814 	event = libinput_get_event(li);
815 	tablet_event = litest_is_tablet_event(event,
816 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
817 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
818 			 LIBINPUT_TABLET_TOOL_TIP_UP);
819 	libinput_event_destroy(event);
820 
821 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
822 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
823 	litest_tablet_tip_down(dev, 40, 40, axes);
824 	litest_drain_events(li);
825 
826 	litest_tablet_motion(dev, 30, 30, axes);
827 	libinput_dispatch(li);
828 
829 	event = libinput_get_event(li);
830 	tablet_event = litest_is_tablet_event(event,
831 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
832 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
833 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
834 	libinput_event_destroy(event);
835 
836 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
837 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
838 	litest_tablet_tip_up(dev, 40, 40, axes);
839 	litest_drain_events(li);
840 
841 	litest_tablet_motion(dev, 40, 80, axes);
842 	libinput_dispatch(li);
843 
844 	event = libinput_get_event(li);
845 	tablet_event = litest_is_tablet_event(event,
846 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
847 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
848 			 LIBINPUT_TABLET_TOOL_TIP_UP);
849 	libinput_event_destroy(event);
850 
851 	litest_assert_empty_queue(li);
852 }
853 END_TEST
854 
START_TEST(tip_state_button)855 START_TEST(tip_state_button)
856 {
857 	struct litest_device *dev = litest_current_device();
858 	struct libinput *li = dev->libinput;
859 	struct libinput_event *event;
860 	struct libinput_event_tablet_tool *tablet_event;
861 	struct axis_replacement axes[] = {
862 		{ ABS_DISTANCE, 10 },
863 		{ ABS_PRESSURE, 0 },
864 		{ -1, -1 }
865 	};
866 	unsigned int button = pick_stylus_or_btn0(dev);
867 
868 	litest_tablet_proximity_in(dev, 10, 10, axes);
869 	litest_drain_events(li);
870 
871 	litest_button_click(dev, button, true);
872 	libinput_dispatch(li);
873 
874 	event = libinput_get_event(li);
875 	tablet_event = litest_is_tablet_event(event,
876 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
877 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
878 			 LIBINPUT_TABLET_TOOL_TIP_UP);
879 	libinput_event_destroy(event);
880 
881 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
882 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
883 	litest_tablet_tip_down(dev, 40, 40, axes);
884 	litest_drain_events(li);
885 
886 	litest_button_click(dev, button, false);
887 	libinput_dispatch(li);
888 
889 	event = libinput_get_event(li);
890 	tablet_event = litest_is_tablet_event(event,
891 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
892 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
893 			 LIBINPUT_TABLET_TOOL_TIP_DOWN);
894 	libinput_event_destroy(event);
895 
896 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
897 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
898 	litest_tablet_tip_up(dev, 40, 40, axes);
899 	litest_drain_events(li);
900 
901 	litest_button_click(dev, button, true);
902 	libinput_dispatch(li);
903 
904 	event = libinput_get_event(li);
905 	tablet_event = litest_is_tablet_event(event,
906 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
907 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
908 			 LIBINPUT_TABLET_TOOL_TIP_UP);
909 	libinput_event_destroy(event);
910 
911 	litest_button_click(dev, button, false);
912 	libinput_dispatch(li);
913 
914 	event = libinput_get_event(li);
915 	tablet_event = litest_is_tablet_event(event,
916 					      LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
917 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
918 			 LIBINPUT_TABLET_TOOL_TIP_UP);
919 	libinput_event_destroy(event);
920 
921 	litest_assert_empty_queue(li);
922 }
923 END_TEST
924 
START_TEST(tip_up_on_delete)925 START_TEST(tip_up_on_delete)
926 {
927 	struct libinput *li = litest_create_context();
928 	struct litest_device *dev = litest_add_device(li, LITEST_WACOM_INTUOS);
929 	struct libinput_event *event;
930 	struct libinput_event_tablet_tool *tablet_event;
931 	struct axis_replacement axes[] = {
932 		{ ABS_DISTANCE, 10 },
933 		{ ABS_PRESSURE, 0 },
934 		{ -1, -1 }
935 	};
936 
937 	litest_tablet_proximity_in(dev, 10, 10, axes);
938 	litest_drain_events(li);
939 
940 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
941 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
942 	litest_tablet_tip_down(dev, 10, 10, axes);
943 
944 	litest_drain_events(li);
945 	litest_delete_device(dev);
946 	libinput_dispatch(li);
947 
948 	event = libinput_get_event(li);
949 	tablet_event = litest_is_tablet_event(event,
950 					      LIBINPUT_EVENT_TABLET_TOOL_TIP);
951 	ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(tablet_event),
952 			 LIBINPUT_TABLET_TOOL_TIP_UP);
953 	libinput_event_destroy(event);
954 
955 	litest_destroy_context(li);
956 }
957 END_TEST
958 
START_TEST(proximity_in_out)959 START_TEST(proximity_in_out)
960 {
961 	struct litest_device *dev = litest_current_device();
962 	struct libinput *li = dev->libinput;
963 	struct libinput_event_tablet_tool *tablet_event;
964 	struct libinput_event *event;
965 	enum libinput_tablet_tool_type type;
966 	bool have_tool_update = false,
967 	     have_proximity_out = false;
968 
969 	struct axis_replacement axes[] = {
970 		{ ABS_DISTANCE, 10 },
971 		{ ABS_PRESSURE, 0 },
972 		{ -1, -1 }
973 	};
974 
975 	litest_drain_events(li);
976 
977 	switch (dev->which) {
978 	case LITEST_DELL_CANVAS_TOTEM:
979 		type = LIBINPUT_TABLET_TOOL_TYPE_TOTEM;
980 		break;
981 	default:
982 		type = LIBINPUT_TABLET_TOOL_TYPE_PEN;
983 		break;
984 	}
985 
986 	litest_tablet_proximity_in(dev, 10, 10, axes);
987 	libinput_dispatch(li);
988 
989 	while ((event = libinput_get_event(li))) {
990 		if (libinput_event_get_type(event) ==
991 		    LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
992 			struct libinput_tablet_tool * tool;
993 
994 			ck_assert(!have_tool_update);
995 			have_tool_update = true;
996 			tablet_event = libinput_event_get_tablet_tool_event(event);
997 			tool = libinput_event_tablet_tool_get_tool(tablet_event);
998 			ck_assert_int_eq(libinput_tablet_tool_get_type(tool), type);
999 		}
1000 		libinput_event_destroy(event);
1001 	}
1002 	ck_assert(have_tool_update);
1003 
1004 	litest_tablet_proximity_out(dev);
1005 	libinput_dispatch(li);
1006 
1007 	litest_timeout_tablet_proxout();
1008 	libinput_dispatch(li);
1009 
1010 	while ((event = libinput_get_event(li))) {
1011 		if (libinput_event_get_type(event) ==
1012 		    LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
1013 			struct libinput_event_tablet_tool *t =
1014 				libinput_event_get_tablet_tool_event(event);
1015 
1016 			if (libinput_event_tablet_tool_get_proximity_state(t) ==
1017 			    LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT)
1018 				have_proximity_out = true;
1019 		}
1020 
1021 		libinput_event_destroy(event);
1022 	}
1023 	ck_assert(have_proximity_out);
1024 
1025 	/* Proximity out must not emit axis events */
1026 	litest_assert_empty_queue(li);
1027 }
1028 END_TEST
1029 
START_TEST(proximity_in_button_down)1030 START_TEST(proximity_in_button_down)
1031 {
1032 	struct litest_device *dev = litest_current_device();
1033 	struct libinput *li = dev->libinput;
1034 	struct axis_replacement axes[] = {
1035 		{ ABS_DISTANCE, 10 },
1036 		{ ABS_PRESSURE, 0 },
1037 		{ -1, -1 }
1038 	};
1039 	unsigned int button = pick_stylus_or_btn0(dev);
1040 
1041 	litest_drain_events(li);
1042 
1043 	litest_push_event_frame(dev);
1044 	litest_tablet_proximity_in(dev, 10, 10, axes);
1045 	litest_event(dev, EV_KEY, button, 1);
1046 	litest_pop_event_frame(dev);
1047 	libinput_dispatch(li);
1048 
1049 	litest_assert_tablet_proximity_event(li,
1050 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
1051 	litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, -1);
1052 	litest_assert_tablet_button_event(li,
1053 					  button,
1054 					  LIBINPUT_BUTTON_STATE_PRESSED);
1055 	litest_assert_empty_queue(li);
1056 }
1057 END_TEST
1058 
START_TEST(proximity_out_button_up)1059 START_TEST(proximity_out_button_up)
1060 {
1061 	struct litest_device *dev = litest_current_device();
1062 	struct libinput *li = dev->libinput;
1063 	struct axis_replacement axes[] = {
1064 		{ ABS_DISTANCE, 10 },
1065 		{ ABS_PRESSURE, 0 },
1066 		{ -1, -1 }
1067 	};
1068 	unsigned int button = pick_stylus_or_btn0(dev);
1069 
1070 	litest_tablet_proximity_in(dev, 10, 10, axes);
1071 
1072 	litest_button_click(dev, button, true);
1073 	litest_drain_events(li);
1074 
1075 	litest_push_event_frame(dev);
1076 	litest_tablet_proximity_out(dev);
1077 	litest_event(dev, EV_KEY, button, 0);
1078 	litest_pop_event_frame(dev);
1079 	libinput_dispatch(li);
1080 
1081 	litest_timeout_tablet_proxout();
1082 	libinput_dispatch(li);
1083 
1084 	litest_assert_tablet_button_event(li,
1085 					  button,
1086 					  LIBINPUT_BUTTON_STATE_RELEASED);
1087 	litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, -1);
1088 	litest_assert_tablet_proximity_event(li,
1089 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1090 	litest_assert_empty_queue(li);
1091 }
1092 END_TEST
1093 
START_TEST(proximity_out_clear_buttons)1094 START_TEST(proximity_out_clear_buttons)
1095 {
1096 	struct litest_device *dev = litest_current_device();
1097 	struct libinput *li = dev->libinput;
1098 	struct libinput_event_tablet_tool *tablet_event;
1099 	struct libinput_event *event;
1100 	uint32_t button;
1101 	struct axis_replacement axes[] = {
1102 		{ ABS_DISTANCE, 10 },
1103 		{ ABS_PRESSURE, 0 },
1104 		{ -1, -1 }
1105 	};
1106 	bool have_proximity = false;
1107 	double x = 50, y = 50;
1108 
1109 	litest_drain_events(li);
1110 
1111 	/* Test that proximity out events send button releases for any currently
1112 	 * pressed stylus buttons
1113 	 */
1114 	for (button = BTN_STYLUS; button <= BTN_STYLUS2; button++) {
1115 		bool button_released = false;
1116 		uint32_t event_button = 0;
1117 		enum libinput_button_state state;
1118 
1119 		if (!libevdev_has_event_code(dev->evdev, EV_KEY, button))
1120 			continue;
1121 
1122 		litest_tablet_proximity_in(dev, x++, y++, axes);
1123 		litest_drain_events(li);
1124 
1125 		litest_event(dev, EV_KEY, button, 1);
1126 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
1127 		litest_tablet_proximity_out(dev);
1128 		libinput_dispatch(li);
1129 
1130 		event = libinput_get_event(li);
1131 		ck_assert_notnull(event);
1132 		do {
1133 			tablet_event = libinput_event_get_tablet_tool_event(event);
1134 
1135 			if (libinput_event_get_type(event) ==
1136 			    LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
1137 				have_proximity = true;
1138 				libinput_event_destroy(event);
1139 				break;
1140 			}
1141 
1142 			if (libinput_event_get_type(event) ==
1143 			    LIBINPUT_EVENT_TABLET_TOOL_BUTTON) {
1144 
1145 				event_button = libinput_event_tablet_tool_get_button(tablet_event);
1146 				state = libinput_event_tablet_tool_get_button_state(tablet_event);
1147 
1148 				if (event_button == button &&
1149 				    state == LIBINPUT_BUTTON_STATE_RELEASED)
1150 					button_released = true;
1151 			}
1152 
1153 			libinput_event_destroy(event);
1154 		} while ((event = libinput_get_event(li)));
1155 
1156 		ck_assert_msg(button_released,
1157 			      "Button %s (%d) was not released.",
1158 			      libevdev_event_code_get_name(EV_KEY, button),
1159 			      event_button);
1160 		litest_assert(have_proximity);
1161 		litest_assert_empty_queue(li);
1162 	}
1163 }
1164 END_TEST
1165 
START_TEST(proximity_has_axes)1166 START_TEST(proximity_has_axes)
1167 {
1168 	struct litest_device *dev = litest_current_device();
1169 	struct libinput *li = dev->libinput;
1170 	struct libinput_event_tablet_tool *tablet_event;
1171 	struct libinput_event *event;
1172 	struct libinput_tablet_tool *tool;
1173 	double x, y,
1174 	       distance;
1175 	double last_x, last_y,
1176 	       last_distance = 0.0,
1177 	       last_tx = 0.0, last_ty = 0.0;
1178 
1179 	struct axis_replacement axes[] = {
1180 		{ ABS_DISTANCE, 10 },
1181 		{ ABS_PRESSURE, 0 },
1182 		{ ABS_TILT_X, 10 },
1183 		{ ABS_TILT_Y, 10 },
1184 		{ -1, -1}
1185 	};
1186 
1187 	litest_drain_events(li);
1188 
1189 	litest_tablet_proximity_in(dev, 10, 10, axes);
1190 	libinput_dispatch(li);
1191 
1192 	event = libinput_get_event(li);
1193 	tablet_event = litest_is_tablet_event(event,
1194 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
1195 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
1196 
1197 	ck_assert(libinput_event_tablet_tool_x_has_changed(tablet_event));
1198 	ck_assert(libinput_event_tablet_tool_y_has_changed(tablet_event));
1199 
1200 	x = libinput_event_tablet_tool_get_x(tablet_event);
1201 	y = libinput_event_tablet_tool_get_y(tablet_event);
1202 
1203 	litest_assert_double_ne(x, 0);
1204 	litest_assert_double_ne(y, 0);
1205 
1206 	if (libinput_tablet_tool_has_distance(tool)) {
1207 		ck_assert(libinput_event_tablet_tool_distance_has_changed(
1208 				tablet_event));
1209 
1210 		distance = libinput_event_tablet_tool_get_distance(tablet_event);
1211 		litest_assert_double_ne(distance, 0);
1212 	}
1213 
1214 	if (libinput_tablet_tool_has_tilt(tool)) {
1215 		ck_assert(libinput_event_tablet_tool_tilt_x_has_changed(
1216 				tablet_event));
1217 		ck_assert(libinput_event_tablet_tool_tilt_y_has_changed(
1218 				tablet_event));
1219 
1220 		x = libinput_event_tablet_tool_get_tilt_x(tablet_event);
1221 		y = libinput_event_tablet_tool_get_tilt_y(tablet_event);
1222 
1223 		litest_assert_double_ne(x, 0);
1224 		litest_assert_double_ne(y, 0);
1225 	}
1226 
1227 	litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, -1);
1228 
1229 	litest_assert_empty_queue(li);
1230 	libinput_event_destroy(event);
1231 
1232 	litest_axis_set_value(axes, ABS_DISTANCE, 20);
1233 	litest_axis_set_value(axes, ABS_TILT_X, 15);
1234 	litest_axis_set_value(axes, ABS_TILT_Y, 25);
1235 
1236 	/* work around axis smoothing */
1237 	litest_tablet_motion(dev, 20, 30, axes);
1238 	litest_tablet_motion(dev, 20, 29, axes);
1239 	litest_tablet_motion(dev, 20, 31, axes);
1240 	litest_drain_events(li);
1241 
1242 	litest_tablet_motion(dev, 20, 30, axes);
1243 	libinput_dispatch(li);
1244 	event = libinput_get_event(li);
1245 	tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
1246 
1247 	last_x = libinput_event_tablet_tool_get_x(tablet_event);
1248 	last_y = libinput_event_tablet_tool_get_y(tablet_event);
1249 	if (libinput_tablet_tool_has_distance(tool))
1250 		last_distance = libinput_event_tablet_tool_get_distance(
1251 					     tablet_event);
1252 	if (libinput_tablet_tool_has_tilt(tool)) {
1253 		last_tx = libinput_event_tablet_tool_get_tilt_x(tablet_event);
1254 		last_ty = libinput_event_tablet_tool_get_tilt_y(tablet_event);
1255 	}
1256 
1257 	libinput_event_destroy(event);
1258 
1259 	/* Make sure that the axes are still present on proximity out */
1260 	litest_tablet_proximity_out(dev);
1261 	libinput_dispatch(li);
1262 
1263 	litest_timeout_tablet_proxout();
1264 	libinput_dispatch(li);
1265 
1266 	litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, -1);
1267 
1268 	event = libinput_get_event(li);
1269 	tablet_event = litest_is_tablet_event(event,
1270 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
1271 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
1272 
1273 	ck_assert(!libinput_event_tablet_tool_x_has_changed(tablet_event));
1274 	ck_assert(!libinput_event_tablet_tool_y_has_changed(tablet_event));
1275 
1276 	x = libinput_event_tablet_tool_get_x(tablet_event);
1277 	y = libinput_event_tablet_tool_get_y(tablet_event);
1278 	litest_assert_double_ge(x, last_x - 1);
1279 	litest_assert_double_le(x, last_x + 1);
1280 	litest_assert_double_ge(y, last_y - 1);
1281 	litest_assert_double_le(y, last_y + 1);
1282 
1283 	if (libinput_tablet_tool_has_distance(tool)) {
1284 		ck_assert(!libinput_event_tablet_tool_distance_has_changed(
1285 				tablet_event));
1286 
1287 		distance = libinput_event_tablet_tool_get_distance(
1288 						tablet_event);
1289 		litest_assert_double_eq(distance, last_distance);
1290 	}
1291 
1292 	if (libinput_tablet_tool_has_tilt(tool)) {
1293 		ck_assert(!libinput_event_tablet_tool_tilt_x_has_changed(
1294 				tablet_event));
1295 		ck_assert(!libinput_event_tablet_tool_tilt_y_has_changed(
1296 				tablet_event));
1297 
1298 		x = libinput_event_tablet_tool_get_tilt_x(tablet_event);
1299 		y = libinput_event_tablet_tool_get_tilt_y(tablet_event);
1300 
1301 		litest_assert_double_eq(x, last_tx);
1302 		litest_assert_double_eq(y, last_ty);
1303 	}
1304 
1305 	litest_assert_empty_queue(li);
1306 	libinput_event_destroy(event);
1307 }
1308 END_TEST
1309 
START_TEST(proximity_range_enter)1310 START_TEST(proximity_range_enter)
1311 {
1312 	struct litest_device *dev = litest_current_device();
1313 	struct libinput *li = dev->libinput;
1314 	struct axis_replacement axes[] = {
1315 		{ ABS_DISTANCE, 90 },
1316 		{ -1, -1 }
1317 	};
1318 
1319 	litest_drain_events(li);
1320 
1321 	litest_push_event_frame(dev);
1322 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1323 	litest_tablet_proximity_in(dev, 10, 10, axes);
1324 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
1325 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1326 	litest_pop_event_frame(dev);
1327 	litest_assert_empty_queue(li);
1328 
1329 	litest_axis_set_value(axes, ABS_DISTANCE, 20);
1330 	litest_tablet_motion(dev, 10, 10, axes);
1331 	libinput_dispatch(li);
1332 
1333 	litest_assert_tablet_proximity_event(li,
1334 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
1335 
1336 	litest_axis_set_value(axes, ABS_DISTANCE, 90);
1337 	litest_tablet_motion(dev, 10, 10, axes);
1338 	libinput_dispatch(li);
1339 	litest_assert_tablet_proximity_event(li,
1340 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1341 
1342 	litest_push_event_frame(dev);
1343 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1344 	litest_tablet_proximity_out(dev);
1345 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
1346 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1347 	litest_pop_event_frame(dev);
1348 	litest_assert_empty_queue(li);
1349 }
1350 END_TEST
1351 
START_TEST(proximity_range_in_out)1352 START_TEST(proximity_range_in_out)
1353 {
1354 	struct litest_device *dev = litest_current_device();
1355 	struct libinput *li = dev->libinput;
1356 	struct axis_replacement axes[] = {
1357 		{ ABS_DISTANCE, 20 },
1358 		{ -1, -1 }
1359 	};
1360 
1361 	litest_drain_events(li);
1362 
1363 	litest_push_event_frame(dev);
1364 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1365 	litest_tablet_proximity_in(dev, 10, 10, axes);
1366 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
1367 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1368 	litest_pop_event_frame(dev);
1369 	libinput_dispatch(li);
1370 	litest_assert_tablet_proximity_event(li,
1371 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
1372 
1373 	litest_axis_set_value(axes, ABS_DISTANCE, 90);
1374 	litest_tablet_motion(dev, 10, 10, axes);
1375 	libinput_dispatch(li);
1376 	litest_assert_tablet_proximity_event(li,
1377 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1378 
1379 	litest_tablet_motion(dev, 30, 30, axes);
1380 	litest_assert_empty_queue(li);
1381 
1382 	litest_axis_set_value(axes, ABS_DISTANCE, 20);
1383 	litest_tablet_motion(dev, 10, 10, axes);
1384 	libinput_dispatch(li);
1385 	litest_assert_tablet_proximity_event(li,
1386 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
1387 
1388 	litest_push_event_frame(dev);
1389 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1390 	litest_tablet_proximity_out(dev);
1391 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
1392 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1393 	litest_pop_event_frame(dev);
1394 	litest_assert_tablet_proximity_event(li,
1395 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1396 	litest_assert_empty_queue(li);
1397 }
1398 END_TEST
1399 
START_TEST(proximity_range_button_click)1400 START_TEST(proximity_range_button_click)
1401 {
1402 	struct litest_device *dev = litest_current_device();
1403 	struct libinput *li = dev->libinput;
1404 	struct axis_replacement axes[] = {
1405 		{ ABS_DISTANCE, 90 },
1406 		{ -1, -1 }
1407 	};
1408 
1409 	litest_drain_events(li);
1410 
1411 	litest_push_event_frame(dev);
1412 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1413 	litest_tablet_proximity_in(dev, 10, 10, axes);
1414 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
1415 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1416 	litest_pop_event_frame(dev);
1417 	litest_drain_events(li);
1418 
1419 	litest_event(dev, EV_KEY, BTN_STYLUS, 1);
1420 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1421 	libinput_dispatch(li);
1422 	litest_event(dev, EV_KEY, BTN_STYLUS, 0);
1423 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1424 	libinput_dispatch(li);
1425 
1426 	litest_push_event_frame(dev);
1427 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1428 	litest_tablet_proximity_out(dev);
1429 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
1430 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1431 	litest_pop_event_frame(dev);
1432 	litest_assert_empty_queue(li);
1433 }
1434 END_TEST
1435 
START_TEST(proximity_range_button_press)1436 START_TEST(proximity_range_button_press)
1437 {
1438 	struct litest_device *dev = litest_current_device();
1439 	struct libinput *li = dev->libinput;
1440 	struct axis_replacement axes[] = {
1441 		{ ABS_DISTANCE, 20 },
1442 		{ -1, -1 }
1443 	};
1444 
1445 	litest_push_event_frame(dev);
1446 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1447 	litest_tablet_proximity_in(dev, 10, 10, axes);
1448 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
1449 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1450 	litest_pop_event_frame(dev);
1451 	litest_drain_events(li);
1452 
1453 	litest_event(dev, EV_KEY, BTN_STYLUS, 1);
1454 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1455 	libinput_dispatch(li);
1456 
1457 	litest_assert_tablet_button_event(li,
1458 					  BTN_STYLUS,
1459 					  LIBINPUT_BUTTON_STATE_PRESSED);
1460 
1461 	litest_axis_set_value(axes, ABS_DISTANCE, 90);
1462 	litest_tablet_motion(dev, 15, 15, axes);
1463 	libinput_dispatch(li);
1464 
1465 	/* expect fake button release */
1466 	litest_assert_tablet_button_event(li,
1467 					  BTN_STYLUS,
1468 					  LIBINPUT_BUTTON_STATE_RELEASED);
1469 	litest_assert_tablet_proximity_event(li,
1470 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1471 
1472 	litest_event(dev, EV_KEY, BTN_STYLUS, 0);
1473 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1474 	libinput_dispatch(li);
1475 
1476 	litest_push_event_frame(dev);
1477 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1478 	litest_tablet_proximity_out(dev);
1479 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
1480 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1481 	litest_pop_event_frame(dev);
1482 	litest_assert_empty_queue(li);
1483 }
1484 END_TEST
1485 
START_TEST(proximity_range_button_release)1486 START_TEST(proximity_range_button_release)
1487 {
1488 	struct litest_device *dev = litest_current_device();
1489 	struct libinput *li = dev->libinput;
1490 	struct axis_replacement axes[] = {
1491 		{ ABS_DISTANCE, 90 },
1492 		{ -1, -1 }
1493 	};
1494 
1495 	litest_push_event_frame(dev);
1496 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1497 	litest_tablet_proximity_in(dev, 10, 10, axes);
1498 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
1499 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1500 	litest_pop_event_frame(dev);
1501 	litest_drain_events(li);
1502 
1503 	litest_event(dev, EV_KEY, BTN_STYLUS, 1);
1504 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1505 	litest_assert_empty_queue(li);
1506 
1507 	litest_axis_set_value(axes, ABS_DISTANCE, 20);
1508 	litest_tablet_motion(dev, 15, 15, axes);
1509 	libinput_dispatch(li);
1510 
1511 	litest_assert_tablet_proximity_event(li,
1512 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
1513 	/* expect fake button press */
1514 	litest_assert_tablet_button_event(li,
1515 					  BTN_STYLUS,
1516 					  LIBINPUT_BUTTON_STATE_PRESSED);
1517 	litest_assert_empty_queue(li);
1518 
1519 	litest_event(dev, EV_KEY, BTN_STYLUS, 0);
1520 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1521 	libinput_dispatch(li);
1522 	litest_assert_tablet_button_event(li,
1523 					  BTN_STYLUS,
1524 					  LIBINPUT_BUTTON_STATE_RELEASED);
1525 
1526 	litest_push_event_frame(dev);
1527 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
1528 	litest_tablet_proximity_out(dev);
1529 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 0);
1530 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
1531 	litest_pop_event_frame(dev);
1532 	litest_assert_tablet_proximity_event(li,
1533 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1534 }
1535 END_TEST
1536 
START_TEST(proximity_out_slow_event)1537 START_TEST(proximity_out_slow_event)
1538 {
1539 	struct litest_device *dev = litest_current_device();
1540 	struct libinput *li = dev->libinput;
1541 	struct axis_replacement axes[] = {
1542 		{ ABS_DISTANCE, 90 },
1543 		{ -1, -1 }
1544 	};
1545 
1546 	litest_tablet_proximity_in(dev, 10, 10, axes);
1547 	litest_tablet_motion(dev, 12, 12, axes);
1548 	litest_drain_events(li);
1549 
1550 	litest_timeout_tablet_proxout();
1551 	libinput_dispatch(li);
1552 
1553 	/* The forced prox out */
1554 	litest_assert_tablet_proximity_event(li,
1555 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1556 	litest_assert_empty_queue(li);
1557 
1558 	litest_tablet_proximity_out(dev);
1559 	litest_assert_empty_queue(li);
1560 }
1561 END_TEST
1562 
START_TEST(proximity_out_not_during_contact)1563 START_TEST(proximity_out_not_during_contact)
1564 {
1565 	struct litest_device *dev = litest_current_device();
1566 	struct libinput *li = dev->libinput;
1567 	struct axis_replacement axes[] = {
1568 		{ ABS_DISTANCE, 0 },
1569 		{ ABS_PRESSURE, 10 },
1570 		{ -1, -1 }
1571 	};
1572 
1573 	litest_tablet_proximity_in(dev, 10, 10, axes);
1574 	litest_tablet_motion(dev, 12, 12, axes);
1575 	litest_drain_events(li);
1576 
1577 	litest_timeout_tablet_proxout();
1578 	libinput_dispatch(li);
1579 
1580 	/* No forced proxout yet */
1581 	litest_assert_empty_queue(li);
1582 
1583 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
1584 	litest_tablet_motion(dev, 14, 14, axes);
1585 	litest_drain_events(li);
1586 
1587 	litest_timeout_tablet_proxout();
1588 	libinput_dispatch(li);
1589 
1590 	/* The forced prox out */
1591 	litest_assert_tablet_proximity_event(li,
1592 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1593 
1594 	litest_tablet_proximity_out(dev);
1595 	litest_assert_empty_queue(li);
1596 }
1597 END_TEST
1598 
START_TEST(proximity_out_not_during_buttonpress)1599 START_TEST(proximity_out_not_during_buttonpress)
1600 {
1601 	struct litest_device *dev = litest_current_device();
1602 	struct libinput *li = dev->libinput;
1603 	struct axis_replacement axes[] = {
1604 		{ ABS_DISTANCE, 10 },
1605 		{ ABS_PRESSURE, 0 },
1606 		{ -1, -1 }
1607 	};
1608 
1609 	litest_tablet_proximity_in(dev, 10, 10, axes);
1610 	litest_tablet_motion(dev, 12, 12, axes);
1611 	litest_drain_events(li);
1612 
1613 	litest_event(dev, EV_KEY, BTN_STYLUS, 1);
1614 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1615 	libinput_dispatch(li);
1616 
1617 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
1618 
1619 	litest_timeout_tablet_proxout();
1620 	libinput_dispatch(li);
1621 
1622 	/* No forced proxout yet */
1623 	litest_assert_empty_queue(li);
1624 
1625 	litest_event(dev, EV_KEY, BTN_STYLUS, 0);
1626 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
1627 	libinput_dispatch(li);
1628 
1629 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
1630 
1631 	litest_timeout_tablet_proxout();
1632 	libinput_dispatch(li);
1633 
1634 	/* The forced prox out */
1635 	litest_assert_tablet_proximity_event(li,
1636 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1637 
1638 	litest_tablet_proximity_out(dev);
1639 	litest_assert_empty_queue(li);
1640 }
1641 END_TEST
1642 
START_TEST(proximity_out_disables_forced)1643 START_TEST(proximity_out_disables_forced)
1644 {
1645 	struct litest_device *dev = litest_current_device();
1646 	struct libinput *li = dev->libinput;
1647 	struct axis_replacement axes[] = {
1648 		{ ABS_DISTANCE, 10 },
1649 		{ ABS_PRESSURE, 0 },
1650 		{ -1, -1 }
1651 	};
1652 
1653 	/* A correct proximity out sequence from the device should disable
1654 	   the forced proximity out */
1655 	litest_tablet_proximity_in(dev, 10, 10, axes);
1656 	litest_tablet_proximity_out(dev);
1657 	litest_drain_events(li);
1658 
1659 	/* expect no timeout-based prox out */
1660 	litest_tablet_proximity_in(dev, 10, 10, axes);
1661 	litest_drain_events(li);
1662 
1663 	litest_timeout_tablet_proxout();
1664 	libinput_dispatch(li);
1665 
1666 	litest_assert_empty_queue(li);
1667 	litest_tablet_proximity_out(dev);
1668 	litest_assert_tablet_proximity_event(li,
1669 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1670 	libinput_dispatch(li);
1671 }
1672 END_TEST
1673 
START_TEST(proximity_out_disables_forced_after_forced)1674 START_TEST(proximity_out_disables_forced_after_forced)
1675 {
1676 	struct litest_device *dev = litest_current_device();
1677 	struct libinput *li = dev->libinput;
1678 	struct axis_replacement axes[] = {
1679 		{ ABS_DISTANCE, 10 },
1680 		{ ABS_PRESSURE, 0 },
1681 		{ -1, -1 }
1682 	};
1683 
1684 	/* A correct proximity out sequence from the device should disable
1685 	   the forced proximity out, even when we had a forced prox-out */
1686 	litest_tablet_proximity_in(dev, 10, 10, axes);
1687 	litest_drain_events(li);
1688 
1689 	/* timeout-based forced prox out */
1690 	litest_timeout_tablet_proxout();
1691 	libinput_dispatch(li);
1692 	litest_assert_tablet_proximity_event(li,
1693 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1694 	litest_assert_empty_queue(li);
1695 
1696 	/* now send the real prox out (we're already in proximity out) and
1697 	 * that should disable the proxout quirk */
1698 	litest_tablet_proximity_out(dev);
1699 	libinput_dispatch(li);
1700 	litest_assert_empty_queue(li);
1701 
1702 	/* same again, but this time we expect no timeout-based prox out */
1703 	litest_tablet_proximity_in(dev, 10, 10, axes);
1704 	litest_drain_events(li);
1705 
1706 	litest_timeout_tablet_proxout();
1707 	libinput_dispatch(li);
1708 
1709 	litest_assert_empty_queue(li);
1710 	litest_tablet_proximity_out(dev);
1711 	litest_assert_tablet_proximity_event(li,
1712 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1713 	libinput_dispatch(li);
1714 }
1715 END_TEST
1716 
START_TEST(proximity_out_on_delete)1717 START_TEST(proximity_out_on_delete)
1718 {
1719 	struct libinput *li = litest_create_context();
1720 	struct litest_device *dev = litest_add_device(li, LITEST_WACOM_INTUOS);
1721 
1722 	litest_tablet_proximity_in(dev, 10, 10, NULL);
1723 	litest_drain_events(li);
1724 
1725 	litest_delete_device(dev);
1726 	libinput_dispatch(li);
1727 
1728 	litest_assert_tablet_proximity_event(li,
1729 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
1730 	litest_destroy_context(li);
1731 }
1732 END_TEST
1733 
START_TEST(motion)1734 START_TEST(motion)
1735 {
1736 	struct litest_device *dev = litest_current_device();
1737 	struct libinput *li = dev->libinput;
1738 	struct libinput_event_tablet_tool *tablet_event;
1739 	struct libinput_event *event;
1740 	int test_x, test_y;
1741 	double last_reported_x = 0, last_reported_y = 0;
1742 	enum libinput_event_type type;
1743 	struct axis_replacement axes[] = {
1744 		{ ABS_DISTANCE, 10 },
1745 		{ ABS_PRESSURE, 0 },
1746 		{ -1, -1 }
1747 	};
1748 	bool x_changed, y_changed;
1749 	double reported_x, reported_y;
1750 
1751 	litest_drain_events(li);
1752 
1753 	litest_tablet_proximity_in(dev, 5, 100, axes);
1754 	libinput_dispatch(li);
1755 
1756 	event = libinput_get_event(li);
1757 	tablet_event = litest_is_tablet_event(event,
1758 				      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
1759 	x_changed = libinput_event_tablet_tool_x_has_changed(tablet_event);
1760 	y_changed = libinput_event_tablet_tool_y_has_changed(tablet_event);
1761 	ck_assert(x_changed);
1762 	ck_assert(y_changed);
1763 
1764 	reported_x = libinput_event_tablet_tool_get_x(tablet_event);
1765 	reported_y = libinput_event_tablet_tool_get_y(tablet_event);
1766 
1767 	litest_assert_double_lt(reported_x, reported_y);
1768 
1769 	last_reported_x = reported_x;
1770 	last_reported_y = reported_y;
1771 
1772 	libinput_event_destroy(event);
1773 
1774 	for (test_x = 10, test_y = 90;
1775 	     test_x <= 100;
1776 	     test_x += 10, test_y -= 10) {
1777 		bool x_changed, y_changed;
1778 		double reported_x, reported_y;
1779 
1780 		litest_tablet_motion(dev, test_x, test_y, axes);
1781 		libinput_dispatch(li);
1782 
1783 		while ((event = libinput_get_event(li))) {
1784 			tablet_event = libinput_event_get_tablet_tool_event(event);
1785 			type = libinput_event_get_type(event);
1786 
1787 			if (type == LIBINPUT_EVENT_TABLET_TOOL_AXIS) {
1788 				x_changed = libinput_event_tablet_tool_x_has_changed(
1789 							    tablet_event);
1790 				y_changed = libinput_event_tablet_tool_y_has_changed(
1791 							    tablet_event);
1792 
1793 				ck_assert(x_changed);
1794 				ck_assert(y_changed);
1795 
1796 				reported_x = libinput_event_tablet_tool_get_x(
1797 								tablet_event);
1798 				reported_y = libinput_event_tablet_tool_get_y(
1799 								tablet_event);
1800 
1801 				litest_assert_double_gt(reported_x,
1802 							last_reported_x);
1803 				litest_assert_double_lt(reported_y,
1804 							last_reported_y);
1805 
1806 				last_reported_x = reported_x;
1807 				last_reported_y = reported_y;
1808 			}
1809 
1810 			libinput_event_destroy(event);
1811 		}
1812 	}
1813 }
1814 END_TEST
1815 
START_TEST(left_handed)1816 START_TEST(left_handed)
1817 {
1818 #if HAVE_LIBWACOM
1819 	struct litest_device *dev = litest_current_device();
1820 	struct libinput *li = dev->libinput;
1821 	struct libinput_event *event;
1822 	struct libinput_event_tablet_tool *tablet_event;
1823 	double libinput_max_x, libinput_max_y;
1824 	double last_x = -1.0, last_y = -1.0;
1825 	double x, y;
1826 	struct axis_replacement axes[] = {
1827 		{ ABS_DISTANCE, 10 },
1828 		{ ABS_PRESSURE, 0 },
1829 		{ -1, -1 }
1830 	};
1831 
1832 	litest_drain_events(li);
1833 
1834 	ck_assert(libinput_device_config_left_handed_is_available(dev->libinput_device));
1835 
1836 	libinput_device_get_size (dev->libinput_device,
1837 				  &libinput_max_x,
1838 				  &libinput_max_y);
1839 
1840 	/* Test that left-handed mode doesn't go into effect until the tool has
1841 	 * left proximity of the tablet. In order to test this, we have to bring
1842 	 * the tool into proximity and make sure libinput processes the
1843 	 * proximity events so that it updates it's internal tablet state, and
1844 	 * then try setting it to left-handed mode. */
1845 	litest_tablet_proximity_in(dev, 0, 100, axes);
1846 	libinput_dispatch(li);
1847 	libinput_device_config_left_handed_set(dev->libinput_device, 1);
1848 
1849 	event = libinput_get_event(li);
1850 	tablet_event = litest_is_tablet_event(event,
1851 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
1852 
1853 	last_x = libinput_event_tablet_tool_get_x(tablet_event);
1854 	last_y = libinput_event_tablet_tool_get_y(tablet_event);
1855 
1856 	litest_assert_double_eq(last_x, 0);
1857 	litest_assert_double_eq(last_y, libinput_max_y);
1858 
1859 	libinput_event_destroy(event);
1860 
1861 	/* work around smoothing */
1862 	litest_axis_set_value(axes, ABS_DISTANCE, 9);
1863 	litest_tablet_motion(dev, 100, 0, axes);
1864 	litest_axis_set_value(axes, ABS_DISTANCE, 7);
1865 	litest_tablet_motion(dev, 100, 0, axes);
1866 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
1867 	litest_tablet_motion(dev, 100, 0, axes);
1868 	litest_drain_events(li);
1869 
1870 	litest_axis_set_value(axes, ABS_DISTANCE, 5);
1871 	litest_tablet_motion(dev, 100, 0, axes);
1872 	libinput_dispatch(li);
1873 
1874 	event = libinput_get_event(li);
1875 	tablet_event = litest_is_tablet_event(event,
1876 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
1877 
1878 	x = libinput_event_tablet_tool_get_x(tablet_event);
1879 	y = libinput_event_tablet_tool_get_y(tablet_event);
1880 
1881 	litest_assert_double_eq(x, libinput_max_x);
1882 	litest_assert_double_eq(y, 0);
1883 
1884 	litest_assert_double_gt(x, last_x);
1885 	litest_assert_double_lt(y, last_y);
1886 
1887 	libinput_event_destroy(event);
1888 
1889 	litest_tablet_proximity_out(dev);
1890 	litest_drain_events(li);
1891 
1892 	/* Since we've drained the events and libinput's aware the tool is out
1893 	 * of proximity, it should have finally transitioned into left-handed
1894 	 * mode, so the axes should be inverted once we bring it back into
1895 	 * proximity */
1896 	litest_tablet_proximity_in(dev, 0, 100, axes);
1897 	libinput_dispatch(li);
1898 
1899 	event = libinput_get_event(li);
1900 	tablet_event = litest_is_tablet_event(event,
1901 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
1902 
1903 	last_x = libinput_event_tablet_tool_get_x(tablet_event);
1904 	last_y = libinput_event_tablet_tool_get_y(tablet_event);
1905 
1906 	litest_assert_double_eq(last_x, libinput_max_x);
1907 	litest_assert_double_eq(last_y, 0);
1908 
1909 	libinput_event_destroy(event);
1910 
1911 	/* work around smoothing */
1912 	litest_axis_set_value(axes, ABS_DISTANCE, 9);
1913 	litest_tablet_motion(dev, 100, 0, axes);
1914 	litest_axis_set_value(axes, ABS_DISTANCE, 7);
1915 	litest_tablet_motion(dev, 100, 0, axes);
1916 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
1917 	litest_tablet_motion(dev, 100, 0, axes);
1918 	litest_drain_events(li);
1919 
1920 	litest_axis_set_value(axes, ABS_DISTANCE, 5);
1921 	litest_tablet_motion(dev, 100, 0, axes);
1922 	libinput_dispatch(li);
1923 
1924 	event = libinput_get_event(li);
1925 	tablet_event = litest_is_tablet_event(event,
1926 				LIBINPUT_EVENT_TABLET_TOOL_AXIS);
1927 
1928 	x = libinput_event_tablet_tool_get_x(tablet_event);
1929 	y = libinput_event_tablet_tool_get_y(tablet_event);
1930 
1931 	litest_assert_double_eq(x, 0);
1932 	litest_assert_double_eq(y, libinput_max_y);
1933 
1934 	litest_assert_double_lt(x, last_x);
1935 	litest_assert_double_gt(y, last_y);
1936 
1937 	libinput_event_destroy(event);
1938 #endif
1939 }
1940 END_TEST
1941 
START_TEST(no_left_handed)1942 START_TEST(no_left_handed)
1943 {
1944 	struct litest_device *dev = litest_current_device();
1945 
1946 	/* Without libwacom we default to left-handed being available */
1947 #if HAVE_LIBWACOM
1948 	ck_assert(!libinput_device_config_left_handed_is_available(dev->libinput_device));
1949 #else
1950 	ck_assert(libinput_device_config_left_handed_is_available(dev->libinput_device));
1951 #endif
1952 }
1953 END_TEST
1954 
START_TEST(left_handed_tilt)1955 START_TEST(left_handed_tilt)
1956 {
1957 #if HAVE_LIBWACOM
1958 	struct litest_device *dev = litest_current_device();
1959 	struct libinput *li = dev->libinput;
1960 	struct libinput_event *event;
1961 	struct libinput_event_tablet_tool *tev;
1962 	enum libinput_config_status status;
1963 	struct axis_replacement axes[] = {
1964 		{ ABS_DISTANCE, 10 },
1965 		{ ABS_PRESSURE, 0 },
1966 		{ ABS_TILT_X, 90 },
1967 		{ ABS_TILT_Y, 10 },
1968 		{ -1, -1 }
1969 	};
1970 	double tx, ty;
1971 
1972 	status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
1973 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
1974 
1975 	litest_drain_events(li);
1976 
1977 	litest_tablet_proximity_in(dev, 10, 10, axes);
1978 	libinput_dispatch(li);
1979 	event = libinput_get_event(li);
1980 	tev = litest_is_tablet_event(event,
1981 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
1982 	tx = libinput_event_tablet_tool_get_tilt_x(tev);
1983 	ty = libinput_event_tablet_tool_get_tilt_y(tev);
1984 
1985 	ck_assert_double_lt(tx, 0);
1986 	ck_assert_double_gt(ty, 0);
1987 
1988 	libinput_event_destroy(event);
1989 #endif
1990 }
1991 END_TEST
1992 
1993 static inline double
rotate_event(struct litest_device * dev,int angle_degrees)1994 rotate_event(struct litest_device *dev, int angle_degrees)
1995 {
1996 	struct libinput *li = dev->libinput;
1997 	struct libinput_event *event;
1998 	struct libinput_event_tablet_tool *tev;
1999 	const struct input_absinfo *abs;
2000 	double a = (angle_degrees - 90 - 175)/180.0 * M_PI;
2001 	double val;
2002 	int x, y;
2003 	int tilt_center_x, tilt_center_y;
2004 
2005 	abs = libevdev_get_abs_info(dev->evdev, ABS_TILT_X);
2006 	ck_assert_notnull(abs);
2007 	tilt_center_x = absinfo_range(abs) / 2;
2008 
2009 	abs = libevdev_get_abs_info(dev->evdev, ABS_TILT_Y);
2010 	ck_assert_notnull(abs);
2011 	tilt_center_y = absinfo_range(abs) / 2;
2012 
2013 	x = cos(a) * 20 + tilt_center_x;
2014 	y = sin(a) * 20 + tilt_center_y;
2015 
2016 	litest_event(dev, EV_ABS, ABS_TILT_X, x);
2017 	litest_event(dev, EV_ABS, ABS_TILT_Y, y);
2018 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2019 	libinput_dispatch(li);
2020 
2021 	event = libinput_get_event(li);
2022 	tev = litest_is_tablet_event(event,
2023 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2024 	ck_assert(libinput_event_tablet_tool_rotation_has_changed(tev));
2025 	val = libinput_event_tablet_tool_get_rotation(tev);
2026 
2027 	libinput_event_destroy(event);
2028 	litest_assert_empty_queue(li);
2029 
2030 	return val;
2031 }
2032 
START_TEST(left_handed_mouse_rotation)2033 START_TEST(left_handed_mouse_rotation)
2034 {
2035 #if HAVE_LIBWACOM
2036 	struct litest_device *dev = litest_current_device();
2037 	struct libinput *li = dev->libinput;
2038 	enum libinput_config_status status;
2039 	int angle;
2040 	double val, old_val = 0;
2041 	struct axis_replacement axes[] = {
2042 		{ ABS_DISTANCE, 10 },
2043 		{ ABS_PRESSURE, 0 },
2044 		{ ABS_TILT_X, 0 },
2045 		{ ABS_TILT_Y, 0 },
2046 		{ -1, -1 }
2047 	};
2048 
2049 	status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
2050 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
2051 
2052 	litest_drain_events(li);
2053 
2054 	litest_push_event_frame(dev);
2055 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
2056 	litest_tablet_proximity_in(dev, 10, 10, axes);
2057 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
2058 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
2059 	litest_pop_event_frame(dev);
2060 
2061 	litest_drain_events(li);
2062 
2063 	/* cos/sin are 90 degrees offset from the north-is-zero that
2064 	   libinput uses. 175 is the CCW offset in the mouse HW */
2065 	for (angle = 185; angle < 540; angle += 5) {
2066 		int expected_angle = angle - 180;
2067 
2068 		val = rotate_event(dev, angle % 360);
2069 
2070 		/* rounding error galore, we can't test for anything more
2071 		   precise than these */
2072 		litest_assert_double_lt(val, 360.0);
2073 		litest_assert_double_gt(val, old_val);
2074 		litest_assert_double_lt(val, expected_angle + 5);
2075 
2076 		old_val = val;
2077 	}
2078 #endif
2079 }
2080 END_TEST
2081 
START_TEST(left_handed_artpen_rotation)2082 START_TEST(left_handed_artpen_rotation)
2083 {
2084 #if HAVE_LIBWACOM
2085 	struct litest_device *dev = litest_current_device();
2086 	struct libinput *li = dev->libinput;
2087 	struct libinput_event *event;
2088 	struct libinput_event_tablet_tool *tev;
2089 	const struct input_absinfo *abs;
2090 	enum libinput_config_status status;
2091 	double val;
2092 	double scale;
2093 	int angle;
2094 
2095 	if (!libevdev_has_event_code(dev->evdev,
2096 				    EV_ABS,
2097 				    ABS_Z))
2098 		return;
2099 
2100 	status = libinput_device_config_left_handed_set(dev->libinput_device, 1);
2101 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
2102 
2103 	litest_drain_events(li);
2104 
2105 	abs = libevdev_get_abs_info(dev->evdev, ABS_Z);
2106 	ck_assert_notnull(abs);
2107 	scale = absinfo_range(abs)/360.0;
2108 
2109 	litest_event(dev, EV_KEY, BTN_TOOL_BRUSH, 1);
2110 	litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
2111 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
2112 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2113 
2114 	litest_event(dev, EV_ABS, ABS_Z, abs->minimum);
2115 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2116 
2117 	litest_drain_events(li);
2118 
2119 	for (angle = 188; angle < 540; angle += 8) {
2120 		int a = angle * scale + abs->minimum;
2121 		int expected_angle = angle - 180;
2122 
2123 		litest_event(dev, EV_ABS, ABS_Z, a);
2124 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
2125 		libinput_dispatch(li);
2126 		event = libinput_get_event(li);
2127 		tev = litest_is_tablet_event(event,
2128 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2129 		ck_assert(libinput_event_tablet_tool_rotation_has_changed(tev));
2130 		val = libinput_event_tablet_tool_get_rotation(tev);
2131 
2132 		/* artpen has a 90 deg offset cw */
2133 		ck_assert_int_eq(round(val), (expected_angle + 90) % 360);
2134 
2135 		libinput_event_destroy(event);
2136 		litest_assert_empty_queue(li);
2137 
2138 	}
2139 #endif
2140 }
2141 END_TEST
2142 
START_TEST(motion_event_state)2143 START_TEST(motion_event_state)
2144 {
2145 	struct litest_device *dev = litest_current_device();
2146 	struct libinput *li = dev->libinput;
2147 	struct libinput_event *event;
2148 	struct libinput_event_tablet_tool *tablet_event;
2149 	int test_x, test_y;
2150 	double last_x, last_y;
2151 	struct axis_replacement axes[] = {
2152 		{ ABS_DISTANCE, 10 },
2153 		{ ABS_PRESSURE, 0 },
2154 		{ -1, -1 }
2155 	};
2156 	unsigned int button = pick_stylus_or_btn0(dev);
2157 
2158 	litest_drain_events(li);
2159 	litest_tablet_proximity_in(dev, 5, 100, axes);
2160 	litest_drain_events(li);
2161 
2162 	/* couple of events that go left/bottom to right/top */
2163 	for (test_x = 0, test_y = 100; test_x < 100; test_x += 10, test_y -= 10)
2164 		litest_tablet_motion(dev, test_x, test_y, axes);
2165 
2166 	libinput_dispatch(li);
2167 
2168 	event = libinput_get_event(li);
2169 	tablet_event = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2170 
2171 	last_x = libinput_event_tablet_tool_get_x(tablet_event);
2172 	last_y = libinput_event_tablet_tool_get_y(tablet_event);
2173 
2174 	/* mark with a button event, then go back to bottom/left */
2175 	litest_button_click(dev, button, true);
2176 
2177 	for (test_x = 100, test_y = 0; test_x > 0; test_x -= 10, test_y += 10)
2178 		litest_tablet_motion(dev, test_x, test_y, axes);
2179 
2180 	libinput_event_destroy(event);
2181 	libinput_dispatch(li);
2182 	ck_assert_int_eq(libinput_next_event_type(li),
2183 			 LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2184 
2185 	/* we expect all events up to the button event to go from
2186 	   bottom/left to top/right */
2187 	while ((event = libinput_get_event(li))) {
2188 		double x, y;
2189 
2190 		if (libinput_event_get_type(event) != LIBINPUT_EVENT_TABLET_TOOL_AXIS)
2191 			break;
2192 
2193 		tablet_event = libinput_event_get_tablet_tool_event(event);
2194 		ck_assert_notnull(tablet_event);
2195 
2196 		x = libinput_event_tablet_tool_get_x(tablet_event);
2197 		y = libinput_event_tablet_tool_get_y(tablet_event);
2198 
2199 		ck_assert(x > last_x);
2200 		ck_assert(y < last_y);
2201 
2202 		last_x = x;
2203 		last_y = y;
2204 		libinput_event_destroy(event);
2205 	}
2206 
2207 	ck_assert_int_eq(libinput_event_get_type(event),
2208 			 LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
2209 	libinput_event_destroy(event);
2210 }
2211 END_TEST
2212 
START_TEST(motion_outside_bounds)2213 START_TEST(motion_outside_bounds)
2214 {
2215 	struct litest_device *dev = litest_current_device();
2216 	struct libinput *li = dev->libinput;
2217 	struct libinput_event *event;
2218 	struct libinput_event_tablet_tool *tablet_event;
2219 	double val;
2220 	int i;
2221 
2222 	struct axis_replacement axes[] = {
2223 		{ ABS_DISTANCE, 10 },
2224 		{ ABS_PRESSURE, 0 },
2225 		{ -1, -1 }
2226 	};
2227 
2228 	litest_tablet_proximity_in(dev, 50, 50, axes);
2229 	litest_drain_events(li);
2230 
2231 	/* Work around smoothing */
2232 	for (i = 5; i > 0; i--) {
2233 		litest_event(dev, EV_ABS, ABS_X, 0 + 5 * i);
2234 		litest_event(dev, EV_ABS, ABS_Y, 1000);
2235 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
2236 		libinput_dispatch(li);
2237 	}
2238 	litest_drain_events(li);
2239 
2240 	/* On the 24HD x/y of 0 is outside the limit */
2241 	litest_event(dev, EV_ABS, ABS_X, 0);
2242 	litest_event(dev, EV_ABS, ABS_Y, 1000);
2243 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2244 	libinput_dispatch(li);
2245 
2246 	event = libinput_get_event(li);
2247 	tablet_event = litest_is_tablet_event(event,
2248 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2249 	val = libinput_event_tablet_tool_get_x(tablet_event);
2250 	ck_assert_double_lt(val, 0.0);
2251 	val = libinput_event_tablet_tool_get_y(tablet_event);
2252 	ck_assert_double_gt(val, 0.0);
2253 
2254 	val = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
2255 	ck_assert_double_lt(val, 0.0);
2256 
2257 	libinput_event_destroy(event);
2258 
2259 	/* Work around smoothing */
2260 	for (i = 5; i > 0; i--) {
2261 		litest_event(dev, EV_ABS, ABS_X, 1000);
2262 		litest_event(dev, EV_ABS, ABS_Y, 0 + 5 * i);
2263 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
2264 		libinput_dispatch(li);
2265 	}
2266 	litest_drain_events(li);
2267 
2268 	/* On the 24HD x/y of 0 is outside the limit */
2269 	litest_event(dev, EV_ABS, ABS_X, 1000);
2270 	litest_event(dev, EV_ABS, ABS_Y, 0);
2271 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2272 	libinput_dispatch(li);
2273 
2274 	event = libinput_get_event(li);
2275 	tablet_event = litest_is_tablet_event(event,
2276 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2277 	val = libinput_event_tablet_tool_get_x(tablet_event);
2278 	ck_assert_double_gt(val, 0.0);
2279 	val = libinput_event_tablet_tool_get_y(tablet_event);
2280 	ck_assert_double_lt(val, 0.0);
2281 
2282 	val = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
2283 	ck_assert_double_lt(val, 0.0);
2284 
2285 	libinput_event_destroy(event);
2286 }
2287 END_TEST
2288 
START_TEST(bad_distance_events)2289 START_TEST(bad_distance_events)
2290 {
2291 	struct litest_device *dev = litest_current_device();
2292 	struct libinput *li = dev->libinput;
2293 	const struct input_absinfo *absinfo;
2294 	struct axis_replacement axes[] = {
2295 		{ -1, -1 },
2296 	};
2297 
2298 	litest_tablet_proximity_in(dev, 10, 10, axes);
2299 	litest_tablet_proximity_out(dev);
2300 	litest_drain_events(li);
2301 
2302 	absinfo = libevdev_get_abs_info(dev->evdev, ABS_DISTANCE);
2303 	ck_assert_notnull(absinfo);
2304 
2305 	litest_event(dev, EV_ABS, ABS_DISTANCE, absinfo->maximum);
2306 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2307 	litest_event(dev, EV_ABS, ABS_DISTANCE, absinfo->minimum);
2308 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2309 
2310 	litest_assert_empty_queue(li);
2311 }
2312 END_TEST
2313 
START_TEST(tool_unique)2314 START_TEST(tool_unique)
2315 {
2316 	struct litest_device *dev = litest_current_device();
2317 	struct libinput *li = dev->libinput;
2318 	struct libinput_event_tablet_tool *tablet_event;
2319 	struct libinput_event *event;
2320 	struct libinput_tablet_tool *tool;
2321 
2322 	litest_drain_events(li);
2323 
2324 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2325 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
2326 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2327 
2328 	libinput_dispatch(li);
2329 	event = libinput_get_event(li);
2330 	tablet_event = litest_is_tablet_event(event,
2331 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2332 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
2333 	ck_assert(libinput_tablet_tool_is_unique(tool));
2334 	libinput_event_destroy(event);
2335 }
2336 END_TEST
2337 
START_TEST(tool_serial)2338 START_TEST(tool_serial)
2339 {
2340 	struct litest_device *dev = litest_current_device();
2341 	struct libinput *li = dev->libinput;
2342 	struct libinput_event_tablet_tool *tablet_event;
2343 	struct libinput_event *event;
2344 	struct libinput_tablet_tool *tool;
2345 
2346 	litest_drain_events(li);
2347 
2348 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2349 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
2350 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2351 	libinput_dispatch(li);
2352 
2353 	event = libinput_get_event(li);
2354 	tablet_event = litest_is_tablet_event(event,
2355 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2356 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
2357 	ck_assert_uint_eq(libinput_tablet_tool_get_serial(tool), 1000);
2358 	libinput_event_destroy(event);
2359 }
2360 END_TEST
2361 
START_TEST(tool_id)2362 START_TEST(tool_id)
2363 {
2364 	struct litest_device *dev = litest_current_device();
2365 	struct libinput *li = dev->libinput;
2366 	struct libinput_event_tablet_tool *tablet_event;
2367 	struct libinput_event *event;
2368 	struct libinput_tablet_tool *tool;
2369 	uint64_t tool_id;
2370 
2371 	litest_drain_events(li);
2372 
2373 	litest_tablet_proximity_in(dev, 10, 10, NULL);
2374 	libinput_dispatch(li);
2375 
2376 	event = libinput_get_event(li);
2377 	tablet_event = litest_is_tablet_event(event,
2378 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2379 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
2380 
2381 	ck_assert_int_eq(libinput_device_get_id_vendor(dev->libinput_device),
2382 			 VENDOR_ID_WACOM);
2383 
2384 	switch (libinput_device_get_id_product(dev->libinput_device)) {
2385 	case 0x27: /* Intuos 5 */
2386 		tool_id = 1050626;
2387 		break;
2388 	case 0xc6: /* Cintiq 12WX */
2389 	case 0xf4: /* Cintiq 24HD */
2390 	case 0x333: /* Cintiq 13HD */
2391 	case 0x350: /* Cintiq Pro 16 */
2392 		tool_id = 2083;
2393 		break;
2394 	default:
2395 		ck_abort();
2396 	}
2397 
2398 	ck_assert(tool_id == libinput_tablet_tool_get_tool_id(tool));
2399 	libinput_event_destroy(event);
2400 }
2401 END_TEST
2402 
START_TEST(serial_changes_tool)2403 START_TEST(serial_changes_tool)
2404 {
2405 	struct litest_device *dev = litest_current_device();
2406 	struct libinput *li = dev->libinput;
2407 	struct libinput_event_tablet_tool *tablet_event;
2408 	struct libinput_event *event;
2409 	struct libinput_tablet_tool *tool;
2410 
2411 	litest_drain_events(li);
2412 
2413 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2414 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
2415 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2416 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
2417 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2418 	litest_drain_events(li);
2419 
2420 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2421 	litest_event(dev, EV_MSC, MSC_SERIAL, 2000);
2422 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2423 	libinput_dispatch(li);
2424 
2425 	event = libinput_get_event(li);
2426 	tablet_event = litest_is_tablet_event(event,
2427 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2428 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
2429 
2430 	ck_assert_uint_eq(libinput_tablet_tool_get_serial(tool), 2000);
2431 	libinput_event_destroy(event);
2432 }
2433 END_TEST
2434 
START_TEST(invalid_serials)2435 START_TEST(invalid_serials)
2436 {
2437 	struct litest_device *dev = litest_current_device();
2438 	struct libinput *li = dev->libinput;
2439 	struct libinput_event *event;
2440 	struct libinput_event_tablet_tool *tablet_event;
2441 	struct libinput_tablet_tool *tool;
2442 
2443 	litest_drain_events(li);
2444 
2445 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2446 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
2447 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2448 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
2449 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2450 	litest_drain_events(li);
2451 
2452 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2453 	litest_event(dev, EV_MSC, MSC_SERIAL, -1);
2454 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2455 
2456 	libinput_dispatch(li);
2457 	while ((event = libinput_get_event(li))) {
2458 		if (libinput_event_get_type(event) ==
2459 		    LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY) {
2460 			tablet_event = libinput_event_get_tablet_tool_event(event);
2461 			tool = libinput_event_tablet_tool_get_tool(tablet_event);
2462 
2463 			ck_assert_uint_eq(libinput_tablet_tool_get_serial(tool), 1000);
2464 		}
2465 
2466 		libinput_event_destroy(event);
2467 	}
2468 }
2469 END_TEST
2470 
START_TEST(tool_ref)2471 START_TEST(tool_ref)
2472 {
2473 	struct litest_device *dev = litest_current_device();
2474 	struct libinput *li = dev->libinput;
2475 	struct libinput_event_tablet_tool *tablet_event;
2476 	struct libinput_event *event;
2477 	struct libinput_tablet_tool *tool;
2478 
2479 	litest_drain_events(li);
2480 
2481 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2482 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
2483 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2484 	libinput_dispatch(li);
2485 
2486 	event = libinput_get_event(li);
2487 	tablet_event = litest_is_tablet_event(event,
2488 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2489 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
2490 
2491 	ck_assert_notnull(tool);
2492 	ck_assert(tool == libinput_tablet_tool_ref(tool));
2493 	ck_assert(tool == libinput_tablet_tool_unref(tool));
2494 	libinput_event_destroy(event);
2495 
2496 	ck_assert(libinput_tablet_tool_unref(tool) == NULL);
2497 }
2498 END_TEST
2499 
START_TEST(tool_user_data)2500 START_TEST(tool_user_data)
2501 {
2502 	struct litest_device *dev = litest_current_device();
2503 	struct libinput *li = dev->libinput;
2504 	struct libinput_event_tablet_tool *tablet_event;
2505 	struct libinput_event *event;
2506 	struct libinput_tablet_tool *tool;
2507 	void *userdata = &dev; /* not dereferenced */
2508 
2509 	litest_drain_events(li);
2510 
2511 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2512 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
2513 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2514 	libinput_dispatch(li);
2515 
2516 	event = libinput_get_event(li);
2517 	tablet_event = litest_is_tablet_event(event,
2518 				LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2519 	tool = libinput_event_tablet_tool_get_tool(tablet_event);
2520 	ck_assert_notnull(tool);
2521 
2522 	ck_assert(libinput_tablet_tool_get_user_data(tool) == NULL);
2523 	libinput_tablet_tool_set_user_data(tool, userdata);
2524 	ck_assert(libinput_tablet_tool_get_user_data(tool) == userdata);
2525 	libinput_tablet_tool_set_user_data(tool, NULL);
2526 	ck_assert(libinput_tablet_tool_get_user_data(tool) == NULL);
2527 
2528 	libinput_event_destroy(event);
2529 }
2530 END_TEST
2531 
START_TEST(pad_buttons_ignored)2532 START_TEST(pad_buttons_ignored)
2533 {
2534 	struct litest_device *dev = litest_current_device();
2535 	struct libinput *li = dev->libinput;
2536 	struct axis_replacement axes[] = {
2537 		{ ABS_DISTANCE, 10 },
2538 		{ ABS_PRESSURE, 0 },
2539 		{ -1, -1 }
2540 	};
2541 	int button;
2542 
2543 	litest_drain_events(li);
2544 
2545 	for (button = BTN_0; button < BTN_MOUSE; button++) {
2546 		litest_event(dev, EV_KEY, button, 1);
2547 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
2548 		litest_event(dev, EV_KEY, button, 0);
2549 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
2550 		libinput_dispatch(li);
2551 	}
2552 
2553 	litest_assert_empty_queue(li);
2554 
2555 	/* same thing while in prox */
2556 	litest_tablet_proximity_in(dev, 10, 10, axes);
2557 	litest_drain_events(li);
2558 
2559 	for (button = BTN_0; button < BTN_MOUSE; button++)
2560 		litest_event(dev, EV_KEY, button, 1);
2561 
2562 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2563 	libinput_dispatch(li);
2564 
2565 	for (button = BTN_0; button < BTN_MOUSE; button++)
2566 		litest_event(dev, EV_KEY, button, 0);
2567 
2568 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2569 	libinput_dispatch(li);
2570 
2571 	litest_assert_empty_queue(li);
2572 }
2573 END_TEST
2574 
START_TEST(tools_with_serials)2575 START_TEST(tools_with_serials)
2576 {
2577 	struct libinput *li = litest_create_context();
2578 	struct litest_device *dev[2];
2579 	struct libinput_tablet_tool *tool[2] = {0};
2580 	struct libinput_event *event;
2581 	struct libinput_event_tablet_tool *tev;
2582 	int i;
2583 
2584 	for (i = 0; i < 2; i++) {
2585 		dev[i] = litest_add_device(li, LITEST_WACOM_INTUOS);
2586 		litest_drain_events(li);
2587 
2588 		/* WARNING: this test fails if UI_GET_SYSNAME isn't
2589 		 * available or isn't used by libevdev (1.3, commit 2ff45c73).
2590 		 * Put a sleep(1) here and that usually fixes it.
2591 		 */
2592 
2593 		litest_push_event_frame(dev[i]);
2594 		litest_tablet_proximity_in(dev[i], 10, 10, NULL);
2595 		litest_event(dev[i], EV_MSC, MSC_SERIAL, 100);
2596 		litest_pop_event_frame(dev[i]);
2597 
2598 		libinput_dispatch(li);
2599 		event = libinput_get_event(li);
2600 		tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2601 		tool[i] = libinput_event_tablet_tool_get_tool(tev);
2602 		libinput_event_destroy(event);
2603 	}
2604 
2605 	/* We should get the same object for both devices */
2606 	ck_assert_notnull(tool[0]);
2607 	ck_assert_notnull(tool[1]);
2608 	ck_assert_ptr_eq(tool[0], tool[1]);
2609 
2610 	litest_delete_device(dev[0]);
2611 	litest_delete_device(dev[1]);
2612 	litest_destroy_context(li);
2613 }
2614 END_TEST
2615 
START_TEST(tools_without_serials)2616 START_TEST(tools_without_serials)
2617 {
2618 	struct libinput *li = litest_create_context();
2619 	struct litest_device *dev[2];
2620 	struct libinput_tablet_tool *tool[2] = {0};
2621 	struct libinput_event *event;
2622 	struct libinput_event_tablet_tool *tev;
2623 	int i;
2624 
2625 	for (i = 0; i < 2; i++) {
2626 		dev[i] = litest_add_device_with_overrides(li,
2627 							  LITEST_WACOM_ISDV4,
2628 							  NULL,
2629 							  NULL,
2630 							  NULL,
2631 							  NULL);
2632 
2633 		litest_drain_events(li);
2634 
2635 		/* WARNING: this test fails if UI_GET_SYSNAME isn't
2636 		 * available or isn't used by libevdev (1.3, commit 2ff45c73).
2637 		 * Put a sleep(1) here and that usually fixes it.
2638 		 */
2639 
2640 		litest_tablet_proximity_in(dev[i], 10, 10, NULL);
2641 
2642 		libinput_dispatch(li);
2643 		event = libinput_get_event(li);
2644 		tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2645 		tool[i] = libinput_event_tablet_tool_get_tool(tev);
2646 		libinput_event_destroy(event);
2647 	}
2648 
2649 	/* We should get different tool objects for each device */
2650 	ck_assert_notnull(tool[0]);
2651 	ck_assert_notnull(tool[1]);
2652 	ck_assert_ptr_ne(tool[0], tool[1]);
2653 
2654 	litest_delete_device(dev[0]);
2655 	litest_delete_device(dev[1]);
2656 	litest_destroy_context(li);
2657 }
2658 END_TEST
2659 
START_TEST(tool_delayed_serial)2660 START_TEST(tool_delayed_serial)
2661 {
2662 	struct litest_device *dev = litest_current_device();
2663 	struct libinput *li = dev->libinput;
2664 	struct libinput_event *event;
2665 	struct libinput_event_tablet_tool *tev;
2666 	struct libinput_tablet_tool *tool;
2667 	unsigned int serial;
2668 
2669 	litest_drain_events(li);
2670 
2671 	litest_event(dev, EV_ABS, ABS_X, 4500);
2672 	litest_event(dev, EV_ABS, ABS_Y, 2000);
2673 	litest_event(dev, EV_MSC, MSC_SERIAL, 0);
2674 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
2675 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2676 	libinput_dispatch(li);
2677 
2678 	event = libinput_get_event(li);
2679 	tev = litest_is_tablet_event(event,
2680 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2681 	tool = libinput_event_tablet_tool_get_tool(tev);
2682 	serial = libinput_tablet_tool_get_serial(tool);
2683 	ck_assert_int_eq(serial, 0);
2684 	libinput_event_destroy(event);
2685 
2686 	for (int x = 4500; x < 8000; x += 1000) {
2687 		litest_event(dev, EV_ABS, ABS_X, x);
2688 		litest_event(dev, EV_ABS, ABS_Y, 2000);
2689 		litest_event(dev, EV_MSC, MSC_SERIAL, 0);
2690 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
2691 		libinput_dispatch(li);
2692 	}
2693 	litest_drain_events(li);
2694 
2695 	/* Now send the serial */
2696 	litest_event(dev, EV_ABS, ABS_X, 4500);
2697 	litest_event(dev, EV_ABS, ABS_Y, 2000);
2698 	litest_event(dev, EV_MSC, MSC_SERIAL, 1234566);
2699 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2700 	libinput_dispatch(li);
2701 
2702 	event = libinput_get_event(li);
2703 	tev = litest_is_tablet_event(event,
2704 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2705 	tool = libinput_event_tablet_tool_get_tool(tev);
2706 	serial = libinput_tablet_tool_get_serial(tool);
2707 	ck_assert_int_eq(serial, 0);
2708 	libinput_event_destroy(event);
2709 
2710 	for (int x = 4500; x < 8000; x += 500) {
2711 		litest_event(dev, EV_ABS, ABS_X, x);
2712 		litest_event(dev, EV_ABS, ABS_Y, 2000);
2713 		litest_event(dev, EV_MSC, MSC_SERIAL, 1234566);
2714 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
2715 		libinput_dispatch(li);
2716 	}
2717 
2718 	event = libinput_get_event(li);
2719 	do {
2720 		tev = litest_is_tablet_event(event,
2721 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2722 		tool = libinput_event_tablet_tool_get_tool(tev);
2723 		serial = libinput_tablet_tool_get_serial(tool);
2724 		ck_assert_int_eq(serial, 0);
2725 		libinput_event_destroy(event);
2726 		event = libinput_get_event(li);
2727 	} while (event != NULL);
2728 
2729 	/* Quirk: tool out event is a serial of 0 */
2730 	litest_event(dev, EV_ABS, ABS_X, 4500);
2731 	litest_event(dev, EV_ABS, ABS_Y, 2000);
2732 	litest_event(dev, EV_MSC, MSC_SERIAL, 0);
2733 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
2734 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2735 	libinput_dispatch(li);
2736 
2737 	event = libinput_get_event(li);
2738 	tev = litest_is_tablet_event(event,
2739 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2740 	tool = libinput_event_tablet_tool_get_tool(tev);
2741 	serial = libinput_tablet_tool_get_serial(tool);
2742 	ck_assert_int_eq(serial, 0);
2743 	libinput_event_destroy(event);
2744 }
2745 END_TEST
2746 
START_TEST(tool_capability)2747 START_TEST(tool_capability)
2748 {
2749 	struct litest_device *dev = litest_current_device();
2750 	struct libinput_device *device = dev->libinput_device;
2751 
2752 	ck_assert(libinput_device_has_capability(device,
2753 						 LIBINPUT_DEVICE_CAP_TABLET_TOOL));
2754 }
2755 END_TEST
2756 
START_TEST(tool_capabilities)2757 START_TEST(tool_capabilities)
2758 {
2759 	struct libinput *li = litest_create_context();
2760 	struct litest_device *intuos;
2761 	struct litest_device *bamboo;
2762 	struct libinput_event *event;
2763 	struct libinput_event_tablet_tool *t;
2764 	struct libinput_tablet_tool *tool;
2765 
2766 	/* The axis capabilities of a tool can differ depending on the type of
2767 	 * tablet the tool is being used with */
2768 	bamboo = litest_add_device(li, LITEST_WACOM_BAMBOO);
2769 	intuos = litest_add_device(li, LITEST_WACOM_INTUOS);
2770 	litest_drain_events(li);
2771 
2772 	litest_event(bamboo, EV_KEY, BTN_TOOL_PEN, 1);
2773 	litest_event(bamboo, EV_SYN, SYN_REPORT, 0);
2774 
2775 	libinput_dispatch(li);
2776 
2777 	event = libinput_get_event(li);
2778 	t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2779 	tool = libinput_event_tablet_tool_get_tool(t);
2780 
2781 	ck_assert(libinput_tablet_tool_has_pressure(tool));
2782 	ck_assert(libinput_tablet_tool_has_distance(tool));
2783 	ck_assert(!libinput_tablet_tool_has_tilt(tool));
2784 
2785 	libinput_event_destroy(event);
2786 	litest_assert_empty_queue(li);
2787 
2788 	litest_event(intuos, EV_KEY, BTN_TOOL_PEN, 1);
2789 	litest_event(intuos, EV_SYN, SYN_REPORT, 0);
2790 	libinput_dispatch(li);
2791 
2792 	event = libinput_get_event(li);
2793 	t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2794 	tool = libinput_event_tablet_tool_get_tool(t);
2795 
2796 	ck_assert(libinput_tablet_tool_has_pressure(tool));
2797 	ck_assert(libinput_tablet_tool_has_distance(tool));
2798 	ck_assert(libinput_tablet_tool_has_tilt(tool));
2799 
2800 	libinput_event_destroy(event);
2801 	litest_assert_empty_queue(li);
2802 
2803 	litest_delete_device(bamboo);
2804 	litest_delete_device(intuos);
2805 	litest_destroy_context(li);
2806 }
2807 END_TEST
2808 
2809 static inline bool
tablet_has_mouse(struct litest_device * dev)2810 tablet_has_mouse(struct litest_device *dev)
2811 {
2812 	return libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_MOUSE) &&
2813 	       libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM;
2814 }
2815 
START_TEST(tool_type)2816 START_TEST(tool_type)
2817 {
2818 	struct litest_device *dev = litest_current_device();
2819 	struct libinput *li = dev->libinput;
2820 	struct libinput_event *event;
2821 	struct libinput_event_tablet_tool *t;
2822 	struct libinput_tablet_tool *tool;
2823 	struct axis_replacement axes[] = {
2824 		{ ABS_DISTANCE, 10 },
2825 		{ ABS_PRESSURE, 0 },
2826 		{ ABS_TILT_X, 0 },
2827 		{ ABS_TILT_Y, 0 },
2828 		{ -1, -1 }
2829 	};
2830 	struct tool_type_match {
2831 		int code;
2832 		enum libinput_tablet_tool_type type;
2833 	} types[] = {
2834 		{ BTN_TOOL_PEN, LIBINPUT_TABLET_TOOL_TYPE_PEN },
2835 		{ BTN_TOOL_RUBBER, LIBINPUT_TABLET_TOOL_TYPE_ERASER },
2836 		{ BTN_TOOL_BRUSH, LIBINPUT_TABLET_TOOL_TYPE_BRUSH },
2837 		{ BTN_TOOL_PENCIL, LIBINPUT_TABLET_TOOL_TYPE_PENCIL },
2838 		{ BTN_TOOL_AIRBRUSH, LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH },
2839 		{ BTN_TOOL_MOUSE, LIBINPUT_TABLET_TOOL_TYPE_MOUSE },
2840 		{ BTN_TOOL_LENS, LIBINPUT_TABLET_TOOL_TYPE_LENS },
2841 		{ -1, -1 }
2842 	};
2843 	struct tool_type_match *tt;
2844 	double x = 50, y = 50;
2845 
2846 	litest_drain_events(li);
2847 
2848 	for (tt = types; tt->code != -1; tt++) {
2849 		enum libinput_tablet_tool_type type;
2850 
2851 		if (!libevdev_has_event_code(dev->evdev,
2852 					     EV_KEY,
2853 					     tt->code))
2854 			continue;
2855 
2856 		if ((tt->code == BTN_TOOL_MOUSE || tt->code == BTN_TOOL_LENS) &&
2857 		    !tablet_has_mouse(dev))
2858 			continue;
2859 
2860 		litest_tablet_set_tool_type(dev, tt->code);
2861 		litest_tablet_proximity_in(dev, x, y, axes);
2862 		libinput_dispatch(li);
2863 
2864 		event = libinput_get_event(li);
2865 		t = litest_is_tablet_event(event,
2866 				   LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2867 		tool = libinput_event_tablet_tool_get_tool(t);
2868 		type = libinput_tablet_tool_get_type(tool);
2869 
2870 		/* Devices with doubled-up tool bits send the pen
2871 		 * in-prox and immediately out-of-prox before the real tool
2872 		 * type. Drop those two and continue with what we expect is
2873 		 * the real prox in event */
2874 		if (tt->type != LIBINPUT_TABLET_TOOL_TYPE_PEN &&
2875 		    type == LIBINPUT_TABLET_TOOL_TYPE_PEN) {
2876 			libinput_event_destroy(event);
2877 			event = libinput_get_event(li);
2878 			litest_is_tablet_event(event,
2879 					       LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2880 			libinput_event_destroy(event);
2881 			event = libinput_get_event(li);
2882 			t = litest_is_tablet_event(event,
2883 					   LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2884 			tool = libinput_event_tablet_tool_get_tool(t);
2885 			type = libinput_tablet_tool_get_type(tool);
2886 		}
2887 
2888 		ck_assert_int_eq(type, tt->type);
2889 
2890 		libinput_event_destroy(event);
2891 		litest_assert_empty_queue(li);
2892 
2893 		litest_tablet_proximity_out(dev);
2894 		litest_drain_events(li);
2895 
2896 		x++;
2897 		y++;
2898 	}
2899 }
2900 END_TEST
2901 
START_TEST(tool_in_prox_before_start)2902 START_TEST(tool_in_prox_before_start)
2903 {
2904 	struct libinput *li;
2905 	struct litest_device *dev = litest_current_device();
2906 	struct libinput_event *event;
2907 	struct libinput_event_tablet_tool *tev;
2908 	struct libinput_tablet_tool *tool;
2909 	struct axis_replacement axes[] = {
2910 		{ ABS_DISTANCE, 10 },
2911 		{ ABS_PRESSURE, 0 },
2912 		{ ABS_TILT_X, 0 },
2913 		{ ABS_TILT_Y, 0 },
2914 		{ -1, -1 }
2915 	};
2916 	const char *devnode;
2917 	unsigned int serial;
2918 
2919 	litest_tablet_proximity_in(dev, 10, 10, axes);
2920 
2921 	/* for simplicity, we create a new litest context */
2922 	devnode = libevdev_uinput_get_devnode(dev->uinput);
2923 	li = litest_create_context();
2924 	libinput_path_add_device(li, devnode);
2925 
2926 	litest_drain_events_of_type(li, LIBINPUT_EVENT_DEVICE_ADDED, -1);
2927 
2928 	litest_assert_empty_queue(li);
2929 
2930 	litest_tablet_motion(dev, 10, 20, axes);
2931 	libinput_dispatch(li);
2932 	event = libinput_get_event(li);
2933 	tev = litest_is_tablet_event(event,
2934 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2935 	tool = libinput_event_tablet_tool_get_tool(tev);
2936 	serial = libinput_tablet_tool_get_serial(tool);
2937 	libinput_event_destroy(event);
2938 
2939 	litest_drain_events_of_type(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, -1);
2940 
2941 	litest_tablet_motion(dev, 30, 40, axes);
2942 	libinput_dispatch(li);
2943 	event = libinput_get_event(li);
2944 	tev = litest_is_tablet_event(event,
2945 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
2946 	tool = libinput_event_tablet_tool_get_tool(tev);
2947 	ck_assert_int_eq(serial,
2948 			 libinput_tablet_tool_get_serial(tool));
2949 	libinput_event_destroy(event);
2950 
2951 	litest_assert_empty_queue(li);
2952 	litest_button_click(dev, BTN_STYLUS, true);
2953 	litest_button_click(dev, BTN_STYLUS, false);
2954 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
2955 	litest_tablet_proximity_out(dev);
2956 	libinput_dispatch(li);
2957 
2958 	litest_timeout_tablet_proxout();
2959 	libinput_dispatch(li);
2960 
2961 	event = libinput_get_event(li);
2962 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2963 	libinput_event_destroy(event);
2964 
2965 	litest_destroy_context(li);
2966 }
2967 END_TEST
2968 
START_TEST(tool_direct_switch_skip_tool_update)2969 START_TEST(tool_direct_switch_skip_tool_update)
2970 {
2971 	struct litest_device *dev = litest_current_device();
2972 	struct libinput *li = dev->libinput;
2973 	struct libinput_event *event;
2974 	struct libinput_event_tablet_tool *tev;
2975 	struct libinput_tablet_tool *tool;
2976 	struct axis_replacement axes[] = {
2977 		{ ABS_DISTANCE, 10 },
2978 		{ ABS_PRESSURE, 0 },
2979 		{ -1, -1 }
2980 	};
2981 
2982 	if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
2983 		return;
2984 
2985 	litest_drain_events(li);
2986 
2987 	litest_tablet_proximity_in(dev, 10, 10, axes);
2988 	libinput_dispatch(li);
2989 
2990 	event = libinput_get_event(li);
2991 	tev = litest_is_tablet_event(event,
2992 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
2993 	tool = libinput_event_tablet_tool_get_tool(tev);
2994 	libinput_tablet_tool_ref(tool);
2995 	libinput_event_destroy(event);
2996 
2997 	litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
2998 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
2999 	libinput_dispatch(li);
3000 
3001 	event = libinput_get_event(li);
3002 	tev = litest_is_tablet_event(event,
3003 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3004 	ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
3005 			 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
3006 	ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev), tool);
3007 	libinput_event_destroy(event);
3008 
3009 	event = libinput_get_event(li);
3010 	tev = litest_is_tablet_event(event,
3011 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3012 	ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
3013 			 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
3014 	ck_assert_ptr_ne(libinput_event_tablet_tool_get_tool(tev), tool);
3015 	libinput_tablet_tool_unref(tool);
3016 	tool = libinput_event_tablet_tool_get_tool(tev);
3017 	libinput_tablet_tool_ref(tool);
3018 	libinput_event_destroy(event);
3019 
3020 	litest_tablet_motion(dev, 20, 30, axes);
3021 	libinput_dispatch(li);
3022 
3023 	event = libinput_get_event(li);
3024 	tev = litest_is_tablet_event(event,
3025 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3026 	ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
3027 			 tool);
3028 	libinput_event_destroy(event);
3029 
3030 	litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
3031 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3032 	libinput_dispatch(li);
3033 
3034 	event = libinput_get_event(li);
3035 	tev = litest_is_tablet_event(event,
3036 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3037 	ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
3038 			 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
3039 	ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
3040 			 tool);
3041 	libinput_event_destroy(event);
3042 
3043 	litest_push_event_frame(dev);
3044 	litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
3045 	litest_tablet_motion(dev, 30, 40, axes);
3046 	litest_pop_event_frame(dev);
3047 	libinput_dispatch(li);
3048 
3049 	event = libinput_get_event(li);
3050 	tev = litest_is_tablet_event(event,
3051 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3052 	ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(tev),
3053 			 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
3054 	ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
3055 			 tool);
3056 	libinput_event_destroy(event);
3057 
3058 	litest_tablet_motion(dev, 40, 30, axes);
3059 	libinput_dispatch(li);
3060 
3061 	event = libinput_get_event(li);
3062 	tev = litest_is_tablet_event(event,
3063 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3064 	ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
3065 			 tool);
3066 	libinput_event_destroy(event);
3067 
3068 	litest_push_event_frame(dev);
3069 	litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
3070 	litest_tablet_proximity_out(dev);
3071 	litest_pop_event_frame(dev);
3072 	libinput_dispatch(li);
3073 	litest_timeout_tablet_proxout();
3074 	libinput_dispatch(li);
3075 
3076 	event = libinput_get_event(li);
3077 	tev = litest_is_tablet_event(event,
3078 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3079 	ck_assert_ptr_eq(libinput_event_tablet_tool_get_tool(tev),
3080 			 tool);
3081 	libinput_event_destroy(event);
3082 
3083 	litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 0);
3084 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3085 	litest_assert_empty_queue(li);
3086 
3087 	libinput_tablet_tool_unref(tool);
3088 }
3089 END_TEST
3090 
START_TEST(tool_direct_switch_with_forced_proxout)3091 START_TEST(tool_direct_switch_with_forced_proxout)
3092 {
3093 	struct litest_device *dev = litest_current_device();
3094 	struct libinput *li = dev->libinput;
3095 	struct libinput_event *event;
3096 	struct axis_replacement axes[] = {
3097 		{ ABS_DISTANCE, 10 },
3098 		{ ABS_PRESSURE, 0 },
3099 		{ -1, -1 }
3100 	};
3101 
3102 	if (!libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_RUBBER))
3103 		return;
3104 
3105 	litest_drain_events(li);
3106 
3107 	/* This is a *very* specific event sequence to trigger a bug:
3108 	   - pen proximity in
3109 	   - pen proximity forced out
3110 	   - eraser proximity in without axis movement
3111 	   - eraser axis move
3112 	 */
3113 
3114 	/* pen prox in */
3115 	litest_tablet_proximity_in(dev, 10, 10, axes);
3116 	libinput_dispatch(li);
3117 	event = libinput_get_event(li);
3118 	litest_is_proximity_event(event,
3119 				  LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
3120 	libinput_event_destroy(event);
3121 
3122 	/* pen motion */
3123 	litest_tablet_motion(dev, 20, 30, axes);
3124 	libinput_dispatch(li);
3125 
3126 	event = libinput_get_event(li);
3127 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3128 	libinput_event_destroy(event);
3129 
3130 	/* pen forced prox out */
3131 	litest_timeout_tablet_proxout();
3132 	libinput_dispatch(li);
3133 
3134 	/* actual prox out for tablets that don't do forced prox out */
3135 	litest_tablet_proximity_out(dev);
3136 	libinput_dispatch(li);
3137 
3138 	event = libinput_get_event(li);
3139 	litest_is_proximity_event(event,
3140 				  LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
3141 	libinput_event_destroy(event);
3142 
3143 	/* eraser prox in without axes */
3144 	litest_event(dev, EV_KEY, BTN_TOOL_RUBBER, 1);
3145 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3146 	libinput_dispatch(li);
3147 	event = libinput_get_event(li);
3148 	litest_is_proximity_event(event,
3149 				  LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
3150 	libinput_event_destroy(event);
3151 
3152 	/* eraser motion */
3153 	litest_tablet_motion(dev, 30, 40, axes);
3154 	litest_tablet_motion(dev, 40, 50, axes);
3155 	libinput_dispatch(li);
3156 
3157 	event = libinput_get_event(li);
3158 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3159 	libinput_event_destroy(event);
3160 
3161 	event = libinput_get_event(li);
3162 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3163 	libinput_event_destroy(event);
3164 
3165 	litest_assert_empty_queue(li);
3166 }
3167 END_TEST
3168 
START_TEST(mouse_tool)3169 START_TEST(mouse_tool)
3170 {
3171 	struct litest_device *dev = litest_current_device();
3172 	struct libinput *li = dev->libinput;
3173 	struct libinput_event *event;
3174 	struct libinput_event_tablet_tool *tev;
3175 	struct libinput_tablet_tool *tool;
3176 
3177 	litest_drain_events(li);
3178 
3179 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
3180 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
3181 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3182 	libinput_dispatch(li);
3183 
3184 	event = libinput_get_event(li);
3185 	tev = litest_is_tablet_event(event,
3186 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3187 	tool = libinput_event_tablet_tool_get_tool(tev);
3188 	ck_assert_notnull(tool);
3189 	ck_assert_int_eq(libinput_tablet_tool_get_type(tool),
3190 			 LIBINPUT_TABLET_TOOL_TYPE_MOUSE);
3191 
3192 	libinput_event_destroy(event);
3193 }
3194 END_TEST
3195 
START_TEST(mouse_buttons)3196 START_TEST(mouse_buttons)
3197 {
3198 	struct litest_device *dev = litest_current_device();
3199 	struct libinput *li = dev->libinput;
3200 	struct libinput_event *event;
3201 	struct libinput_event_tablet_tool *tev;
3202 	struct libinput_tablet_tool *tool;
3203 	int code;
3204 
3205 	litest_drain_events(li);
3206 
3207 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
3208 	litest_event(dev, EV_ABS, ABS_MISC, 0x806); /* 5-button mouse tool_id */
3209 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
3210 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3211 	libinput_dispatch(li);
3212 
3213 	event = libinput_get_event(li);
3214 	tev = litest_is_tablet_event(event,
3215 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3216 	tool = libinput_event_tablet_tool_get_tool(tev);
3217 	ck_assert_notnull(tool);
3218 	libinput_tablet_tool_ref(tool);
3219 
3220 	libinput_event_destroy(event);
3221 
3222 	for (code = BTN_LEFT; code <= BTN_TASK; code++) {
3223 		bool has_button = libevdev_has_event_code(dev->evdev,
3224 							  EV_KEY,
3225 							  code);
3226 		ck_assert_int_eq(!!has_button,
3227 				 !!libinput_tablet_tool_has_button(tool, code));
3228 
3229 		if (!has_button)
3230 			continue;
3231 
3232 		litest_event(dev, EV_KEY, code, 1);
3233 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
3234 		libinput_dispatch(li);
3235 		litest_event(dev, EV_KEY, code, 0);
3236 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
3237 		libinput_dispatch(li);
3238 
3239 		litest_assert_tablet_button_event(li,
3240 					  code,
3241 					  LIBINPUT_BUTTON_STATE_PRESSED);
3242 		litest_assert_tablet_button_event(li,
3243 					  code,
3244 					  LIBINPUT_BUTTON_STATE_RELEASED);
3245 	}
3246 
3247 	libinput_tablet_tool_unref(tool);
3248 }
3249 END_TEST
3250 
START_TEST(mouse_rotation)3251 START_TEST(mouse_rotation)
3252 {
3253 	struct litest_device *dev = litest_current_device();
3254 	struct libinput *li = dev->libinput;
3255 	int angle;
3256 	double val, old_val = 0;
3257 
3258 	struct axis_replacement axes[] = {
3259 		{ ABS_DISTANCE, 10 },
3260 		{ ABS_PRESSURE, 0 },
3261 		{ ABS_TILT_X, 0 },
3262 		{ ABS_TILT_Y, 0 },
3263 		{ -1, -1 }
3264 	};
3265 
3266 	litest_drain_events(li);
3267 
3268 	litest_push_event_frame(dev);
3269 	litest_filter_event(dev, EV_KEY, BTN_TOOL_PEN);
3270 	litest_tablet_proximity_in(dev, 10, 10, axes);
3271 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
3272 	litest_unfilter_event(dev, EV_KEY, BTN_TOOL_PEN);
3273 	litest_pop_event_frame(dev);
3274 
3275 	litest_drain_events(li);
3276 
3277 	/* cos/sin are 90 degrees offset from the north-is-zero that
3278 	   libinput uses. 175 is the CCW offset in the mouse HW */
3279 	for (angle = 5; angle < 360; angle += 5) {
3280 		val = rotate_event(dev, angle);
3281 
3282 		/* rounding error galore, we can't test for anything more
3283 		   precise than these */
3284 		litest_assert_double_lt(val, 360.0);
3285 		litest_assert_double_gt(val, old_val);
3286 		litest_assert_double_lt(val, angle + 5);
3287 
3288 		old_val = val;
3289 	}
3290 }
3291 END_TEST
3292 
START_TEST(mouse_wheel)3293 START_TEST(mouse_wheel)
3294 {
3295 	struct litest_device *dev = litest_current_device();
3296 	struct libinput *li = dev->libinput;
3297 	struct libinput_event *event;
3298 	struct libinput_event_tablet_tool *tev;
3299 	struct libinput_tablet_tool *tool;
3300 	const struct input_absinfo *abs;
3301 	double val;
3302 	int i;
3303 
3304 	if (!libevdev_has_event_code(dev->evdev,
3305 				     EV_REL,
3306 				     REL_WHEEL))
3307 		return;
3308 
3309 	litest_drain_events(li);
3310 
3311 	litest_event(dev, EV_KEY, BTN_TOOL_MOUSE, 1);
3312 	litest_event(dev, EV_ABS, ABS_MISC, 0x806); /* 5-button mouse tool_id */
3313 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
3314 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3315 	libinput_dispatch(li);
3316 
3317 	event = libinput_get_event(li);
3318 	tev = litest_is_tablet_event(event,
3319 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3320 	tool = libinput_event_tablet_tool_get_tool(tev);
3321 	ck_assert_notnull(tool);
3322 	libinput_tablet_tool_ref(tool);
3323 
3324 	libinput_event_destroy(event);
3325 
3326 	ck_assert(libinput_tablet_tool_has_wheel(tool));
3327 
3328 	for (i = 0; i < 3; i++) {
3329 		litest_event(dev, EV_REL, REL_WHEEL, -1);
3330 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
3331 		libinput_dispatch(li);
3332 
3333 		event = libinput_get_event(li);
3334 		tev = litest_is_tablet_event(event,
3335 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3336 		ck_assert(libinput_event_tablet_tool_wheel_has_changed(tev));
3337 
3338 		val = libinput_event_tablet_tool_get_wheel_delta(tev);
3339 		ck_assert_int_eq(val, 15);
3340 
3341 		val = libinput_event_tablet_tool_get_wheel_delta_discrete(tev);
3342 		ck_assert_int_eq(val, 1);
3343 
3344 		libinput_event_destroy(event);
3345 
3346 		litest_assert_empty_queue(li);
3347 	}
3348 
3349 	for (i = 2; i < 5; i++) {
3350 		/* send  x/y events to make sure we reset the wheel */
3351 		abs = libevdev_get_abs_info(dev->evdev, ABS_X);
3352 		litest_event(dev, EV_ABS, ABS_X, absinfo_range(abs)/i);
3353 		abs = libevdev_get_abs_info(dev->evdev, ABS_Y);
3354 		litest_event(dev, EV_ABS, ABS_Y, absinfo_range(abs)/i);
3355 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
3356 		libinput_dispatch(li);
3357 
3358 		event = libinput_get_event(li);
3359 		tev = litest_is_tablet_event(event,
3360 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3361 		ck_assert(!libinput_event_tablet_tool_wheel_has_changed(tev));
3362 
3363 		val = libinput_event_tablet_tool_get_wheel_delta(tev);
3364 		ck_assert_int_eq(val, 0);
3365 
3366 		val = libinput_event_tablet_tool_get_wheel_delta_discrete(tev);
3367 		ck_assert_int_eq(val, 0);
3368 
3369 		libinput_event_destroy(event);
3370 
3371 		litest_assert_empty_queue(li);
3372 	}
3373 
3374 	libinput_tablet_tool_unref(tool);
3375 }
3376 END_TEST
3377 
START_TEST(airbrush_tool)3378 START_TEST(airbrush_tool)
3379 {
3380 	struct litest_device *dev = litest_current_device();
3381 	struct libinput *li = dev->libinput;
3382 	struct libinput_event *event;
3383 	struct libinput_event_tablet_tool *tev;
3384 	struct libinput_tablet_tool *tool;
3385 
3386 	if (!libevdev_has_event_code(dev->evdev,
3387 				    EV_KEY,
3388 				    BTN_TOOL_AIRBRUSH))
3389 		return;
3390 
3391 	litest_drain_events(li);
3392 
3393 	litest_event(dev, EV_KEY, BTN_TOOL_AIRBRUSH, 1);
3394 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
3395 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3396 	libinput_dispatch(li);
3397 
3398 	event = libinput_get_event(li);
3399 	tev = litest_is_tablet_event(event,
3400 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3401 	tool = libinput_event_tablet_tool_get_tool(tev);
3402 
3403 	ck_assert_notnull(tool);
3404 	ck_assert_int_eq(libinput_tablet_tool_get_type(tool),
3405 			 LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH);
3406 
3407 	ck_assert(libinput_tablet_tool_has_slider(tool));
3408 
3409 	libinput_event_destroy(event);
3410 }
3411 END_TEST
3412 
START_TEST(airbrush_slider)3413 START_TEST(airbrush_slider)
3414 {
3415 	struct litest_device *dev = litest_current_device();
3416 	struct libinput *li = dev->libinput;
3417 	struct libinput_event *event;
3418 	struct libinput_event_tablet_tool *tev;
3419 	const struct input_absinfo *abs;
3420 	double val;
3421 	double scale;
3422 	double expected;
3423 	int v;
3424 
3425 	if (!libevdev_has_event_code(dev->evdev,
3426 				    EV_KEY,
3427 				    BTN_TOOL_AIRBRUSH))
3428 		return;
3429 
3430 	litest_drain_events(li);
3431 
3432 	abs = libevdev_get_abs_info(dev->evdev, ABS_WHEEL);
3433 	ck_assert_notnull(abs);
3434 
3435 	litest_event(dev, EV_KEY, BTN_TOOL_AIRBRUSH, 1);
3436 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
3437 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3438 
3439 	/* start with non-zero */
3440 	litest_event(dev, EV_ABS, ABS_WHEEL, 10);
3441 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3442 
3443 	litest_drain_events(li);
3444 
3445 	scale = absinfo_range(abs);
3446 	for (v = abs->minimum; v < abs->maximum; v += 8) {
3447 		litest_event(dev, EV_ABS, ABS_WHEEL, v);
3448 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
3449 		libinput_dispatch(li);
3450 		event = libinput_get_event(li);
3451 		tev = litest_is_tablet_event(event,
3452 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3453 		ck_assert(libinput_event_tablet_tool_slider_has_changed(tev));
3454 		val = libinput_event_tablet_tool_get_slider_position(tev);
3455 
3456 		expected = ((v - abs->minimum)/scale) * 2 - 1;
3457 		ck_assert_double_eq(val, expected);
3458 		ck_assert_double_ge(val, -1.0);
3459 		ck_assert_double_le(val, 1.0);
3460 		libinput_event_destroy(event);
3461 		litest_assert_empty_queue(li);
3462 	}
3463 }
3464 END_TEST
3465 
START_TEST(artpen_tool)3466 START_TEST(artpen_tool)
3467 {
3468 	struct litest_device *dev = litest_current_device();
3469 	struct libinput *li = dev->libinput;
3470 	struct libinput_event *event;
3471 	struct libinput_event_tablet_tool *tev;
3472 	struct libinput_tablet_tool *tool;
3473 
3474 	if (!libevdev_has_event_code(dev->evdev,
3475 				    EV_ABS,
3476 				    ABS_Z))
3477 		return;
3478 
3479 	litest_drain_events(li);
3480 
3481 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
3482 	litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
3483 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
3484 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3485 	libinput_dispatch(li);
3486 	event = libinput_get_event(li);
3487 	tev = litest_is_tablet_event(event,
3488 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3489 	tool = libinput_event_tablet_tool_get_tool(tev);
3490 	ck_assert_notnull(tool);
3491 	ck_assert_int_eq(libinput_tablet_tool_get_type(tool),
3492 			 LIBINPUT_TABLET_TOOL_TYPE_PEN);
3493 	ck_assert(libinput_tablet_tool_has_rotation(tool));
3494 
3495 	libinput_event_destroy(event);
3496 }
3497 END_TEST
3498 
START_TEST(artpen_rotation)3499 START_TEST(artpen_rotation)
3500 {
3501 	struct litest_device *dev = litest_current_device();
3502 	struct libinput *li = dev->libinput;
3503 	struct libinput_event *event;
3504 	struct libinput_event_tablet_tool *tev;
3505 	const struct input_absinfo *abs;
3506 	double val;
3507 	double scale;
3508 	int angle;
3509 
3510 	if (!libevdev_has_event_code(dev->evdev,
3511 				    EV_ABS,
3512 				    ABS_Z))
3513 		return;
3514 
3515 	litest_drain_events(li);
3516 
3517 	abs = libevdev_get_abs_info(dev->evdev, ABS_Z);
3518 	ck_assert_notnull(abs);
3519 	scale = absinfo_range(abs)/360.0;
3520 
3521 	litest_event(dev, EV_KEY, BTN_TOOL_BRUSH, 1);
3522 	litest_event(dev, EV_ABS, ABS_MISC, 0x804); /* Art Pen */
3523 	litest_event(dev, EV_MSC, MSC_SERIAL, 1000);
3524 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3525 
3526 	litest_event(dev, EV_ABS, ABS_Z, abs->minimum);
3527 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
3528 
3529 	litest_drain_events(li);
3530 
3531 	for (angle = 8; angle < 360; angle += 8) {
3532 		int a = angle * scale + abs->minimum;
3533 
3534 		litest_event(dev, EV_ABS, ABS_Z, a);
3535 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
3536 		libinput_dispatch(li);
3537 		event = libinput_get_event(li);
3538 		tev = litest_is_tablet_event(event,
3539 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3540 		ck_assert(libinput_event_tablet_tool_rotation_has_changed(tev));
3541 		val = libinput_event_tablet_tool_get_rotation(tev);
3542 
3543 		/* artpen has a 90 deg offset cw */
3544 		ck_assert_int_eq(round(val), (angle + 90) % 360);
3545 
3546 		libinput_event_destroy(event);
3547 		litest_assert_empty_queue(li);
3548 
3549 	}
3550 }
3551 END_TEST
3552 
START_TEST(tablet_time_usec)3553 START_TEST(tablet_time_usec)
3554 {
3555 	struct litest_device *dev = litest_current_device();
3556 	struct libinput *li = dev->libinput;
3557 	struct libinput_event *event;
3558 	struct libinput_event_tablet_tool *tev;
3559 	struct axis_replacement axes[] = {
3560 		{ ABS_DISTANCE, 10 },
3561 		{ ABS_PRESSURE, 0 },
3562 		{ -1, -1 }
3563 	};
3564 	uint64_t time_usec;
3565 
3566 	litest_drain_events(li);
3567 
3568 	litest_tablet_proximity_in(dev, 5, 100, axes);
3569 	libinput_dispatch(li);
3570 
3571 	event = libinput_get_event(li);
3572 	tev = litest_is_tablet_event(event,
3573 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3574 	time_usec = libinput_event_tablet_tool_get_time_usec(tev);
3575 	ck_assert_int_eq(libinput_event_tablet_tool_get_time(tev),
3576 			 (uint32_t) (time_usec / 1000));
3577 	libinput_event_destroy(event);
3578 }
3579 END_TEST
3580 
START_TEST(tablet_pressure_distance_exclusive)3581 START_TEST(tablet_pressure_distance_exclusive)
3582 {
3583 	struct litest_device *dev = litest_current_device();
3584 	struct libinput *li = dev->libinput;
3585 	struct libinput_event *event;
3586 	struct libinput_event_tablet_tool *tev;
3587 	struct axis_replacement axes[] = {
3588 		{ ABS_DISTANCE, 10 },
3589 		{ ABS_PRESSURE, 0 },
3590 		{ -1, -1 },
3591 	};
3592 	double pressure, distance;
3593 
3594 	litest_tablet_proximity_in(dev, 5, 50, axes);
3595 	litest_drain_events(li);
3596 
3597 	/* We have 0.1% pressure above minimum threshold but we're still below
3598 	 * the tip threshold */
3599 	litest_axis_set_value(axes, ABS_PRESSURE, 1.1);
3600 	litest_tablet_motion(dev, 70, 70, axes);
3601 	libinput_dispatch(li);
3602 
3603 	event = libinput_get_event(li);
3604 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3605 
3606 	pressure = libinput_event_tablet_tool_get_pressure(tev);
3607 	distance = libinput_event_tablet_tool_get_distance(tev);
3608 
3609 	ck_assert_double_eq(pressure, 0.001);
3610 	ck_assert_double_eq(distance, 0.0);
3611 	libinput_event_destroy(event);
3612 
3613 	/* We have pressure and we're above the tip threshold now */
3614 	litest_axis_set_value(axes, ABS_PRESSURE, 5.5);
3615 	litest_tablet_motion(dev, 70, 70, axes);
3616 	libinput_dispatch(li);
3617 
3618 	event = libinput_get_event(li);
3619 	tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
3620 
3621 	pressure = libinput_event_tablet_tool_get_pressure(tev);
3622 	distance = libinput_event_tablet_tool_get_distance(tev);
3623 
3624 	ck_assert_double_gt(pressure, 0.0);
3625 	ck_assert_double_eq(distance, 0.0);
3626 
3627 	libinput_event_destroy(event);
3628 }
3629 END_TEST
3630 
START_TEST(tablet_calibration_has_matrix)3631 START_TEST(tablet_calibration_has_matrix)
3632 {
3633 	struct litest_device *dev = litest_current_device();
3634 	struct libinput_device *d = dev->libinput_device;
3635 	enum libinput_config_status status;
3636 	int rc;
3637 	float calibration[6] = {1, 0, 0, 0, 1, 0};
3638 	int has_calibration;
3639 
3640 	has_calibration = libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
3641 
3642 	rc = libinput_device_config_calibration_has_matrix(d);
3643 	ck_assert_int_eq(rc, has_calibration);
3644 	rc = libinput_device_config_calibration_get_matrix(d, calibration);
3645 	ck_assert_int_eq(rc, 0);
3646 	rc = libinput_device_config_calibration_get_default_matrix(d,
3647 								   calibration);
3648 	ck_assert_int_eq(rc, 0);
3649 
3650 	status = libinput_device_config_calibration_set_matrix(d,
3651 							       calibration);
3652 	if (has_calibration)
3653 		ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
3654 	else
3655 		ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
3656 }
3657 END_TEST
3658 
START_TEST(tablet_calibration_set_matrix_delta)3659 START_TEST(tablet_calibration_set_matrix_delta)
3660 {
3661 	struct litest_device *dev = litest_current_device();
3662 	struct libinput *li = dev->libinput;
3663 	struct libinput_device *d = dev->libinput_device;
3664 	enum libinput_config_status status;
3665 	float calibration[6] = {0.5, 0, 0, 0, 0.5, 0};
3666 	struct libinput_event *event;
3667 	struct libinput_event_tablet_tool *tablet_event;
3668 	struct axis_replacement axes[] = {
3669 		{ ABS_DISTANCE, 0 },
3670 		{ ABS_PRESSURE, 10 },
3671 		{ -1, -1 }
3672 	};
3673 	int has_calibration;
3674 	double x, y, dx, dy, mdx, mdy;
3675 
3676 	has_calibration = libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
3677 	if (!has_calibration)
3678 		return;
3679 
3680 	litest_drain_events(li);
3681 
3682 	litest_tablet_proximity_in(dev, 100, 100, axes);
3683 	libinput_dispatch(li);
3684 	event = libinput_get_event(li);
3685 	tablet_event = litest_is_tablet_event(event,
3686 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3687 	x = libinput_event_tablet_tool_get_x(tablet_event);
3688 	y = libinput_event_tablet_tool_get_y(tablet_event);
3689 	libinput_event_destroy(event);
3690 
3691 	event = libinput_get_event(li);
3692 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
3693 	libinput_event_destroy(event);
3694 
3695 	litest_tablet_motion(dev, 80, 80, axes);
3696 	libinput_dispatch(li);
3697 
3698 	event = libinput_get_event(li);
3699 	tablet_event = litest_is_tablet_event(event,
3700 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3701 
3702 	dx = libinput_event_tablet_tool_get_x(tablet_event) - x;
3703 	dy = libinput_event_tablet_tool_get_y(tablet_event) - y;
3704 	libinput_event_destroy(event);
3705 	litest_tablet_proximity_out(dev);
3706 	litest_drain_events(li);
3707 
3708 	status = libinput_device_config_calibration_set_matrix(d,
3709 							       calibration);
3710 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
3711 
3712 	litest_tablet_proximity_in(dev, 100, 100, axes);
3713 	libinput_dispatch(li);
3714 	event = libinput_get_event(li);
3715 	tablet_event = litest_is_tablet_event(event,
3716 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3717 	x = libinput_event_tablet_tool_get_x(tablet_event);
3718 	y = libinput_event_tablet_tool_get_y(tablet_event);
3719 	libinput_event_destroy(event);
3720 
3721 	event = libinput_get_event(li);
3722 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
3723 	libinput_event_destroy(event);
3724 
3725 	litest_tablet_motion(dev, 80, 80, axes);
3726 	libinput_dispatch(li);
3727 
3728 	event = libinput_get_event(li);
3729 	tablet_event = litest_is_tablet_event(event,
3730 					      LIBINPUT_EVENT_TABLET_TOOL_AXIS);
3731 
3732 	mdx = libinput_event_tablet_tool_get_x(tablet_event) - x;
3733 	mdy = libinput_event_tablet_tool_get_y(tablet_event) - y;
3734 	libinput_event_destroy(event);
3735 	litest_drain_events(li);
3736 
3737 	ck_assert_double_gt(dx, mdx * 2 - 1);
3738 	ck_assert_double_lt(dx, mdx * 2 + 1);
3739 	ck_assert_double_gt(dy, mdy * 2 - 1);
3740 	ck_assert_double_lt(dy, mdy * 2 + 1);
3741 }
3742 END_TEST
3743 
START_TEST(tablet_calibration_set_matrix)3744 START_TEST(tablet_calibration_set_matrix)
3745 {
3746 	struct litest_device *dev = litest_current_device();
3747 	struct libinput *li = dev->libinput;
3748 	struct libinput_device *d = dev->libinput_device;
3749 	enum libinput_config_status status;
3750 	float calibration[6] = {0.5, 0, 0, 0, 1, 0};
3751 	struct libinput_event *event;
3752 	struct libinput_event_tablet_tool *tablet_event;
3753 	struct axis_replacement axes[] = {
3754 		{ ABS_DISTANCE, 10 },
3755 		{ ABS_PRESSURE, 0 },
3756 		{ -1, -1 }
3757 	};
3758 	int has_calibration;
3759 	double x, y;
3760 
3761 	has_calibration = libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
3762 	if (!has_calibration)
3763 		return;
3764 
3765 	litest_drain_events(li);
3766 
3767 	status = libinput_device_config_calibration_set_matrix(d,
3768 							       calibration);
3769 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
3770 
3771 	litest_tablet_proximity_in(dev, 100, 100, axes);
3772 	libinput_dispatch(li);
3773 
3774 	event = libinput_get_event(li);
3775 	tablet_event = litest_is_tablet_event(event,
3776 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3777 	x = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
3778 	y = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
3779 	libinput_event_destroy(event);
3780 
3781 	ck_assert_double_gt(x, 49.0);
3782 	ck_assert_double_lt(x, 51.0);
3783 	ck_assert_double_gt(y, 99.0);
3784 	ck_assert_double_lt(y, 100.0);
3785 
3786 	litest_tablet_proximity_out(dev);
3787 	libinput_dispatch(li);
3788 	litest_tablet_proximity_in(dev, 50, 50, axes);
3789 	litest_tablet_proximity_out(dev);
3790 	litest_drain_events(li);
3791 
3792 	calibration[0] = 1;
3793 	calibration[4] = 0.5;
3794 	status = libinput_device_config_calibration_set_matrix(d,
3795 							       calibration);
3796 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
3797 
3798 	litest_tablet_proximity_in(dev, 100, 100, axes);
3799 	libinput_dispatch(li);
3800 
3801 	event = libinput_get_event(li);
3802 	tablet_event = litest_is_tablet_event(event,
3803 					      LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
3804 	x = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100);
3805 	y = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100);
3806 	libinput_event_destroy(event);
3807 
3808 	ck_assert(x > 99.0);
3809 	ck_assert(x < 100.0);
3810 	ck_assert(y > 49.0);
3811 	ck_assert(y < 51.0);
3812 
3813 	litest_tablet_proximity_out(dev);
3814 }
3815 END_TEST
3816 
3817 static void
assert_pressure(struct libinput * li,enum libinput_event_type type,double expected_pressure)3818 assert_pressure(struct libinput *li, enum libinput_event_type type, double expected_pressure)
3819 {
3820 	struct libinput_event *event = libinput_get_event(li);
3821 	struct libinput_event_tablet_tool *tev = litest_is_tablet_event(event, type);
3822 	double pressure = libinput_event_tablet_tool_get_pressure(tev);
3823 	ck_assert_double_eq_tol(pressure, expected_pressure, 0.01);
3824 	libinput_event_destroy(event);
3825 }
3826 
START_TEST(tablet_pressure_offset_set)3827 START_TEST(tablet_pressure_offset_set)
3828 {
3829 	struct litest_device *dev = litest_current_device();
3830 	struct libinput *li = dev->libinput;
3831 	struct libinput_event *event;
3832 	struct axis_replacement axes[] = {
3833 		{ ABS_DISTANCE, 70 },
3834 		{ ABS_PRESSURE, 20 },
3835 		{ -1, -1 },
3836 	};
3837 
3838 	litest_drain_events(li);
3839 
3840 	if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_DISTANCE)) {
3841 		/* First two prox ins won't do anything, coming with 10% should give
3842 		 * us ~10% pressure */
3843 		for (int i = 0; i < 2; i++) {
3844 			litest_tablet_proximity_in(dev, 5, 100, axes);
3845 			libinput_dispatch(li);
3846 
3847 			assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.20);
3848 			assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.20);
3849 			litest_tablet_proximity_out(dev);
3850 			litest_drain_events(li);
3851 		}
3852 	}
3853 
3854 	/* This activates the pressure offset */
3855 	litest_tablet_proximity_in(dev, 5, 100, axes);
3856 	litest_drain_events(li);
3857 
3858 	/* Put the pen down, with a pressure high enough to meet the
3859 	 * new offset */
3860 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
3861 	litest_axis_set_value(axes, ABS_PRESSURE, 26);
3862 
3863 	/* Tablet motion above threshold should trigger axis + tip down. Use
3864 	 * the litest motion helper here to avoid false positives caused by
3865 	 * BTN_TOUCH */
3866 	litest_tablet_motion(dev, 70, 70, axes);
3867 	libinput_dispatch(li);
3868 	event = libinput_get_event(li);
3869 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
3870 	libinput_event_destroy(event);
3871 
3872 	/* Reduce pressure to just a tick over the offset, otherwise we get
3873 	 * the tip up event again */
3874 	litest_axis_set_value(axes, ABS_PRESSURE, 20.1);
3875 	litest_tablet_motion(dev, 70, 70, axes);
3876 	libinput_dispatch(li);
3877 
3878 	/* we can't actually get a real 0.0 because that would trigger a tip
3879 	   up. but it's close enough to zero. */
3880 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.01);
3881 	litest_drain_events(li);
3882 
3883 	litest_axis_set_value(axes, ABS_PRESSURE, 21);
3884 	litest_tablet_motion(dev, 70, 70, axes);
3885 
3886 	libinput_dispatch(li);
3887 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.015);
3888 
3889 
3890 	/* Make sure we can reach the upper range too */
3891 	litest_axis_set_value(axes, ABS_PRESSURE, 100);
3892 	litest_tablet_motion(dev, 70, 70, axes);
3893 
3894 	libinput_dispatch(li);
3895 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 1.0);
3896 
3897 	/* Tablet motion at offset should trigger tip up. Use
3898 	 * the litest motion helper here to avoid false positives caused by
3899 	 * BTN_TOUCH */
3900 	litest_axis_set_value(axes, ABS_PRESSURE, 20);
3901 	litest_tablet_motion(dev, 71, 71, axes);
3902 	libinput_dispatch(li);
3903 	event = libinput_get_event(li);
3904 	litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_TIP);
3905 	libinput_event_destroy(event);
3906 
3907 }
3908 END_TEST
3909 
START_TEST(tablet_pressure_offset_decrease)3910 START_TEST(tablet_pressure_offset_decrease)
3911 {
3912 	struct litest_device *dev = litest_current_device();
3913 	struct libinput *li = dev->libinput;
3914 	struct axis_replacement axes[] = {
3915 		{ ABS_DISTANCE, 70 },
3916 		{ ABS_PRESSURE, 20 },
3917 		{ -1, -1 },
3918 	};
3919 
3920 	/* offset 20 on prox in */
3921 	litest_tablet_proximity_in(dev, 5, 100, axes);
3922 	litest_tablet_proximity_out(dev);
3923 	litest_drain_events(li);
3924 
3925 	/* offset 15 on prox in - this one is so we trigger on the next prox
3926 	 * in for the no-distance tablets */
3927 	litest_axis_set_value(axes, ABS_PRESSURE, 15);
3928 	litest_tablet_proximity_in(dev, 5, 100, axes);
3929 	litest_tablet_proximity_out(dev);
3930 	litest_drain_events(li);
3931 
3932 	/* a reduced pressure value must reduce the offset */
3933 	litest_axis_set_value(axes, ABS_PRESSURE, 10);
3934 	litest_tablet_proximity_in(dev, 5, 100, axes);
3935 	litest_tablet_proximity_out(dev);
3936 	litest_drain_events(li);
3937 
3938 	litest_tablet_proximity_in(dev, 5, 100, axes);
3939 	libinput_dispatch(li);
3940 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.0);
3941 	litest_drain_events(li);
3942 
3943 	/* trigger the pressure threshold */
3944 	litest_axis_set_value(axes, ABS_PRESSURE, 15);
3945 	litest_tablet_tip_down(dev, 70, 70, axes);
3946 	libinput_dispatch(li);
3947 
3948 	/* offset 10 + lower threshold of ~1% of original range,
3949 	 * value 15 is 5% over original range but with the above taken into
3950 	 * account it's closer to 5% into the remaining effective 89% range
3951 	 */
3952 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.05);
3953 
3954 	/* a reduced pressure value during motion events must reduce the offset
3955 	 * - here back down to 5%.
3956 	 * FIXME: this causes a tip up event which is a bug but working around
3957 	 * this is more effort than it's worth for what should be quite a niche
3958 	 * case.
3959 	 */
3960 	litest_axis_set_value(axes, ABS_PRESSURE, 5);
3961 	litest_tablet_motion(dev, 75, 75, axes);
3962 	libinput_dispatch(li);
3963 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.0);
3964 	litest_drain_events(li);
3965 
3966 	/* back to 10% should now give us 5% pressure because we reduced the
3967 	 * offset */
3968         litest_axis_set_value(axes, ABS_PRESSURE, 10);
3969 	litest_tablet_motion(dev, 75, 75, axes);
3970 	libinput_dispatch(li);
3971 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.05);
3972 	litest_drain_events(li);
3973 }
3974 END_TEST
3975 
START_TEST(tablet_pressure_offset_increase)3976 START_TEST(tablet_pressure_offset_increase)
3977 {
3978 	struct litest_device *dev = litest_current_device();
3979 	struct libinput *li = dev->libinput;
3980 	struct axis_replacement axes[] = {
3981 		{ ABS_DISTANCE, 70 },
3982 		{ ABS_PRESSURE, 20 },
3983 		{ -1, -1 },
3984 	};
3985 
3986 	/* offset 20 on first prox in */
3987 	litest_tablet_proximity_in(dev, 5, 100, axes);
3988 	litest_tablet_proximity_out(dev);
3989 	litest_drain_events(li);
3990 
3991 	/* offset 25 on second prox in - must not change the offset */
3992 	litest_axis_set_value(axes, ABS_PRESSURE, 25);
3993 	litest_tablet_proximity_in(dev, 5, 100, axes);
3994 	litest_tablet_proximity_out(dev);
3995 	litest_drain_events(li);
3996 
3997 	/* offset 30 on third prox in - must not change the offset */
3998 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
3999 	litest_tablet_proximity_in(dev, 5, 100, axes);
4000 	litest_drain_events(li);
4001 
4002 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
4003 	litest_axis_set_value(axes, ABS_PRESSURE, 31);
4004 	litest_tablet_tip_down(dev, 70, 70, axes);
4005 	libinput_dispatch(li);
4006 	litest_drain_events(li);
4007 
4008 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
4009 	litest_tablet_motion(dev, 70, 70, axes);
4010 	libinput_dispatch(li);
4011 
4012 	/* offset 20 + lower threshold of 1% of original range,
4013 	 * value 30 is 5% over original range but with the above taken into
4014 	 * account it's closer to 12% into the remaining effective 79% range
4015 	 */
4016 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.12);
4017 
4018 	litest_drain_events(li);
4019 
4020 	litest_axis_set_value(axes, ABS_PRESSURE, 20);
4021 	litest_tablet_motion(dev, 70, 70, axes);
4022 	libinput_dispatch(li);
4023 
4024 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_TIP, 0.0);
4025 }
4026 END_TEST
4027 
START_TEST(tablet_pressure_min_max)4028 START_TEST(tablet_pressure_min_max)
4029 {
4030 	struct litest_device *dev = litest_current_device();
4031 	struct libinput *li = dev->libinput;
4032 	struct axis_replacement axes[] = {
4033 		{ ABS_DISTANCE, 10 },
4034 		{ ABS_PRESSURE, 0 },
4035 		{ -1, -1 },
4036 	};
4037 
4038 	if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_PRESSURE))
4039 		return;
4040 
4041 	litest_tablet_proximity_in(dev, 5, 50, axes);
4042 	litest_drain_events(li);
4043 	libinput_dispatch(li);
4044 
4045 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
4046 	/* Default pressure threshold is 1% of range */
4047 	litest_axis_set_value(axes, ABS_PRESSURE, 1.1);
4048 	litest_tablet_motion(dev, 5, 50, axes);
4049 	libinput_dispatch(li);
4050 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.0);
4051 
4052 	/* skip over pressure-based tip down */
4053 	litest_axis_set_value(axes, ABS_PRESSURE, 90);
4054 	litest_tablet_motion(dev, 5, 50, axes);
4055 	litest_drain_events(li);
4056 
4057 	/* need to fill the motion history */
4058 	litest_axis_set_value(axes, ABS_PRESSURE, 100);
4059 	litest_tablet_motion(dev, 5, 50, axes);
4060 	litest_tablet_motion(dev, 6, 50, axes);
4061 	litest_tablet_motion(dev, 7, 50, axes);
4062 	litest_tablet_motion(dev, 8, 50, axes);
4063 	litest_drain_events(li);
4064 
4065 	litest_tablet_motion(dev, 5, 50, axes);
4066 	libinput_dispatch(li);
4067 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 1.0);
4068 }
4069 END_TEST
4070 
START_TEST(tablet_pressure_range)4071 START_TEST(tablet_pressure_range)
4072 {
4073 	struct litest_device *dev = litest_current_device();
4074 	struct libinput *li = dev->libinput;
4075 	struct libinput_event *event;
4076 	struct libinput_event_tablet_tool *tev;
4077 	struct axis_replacement axes[] = {
4078 		{ ABS_DISTANCE, 0 },
4079 		{ ABS_PRESSURE, 10 },
4080 		{ -1, -1 },
4081 	};
4082 	int pressure;
4083 	double p;
4084 
4085 	litest_tablet_proximity_in(dev, 5, 100, axes);
4086 	litest_drain_events(li);
4087 	libinput_dispatch(li);
4088 
4089 	for (pressure = 10; pressure <= 100; pressure += 10) {
4090 		litest_axis_set_value(axes, ABS_PRESSURE, pressure);
4091 		litest_tablet_motion(dev, 70, 70, axes);
4092 		libinput_dispatch(li);
4093 
4094 		event = libinput_get_event(li);
4095 		tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4096 		p = libinput_event_tablet_tool_get_pressure(tev);
4097 		ck_assert_double_ge(p, 0.0);
4098 		ck_assert_double_le(p, 1.0);
4099 		libinput_event_destroy(event);
4100 	}
4101 }
4102 END_TEST
4103 
4104 static void
pressure_threshold_warning(struct libinput * libinput,enum libinput_log_priority priority,const char * format,va_list args)4105 pressure_threshold_warning(struct libinput *libinput,
4106 			   enum libinput_log_priority priority,
4107 			   const char *format,
4108 			   va_list args)
4109 {
4110 	struct litest_user_data *user_data = libinput_get_user_data(libinput);
4111 	int *warning_triggered = user_data->private;
4112 
4113 	if (priority == LIBINPUT_LOG_PRIORITY_ERROR &&
4114 	    strstr(format, "pressure offset greater"))
4115 		(*warning_triggered)++;
4116 }
4117 
START_TEST(tablet_pressure_offset_exceed_threshold)4118 START_TEST(tablet_pressure_offset_exceed_threshold)
4119 {
4120 	struct litest_device *dev = litest_current_device();
4121 	struct libinput *li = dev->libinput;
4122 	struct axis_replacement axes[] = {
4123 		{ ABS_DISTANCE, 70 },
4124 		{ ABS_PRESSURE, 60 },
4125 		{ -1, -1 },
4126 	};
4127 	int warning_triggered = 0;
4128 	struct litest_user_data *user_data = libinput_get_user_data(li);
4129 
4130 	/* Tablet without distance: offset takes effect on third prox-in */
4131 	if (!libevdev_has_event_code(dev->evdev, EV_ABS, ABS_DISTANCE)) {
4132 		for (int i = 0; i < 2; i++) {
4133 			litest_tablet_proximity_in(dev, 5, 100, axes);
4134 			litest_tablet_proximity_out(dev);
4135 			libinput_dispatch(li);
4136 		}
4137 	}
4138 
4139 	litest_drain_events(li);
4140 
4141 	user_data->private = &warning_triggered;
4142 
4143 	libinput_log_set_handler(li, pressure_threshold_warning);
4144 	litest_tablet_proximity_in(dev, 5, 100, axes);
4145 	libinput_dispatch(li);
4146 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.60);
4147 
4148 	ck_assert_int_eq(warning_triggered, 1);
4149 	litest_restore_log_handler(li);
4150 }
4151 END_TEST
4152 
START_TEST(tablet_pressure_offset_none_for_zero_distance)4153 START_TEST(tablet_pressure_offset_none_for_zero_distance)
4154 {
4155 	struct litest_device *dev = litest_current_device();
4156 	struct libinput *li = dev->libinput;
4157 	struct axis_replacement axes[] = {
4158 		{ ABS_DISTANCE, 0 },
4159 		{ ABS_PRESSURE, 20 },
4160 		{ -1, -1 },
4161 	};
4162 
4163 	litest_drain_events(li);
4164 
4165 	/* we're going straight to touch on proximity, make sure we don't
4166 	 * offset the pressure here */
4167 	litest_push_event_frame(dev);
4168 	litest_tablet_proximity_in(dev, 5, 100, axes);
4169 	litest_tablet_tip_down(dev, 5, 100, axes);
4170 	litest_pop_event_frame(dev);
4171 	libinput_dispatch(li);
4172 
4173 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY, 0.20);
4174 }
4175 END_TEST
4176 
START_TEST(tablet_pressure_offset_none_for_small_distance)4177 START_TEST(tablet_pressure_offset_none_for_small_distance)
4178 {
4179 	struct litest_device *dev = litest_current_device();
4180 	struct libinput *li = dev->libinput;
4181 	struct axis_replacement axes[] = {
4182 		{ ABS_DISTANCE, 20 },
4183 		{ ABS_PRESSURE, 20 },
4184 		{ -1, -1 },
4185 	};
4186 
4187 	/* stylus too close to the tablet on the proximity in, ignore any
4188 	 * pressure offset */
4189 	litest_tablet_proximity_in(dev, 5, 100, axes);
4190 	litest_drain_events(li);
4191 	libinput_dispatch(li);
4192 
4193 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
4194 	litest_axis_set_value(axes, ABS_PRESSURE, 21);
4195 	litest_tablet_tip_down(dev, 70, 70, axes);
4196 	litest_drain_events(li);
4197 
4198 	litest_axis_set_value(axes, ABS_PRESSURE, 20);
4199 	litest_tablet_motion(dev, 70, 70, axes);
4200 	libinput_dispatch(li);
4201 
4202 	assert_pressure(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS, 0.20);
4203 }
4204 END_TEST
4205 
START_TEST(tablet_distance_range)4206 START_TEST(tablet_distance_range)
4207 {
4208 	struct litest_device *dev = litest_current_device();
4209 	struct libinput *li = dev->libinput;
4210 	struct libinput_event *event;
4211 	struct libinput_event_tablet_tool *tev;
4212 	struct axis_replacement axes[] = {
4213 		{ ABS_DISTANCE, 20 },
4214 		{ ABS_PRESSURE, 0 },
4215 		{ -1, -1 },
4216 	};
4217 	int distance;
4218 	double dist;
4219 
4220 	litest_tablet_proximity_in(dev, 5, 100, axes);
4221 	litest_drain_events(li);
4222 	libinput_dispatch(li);
4223 
4224 	for (distance = 0; distance <= 100; distance += 10) {
4225 		litest_axis_set_value(axes, ABS_DISTANCE, distance);
4226 		litest_tablet_motion(dev, 70, 70, axes);
4227 		libinput_dispatch(li);
4228 
4229 		event = libinput_get_event(li);
4230 		tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4231 		dist = libinput_event_tablet_tool_get_distance(tev);
4232 		ck_assert_double_ge(dist, 0.0);
4233 		ck_assert_double_le(dist, 1.0);
4234 		libinput_event_destroy(event);
4235 	}
4236 }
4237 END_TEST
4238 
START_TEST(tilt_available)4239 START_TEST(tilt_available)
4240 {
4241 	struct litest_device *dev = litest_current_device();
4242 	struct libinput *li = dev->libinput;
4243 	struct libinput_event *event;
4244 	struct libinput_event_tablet_tool *tev;
4245 	struct libinput_tablet_tool *tool;
4246 	struct axis_replacement axes[] = {
4247 		{ ABS_DISTANCE, 10 },
4248 		{ ABS_PRESSURE, 0 },
4249 		{ ABS_TILT_X, 80 },
4250 		{ ABS_TILT_Y, 20 },
4251 		{ -1, -1 }
4252 	};
4253 
4254 	litest_drain_events(li);
4255 
4256 	litest_tablet_proximity_in(dev, 10, 10, axes);
4257 	libinput_dispatch(li);
4258 	event = libinput_get_event(li);
4259 	tev = litest_is_tablet_event(event,
4260 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
4261 
4262 	tool = libinput_event_tablet_tool_get_tool(tev);
4263 	ck_assert(libinput_tablet_tool_has_tilt(tool));
4264 
4265 	libinput_event_destroy(event);
4266 }
4267 END_TEST
4268 
START_TEST(tilt_not_available)4269 START_TEST(tilt_not_available)
4270 {
4271 	struct litest_device *dev = litest_current_device();
4272 	struct libinput *li = dev->libinput;
4273 	struct libinput_event *event;
4274 	struct libinput_event_tablet_tool *tev;
4275 	struct libinput_tablet_tool *tool;
4276 	struct axis_replacement axes[] = {
4277 		{ ABS_DISTANCE, 10 },
4278 		{ ABS_PRESSURE, 0 },
4279 		{ ABS_TILT_X, 80 },
4280 		{ ABS_TILT_Y, 20 },
4281 		{ -1, -1 }
4282 	};
4283 
4284 	litest_drain_events(li);
4285 
4286 	litest_tablet_proximity_in(dev, 10, 10, axes);
4287 	libinput_dispatch(li);
4288 	event = libinput_get_event(li);
4289 	tev = litest_is_tablet_event(event,
4290 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
4291 
4292 	tool = libinput_event_tablet_tool_get_tool(tev);
4293 	ck_assert(!libinput_tablet_tool_has_tilt(tool));
4294 
4295 	libinput_event_destroy(event);
4296 }
4297 END_TEST
4298 
START_TEST(tilt_x)4299 START_TEST(tilt_x)
4300 {
4301 	struct litest_device *dev = litest_current_device();
4302 	struct libinput *li = dev->libinput;
4303 	struct libinput_event *event;
4304 	struct libinput_event_tablet_tool *tev;
4305 	struct axis_replacement axes[] = {
4306 		{ ABS_DISTANCE, 10 },
4307 		{ ABS_PRESSURE, 0 },
4308 		{ ABS_TILT_X, 10 },
4309 		{ ABS_TILT_Y, 0 },
4310 		{ -1, -1 }
4311 	};
4312 	double tx, ty;
4313 	int tilt;
4314 	double expected_tx;
4315 
4316 	litest_drain_events(li);
4317 
4318 	litest_tablet_proximity_in(dev, 10, 10, axes);
4319 	libinput_dispatch(li);
4320 	event = libinput_get_event(li);
4321 	tev = litest_is_tablet_event(event,
4322 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
4323 
4324 	/* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
4325 	 * we expect 51 degrees ± rounding errors */
4326 	tx = libinput_event_tablet_tool_get_tilt_x(tev);
4327 	ck_assert_double_le(tx, -50);
4328 	ck_assert_double_ge(tx, -52);
4329 
4330 	ty = libinput_event_tablet_tool_get_tilt_y(tev);
4331 	ck_assert_double_ge(ty, -65);
4332 	ck_assert_double_lt(ty, -63);
4333 
4334 	libinput_event_destroy(event);
4335 
4336 	expected_tx = -64.0;
4337 
4338 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
4339 	litest_axis_set_value(axes, ABS_PRESSURE, 1);
4340 
4341 	for (tilt = 0; tilt <= 100; tilt += 5) {
4342 		litest_axis_set_value(axes, ABS_TILT_X, tilt);
4343 		/* work around smoothing */
4344 		litest_tablet_motion(dev, 10, 10, axes);
4345 		litest_tablet_motion(dev, 10, 11, axes);
4346 		litest_tablet_motion(dev, 10, 10, axes);
4347 		litest_drain_events(li);
4348 		litest_tablet_motion(dev, 10, 11, axes);
4349 		libinput_dispatch(li);
4350 		event = libinput_get_event(li);
4351 		tev = litest_is_tablet_event(event,
4352 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4353 
4354 		tx = libinput_event_tablet_tool_get_tilt_x(tev);
4355 		ck_assert_double_ge(tx, expected_tx - 2);
4356 		ck_assert_double_le(tx, expected_tx + 2);
4357 
4358 		ty = libinput_event_tablet_tool_get_tilt_y(tev);
4359 		ck_assert_double_ge(ty, -65);
4360 		ck_assert_double_lt(ty, -63);
4361 
4362 		libinput_event_destroy(event);
4363 
4364 		expected_tx = tx + 6.04;
4365 	}
4366 
4367 	/* the last event must reach the max */
4368 	ck_assert_double_ge(tx, 63.0);
4369 	ck_assert_double_le(tx, 64.0);
4370 }
4371 END_TEST
4372 
START_TEST(tilt_y)4373 START_TEST(tilt_y)
4374 {
4375 	struct litest_device *dev = litest_current_device();
4376 	struct libinput *li = dev->libinput;
4377 	struct libinput_event *event;
4378 	struct libinput_event_tablet_tool *tev;
4379 	struct axis_replacement axes[] = {
4380 		{ ABS_DISTANCE, 10 },
4381 		{ ABS_PRESSURE, 0 },
4382 		{ ABS_TILT_X, 0 },
4383 		{ ABS_TILT_Y, 10 },
4384 		{ -1, -1 }
4385 	};
4386 	double tx, ty;
4387 	int tilt;
4388 	double expected_ty;
4389 
4390 	litest_drain_events(li);
4391 
4392 	litest_tablet_proximity_in(dev, 10, 10, axes);
4393 	libinput_dispatch(li);
4394 	event = libinput_get_event(li);
4395 	tev = litest_is_tablet_event(event,
4396 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
4397 
4398 	/* 90% of the actual axis but mapped into a [-64, 64] tilt range, so
4399 	 * we expect 50 degrees ± rounding errors */
4400 	ty = libinput_event_tablet_tool_get_tilt_y(tev);
4401 	ck_assert_double_le(ty, -50);
4402 	ck_assert_double_ge(ty, -52);
4403 
4404 	tx = libinput_event_tablet_tool_get_tilt_x(tev);
4405 	ck_assert_double_ge(tx, -65);
4406 	ck_assert_double_lt(tx, -63);
4407 
4408 	libinput_event_destroy(event);
4409 
4410 	expected_ty = -64;
4411 
4412 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
4413 	litest_axis_set_value(axes, ABS_PRESSURE, 1);
4414 
4415 	for (tilt = 0; tilt <= 100; tilt += 5) {
4416 		litest_axis_set_value(axes, ABS_TILT_Y, tilt);
4417 		/* work around smoothing */
4418 		litest_tablet_motion(dev, 10, 11, axes);
4419 		litest_tablet_motion(dev, 10, 10, axes);
4420 		litest_tablet_motion(dev, 10, 11, axes);
4421 		litest_drain_events(li);
4422 		litest_tablet_motion(dev, 10, 10, axes);
4423 		libinput_dispatch(li);
4424 		event = libinput_get_event(li);
4425 		tev = litest_is_tablet_event(event,
4426 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4427 
4428 		ty = libinput_event_tablet_tool_get_tilt_y(tev);
4429 		ck_assert_double_ge(ty, expected_ty - 2);
4430 		ck_assert_double_le(ty, expected_ty + 2);
4431 
4432 		tx = libinput_event_tablet_tool_get_tilt_x(tev);
4433 		ck_assert_double_ge(tx, -65);
4434 		ck_assert_double_lt(tx, -63);
4435 
4436 		libinput_event_destroy(event);
4437 
4438 		expected_ty = ty + 6;
4439 	}
4440 
4441 	/* the last event must reach the max */
4442 	ck_assert_double_ge(ty, 63.0);
4443 	ck_assert_double_le(tx, 64.0);
4444 }
4445 END_TEST
4446 
START_TEST(relative_no_profile)4447 START_TEST(relative_no_profile)
4448 {
4449 	struct litest_device *dev = litest_current_device();
4450 	struct libinput_device *device = dev->libinput_device;
4451 	enum libinput_config_accel_profile profile;
4452 	enum libinput_config_status status;
4453 	uint32_t profiles;
4454 
4455 	ck_assert(libinput_device_config_accel_is_available(device));
4456 
4457 	profile = libinput_device_config_accel_get_default_profile(device);
4458 	ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
4459 
4460 	profile = libinput_device_config_accel_get_profile(device);
4461 	ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
4462 
4463 	profiles = libinput_device_config_accel_get_profiles(device);
4464 	ck_assert_int_eq(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, 0);
4465 	ck_assert_int_eq(profiles & LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, 0);
4466 
4467 	status = libinput_device_config_accel_set_profile(device,
4468 							  LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT);
4469 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
4470 	profile = libinput_device_config_accel_get_profile(device);
4471 	ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
4472 
4473 	status = libinput_device_config_accel_set_profile(device,
4474 							  LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE);
4475 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED);
4476 	profile = libinput_device_config_accel_get_profile(device);
4477 	ck_assert_int_eq(profile, LIBINPUT_CONFIG_ACCEL_PROFILE_NONE);
4478 }
4479 END_TEST
4480 
START_TEST(relative_no_delta_prox_in)4481 START_TEST(relative_no_delta_prox_in)
4482 {
4483 	struct litest_device *dev = litest_current_device();
4484 	struct libinput *li = dev->libinput;
4485 	struct libinput_event *event;
4486 	struct libinput_event_tablet_tool *tev;
4487 	struct axis_replacement axes[] = {
4488 		{ ABS_DISTANCE, 10 },
4489 		{ ABS_PRESSURE, 0 },
4490 		{ -1, -1 }
4491 	};
4492 	double dx, dy;
4493 
4494 	litest_drain_events(li);
4495 
4496 	litest_tablet_proximity_in(dev, 10, 10, axes);
4497 	libinput_dispatch(li);
4498 	event = libinput_get_event(li);
4499 	tev = litest_is_tablet_event(event,
4500 				     LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
4501 	dx = libinput_event_tablet_tool_get_dx(tev);
4502 	dy = libinput_event_tablet_tool_get_dy(tev);
4503 	ck_assert(dx == 0.0);
4504 	ck_assert(dy == 0.0);
4505 
4506 	libinput_event_destroy(event);
4507 }
4508 END_TEST
4509 
START_TEST(relative_delta)4510 START_TEST(relative_delta)
4511 {
4512 	struct litest_device *dev = litest_current_device();
4513 	struct libinput *li = dev->libinput;
4514 	struct libinput_event *event;
4515 	struct libinput_event_tablet_tool *tev;
4516 	struct axis_replacement axes[] = {
4517 		{ ABS_DISTANCE, 10 },
4518 		{ ABS_PRESSURE, 0 },
4519 		{ -1, -1 }
4520 	};
4521 	double dx, dy;
4522 
4523 	litest_tablet_proximity_in(dev, 10, 10, axes);
4524 	litest_drain_events(li);
4525 
4526 	/* flush the motion history */
4527 	for (int i = 0; i < 5; i ++)
4528 		litest_tablet_motion(dev, 10 + i, 10, axes);
4529 	litest_drain_events(li);
4530 
4531 	litest_tablet_motion(dev, 20, 10, axes);
4532 	libinput_dispatch(li);
4533 
4534 	event = libinput_get_event(li);
4535 	tev = litest_is_tablet_event(event,
4536 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4537 	dx = libinput_event_tablet_tool_get_dx(tev);
4538 	dy = libinput_event_tablet_tool_get_dy(tev);
4539 	ck_assert(dx > 0.0);
4540 	ck_assert(dy == 0.0);
4541 	libinput_event_destroy(event);
4542 
4543 	/* flush the motion history */
4544 	for (int i = 0; i < 5; i ++)
4545 		litest_tablet_motion(dev, 20 - i, 10, axes);
4546 	litest_drain_events(li);
4547 
4548 	litest_tablet_motion(dev, 5, 10, axes);
4549 	libinput_dispatch(li);
4550 	event = libinput_get_event(li);
4551 	tev = litest_is_tablet_event(event,
4552 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4553 	dx = libinput_event_tablet_tool_get_dx(tev);
4554 	dy = libinput_event_tablet_tool_get_dy(tev);
4555 	ck_assert(dx < 0.0);
4556 	ck_assert(dy == 0.0);
4557 	libinput_event_destroy(event);
4558 
4559 	/* flush the motion history */
4560 	for (int i = 0; i < 5; i ++)
4561 		litest_tablet_motion(dev, 5, 10 + i, axes);
4562 	litest_drain_events(li);
4563 
4564 	litest_tablet_motion(dev, 5, 20, axes);
4565 	libinput_dispatch(li);
4566 	event = libinput_get_event(li);
4567 	tev = litest_is_tablet_event(event,
4568 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4569 	dx = libinput_event_tablet_tool_get_dx(tev);
4570 	dy = libinput_event_tablet_tool_get_dy(tev);
4571 	ck_assert(dx == 0.0);
4572 	ck_assert(dy > 0.0);
4573 	libinput_event_destroy(event);
4574 
4575 
4576 	/* flush the motion history */
4577 	for (int i = 0; i < 5; i ++)
4578 		litest_tablet_motion(dev, 5, 20 - i, axes);
4579 	litest_drain_events(li);
4580 
4581 	litest_tablet_motion(dev, 5, 10, axes);
4582 	libinput_dispatch(li);
4583 	event = libinput_get_event(li);
4584 	tev = litest_is_tablet_event(event,
4585 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4586 	dx = libinput_event_tablet_tool_get_dx(tev);
4587 	dy = libinput_event_tablet_tool_get_dy(tev);
4588 	ck_assert(dx == 0.0);
4589 	ck_assert(dy < 0.0);
4590 	libinput_event_destroy(event);
4591 }
4592 END_TEST
4593 
START_TEST(relative_no_delta_on_tip)4594 START_TEST(relative_no_delta_on_tip)
4595 {
4596 	struct litest_device *dev = litest_current_device();
4597 	struct libinput *li = dev->libinput;
4598 	struct libinput_event *event;
4599 	struct libinput_event_tablet_tool *tev;
4600 	struct axis_replacement axes[] = {
4601 		{ ABS_DISTANCE, 10 },
4602 		{ ABS_PRESSURE, 0 },
4603 		{ -1, -1 }
4604 	};
4605 	double dx, dy;
4606 
4607 	litest_tablet_proximity_in(dev, 10, 10, axes);
4608 	litest_drain_events(li);
4609 
4610 	litest_tablet_motion(dev, 20, 10, axes);
4611 	litest_drain_events(li);
4612 
4613 	/* tip down */
4614 	litest_axis_set_value(axes, ABS_DISTANCE, 0);
4615 	litest_axis_set_value(axes, ABS_PRESSURE, 30);
4616 	litest_tablet_tip_down(dev, 30, 20, axes);
4617 
4618 	libinput_dispatch(li);
4619 	event = libinput_get_event(li);
4620 	tev = litest_is_tablet_event(event,
4621 				     LIBINPUT_EVENT_TABLET_TOOL_TIP);
4622 	ck_assert(libinput_event_tablet_tool_x_has_changed(tev));
4623 	ck_assert(libinput_event_tablet_tool_y_has_changed(tev));
4624 	dx = libinput_event_tablet_tool_get_dx(tev);
4625 	dy = libinput_event_tablet_tool_get_dy(tev);
4626 	ck_assert(dx == 0.0);
4627 	ck_assert(dy == 0.0);
4628 	libinput_event_destroy(event);
4629 
4630 	/* normal motion */
4631 	litest_tablet_motion(dev, 40, 30, axes);
4632 	libinput_dispatch(li);
4633 	event = libinput_get_event(li);
4634 	tev = litest_is_tablet_event(event,
4635 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4636 	dx = libinput_event_tablet_tool_get_dx(tev);
4637 	dy = libinput_event_tablet_tool_get_dy(tev);
4638 	ck_assert(dx > 0.0);
4639 	ck_assert(dy > 0.0);
4640 	libinput_event_destroy(event);
4641 
4642 	/* tip up */
4643 	litest_axis_set_value(axes, ABS_DISTANCE, 10);
4644 	litest_axis_set_value(axes, ABS_PRESSURE, 0);
4645 	litest_tablet_tip_up(dev, 50, 40, axes);
4646 	libinput_dispatch(li);
4647 	event = libinput_get_event(li);
4648 	tev = litest_is_tablet_event(event,
4649 				     LIBINPUT_EVENT_TABLET_TOOL_TIP);
4650 	ck_assert(libinput_event_tablet_tool_x_has_changed(tev));
4651 	ck_assert(libinput_event_tablet_tool_y_has_changed(tev));
4652 	dx = libinput_event_tablet_tool_get_dx(tev);
4653 	dy = libinput_event_tablet_tool_get_dy(tev);
4654 	ck_assert(dx == 0.0);
4655 	ck_assert(dy == 0.0);
4656 	libinput_event_destroy(event);
4657 }
4658 END_TEST
4659 
START_TEST(relative_calibration)4660 START_TEST(relative_calibration)
4661 {
4662 	struct litest_device *dev = litest_current_device();
4663 	struct libinput *li = dev->libinput;
4664 	struct libinput_event *event;
4665 	struct libinput_event_tablet_tool *tev;
4666 	struct axis_replacement axes[] = {
4667 		{ ABS_DISTANCE, 10 },
4668 		{ ABS_PRESSURE, 0 },
4669 		{ -1, -1 }
4670 	};
4671 	double dx, dy;
4672 	float calibration[] = { -1, 0, 1, 0, -1, 1 };
4673 	enum libinput_config_status status;
4674 
4675 	if (!libinput_device_config_calibration_has_matrix(dev->libinput_device))
4676 		return;
4677 
4678 	status = libinput_device_config_calibration_set_matrix(
4679 							dev->libinput_device,
4680 							calibration);
4681 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
4682 
4683 	litest_tablet_proximity_in(dev, 10, 10, axes);
4684 	litest_drain_events(li);
4685 
4686 	litest_tablet_motion(dev, 20, 10, axes);
4687 	libinput_dispatch(li);
4688 
4689 	event = libinput_get_event(li);
4690 	tev = litest_is_tablet_event(event,
4691 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4692 	dx = libinput_event_tablet_tool_get_dx(tev);
4693 	dy = libinput_event_tablet_tool_get_dy(tev);
4694 	ck_assert(dx < 0.0);
4695 	ck_assert(dy == 0.0);
4696 	libinput_event_destroy(event);
4697 
4698 	/* work around axis smoothing */
4699 	litest_tablet_motion(dev, 19, 10, axes);
4700 	litest_tablet_motion(dev, 18, 10, axes);
4701 	litest_tablet_motion(dev, 17, 10, axes);
4702 	litest_drain_events(li);
4703 
4704 	litest_tablet_motion(dev, 5, 10, axes);
4705 	libinput_dispatch(li);
4706 	event = libinput_get_event(li);
4707 	tev = litest_is_tablet_event(event,
4708 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4709 	dx = libinput_event_tablet_tool_get_dx(tev);
4710 	dy = libinput_event_tablet_tool_get_dy(tev);
4711 	ck_assert(dx > 0.0);
4712 	ck_assert(dy == 0.0);
4713 	libinput_event_destroy(event);
4714 
4715 	/* work around axis smoothing */
4716 	litest_tablet_motion(dev, 5, 11, axes);
4717 	litest_tablet_motion(dev, 5, 12, axes);
4718 	litest_tablet_motion(dev, 5, 13, axes);
4719 	litest_drain_events(li);
4720 
4721 	litest_tablet_motion(dev, 5, 20, axes);
4722 	libinput_dispatch(li);
4723 	event = libinput_get_event(li);
4724 	tev = litest_is_tablet_event(event,
4725 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4726 	dx = libinput_event_tablet_tool_get_dx(tev);
4727 	dy = libinput_event_tablet_tool_get_dy(tev);
4728 	ck_assert(dx == 0.0);
4729 	ck_assert(dy < 0.0);
4730 	libinput_event_destroy(event);
4731 
4732 	/* work around axis smoothing */
4733 	litest_tablet_motion(dev, 5, 19, axes);
4734 	litest_tablet_motion(dev, 5, 18, axes);
4735 	litest_tablet_motion(dev, 5, 17, axes);
4736 	litest_drain_events(li);
4737 
4738 	litest_tablet_motion(dev, 5, 5, axes);
4739 	libinput_dispatch(li);
4740 	event = libinput_get_event(li);
4741 	tev = litest_is_tablet_event(event,
4742 				     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4743 	dx = libinput_event_tablet_tool_get_dx(tev);
4744 	dy = libinput_event_tablet_tool_get_dy(tev);
4745 	ck_assert(dx == 0.0);
4746 	ck_assert(dy > 0.0);
4747 	libinput_event_destroy(event);
4748 }
4749 END_TEST
4750 
4751 static enum litest_device_type
paired_device(struct litest_device * dev)4752 paired_device(struct litest_device *dev)
4753 {
4754 	switch(dev->which) {
4755 	case LITEST_WACOM_INTUOS:
4756 		return LITEST_WACOM_FINGER;
4757 	case LITEST_WACOM_FINGER:
4758 		return LITEST_WACOM_INTUOS;
4759 	case LITEST_WACOM_CINTIQ_13HDT_PEN:
4760 		return LITEST_WACOM_CINTIQ_13HDT_FINGER;
4761 	case LITEST_WACOM_CINTIQ_13HDT_FINGER:
4762 		return LITEST_WACOM_CINTIQ_13HDT_PEN;
4763 	default:
4764 		return LITEST_NO_DEVICE;
4765 	}
4766 }
4767 
4768 static void
assert_touch_is_arbitrated(struct litest_device * dev,struct litest_device * finger)4769 assert_touch_is_arbitrated(struct litest_device *dev, struct litest_device *finger)
4770 {
4771 	struct libinput *li = dev->libinput;
4772 	bool is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
4773 	struct axis_replacement axes[] = {
4774 		{ ABS_TILT_X, 80 },
4775 		{ ABS_TILT_Y, 80 },
4776 		{ ABS_DISTANCE, 10 },
4777 		{ ABS_PRESSURE, 0 },
4778 		{ -1, -1 }
4779 	};
4780 
4781 	litest_tablet_proximity_in(dev, 10, 10, axes);
4782 	litest_tablet_motion(dev, 10, 10, axes);
4783 	litest_tablet_motion(dev, 20, 40, axes);
4784 	litest_drain_events(li);
4785 
4786 	double tx = 20;
4787 	double ty = 40;
4788 	double x = 21;
4789 	double y = 41;
4790 	litest_touch_down(finger, 0, x, y);
4791 
4792 	/* We need to intersperce the touch events with tablets so we don't
4793 	   trigger the tablet proximity timeout. */
4794 	for (int i = 0; i < 60; i += 5) {
4795 		litest_touch_move(finger, 0, x + i, y + i);
4796 		litest_tablet_motion(dev, tx + 0.1 * i, ty + 0.1 * i, axes);
4797 	}
4798 	litest_assert_only_typed_events(li,
4799 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
4800 	litest_tablet_proximity_out(dev);
4801 	litest_assert_only_typed_events(li,
4802 					LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
4803 
4804 	litest_timeout_touch_arbitration();
4805 	libinput_dispatch(li);
4806 
4807 	/* finger still down */
4808 	litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10);
4809 	litest_touch_up(finger, 0);
4810 	litest_assert_empty_queue(li);
4811 
4812 	litest_timeout_touch_arbitration();
4813 	libinput_dispatch(li);
4814 
4815 	/* lift finger, expect expect events */
4816 	litest_touch_down(finger, 0, 30, 30);
4817 	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
4818 	litest_touch_up(finger, 0);
4819 	libinput_dispatch(li);
4820 
4821 	if (is_touchpad)
4822 		litest_assert_only_typed_events(li,
4823 						LIBINPUT_EVENT_POINTER_MOTION);
4824 	else
4825 		litest_assert_touch_sequence(li);
4826 }
4827 
START_TEST(touch_arbitration)4828 START_TEST(touch_arbitration)
4829 {
4830 	struct litest_device *dev = litest_current_device();
4831 	enum litest_device_type other;
4832 	struct libinput *li = dev->libinput;
4833 
4834 	other = paired_device(dev);
4835 	if (other == LITEST_NO_DEVICE)
4836 		return;
4837 
4838 	struct litest_device *finger = litest_add_device(li, other);
4839 	litest_drain_events(li);
4840 
4841 	bool is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
4842 	if (is_touchpad)
4843 		litest_disable_hold_gestures(finger->libinput_device);
4844 
4845 	assert_touch_is_arbitrated(dev, finger);
4846 
4847 	litest_delete_device(finger);
4848 }
4849 END_TEST
4850 
START_TEST(touch_arbitration_outside_rect)4851 START_TEST(touch_arbitration_outside_rect)
4852 {
4853 	struct litest_device *dev = litest_current_device();
4854 	enum litest_device_type other;
4855 	struct litest_device *finger;
4856 	struct libinput *li = dev->libinput;
4857 	struct axis_replacement axes[] = {
4858 		{ ABS_TILT_X, 80 },
4859 		{ ABS_TILT_Y, 80 },
4860 		{ ABS_DISTANCE, 10 },
4861 		{ ABS_PRESSURE, 0 },
4862 		{ -1, -1 }
4863 	};
4864 	double x, y;
4865 	bool is_touchpad;
4866 
4867 	other = paired_device(dev);
4868 	if (other == LITEST_NO_DEVICE)
4869 		return;
4870 
4871 	finger = litest_add_device(li, other);
4872 	litest_drain_events(li);
4873 
4874 	is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
4875 	if (is_touchpad)
4876 		return;
4877 
4878 	x = 20;
4879 	y = 70;
4880 
4881 	/* disable prox-out timer quirk */
4882 	litest_tablet_proximity_in(dev, x, y - 1, axes);
4883 	litest_tablet_proximity_out(dev);
4884 
4885 	litest_tablet_proximity_in(dev, x, y - 1, axes);
4886 	litest_drain_events(li);
4887 
4888 	/* these are in percent, but the pen/finger have different
4889 	 * resolution and the rect works in mm, so the numbers below are
4890 	 * hand-picked for the test device */
4891 	litest_tablet_motion(dev, x, y, axes);
4892 	litest_drain_events(li);
4893 
4894 	/* left of rect */
4895 	litest_touch_sequence(finger, 0, x - 10, y + 2, x - 10, y + 20, 3);
4896 	libinput_dispatch(li);
4897 	litest_assert_touch_sequence(li);
4898 
4899 	/* above rect */
4900 	litest_touch_sequence(finger, 0, x + 2, y - 65, x + 20, y - 40, 3);
4901 	libinput_dispatch(li);
4902 	litest_assert_touch_sequence(li);
4903 
4904 	/* right of rect */
4905 	litest_touch_sequence(finger, 0, x + 80, y + 2, x + 20, y + 10, 3);
4906 	libinput_dispatch(li);
4907 	litest_assert_touch_sequence(li);
4908 
4909 #if 0
4910 	/* This *should* work but the Cintiq test devices is <200mm
4911 	   high, so we can't test for anything below the tip */
4912 	x = 20;
4913 	y = 10;
4914 	litest_tablet_proximity_out(dev);
4915 	litest_tablet_motion(dev, x, y, axes);
4916 	litest_tablet_proximity_in(dev, x, y - 1, axes);
4917 	litest_drain_events(li);
4918 
4919 	/* below rect */
4920 	litest_touch_sequence(finger, 0, x + 2, y + 80, x + 20, y + 20, 30);
4921 	libinput_dispatch(li);
4922 	litest_assert_touch_sequence(li);
4923 #endif
4924 
4925 	litest_delete_device(finger);
4926 }
4927 END_TEST
4928 
START_TEST(touch_arbitration_remove_after)4929 START_TEST(touch_arbitration_remove_after)
4930 {
4931 	struct litest_device *dev = litest_current_device();
4932 	enum litest_device_type other;
4933 	struct litest_device *finger;
4934 	struct libinput *li = dev->libinput;
4935 	struct axis_replacement axes[] = {
4936 		{ ABS_TILT_X, 80 },
4937 		{ ABS_TILT_Y, 80 },
4938 		{ ABS_DISTANCE, 10 },
4939 		{ ABS_PRESSURE, 0 },
4940 		{ -1, -1 }
4941 	};
4942 	bool is_touchpad;
4943 
4944 	other = paired_device(dev);
4945 	if (other == LITEST_NO_DEVICE)
4946 		return;
4947 
4948 	finger = litest_add_device(li, other);
4949 	litest_drain_events(li);
4950 
4951 	is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
4952 	if (is_touchpad)
4953 		return;
4954 
4955 	litest_tablet_proximity_in(dev, 50, 50, axes);
4956 	litest_drain_events(li);
4957 
4958 	litest_touch_down(finger, 0, 70, 70);
4959 	litest_drain_events(li);
4960 	litest_tablet_proximity_out(dev);
4961 	libinput_dispatch(li);
4962 
4963 	/* Delete the device immediately after the tablet goes out of prox.
4964 	 * This merely tests that the arbitration timer gets cleaned up */
4965 	litest_delete_device(finger);
4966 }
4967 END_TEST
4968 
START_TEST(touch_arbitration_stop_touch)4969 START_TEST(touch_arbitration_stop_touch)
4970 {
4971 	struct litest_device *dev = litest_current_device();
4972 	enum litest_device_type other;
4973 	struct litest_device *finger;
4974 	struct libinput *li = dev->libinput;
4975 	struct axis_replacement axes[] = {
4976 		{ ABS_DISTANCE, 10 },
4977 		{ ABS_PRESSURE, 0 },
4978 		{ -1, -1 }
4979 	};
4980 	bool is_touchpad;
4981 
4982 	other = paired_device(dev);
4983 	if (other == LITEST_NO_DEVICE)
4984 		return;
4985 
4986 	finger = litest_add_device(li, other);
4987 
4988 	is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
4989 
4990 	if (is_touchpad)
4991 		litest_disable_hold_gestures(finger->libinput_device);
4992 
4993 	/* disable prox-out timer quirk */
4994 	litest_tablet_proximity_in(dev, 30, 30, axes);
4995 	litest_tablet_proximity_out(dev);
4996 	litest_drain_events(li);
4997 
4998 	litest_touch_down(finger, 0, 30, 30);
4999 	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
5000 
5001 	litest_tablet_proximity_in(dev, 10, 10, axes);
5002 	litest_tablet_motion(dev, 10, 10, axes);
5003 	litest_tablet_motion(dev, 20, 40, axes);
5004 	litest_drain_events(li);
5005 
5006 	litest_touch_move_to(finger, 0, 80, 80, 30, 30, 10);
5007 	litest_assert_empty_queue(li);
5008 
5009 	/* tablet event so we don't time out for proximity */
5010 	litest_tablet_motion(dev, 30, 40, axes);
5011 	litest_drain_events(li);
5012 
5013 	/* start another finger to make sure that one doesn't send events
5014 	   either */
5015 	litest_touch_down(finger, 1, 30, 30);
5016 	litest_touch_move_to(finger, 1, 30, 30, 80, 80, 3);
5017 	litest_assert_empty_queue(li);
5018 
5019 	litest_tablet_motion(dev, 10, 10, axes);
5020 	litest_tablet_motion(dev, 20, 40, axes);
5021 	litest_assert_only_typed_events(li,
5022 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5023 	litest_tablet_proximity_out(dev);
5024 	litest_drain_events(li);
5025 
5026 	litest_timeout_tablet_proxout();
5027 	litest_drain_events(li);
5028 
5029 	/* Finger needs to be lifted for events to happen*/
5030 	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 3);
5031 	litest_assert_empty_queue(li);
5032 	litest_touch_move_to(finger, 1, 80, 80, 30, 30, 3);
5033 	litest_assert_empty_queue(li);
5034 	litest_touch_up(finger, 0);
5035 	litest_touch_move_to(finger, 1, 30, 30, 80, 80, 3);
5036 	litest_assert_empty_queue(li);
5037 	litest_touch_up(finger, 1);
5038 	libinput_dispatch(li);
5039 
5040 	litest_touch_down(finger, 0, 30, 30);
5041 	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 3);
5042 	litest_touch_up(finger, 0);
5043 	libinput_dispatch(li);
5044 
5045 	if (is_touchpad)
5046 		litest_assert_only_typed_events(li,
5047 						LIBINPUT_EVENT_POINTER_MOTION);
5048 	else
5049 		litest_assert_touch_sequence(li);
5050 
5051 	litest_delete_device(finger);
5052 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
5053 }
5054 END_TEST
5055 
START_TEST(touch_arbitration_suspend_touch_device)5056 START_TEST(touch_arbitration_suspend_touch_device)
5057 {
5058 	struct litest_device *dev = litest_current_device();
5059 	enum litest_device_type other;
5060 	struct litest_device *tablet;
5061 	struct libinput *li = dev->libinput;
5062 	enum libinput_config_status status;
5063 	struct axis_replacement axes[] = {
5064 		{ ABS_DISTANCE, 10 },
5065 		{ ABS_PRESSURE, 0 },
5066 		{ -1, -1 }
5067 	};
5068 	bool is_touchpad;
5069 
5070 	other = paired_device(dev);
5071 	if (other == LITEST_NO_DEVICE)
5072 		return;
5073 
5074 	tablet = litest_add_device(li, other);
5075 
5076 	is_touchpad = !libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
5077 
5078 	if (is_touchpad)
5079 		litest_disable_hold_gestures(dev->libinput_device);
5080 
5081 	/* we can't force a device suspend, but we can at least make sure
5082 	   the device doesn't send events */
5083 	status = libinput_device_config_send_events_set_mode(
5084 			     dev->libinput_device,
5085 			     LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
5086 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
5087 
5088 	litest_drain_events(li);
5089 
5090 	litest_tablet_proximity_in(tablet, 10, 10, axes);
5091 	litest_tablet_motion(tablet, 10, 10, axes);
5092 	litest_tablet_motion(tablet, 20, 40, axes);
5093 	litest_drain_events(li);
5094 
5095 	litest_touch_down(dev, 0, 30, 30);
5096 	litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
5097 	litest_touch_up(dev, 0);
5098 	litest_assert_empty_queue(li);
5099 
5100 	/* Remove tablet device to unpair, still disabled though */
5101 	litest_delete_device(tablet);
5102 	litest_assert_tablet_proximity_event(li,
5103 					     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
5104 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
5105 
5106 	litest_timeout_touch_arbitration();
5107 	libinput_dispatch(li);
5108 
5109 	litest_touch_down(dev, 0, 30, 30);
5110 	litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
5111 	litest_touch_up(dev, 0);
5112 	litest_assert_empty_queue(li);
5113 
5114 	/* Touch device is still disabled */
5115 	litest_touch_down(dev, 0, 30, 30);
5116 	litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
5117 	litest_touch_up(dev, 0);
5118 	litest_assert_empty_queue(li);
5119 
5120 	status = libinput_device_config_send_events_set_mode(
5121 			     dev->libinput_device,
5122 			     LIBINPUT_CONFIG_SEND_EVENTS_ENABLED);
5123 	ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS);
5124 
5125 	litest_touch_down(dev, 0, 30, 30);
5126 	litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
5127 	litest_touch_up(dev, 0);
5128 	libinput_dispatch(li);
5129 
5130 	if (is_touchpad)
5131 		litest_assert_only_typed_events(li,
5132 						LIBINPUT_EVENT_POINTER_MOTION);
5133 	else
5134 		litest_assert_touch_sequence(li);
5135 }
5136 END_TEST
5137 
START_TEST(touch_arbitration_remove_touch)5138 START_TEST(touch_arbitration_remove_touch)
5139 {
5140 	struct litest_device *dev = litest_current_device();
5141 	enum litest_device_type other;
5142 	struct litest_device *finger;
5143 	struct libinput *li = dev->libinput;
5144 	struct axis_replacement axes[] = {
5145 		{ ABS_DISTANCE, 10 },
5146 		{ ABS_PRESSURE, 0 },
5147 		{ -1, -1 }
5148 	};
5149 
5150 	other = paired_device(dev);
5151 	if (other == LITEST_NO_DEVICE)
5152 		return;
5153 
5154 	finger = litest_add_device(li, other);
5155 	litest_touch_down(finger, 0, 30, 30);
5156 	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
5157 
5158 	litest_tablet_proximity_in(dev, 10, 10, axes);
5159 	litest_drain_events(li);
5160 
5161 	litest_delete_device(finger);
5162 	libinput_dispatch(li);
5163 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
5164 	litest_assert_empty_queue(li);
5165 
5166 	litest_tablet_motion(dev, 10, 10, axes);
5167 	litest_tablet_motion(dev, 20, 40, axes);
5168 	litest_assert_only_typed_events(li,
5169 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5170 }
5171 END_TEST
5172 
START_TEST(touch_arbitration_remove_tablet)5173 START_TEST(touch_arbitration_remove_tablet)
5174 {
5175 	struct litest_device *dev = litest_current_device();
5176 	enum litest_device_type other;
5177 	struct litest_device *tablet;
5178 	struct libinput *li = dev->libinput;
5179 	struct axis_replacement axes[] = {
5180 		{ ABS_DISTANCE, 10 },
5181 		{ ABS_PRESSURE, 0 },
5182 		{ -1, -1 }
5183 	};
5184 	bool is_touchpad;
5185 
5186 	other = paired_device(dev);
5187 	if (other == LITEST_NO_DEVICE)
5188 		return;
5189 
5190 	tablet = litest_add_device(li, other);
5191 
5192 	is_touchpad = !libevdev_has_property(dev->evdev, INPUT_PROP_DIRECT);
5193 
5194 	if (is_touchpad)
5195 		litest_disable_hold_gestures(dev->libinput_device);
5196 
5197 	libinput_dispatch(li);
5198 	litest_tablet_proximity_in(tablet, 10, 10, axes);
5199 	litest_tablet_motion(tablet, 10, 10, axes);
5200 	litest_tablet_motion(tablet, 20, 40, axes);
5201 	litest_drain_events(li);
5202 
5203 	litest_touch_down(dev, 0, 30, 30);
5204 	litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
5205 	litest_assert_empty_queue(li);
5206 
5207 	litest_delete_device(tablet);
5208 	litest_assert_tablet_proximity_event(li,
5209 			     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
5210 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
5211 
5212 	litest_timeout_touch_arbitration();
5213 	libinput_dispatch(li);
5214 
5215 	/* Touch is still down, don't enable */
5216 	litest_touch_move_to(dev, 0, 80, 80, 30, 30, 10);
5217 	litest_touch_up(dev, 0);
5218 	litest_assert_empty_queue(li);
5219 
5220 	litest_touch_down(dev, 0, 30, 30);
5221 	litest_touch_move_to(dev, 0, 30, 30, 80, 80, 10);
5222 	litest_touch_up(dev, 0);
5223 	libinput_dispatch(li);
5224 
5225 	if (is_touchpad)
5226 		litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION);
5227 	else
5228 		litest_assert_touch_sequence(li);
5229 }
5230 END_TEST
5231 
START_TEST(touch_arbitration_keep_ignoring)5232 START_TEST(touch_arbitration_keep_ignoring)
5233 {
5234 	struct litest_device *tablet = litest_current_device();
5235 	enum litest_device_type other;
5236 	struct litest_device *finger;
5237 	struct libinput *li = tablet->libinput;
5238 	struct axis_replacement axes[] = {
5239 		{ ABS_DISTANCE, 10 },
5240 		{ ABS_PRESSURE, 0 },
5241 		{ -1, -1 }
5242 	};
5243 
5244 	other = paired_device(tablet);
5245 	if (other == LITEST_NO_DEVICE)
5246 		return;
5247 
5248 	finger = litest_add_device(li, other);
5249 	litest_tablet_proximity_in(tablet, 10, 10, axes);
5250 	litest_tablet_motion(tablet, 10, 10, axes);
5251 	litest_tablet_motion(tablet, 20, 40, axes);
5252 
5253 	litest_touch_down(finger, 0, 30, 30);
5254 	litest_drain_events(li);
5255 
5256 	litest_tablet_proximity_out(tablet);
5257 	litest_drain_events(li);
5258 
5259 	/* a touch during pen interaction stays a palm after the pen lifts.
5260 	 */
5261 	litest_touch_move_to(finger, 0, 30, 30, 80, 80, 10);
5262 	litest_touch_up(finger, 0);
5263 	libinput_dispatch(li);
5264 
5265 	litest_assert_empty_queue(li);
5266 
5267 	litest_delete_device(finger);
5268 }
5269 END_TEST
5270 
START_TEST(touch_arbitration_late_touch_lift)5271 START_TEST(touch_arbitration_late_touch_lift)
5272 {
5273 	struct litest_device *tablet = litest_current_device();
5274 	enum litest_device_type other;
5275 	struct litest_device *finger;
5276 	struct libinput *li = tablet->libinput;
5277 	struct axis_replacement axes[] = {
5278 		{ ABS_DISTANCE, 10 },
5279 		{ ABS_PRESSURE, 0 },
5280 		{ -1, -1 }
5281 	};
5282 	bool is_touchpad;
5283 
5284 	other = paired_device(tablet);
5285 	if (other == LITEST_NO_DEVICE)
5286 		return;
5287 
5288 	finger = litest_add_device(li, other);
5289 	is_touchpad = !libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT);
5290 	if (is_touchpad) {
5291 		litest_enable_tap(finger->libinput_device);
5292 		litest_disable_hold_gestures(finger->libinput_device);
5293 	}
5294 
5295 	litest_tablet_proximity_in(tablet, 10, 10, axes);
5296 	litest_tablet_motion(tablet, 10, 10, axes);
5297 	litest_tablet_motion(tablet, 20, 40, axes);
5298 	litest_drain_events(li);
5299 
5300 	litest_tablet_proximity_out(tablet);
5301 	litest_drain_events(li);
5302 
5303 	/* with kernel arbitration, a finger + stylus in prox only generates
5304 	 * stylus events. When a user lifts the hand with the stylus, the
5305 	 * stylus usually goes out of prox while the hand is still touching
5306 	 * the surface. This causes a touch down event now that the stylus
5307 	 * is out of proximity. A few ms later, the hand really lifts off
5308 	 * the surface, causing a touch down and thus a fake tap event.
5309 	 */
5310 	litest_touch_down(finger, 0, 30, 30);
5311 	litest_touch_up(finger, 0);
5312 	libinput_dispatch(li);
5313 	litest_timeout_tap();
5314 	libinput_dispatch(li);
5315 
5316 	litest_assert_empty_queue(li);
5317 
5318 	litest_delete_device(finger);
5319 }
5320 END_TEST
5321 
START_TEST(touch_arbitration_swap_device)5322 START_TEST(touch_arbitration_swap_device)
5323 {
5324 	struct litest_device *tablet = litest_current_device();
5325 	struct libinput *li = tablet->libinput;
5326 
5327 	enum litest_device_type paired = paired_device(tablet);
5328 	if (paired == LITEST_NO_DEVICE)
5329 		return;
5330 
5331 	/* First, add a normal touchscreen */
5332 	struct litest_device *touchscreen = litest_add_device(li, LITEST_GENERIC_MULTITOUCH_SCREEN);
5333 	libinput_device_config_gesture_set_hold_enabled(touchscreen->libinput_device,
5334 							LIBINPUT_CONFIG_HOLD_DISABLED);
5335 	litest_drain_events(li);
5336 	assert_touch_is_arbitrated(tablet, touchscreen);
5337 
5338 	/* Now add a better device to override the pairing */
5339 	struct litest_device *finger = litest_add_device(li, paired);
5340 	libinput_device_config_gesture_set_hold_enabled(finger->libinput_device,
5341 							LIBINPUT_CONFIG_HOLD_DISABLED);
5342 	litest_drain_events(li);
5343 	assert_touch_is_arbitrated(tablet, finger);
5344 
5345 	litest_delete_device(touchscreen);
5346 	litest_delete_device(finger);
5347 }
5348 END_TEST
5349 
5350 #if HAVE_LIBWACOM
5351 static void
verify_left_handed_tablet_motion(struct litest_device * tablet,struct libinput * li,int x,int y,bool left_handed)5352 verify_left_handed_tablet_motion(struct litest_device *tablet,
5353 				 struct libinput *li,
5354 				 int x, int y,
5355 				 bool left_handed)
5356 {
5357 	struct libinput_event *event;
5358 	struct libinput_event_tablet_tool *t;
5359 
5360 	/* proximity in/out must be handled by caller */
5361 
5362 	for (int i = 5; i < 25; i += 5) {
5363 		litest_tablet_motion(tablet, x + i, y - i, NULL);
5364 		libinput_dispatch(li);
5365 	}
5366 
5367 	event = libinput_get_event(li);
5368 	t = litest_is_tablet_event(event,
5369 				   LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5370 	x = libinput_event_tablet_tool_get_x(t);
5371 	y = libinput_event_tablet_tool_get_y(t);
5372 	libinput_event_destroy(event);
5373 
5374 	event = libinput_get_event(li);
5375 	litest_assert_ptr_notnull(event);
5376 
5377 	while (event) {
5378 		double last_x = x, last_y = y;
5379 
5380 		t = litest_is_tablet_event(event,
5381 					   LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5382 		x = libinput_event_tablet_tool_get_x(t);
5383 		y = libinput_event_tablet_tool_get_y(t);
5384 
5385 		if (left_handed) {
5386 			litest_assert_double_lt(x, last_x);
5387 			litest_assert_double_gt(y, last_y);
5388 		} else {
5389 			litest_assert_double_gt(x, last_x);
5390 			litest_assert_double_lt(y, last_y);
5391 		}
5392 
5393 		libinput_event_destroy(event);
5394 		event = libinput_get_event(li);
5395 	}
5396 }
5397 
5398 static void
verify_left_handed_tablet_sequence(struct litest_device * tablet,struct libinput * li,bool left_handed)5399 verify_left_handed_tablet_sequence(struct litest_device *tablet,
5400 				   struct libinput *li,
5401 				   bool left_handed)
5402 {
5403 	double x, y;
5404 
5405 	/* verifies a whole sequence, including prox in/out and timeouts */
5406 	x = 60;
5407 	y = 60;
5408 	litest_tablet_proximity_in(tablet, x, y, NULL);
5409 	libinput_dispatch(li);
5410 	litest_drain_events(li);
5411 	verify_left_handed_tablet_motion(tablet, li, x, y, left_handed);
5412 	litest_tablet_proximity_out(tablet);
5413 	libinput_dispatch(li);
5414 	litest_timeout_tablet_proxout();
5415 	litest_drain_events(li);
5416 }
5417 
5418 static void
verify_left_handed_touch_motion(struct litest_device * finger,struct libinput * li,double x,double y,bool left_handed)5419 verify_left_handed_touch_motion(struct litest_device *finger,
5420 				struct libinput *li,
5421 				double x, double y,
5422 				bool left_handed)
5423 {
5424 	struct libinput_event *event;
5425 	struct libinput_event_pointer *p;
5426 
5427 	/* touch down/up must be handled by caller */
5428 
5429 	litest_touch_move_to(finger, 0, x + 1, y - 1, x + 20, y - 20, 10);
5430 	libinput_dispatch(li);
5431 
5432 	event = libinput_get_event(li);
5433 	ck_assert_notnull(event);
5434 
5435 	while (event) {
5436 		p = litest_is_motion_event(event);
5437 		x = libinput_event_pointer_get_dx(p);
5438 		y = libinput_event_pointer_get_dy(p);
5439 
5440 		if (left_handed) {
5441 			litest_assert_double_lt(x, 0);
5442 			litest_assert_double_gt(y, 0);
5443 		} else {
5444 			litest_assert_double_gt(x, 0);
5445 			litest_assert_double_lt(y, 0);
5446 		}
5447 
5448 		libinput_event_destroy(event);
5449 		event = libinput_get_event(li);
5450 	}
5451 }
5452 
5453 static void
verify_left_handed_touch_sequence(struct litest_device * finger,struct libinput * li,bool left_handed)5454 verify_left_handed_touch_sequence(struct litest_device *finger,
5455 				  struct libinput *li,
5456 				  bool left_handed)
5457 {
5458 	double x, y;
5459 
5460 	/* verifies a whole sequence, including prox in/out and timeouts */
5461 
5462 	x = 10;
5463 	y = 30;
5464 	litest_touch_down(finger, 0, x, y);
5465 	litest_drain_events(li);
5466 	verify_left_handed_touch_motion(finger, li, x, y, left_handed);
5467 	litest_touch_up(finger, 0);
5468 	libinput_dispatch(li);
5469 }
5470 #endif
5471 
START_TEST(tablet_rotation_left_handed)5472 START_TEST(tablet_rotation_left_handed)
5473 {
5474 #if HAVE_LIBWACOM
5475 	struct litest_device *tablet = litest_current_device();
5476 	enum litest_device_type other;
5477 	struct litest_device *finger;
5478 	struct libinput *li = tablet->libinput;
5479 	unsigned int transition = _i; /* ranged test */
5480 	bool tablet_from, touch_from, tablet_to, touch_to;
5481 	bool enabled_from, enabled_to;
5482 
5483 	other = paired_device(tablet);
5484 	if (other == LITEST_NO_DEVICE)
5485 		return;
5486 
5487 	finger = litest_add_device(li, other);
5488 	litest_drain_events(li);
5489 
5490 	if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
5491 		goto out;
5492 
5493 	tablet_from = !!(transition & bit(0));
5494 	touch_from  = !!(transition & bit(1));
5495 	tablet_to   = !!(transition & bit(2));
5496 	touch_to    = !!(transition & bit(3));
5497 
5498 	enabled_from = tablet_from || touch_from;
5499 	enabled_to   = tablet_to   || touch_to;
5500 
5501 	litest_disable_hold_gestures(finger->libinput_device);
5502 	libinput_device_config_left_handed_set(tablet->libinput_device,
5503 					       tablet_from);
5504 	libinput_device_config_left_handed_set(finger->libinput_device,
5505 					       touch_from);
5506 	verify_left_handed_tablet_sequence(tablet, li, enabled_from);
5507 	verify_left_handed_touch_sequence(finger, li, enabled_from);
5508 
5509 	libinput_device_config_left_handed_set(tablet->libinput_device,
5510 					       tablet_to);
5511 	libinput_device_config_left_handed_set(finger->libinput_device,
5512 					       touch_to);
5513 	verify_left_handed_tablet_sequence(tablet, li, enabled_to);
5514 	verify_left_handed_touch_sequence(finger, li, enabled_to);
5515 
5516 out:
5517 	litest_delete_device(finger);
5518 #endif
5519 }
5520 END_TEST
5521 
START_TEST(tablet_rotation_left_handed_configuration)5522 START_TEST(tablet_rotation_left_handed_configuration)
5523 {
5524 #if HAVE_LIBWACOM
5525 	struct litest_device *tablet = litest_current_device();
5526 	enum litest_device_type other;
5527 	struct litest_device *finger;
5528 	struct libinput *li = tablet->libinput;
5529 	unsigned int transition = _i; /* ranged test */
5530 	bool tablet_from, touch_from, tablet_to, touch_to;
5531 	bool tablet_enabled, touch_enabled;
5532 	struct libinput_device *tablet_dev, *touch_dev;
5533 
5534 	other = paired_device(tablet);
5535 	if (other == LITEST_NO_DEVICE)
5536 		return;
5537 
5538 	finger = litest_add_device(li, other);
5539 	litest_drain_events(li);
5540 
5541 	if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
5542 		goto out;
5543 
5544 	tablet_from = !!(transition & bit(0));
5545 	touch_from  = !!(transition & bit(1));
5546 	tablet_to   = !!(transition & bit(2));
5547 	touch_to    = !!(transition & bit(3));
5548 
5549 	tablet_dev = tablet->libinput_device;
5550 	touch_dev = finger->libinput_device;
5551 
5552 	/* Make sure that toggling one device doesn't toggle the other one */
5553 
5554 	libinput_device_config_left_handed_set(tablet_dev, tablet_from);
5555 	libinput_device_config_left_handed_set(touch_dev, touch_from);
5556 	libinput_dispatch(li);
5557 	tablet_enabled = libinput_device_config_left_handed_get(tablet_dev);
5558 	touch_enabled = libinput_device_config_left_handed_get(touch_dev);
5559 	ck_assert_int_eq(tablet_enabled, tablet_from);
5560 	ck_assert_int_eq(touch_enabled, touch_from);
5561 
5562 	libinput_device_config_left_handed_set(tablet_dev, tablet_to);
5563 	libinput_device_config_left_handed_set(touch_dev, touch_to);
5564 	libinput_dispatch(li);
5565 	tablet_enabled = libinput_device_config_left_handed_get(tablet_dev);
5566 	touch_enabled = libinput_device_config_left_handed_get(touch_dev);
5567 	ck_assert_int_eq(tablet_enabled, tablet_to);
5568 	ck_assert_int_eq(touch_enabled, touch_to);
5569 
5570 out:
5571 	litest_delete_device(finger);
5572 #endif
5573 }
5574 END_TEST
5575 
START_TEST(tablet_rotation_left_handed_while_in_prox)5576 START_TEST(tablet_rotation_left_handed_while_in_prox)
5577 {
5578 #if HAVE_LIBWACOM
5579 	struct litest_device *tablet = litest_current_device();
5580 	enum litest_device_type other;
5581 	struct litest_device *finger;
5582 	struct libinput *li = tablet->libinput;
5583 	unsigned int transition = _i; /* ranged test */
5584 	bool tablet_from, touch_from, tablet_to, touch_to;
5585 	bool enabled_from, enabled_to;
5586 	double x, y;
5587 	double tx, ty;
5588 
5589 	other = paired_device(tablet);
5590 	if (other == LITEST_NO_DEVICE)
5591 		return;
5592 
5593 	finger = litest_add_device(li, other);
5594 	litest_drain_events(li);
5595 
5596 	if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
5597 		goto out;
5598 
5599 	tablet_from = !!(transition & bit(0));
5600 	touch_from  = !!(transition & bit(1));
5601 	tablet_to   = !!(transition & bit(2));
5602 	touch_to    = !!(transition & bit(3));
5603 
5604 	enabled_from = tablet_from || touch_from;
5605 	enabled_to   = tablet_to   || touch_to;
5606 
5607 	litest_disable_hold_gestures(finger->libinput_device);
5608 	libinput_device_config_left_handed_set(finger->libinput_device,
5609 					       touch_from);
5610 	libinput_device_config_left_handed_set(tablet->libinput_device,
5611 					       tablet_from);
5612 
5613 
5614 	/* Tablet in-prox when setting to left-handed */
5615 	tx = 60;
5616 	ty = 60;
5617 	litest_tablet_proximity_in(tablet, tx, ty, NULL);
5618 	libinput_dispatch(li);
5619 	litest_drain_events(li);
5620 
5621 	libinput_device_config_left_handed_set(tablet->libinput_device,
5622 					       tablet_to);
5623 	libinput_device_config_left_handed_set(finger->libinput_device,
5624 					       touch_to);
5625 
5626 	/* not yet neutral, so still whatever the original was */
5627 	verify_left_handed_tablet_motion(tablet, li, tx, ty, enabled_from);
5628 	litest_drain_events(li);
5629 
5630 	/* test pointer, should be left-handed already */
5631 #if 0
5632 	/* Touch arbitration discards events, so we can't check for the
5633 	   right behaviour here. */
5634 	verify_left_handed_touch_sequence(finger, li, enabled_to);
5635 #else
5636 	x = 10;
5637 	y = 30;
5638 	litest_touch_down(finger, 0, x, y);
5639 
5640 	/* We need to intersperce the touch events with tablets so we don't
5641 	   trigger the tablet proximity timeout. */
5642 	for (int i = 0; i < 10; i++) {
5643 		litest_touch_move(finger, 0, x + i, y - i);
5644 		litest_tablet_motion(tablet,
5645 				     tx + 0.1 * i, ty + 0.1 * i,
5646 				     NULL);
5647 	}
5648 
5649 	litest_touch_up(finger, 0);
5650 	libinput_dispatch(li);
5651 	/* this will fail once we have location-based touch arbitration on
5652 	 * touchpads */
5653 	litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5654 #endif
5655 	litest_tablet_proximity_out(tablet);
5656 	libinput_dispatch(li);
5657 	litest_timeout_tablet_proxout();
5658 	litest_drain_events(li);
5659 
5660 	/* now both should've switched */
5661 	verify_left_handed_tablet_sequence(tablet, li, enabled_to);
5662 	verify_left_handed_touch_sequence(finger, li, enabled_to);
5663 
5664 out:
5665 	litest_delete_device(finger);
5666 #endif
5667 }
5668 END_TEST
5669 
START_TEST(tablet_rotation_left_handed_while_touch_down)5670 START_TEST(tablet_rotation_left_handed_while_touch_down)
5671 {
5672 #if HAVE_LIBWACOM
5673 	struct litest_device *tablet = litest_current_device();
5674 	enum litest_device_type other;
5675 	struct litest_device *finger;
5676 	struct libinput *li = tablet->libinput;
5677 	unsigned int transition = _i; /* ranged test */
5678 	bool tablet_from, touch_from, tablet_to, touch_to;
5679 	bool enabled_from, enabled_to;
5680 
5681 	double x, y;
5682 
5683 	other = paired_device(tablet);
5684 	if (other == LITEST_NO_DEVICE)
5685 		return;
5686 
5687 	finger = litest_add_device(li, other);
5688 	litest_drain_events(li);
5689 
5690 	if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
5691 		goto out;
5692 
5693 	tablet_from = !!(transition & bit(0));
5694 	touch_from  = !!(transition & bit(1));
5695 	tablet_to   = !!(transition & bit(2));
5696 	touch_to    = !!(transition & bit(3));
5697 
5698 	enabled_from = tablet_from || touch_from;
5699 	enabled_to   = tablet_to   || touch_to;
5700 
5701 	litest_disable_hold_gestures(finger->libinput_device);
5702 	libinput_device_config_left_handed_set(finger->libinput_device,
5703 					       touch_from);
5704 	libinput_device_config_left_handed_set(tablet->libinput_device,
5705 					       tablet_from);
5706 
5707 	/* Touch down when setting to left-handed */
5708 	x = 10;
5709 	y = 30;
5710 	litest_touch_down(finger, 0, x, y);
5711 	libinput_dispatch(li);
5712 	litest_drain_events(li);
5713 
5714 	libinput_device_config_left_handed_set(tablet->libinput_device,
5715 					       tablet_to);
5716 	libinput_device_config_left_handed_set(finger->libinput_device,
5717 					       touch_to);
5718 
5719 	/* not yet neutral, so still whatever the original was */
5720 	verify_left_handed_touch_motion(finger, li, x, y, enabled_from);
5721 	litest_assert_empty_queue(li);
5722 
5723 	/* test tablet, should be left-handed already */
5724 	verify_left_handed_tablet_sequence(tablet, li, enabled_to);
5725 
5726 	litest_touch_up(finger, 0);
5727 	litest_drain_events(li);
5728 
5729 	/* now both should've switched */
5730 	verify_left_handed_tablet_sequence(tablet, li, enabled_to);
5731 	verify_left_handed_touch_sequence(finger, li, enabled_to);
5732 
5733 out:
5734 	litest_delete_device(finger);
5735 #endif
5736 }
5737 END_TEST
5738 
START_TEST(tablet_rotation_left_handed_add_touchpad)5739 START_TEST(tablet_rotation_left_handed_add_touchpad)
5740 {
5741 #if HAVE_LIBWACOM
5742 	struct litest_device *tablet = litest_current_device();
5743 	enum litest_device_type other;
5744 	struct litest_device *finger;
5745 	struct libinput *li = tablet->libinput;
5746 	unsigned int transition = _i; /* ranged test */
5747 	bool tablet_from, touch_from, tablet_to, touch_to;
5748 	bool enabled_from, enabled_to;
5749 
5750 	other = paired_device(tablet);
5751 	if (other == LITEST_NO_DEVICE)
5752 		return;
5753 
5754 	tablet_from = !!(transition & bit(0));
5755 	touch_from  = !!(transition & bit(1));
5756 	tablet_to   = !!(transition & bit(2));
5757 	touch_to    = !!(transition & bit(3));
5758 
5759 	enabled_from = tablet_from || touch_from;
5760 	enabled_to   = tablet_to   || touch_to;
5761 
5762 	/* change left-handed before touchpad appears */
5763 
5764 	libinput_device_config_left_handed_set(tablet->libinput_device,
5765 					       tablet_from);
5766 
5767 	finger = litest_add_device(li, other);
5768 	litest_drain_events(li);
5769 
5770 	if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
5771 		goto out;
5772 
5773 	libinput_device_config_left_handed_set(finger->libinput_device,
5774 					       touch_from);
5775 	litest_disable_hold_gestures(finger->libinput_device);
5776 
5777 	verify_left_handed_touch_sequence(finger, li, enabled_from);
5778 	verify_left_handed_tablet_sequence(tablet, li, enabled_from);
5779 
5780 	libinput_device_config_left_handed_set(tablet->libinput_device,
5781 					       tablet_to);
5782 	libinput_device_config_left_handed_set(finger->libinput_device,
5783 					       touch_to);
5784 
5785 	verify_left_handed_touch_sequence(finger, li, enabled_to);
5786 	verify_left_handed_tablet_sequence(tablet, li, enabled_to);
5787 
5788 out:
5789 	litest_delete_device(finger);
5790 #endif
5791 }
5792 END_TEST
5793 
START_TEST(tablet_rotation_left_handed_add_tablet)5794 START_TEST(tablet_rotation_left_handed_add_tablet)
5795 {
5796 #if HAVE_LIBWACOM
5797 	struct litest_device *finger = litest_current_device();
5798 	enum litest_device_type other;
5799 	struct litest_device *tablet;
5800 	struct libinput *li = finger->libinput;
5801 	unsigned int transition = _i; /* ranged test */
5802 	bool tablet_from, touch_from, tablet_to, touch_to;
5803 	bool enabled_from, enabled_to;
5804 
5805 	if (libevdev_has_property(finger->evdev, INPUT_PROP_DIRECT))
5806 		return;
5807 
5808 	other = paired_device(finger);
5809 	if (other == LITEST_NO_DEVICE)
5810 		return;
5811 
5812 	tablet_from = !!(transition & bit(0));
5813 	touch_from  = !!(transition & bit(1));
5814 	tablet_to   = !!(transition & bit(2));
5815 	touch_to    = !!(transition & bit(3));
5816 
5817 	enabled_from = tablet_from || touch_from;
5818 	enabled_to   = tablet_to   || touch_to;
5819 
5820 	/* change left-handed before tablet appears */
5821 	libinput_device_config_left_handed_set(finger->libinput_device,
5822 					       touch_from);
5823 	litest_disable_hold_gestures(finger->libinput_device);
5824 
5825 	tablet = litest_add_device(li, other);
5826 	litest_drain_events(li);
5827 
5828 	libinput_device_config_left_handed_set(tablet->libinput_device,
5829 					       tablet_from);
5830 
5831 	verify_left_handed_touch_sequence(finger, li, enabled_from);
5832 	verify_left_handed_tablet_sequence(tablet, li, enabled_from);
5833 
5834 	libinput_device_config_left_handed_set(tablet->libinput_device,
5835 					       tablet_to);
5836 	libinput_device_config_left_handed_set(finger->libinput_device,
5837 					       touch_to);
5838 
5839 	verify_left_handed_touch_sequence(finger, li, enabled_to);
5840 	verify_left_handed_tablet_sequence(tablet, li, enabled_to);
5841 
5842 	litest_delete_device(tablet);
5843 #endif
5844 }
5845 END_TEST
5846 
START_TEST(huion_static_btn_tool_pen)5847 START_TEST(huion_static_btn_tool_pen)
5848 {
5849 	struct litest_device *dev = litest_current_device();
5850 	struct libinput *li = dev->libinput;
5851 	int i;
5852 
5853 	litest_drain_events(li);
5854 
5855 	litest_event(dev, EV_ABS, ABS_X, 20000);
5856 	litest_event(dev, EV_ABS, ABS_Y, 20000);
5857 	litest_event(dev, EV_ABS, ABS_PRESSURE, 100);
5858 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
5859 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
5860 	litest_drain_events(li);
5861 
5862 	for (i = 0; i < 10; i++) {
5863 		litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
5864 		litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
5865 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
5866 		libinput_dispatch(li);
5867 	}
5868 	litest_assert_only_typed_events(li,
5869 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5870 
5871 	/* Wait past the timeout to expect a proximity out */
5872 	litest_timeout_tablet_proxout();
5873 	libinput_dispatch(li);
5874 	litest_assert_tablet_proximity_event(li,
5875 			     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
5876 	libinput_dispatch(li);
5877 
5878 	/* New events should fake a proximity in again */
5879 	litest_event(dev, EV_ABS, ABS_X, 20000);
5880 	litest_event(dev, EV_ABS, ABS_Y, 20000);
5881 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
5882 	libinput_dispatch(li);
5883 	litest_assert_tablet_proximity_event(li,
5884 			     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
5885 	libinput_dispatch(li);
5886 
5887 	for (i = 0; i < 10; i++) {
5888 		litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
5889 		litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
5890 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
5891 		libinput_dispatch(li);
5892 	}
5893 	litest_assert_only_typed_events(li,
5894 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5895 	litest_timeout_tablet_proxout();
5896 	libinput_dispatch(li);
5897 	litest_assert_tablet_proximity_event(li,
5898 			     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
5899 	libinput_dispatch(li);
5900 
5901 	/* New events, just to ensure cleanup paths are correct */
5902 	litest_event(dev, EV_ABS, ABS_X, 20000);
5903 	litest_event(dev, EV_ABS, ABS_Y, 20000);
5904 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
5905 	libinput_dispatch(li);
5906 }
5907 END_TEST
5908 
START_TEST(huion_static_btn_tool_pen_no_timeout_during_usage)5909 START_TEST(huion_static_btn_tool_pen_no_timeout_during_usage)
5910 {
5911 	struct litest_device *dev = litest_current_device();
5912 	struct libinput *li = dev->libinput;
5913 	int i;
5914 
5915 	litest_drain_events(li);
5916 
5917 	litest_event(dev, EV_ABS, ABS_X, 20000);
5918 	litest_event(dev, EV_ABS, ABS_Y, 20000);
5919 	litest_event(dev, EV_ABS, ABS_PRESSURE, 100);
5920 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
5921 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
5922 	litest_drain_events(li);
5923 
5924 	/* take longer than the no-activity timeout */
5925 	for (i = 0; i < 50; i++) {
5926 		litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
5927 		litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
5928 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
5929 		libinput_dispatch(li);
5930 		msleep(5);
5931 	}
5932 	litest_assert_only_typed_events(li,
5933 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5934 	litest_timeout_tablet_proxout();
5935 	libinput_dispatch(li);
5936 	litest_assert_tablet_proximity_event(li,
5937 			     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
5938 	libinput_dispatch(li);
5939 }
5940 END_TEST
5941 
START_TEST(huion_static_btn_tool_pen_disable_quirk_on_prox_out)5942 START_TEST(huion_static_btn_tool_pen_disable_quirk_on_prox_out)
5943 {
5944 	struct litest_device *dev = litest_current_device();
5945 	struct libinput *li = dev->libinput;
5946 	bool with_timeout = _i; /* ranged test */
5947 	int i;
5948 
5949 	/* test is run twice, once where the real BTN_TOOL_PEN is triggered
5950 	 * during proximity out, one where the real BTN_TOOL_PEN is
5951 	 * triggered after we already triggered the quirk timeout
5952 	 */
5953 
5954 	litest_drain_events(li);
5955 
5956 	litest_event(dev, EV_ABS, ABS_X, 20000);
5957 	litest_event(dev, EV_ABS, ABS_Y, 20000);
5958 	litest_event(dev, EV_ABS, ABS_PRESSURE, 100);
5959 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 1);
5960 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
5961 	litest_drain_events(li);
5962 
5963 	for (i = 0; i < 10; i++) {
5964 		litest_event(dev, EV_ABS, ABS_X, 20000 + 10 * i);
5965 		litest_event(dev, EV_ABS, ABS_Y, 20000 - 10 * i);
5966 		litest_event(dev, EV_SYN, SYN_REPORT, 0);
5967 		libinput_dispatch(li);
5968 	}
5969 	litest_assert_only_typed_events(li,
5970 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
5971 
5972 	/* Wait past the timeout to expect a proximity out */
5973 	if (with_timeout) {
5974 		litest_timeout_tablet_proxout();
5975 		libinput_dispatch(li);
5976 		litest_assert_tablet_proximity_event(li,
5977 						     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
5978 	}
5979 
5980 	/* Send a real prox out, expect quirk to be disabled */
5981 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
5982 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
5983 	libinput_dispatch(li);
5984 
5985 	if (with_timeout) {
5986 		/* we got the proximity event above already */
5987 		litest_assert_empty_queue(li);
5988 	} else {
5989 		litest_assert_tablet_proximity_event(li,
5990 						     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
5991 	}
5992 
5993 	litest_tablet_proximity_in(dev, 50, 50, NULL);
5994 	libinput_dispatch(li);
5995 	litest_assert_tablet_proximity_event(li,
5996 			     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
5997 
5998 	for (i = 0; i < 10; i++) {
5999 		litest_tablet_motion(dev, 50 + i, 50 + i, NULL);
6000 		libinput_dispatch(li);
6001 	}
6002 
6003 	litest_assert_only_typed_events(li,
6004 					LIBINPUT_EVENT_TABLET_TOOL_AXIS);
6005 
6006 	libinput_dispatch(li);
6007 	litest_timeout_tablet_proxout();
6008 	libinput_dispatch(li);
6009 
6010 	litest_assert_empty_queue(li);
6011 
6012 	litest_push_event_frame(dev);
6013 	litest_tablet_proximity_out(dev);
6014 	litest_event(dev, EV_KEY, BTN_TOOL_PEN, 0);
6015 	litest_event(dev, EV_SYN, SYN_REPORT, 0);
6016 	litest_pop_event_frame(dev);
6017 	libinput_dispatch(li);
6018 
6019 	litest_assert_tablet_proximity_event(li,
6020 			     LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
6021 	litest_assert_empty_queue(li);
6022 }
6023 END_TEST
6024 
START_TEST(tablet_smoothing)6025 START_TEST(tablet_smoothing)
6026 {
6027 #if HAVE_LIBWACOM
6028 	struct litest_device *dev = litest_current_device();
6029 	struct libinput *li = dev->libinput;
6030 	double x, y;
6031 	struct point {
6032 		double x, y;
6033 	} coordinates[100] = {0};
6034 	size_t npoints = 0;
6035 	size_t idx = 0;
6036 	struct axis_replacement axes[] = {
6037 		{ ABS_DISTANCE, 10 },
6038 		{ ABS_PRESSURE, 0 },
6039 		{ -1, -1 }
6040 	};
6041 
6042 	litest_drain_events(li);
6043 
6044 	litest_tablet_proximity_in(dev, 10, 10, axes);
6045 	libinput_dispatch(li);
6046 	litest_drain_events(li);
6047 
6048 	/* Move in a straight line, collect the resulting points */
6049 	for (x = 11, y = 11; x < 50; x++, y++) {
6050 		struct libinput_event *event;
6051 		struct libinput_event_tablet_tool *tev;
6052 		struct point *p = &coordinates[npoints++];
6053 
6054 		litest_assert(npoints <= ARRAY_LENGTH(coordinates));
6055 
6056 		litest_tablet_motion(dev, x, y, axes);
6057 		libinput_dispatch(li);
6058 
6059 		event = libinput_get_event(li);
6060 		tev = litest_is_tablet_event(event,
6061 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
6062 		p->x = libinput_event_tablet_tool_get_x(tev);
6063 		p->y = libinput_event_tablet_tool_get_y(tev);
6064 
6065 		libinput_event_destroy(event);
6066 	}
6067 
6068 	litest_tablet_proximity_out(dev);
6069 	litest_tablet_proximity_in(dev, 10, 10, axes);
6070 	libinput_dispatch(li);
6071 	litest_drain_events(li);
6072 
6073 	/* Move in a wobbly line, collect every second point */
6074 	for (x = 11, y = 11; x < 50; x++, y++) {
6075 		struct libinput_event *event;
6076 		struct libinput_event_tablet_tool *tev;
6077 		double ex, ey;
6078 		struct point *p = &coordinates[idx++];
6079 
6080 		litest_assert(idx <= npoints);
6081 
6082 		/* point off position */
6083 		litest_tablet_motion(dev, x - 2, y + 1, axes);
6084 		libinput_dispatch(li);
6085 		event = libinput_get_event(li);
6086 		litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
6087 		libinput_event_destroy(event);
6088 
6089 		/* same position as before */
6090 		litest_tablet_motion(dev, x, y, axes);
6091 		libinput_dispatch(li);
6092 		event = libinput_get_event(li);
6093 		tev = litest_is_tablet_event(event,
6094 					     LIBINPUT_EVENT_TABLET_TOOL_AXIS);
6095 		ex = libinput_event_tablet_tool_get_x(tev);
6096 		ey = libinput_event_tablet_tool_get_y(tev);
6097 
6098 		ck_assert_double_eq(ex, p->x);
6099 		ck_assert_double_eq(ey, p->y);
6100 
6101 		libinput_event_destroy(event);
6102 	}
6103 #endif
6104 }
6105 END_TEST
6106 
TEST_COLLECTION(tablet)6107 TEST_COLLECTION(tablet)
6108 {
6109 	struct range with_timeout = { 0, 2 };
6110 	struct range xyaxes = { ABS_X, ABS_Y + 1 };
6111 	struct range lh_transitions = {0, 16}; /* 2 bits for in, 2 bits for out */
6112 
6113 	litest_add(tool_ref, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
6114 	litest_add(tool_user_data, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
6115 	litest_add(tool_capability, LITEST_TABLET, LITEST_ANY);
6116 	litest_add_no_device(tool_capabilities);
6117 	litest_add(tool_type, LITEST_TABLET, LITEST_FORCED_PROXOUT);
6118 	litest_add(tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM);
6119 	litest_add(tool_direct_switch_skip_tool_update, LITEST_TABLET, LITEST_ANY);
6120 	litest_add(tool_direct_switch_with_forced_proxout, LITEST_TABLET, LITEST_ANY);
6121 
6122 	/* Tablets hold back the proximity until the first event from the
6123 	 * kernel, the totem sends it immediately */
6124 	litest_add(tool_in_prox_before_start, LITEST_TABLET, LITEST_TOTEM);
6125 	litest_add(tool_unique, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
6126 	litest_add(tool_serial, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
6127 	litest_add(tool_id, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
6128 	litest_add(serial_changes_tool, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
6129 	litest_add(invalid_serials, LITEST_TABLET | LITEST_TOOL_SERIAL, LITEST_ANY);
6130 	litest_add_no_device(tools_with_serials);
6131 	litest_add_no_device(tools_without_serials);
6132 	litest_add_for_device(tool_delayed_serial, LITEST_WACOM_HID4800_PEN);
6133 	litest_add(proximity_out_clear_buttons, LITEST_TABLET, LITEST_FORCED_PROXOUT);
6134 	litest_add(proximity_in_out, LITEST_TABLET, LITEST_ANY);
6135 	litest_add(proximity_in_button_down, LITEST_TABLET, LITEST_ANY);
6136 	litest_add(proximity_out_button_up, LITEST_TABLET, LITEST_ANY);
6137 	litest_add(proximity_has_axes, LITEST_TABLET, LITEST_ANY);
6138 	litest_add(bad_distance_events, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
6139 	litest_add(proximity_range_enter, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
6140 	litest_add(proximity_range_in_out, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
6141 	litest_add(proximity_range_button_click, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
6142 	litest_add(proximity_range_button_press, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
6143 	litest_add(proximity_range_button_release, LITEST_TABLET | LITEST_DISTANCE | LITEST_TOOL_MOUSE, LITEST_ANY);
6144 	litest_add(proximity_out_slow_event, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
6145 	litest_add(proximity_out_not_during_contact, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
6146 	litest_add(proximity_out_not_during_buttonpress, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
6147 	litest_add(proximity_out_disables_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM);
6148 	litest_add(proximity_out_disables_forced_after_forced, LITEST_TABLET, LITEST_FORCED_PROXOUT|LITEST_TOTEM);
6149 	litest_add_no_device(proximity_out_on_delete);
6150 	litest_add(button_down_up, LITEST_TABLET, LITEST_ANY);
6151 	litest_add(button_seat_count, LITEST_TABLET, LITEST_ANY);
6152 	litest_add_no_device(button_up_on_delete);
6153 	litest_add(tip_down_up, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6154 	litest_add(tip_down_prox_in, LITEST_TABLET, LITEST_ANY);
6155 	litest_add(tip_up_prox_out, LITEST_TABLET, LITEST_ANY);
6156 	litest_add(tip_down_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6157 	litest_add(tip_up_btn_change, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6158 	litest_add(tip_down_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6159 	litest_add(tip_up_motion, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6160 	litest_add(tip_down_up_eraser, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6161 	litest_add_ranged(tip_up_motion_one_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY, &xyaxes);
6162 	litest_add(tip_state_proximity, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6163 	litest_add(tip_state_axis, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6164 	litest_add(tip_state_button, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6165 	litest_add_no_device(tip_up_on_delete);
6166 	litest_add(motion, LITEST_TABLET, LITEST_ANY);
6167 	litest_add(motion_event_state, LITEST_TABLET, LITEST_ANY);
6168 	litest_add_for_device(motion_outside_bounds, LITEST_WACOM_CINTIQ_24HD);
6169 	litest_add(tilt_available, LITEST_TABLET|LITEST_TILT, LITEST_ANY);
6170 	litest_add(tilt_not_available, LITEST_TABLET, LITEST_TILT);
6171 	litest_add(tilt_x, LITEST_TABLET|LITEST_TILT, LITEST_ANY);
6172 	litest_add(tilt_y, LITEST_TABLET|LITEST_TILT, LITEST_ANY);
6173 	litest_add_for_device(left_handed, LITEST_WACOM_INTUOS);
6174 	litest_add_for_device(left_handed_tilt, LITEST_WACOM_INTUOS);
6175 	litest_add_for_device(left_handed_mouse_rotation, LITEST_WACOM_INTUOS);
6176 	litest_add_for_device(left_handed_artpen_rotation, LITEST_WACOM_INTUOS);
6177 	litest_add_for_device(no_left_handed, LITEST_WACOM_CINTIQ);
6178 	litest_add(pad_buttons_ignored, LITEST_TABLET, LITEST_TOTEM);
6179 	litest_add(mouse_tool, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY);
6180 	litest_add(mouse_buttons, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY);
6181 	litest_add(mouse_rotation, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_ANY);
6182 	litest_add(mouse_wheel, LITEST_TABLET | LITEST_TOOL_MOUSE, LITEST_WHEEL);
6183 	litest_add(airbrush_tool, LITEST_TABLET, LITEST_ANY);
6184 	litest_add(airbrush_slider, LITEST_TABLET, LITEST_ANY);
6185 	litest_add(artpen_tool, LITEST_TABLET, LITEST_ANY);
6186 	litest_add(artpen_rotation, LITEST_TABLET, LITEST_ANY);
6187 
6188 	litest_add(tablet_time_usec, LITEST_TABLET, LITEST_ANY);
6189 	litest_add(tablet_pressure_distance_exclusive, LITEST_TABLET | LITEST_DISTANCE, LITEST_ANY);
6190 
6191 	/* The totem doesn't need calibration */
6192 	litest_add(tablet_calibration_has_matrix, LITEST_TABLET, LITEST_TOTEM|LITEST_PRECALIBRATED);
6193 	litest_add(tablet_calibration_set_matrix, LITEST_TABLET, LITEST_TOTEM|LITEST_PRECALIBRATED);
6194 	litest_add(tablet_calibration_set_matrix_delta, LITEST_TABLET, LITEST_TOTEM|LITEST_PRECALIBRATED);
6195 
6196 	litest_add(tablet_pressure_min_max, LITEST_TABLET, LITEST_ANY);
6197 	/* Tests for pressure offset with distance */
6198 	litest_add_for_device(tablet_pressure_range, LITEST_WACOM_INTUOS);
6199 	litest_add_for_device(tablet_pressure_offset_set, LITEST_WACOM_INTUOS);
6200 	litest_add_for_device(tablet_pressure_offset_decrease, LITEST_WACOM_INTUOS);
6201 	litest_add_for_device(tablet_pressure_offset_increase, LITEST_WACOM_INTUOS);
6202 	litest_add_for_device(tablet_pressure_offset_exceed_threshold, LITEST_WACOM_INTUOS);
6203 	litest_add_for_device(tablet_pressure_offset_none_for_zero_distance, LITEST_WACOM_INTUOS);
6204 	litest_add_for_device(tablet_pressure_offset_none_for_small_distance, LITEST_WACOM_INTUOS);
6205 	/* Tests for pressure offset without distance */
6206 	litest_add_for_device(tablet_pressure_range, LITEST_WACOM_HID4800_PEN);
6207 	litest_add_for_device(tablet_pressure_offset_set, LITEST_WACOM_HID4800_PEN);
6208 	litest_add_for_device(tablet_pressure_offset_decrease, LITEST_WACOM_HID4800_PEN);
6209 	litest_add_for_device(tablet_pressure_offset_increase, LITEST_WACOM_HID4800_PEN);
6210 	litest_add_for_device(tablet_pressure_offset_exceed_threshold, LITEST_WACOM_HID4800_PEN);
6211 
6212 
6213 	litest_add_for_device(tablet_distance_range, LITEST_WACOM_INTUOS);
6214 
6215 	litest_add(relative_no_profile, LITEST_TABLET, LITEST_ANY);
6216 	litest_add(relative_no_delta_prox_in, LITEST_TABLET, LITEST_ANY);
6217 	litest_add(relative_delta, LITEST_TABLET, LITEST_ANY);
6218 	litest_add(relative_no_delta_on_tip, LITEST_TABLET|LITEST_HOVER, LITEST_ANY);
6219 	litest_add(relative_calibration, LITEST_TABLET, LITEST_PRECALIBRATED);
6220 
6221 	litest_add(touch_arbitration, LITEST_TABLET, LITEST_ANY);
6222 	litest_add(touch_arbitration_stop_touch, LITEST_TABLET, LITEST_ANY);
6223 	litest_add(touch_arbitration_suspend_touch_device, LITEST_TOUCH, LITEST_ANY);
6224 	litest_add(touch_arbitration_remove_touch, LITEST_TABLET, LITEST_ANY);
6225 	litest_add(touch_arbitration_remove_tablet, LITEST_TOUCH, LITEST_ANY);
6226 	litest_add(touch_arbitration_keep_ignoring, LITEST_TABLET, LITEST_ANY);
6227 	litest_add(touch_arbitration_late_touch_lift, LITEST_TABLET, LITEST_ANY);
6228 	litest_add(touch_arbitration_outside_rect, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY);
6229 	litest_add(touch_arbitration_remove_after, LITEST_TABLET | LITEST_DIRECT, LITEST_ANY);
6230 	litest_add(touch_arbitration_swap_device, LITEST_TABLET, LITEST_ANY);
6231 
6232 	litest_add_ranged(tablet_rotation_left_handed, LITEST_TABLET, LITEST_ANY, &lh_transitions);
6233 	litest_add_ranged(tablet_rotation_left_handed_configuration, LITEST_TABLET, LITEST_ANY, &lh_transitions);
6234 	litest_add_ranged(tablet_rotation_left_handed_while_in_prox, LITEST_TABLET, LITEST_ANY, &lh_transitions);
6235 	litest_add_ranged(tablet_rotation_left_handed_while_touch_down, LITEST_TABLET, LITEST_ANY, &lh_transitions);
6236 	litest_add_ranged(tablet_rotation_left_handed_add_touchpad, LITEST_TABLET, LITEST_ANY, &lh_transitions);
6237 	litest_add_ranged(tablet_rotation_left_handed_add_tablet, LITEST_TOUCHPAD, LITEST_ANY, &lh_transitions);
6238 
6239 	litest_add_for_device(huion_static_btn_tool_pen, LITEST_HUION_TABLET);
6240 	litest_add_for_device(huion_static_btn_tool_pen_no_timeout_during_usage, LITEST_HUION_TABLET);
6241 	litest_add_ranged_for_device(huion_static_btn_tool_pen_disable_quirk_on_prox_out, LITEST_HUION_TABLET, &with_timeout);
6242 
6243 	litest_add_for_device(tablet_smoothing, LITEST_WACOM_HID4800_PEN);
6244 }
6245