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