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