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