1 /*
2 * Copyright © 2018 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <config.h>
25
26 #include <check.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <libinput.h>
30 #include <unistd.h>
31 #include <stdbool.h>
32 #include <stdarg.h>
33
34 #include "libinput-util.h"
35 #include "evdev-tablet.h"
36 #include "litest.h"
37
START_TEST(totem_type)38 START_TEST(totem_type)
39 {
40 struct litest_device *dev = litest_current_device();
41 struct libinput *li = dev->libinput;
42 struct libinput_event *event;
43 struct libinput_event_tablet_tool *t;
44 struct libinput_tablet_tool *tool;
45
46 litest_drain_events(li);
47
48 litest_tablet_proximity_in(dev, 50, 50, NULL);
49 libinput_dispatch(li);
50
51 event = libinput_get_event(li);
52 t = litest_is_tablet_event(event,
53 LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
54 tool = libinput_event_tablet_tool_get_tool(t);
55
56 ck_assert_int_eq(libinput_tablet_tool_get_type(tool),
57 LIBINPUT_TABLET_TOOL_TYPE_TOTEM);
58 libinput_event_destroy(event);
59 }
60 END_TEST
61
START_TEST(totem_axes)62 START_TEST(totem_axes)
63 {
64 struct litest_device *dev = litest_current_device();
65 struct libinput *li = dev->libinput;
66 struct libinput_event *event;
67 struct libinput_event_tablet_tool *t;
68 struct libinput_tablet_tool *tool;
69
70 litest_drain_events(li);
71
72 litest_tablet_proximity_in(dev, 50, 50, NULL);
73 libinput_dispatch(li);
74
75 event = libinput_get_event(li);
76 t = litest_is_tablet_event(event,
77 LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
78 tool = libinput_event_tablet_tool_get_tool(t);
79
80 ck_assert(libinput_tablet_tool_has_rotation(tool));
81 ck_assert(libinput_tablet_tool_has_size(tool));
82 ck_assert(libinput_tablet_tool_has_button(tool, BTN_0));
83
84 libinput_event_destroy(event);
85 }
86 END_TEST
87
START_TEST(totem_proximity_in_out)88 START_TEST(totem_proximity_in_out)
89 {
90 struct litest_device *dev = litest_current_device();
91 struct libinput *li = dev->libinput;
92 struct libinput_event *event;
93 struct libinput_event_tablet_tool *t;
94
95 litest_drain_events(li);
96
97 litest_tablet_proximity_in(dev, 50, 50, NULL);
98 libinput_dispatch(li);
99
100 event = libinput_get_event(li);
101 t = litest_is_tablet_event(event,
102 LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
103 ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(t),
104 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
105 libinput_event_destroy(event);
106
107 event = libinput_get_event(li);
108 t = litest_is_tablet_event(event,
109 LIBINPUT_EVENT_TABLET_TOOL_TIP);
110 ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(t),
111 LIBINPUT_TABLET_TOOL_TIP_DOWN);
112 libinput_event_destroy(event);
113
114 litest_assert_empty_queue(li);
115 litest_tablet_proximity_out(dev);
116 libinput_dispatch(li);
117
118 event = libinput_get_event(li);
119 t = litest_is_tablet_event(event,
120 LIBINPUT_EVENT_TABLET_TOOL_TIP);
121 ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(t),
122 LIBINPUT_TABLET_TOOL_TIP_UP);
123 libinput_event_destroy(event);
124
125 event = libinput_get_event(li);
126 t = litest_is_tablet_event(event,
127 LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
128 ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(t),
129 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
130 libinput_event_destroy(event);
131 }
132 END_TEST
133
START_TEST(totem_proximity_in_on_init)134 START_TEST(totem_proximity_in_on_init)
135 {
136 struct litest_device *dev = litest_current_device();
137 struct libinput *li;
138 struct libinput_event *event;
139 struct libinput_event_tablet_tool *t;
140 const char *devnode;
141 double x, y;
142 double w, h;
143 const struct input_absinfo *abs;
144
145 abs = libevdev_get_abs_info(dev->evdev, ABS_MT_POSITION_X);
146 w = (abs->maximum - abs->minimum + 1)/abs->resolution;
147 abs = libevdev_get_abs_info(dev->evdev, ABS_MT_POSITION_Y);
148 h = (abs->maximum - abs->minimum + 1)/abs->resolution;
149
150 litest_tablet_proximity_in(dev, 50, 50, NULL);
151
152 /* for simplicity, we create a new litest context */
153 devnode = libevdev_uinput_get_devnode(dev->uinput);
154 li = litest_create_context();
155 libinput_path_add_device(li, devnode);
156 libinput_dispatch(li);
157
158 litest_wait_for_event_of_type(li,
159 LIBINPUT_EVENT_DEVICE_ADDED,
160 -1);
161 event = libinput_get_event(li);
162 libinput_event_destroy(event);
163
164 event = libinput_get_event(li);
165 t = litest_is_tablet_event(event,
166 LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
167 ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(t),
168 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
169 x = libinput_event_tablet_tool_get_x(t);
170 y = libinput_event_tablet_tool_get_y(t);
171
172 ck_assert_double_gt(x, w/2 - 1);
173 ck_assert_double_lt(x, w/2 + 1);
174 ck_assert_double_gt(y, h/2 - 1);
175 ck_assert_double_lt(y, h/2 + 1);
176
177 libinput_event_destroy(event);
178
179 event = libinput_get_event(li);
180 t = litest_is_tablet_event(event,
181 LIBINPUT_EVENT_TABLET_TOOL_TIP);
182 ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(t),
183 LIBINPUT_TABLET_TOOL_TIP_DOWN);
184 x = libinput_event_tablet_tool_get_x(t);
185 y = libinput_event_tablet_tool_get_y(t);
186
187 ck_assert_double_gt(x, w/2 - 1);
188 ck_assert_double_lt(x, w/2 + 1);
189 ck_assert_double_gt(y, h/2 - 1);
190 ck_assert_double_lt(y, h/2 + 1);
191
192 libinput_event_destroy(event);
193
194 litest_assert_empty_queue(li);
195
196 litest_destroy_context(li);
197 }
198 END_TEST
199
START_TEST(totem_proximity_out_on_suspend)200 START_TEST(totem_proximity_out_on_suspend)
201 {
202 struct litest_device *dev = litest_current_device();
203 struct libinput *li;
204 struct libinput_event *event;
205 struct libinput_event_tablet_tool *t;
206 const char *devnode;
207
208 /* for simplicity, we create a new litest context */
209 devnode = libevdev_uinput_get_devnode(dev->uinput);
210 li = litest_create_context();
211 libinput_path_add_device(li, devnode);
212
213 litest_tablet_proximity_in(dev, 50, 50, NULL);
214 litest_drain_events(li);
215
216 libinput_suspend(li);
217
218 libinput_dispatch(li);
219 event = libinput_get_event(li);
220 t = litest_is_tablet_event(event,
221 LIBINPUT_EVENT_TABLET_TOOL_TIP);
222 ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(t),
223 LIBINPUT_TABLET_TOOL_TIP_UP);
224 libinput_event_destroy(event);
225
226 event = libinput_get_event(li);
227 t = litest_is_tablet_event(event,
228 LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
229 ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(t),
230 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
231 libinput_event_destroy(event);
232
233 litest_assert_only_typed_events(li, LIBINPUT_EVENT_DEVICE_REMOVED);
234 litest_destroy_context(li);
235 }
236 END_TEST
237
START_TEST(totem_motion)238 START_TEST(totem_motion)
239 {
240 struct litest_device *dev = litest_current_device();
241 struct libinput *li = dev->libinput;
242 struct libinput_event *event;
243 double x = 50, y = 50;
244 double current_x, current_y, old_x, old_y;
245
246 litest_tablet_proximity_in(dev, x, y, NULL);
247 litest_drain_events(li);
248
249 for (int i = 0; i < 30; i++, x++, y--) {
250 struct libinput_event_tablet_tool *t;
251
252 litest_tablet_motion(dev, x + 1, y + 1, NULL);
253 libinput_dispatch(li);
254
255 event = libinput_get_event(li);
256 t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
257
258 ck_assert(libinput_event_tablet_tool_x_has_changed(t));
259 ck_assert(libinput_event_tablet_tool_y_has_changed(t));
260
261 current_x = libinput_event_tablet_tool_get_x(t);
262 current_y = libinput_event_tablet_tool_get_y(t);
263 if (i != 0) {
264 ck_assert_double_gt(current_x, old_x);
265 ck_assert_double_lt(current_y, old_y);
266 }
267 old_x = current_x;
268 old_y = current_y;
269
270 libinput_event_destroy(event);
271 }
272 }
273 END_TEST
274
START_TEST(totem_rotation)275 START_TEST(totem_rotation)
276 {
277 struct litest_device *dev = litest_current_device();
278 struct libinput *li = dev->libinput;
279 struct libinput_event *event;
280 double r, old_r;
281 struct axis_replacement axes[] = {
282 { ABS_MT_ORIENTATION, 50 }, /* mid-point is 0 */
283 { -1, -1 }
284 };
285
286 litest_tablet_proximity_in(dev, 50, 50, axes);
287 litest_drain_events(li);
288
289 old_r = 360;
290
291 for (int i = 1; i < 30; i++) {
292 struct libinput_event_tablet_tool *t;
293
294
295 litest_axis_set_value(axes, ABS_MT_ORIENTATION, 50 + i);
296 litest_tablet_motion(dev, 50, 50, axes);
297 libinput_dispatch(li);
298
299 event = libinput_get_event(li);
300 t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
301
302 ck_assert(!libinput_event_tablet_tool_x_has_changed(t));
303 ck_assert(!libinput_event_tablet_tool_y_has_changed(t));
304 ck_assert(libinput_event_tablet_tool_rotation_has_changed(t));
305
306 r = libinput_event_tablet_tool_get_rotation(t);
307 ck_assert_double_lt(r, old_r);
308 old_r = r;
309
310 libinput_event_destroy(event);
311 }
312
313 old_r = 0;
314
315 for (int i = 1; i < 30; i++) {
316 struct libinput_event_tablet_tool *t;
317
318
319 litest_axis_set_value(axes, ABS_MT_ORIENTATION, 50 - i);
320 litest_tablet_motion(dev, 50, 50, axes);
321 libinput_dispatch(li);
322
323 event = libinput_get_event(li);
324 t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
325
326 ck_assert(!libinput_event_tablet_tool_x_has_changed(t));
327 ck_assert(!libinput_event_tablet_tool_y_has_changed(t));
328 ck_assert(libinput_event_tablet_tool_rotation_has_changed(t));
329
330 r = libinput_event_tablet_tool_get_rotation(t);
331 ck_assert_double_gt(r, old_r);
332 old_r = r;
333
334 libinput_event_destroy(event);
335 }
336 }
337 END_TEST
338
START_TEST(totem_size)339 START_TEST(totem_size)
340 {
341 struct litest_device *dev = litest_current_device();
342 struct libinput *li = dev->libinput;
343 struct libinput_event *event;
344 struct libinput_event_tablet_tool *t;
345 double smin, smaj;
346
347 litest_drain_events(li);
348
349 litest_tablet_proximity_in(dev, 50, 50, NULL);
350 libinput_dispatch(li);
351
352 event = libinput_get_event(li);
353 t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
354 ck_assert(libinput_event_tablet_tool_size_major_has_changed(t));
355 ck_assert(libinput_event_tablet_tool_size_minor_has_changed(t));
356 smaj = libinput_event_tablet_tool_get_size_major(t);
357 smin = libinput_event_tablet_tool_get_size_minor(t);
358 libinput_event_destroy(event);
359
360 ck_assert_double_eq(smaj, 71.8);
361 ck_assert_double_eq(smin, 71.8);
362
363 litest_drain_events(li);
364 }
365 END_TEST
366
START_TEST(totem_button)367 START_TEST(totem_button)
368 {
369 struct litest_device *dev = litest_current_device();
370 struct libinput *li = dev->libinput;
371 struct libinput_event *event;
372 struct libinput_event_tablet_tool *t;
373
374 litest_tablet_proximity_in(dev, 30, 40, NULL);
375 litest_drain_events(li);
376
377 litest_button_click(dev, BTN_0, true);
378 libinput_dispatch(li);
379 event = libinput_get_event(li);
380 t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
381 ck_assert_int_eq(libinput_event_tablet_tool_get_button(t), BTN_0);
382 ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(t),
383 LIBINPUT_BUTTON_STATE_PRESSED);
384 ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(t),
385 LIBINPUT_TABLET_TOOL_TIP_DOWN);
386 libinput_event_destroy(event);
387
388 litest_button_click(dev, BTN_0, false);
389 libinput_dispatch(li);
390
391 event = libinput_get_event(li);
392 t = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
393 ck_assert_int_eq(libinput_event_tablet_tool_get_button(t), BTN_0);
394 ck_assert_int_eq(libinput_event_tablet_tool_get_button_state(t),
395 LIBINPUT_BUTTON_STATE_RELEASED);
396 ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(t),
397 LIBINPUT_TABLET_TOOL_TIP_DOWN);
398 libinput_event_destroy(event);
399 }
400 END_TEST
401
START_TEST(totem_button_down_on_init)402 START_TEST(totem_button_down_on_init)
403 {
404 struct litest_device *dev = litest_current_device();
405 struct libinput *li;
406 struct libinput_event *event;
407 struct libinput_event_tablet_tool *t;
408 const char *devnode;
409
410 litest_tablet_proximity_in(dev, 50, 50, NULL);
411 litest_button_click(dev, BTN_0, true);
412
413 /* for simplicity, we create a new litest context */
414 devnode = libevdev_uinput_get_devnode(dev->uinput);
415 li = litest_create_context();
416 libinput_path_add_device(li, devnode);
417 libinput_dispatch(li);
418
419 litest_wait_for_event_of_type(li,
420 LIBINPUT_EVENT_DEVICE_ADDED,
421 -1);
422 event = libinput_get_event(li);
423 libinput_event_destroy(event);
424
425 event = libinput_get_event(li);
426 t = litest_is_tablet_event(event,
427 LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
428 ck_assert_int_eq(libinput_event_tablet_tool_get_proximity_state(t),
429 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
430
431 libinput_event_destroy(event);
432
433 event = libinput_get_event(li);
434 t = litest_is_tablet_event(event,
435 LIBINPUT_EVENT_TABLET_TOOL_TIP);
436 ck_assert_int_eq(libinput_event_tablet_tool_get_tip_state(t),
437 LIBINPUT_TABLET_TOOL_TIP_DOWN);
438
439 libinput_event_destroy(event);
440
441 /* The button is down on init but we don't expect an event */
442 litest_assert_empty_queue(li);
443
444 litest_button_click(dev, BTN_0, false);
445 libinput_dispatch(li);
446 litest_assert_empty_queue(li);
447
448 /* but buttons after this should be sent */
449 litest_button_click(dev, BTN_0, true);
450 libinput_dispatch(li);
451 litest_assert_tablet_button_event(li, BTN_0, LIBINPUT_BUTTON_STATE_PRESSED);
452 litest_button_click(dev, BTN_0, false);
453 libinput_dispatch(li);
454 litest_assert_tablet_button_event(li, BTN_0, LIBINPUT_BUTTON_STATE_RELEASED);
455
456 litest_destroy_context(li);
457 }
458 END_TEST
459
START_TEST(totem_button_up_on_delete)460 START_TEST(totem_button_up_on_delete)
461 {
462 struct libinput *li = litest_create_context();
463 struct litest_device *dev = litest_add_device(li, LITEST_DELL_CANVAS_TOTEM);
464 struct libevdev *evdev = libevdev_new();
465
466 litest_tablet_proximity_in(dev, 10, 10, NULL);
467 litest_drain_events(li);
468
469 litest_button_click(dev, BTN_0, true);
470 litest_drain_events(li);
471
472 litest_delete_device(dev);
473 libinput_dispatch(li);
474
475 litest_assert_tablet_button_event(li,
476 BTN_0,
477 LIBINPUT_BUTTON_STATE_RELEASED);
478
479 litest_assert_tablet_tip_event(li, LIBINPUT_TABLET_TOOL_TIP_UP);
480 litest_assert_tablet_proximity_event(li,
481 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT);
482 libevdev_free(evdev);
483 litest_destroy_context(li);
484 }
485 END_TEST
486
START_TEST(totem_arbitration_below)487 START_TEST(totem_arbitration_below)
488 {
489 struct litest_device *totem = litest_current_device();
490 struct litest_device *touch;
491 struct libinput *li = totem->libinput;
492
493 touch = litest_add_device(li, LITEST_DELL_CANVAS_TOTEM_TOUCH);
494 litest_drain_events(li);
495
496 /* touches below the totem, cancelled once the totem is down */
497 litest_touch_down(touch, 0, 50, 50);
498 libinput_dispatch(li);
499 litest_assert_touch_down_frame(li);
500 litest_touch_move_to(touch, 0, 50, 50, 50, 70, 10);
501 libinput_dispatch(li);
502 while (libinput_next_event_type(li)) {
503 litest_assert_touch_motion_frame(li);
504 }
505
506 litest_tablet_proximity_in(totem, 50, 70, NULL);
507 libinput_dispatch(li);
508
509 litest_assert_tablet_proximity_event(li, LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
510 litest_assert_tablet_tip_event(li, LIBINPUT_TABLET_TOOL_TIP_DOWN);
511 litest_assert_touch_cancel(li);
512
513 litest_touch_move_to(touch, 0, 50, 70, 20, 50, 10);
514 litest_assert_empty_queue(li);
515
516 litest_tablet_motion(totem, 20, 50, NULL);
517 litest_assert_only_typed_events(li, LIBINPUT_EVENT_TABLET_TOOL_AXIS);
518
519 litest_touch_up(touch, 0);
520 litest_assert_empty_queue(li);
521
522 litest_delete_device(touch);
523 }
524 END_TEST
525
START_TEST(totem_arbitration_during)526 START_TEST(totem_arbitration_during)
527 {
528 struct litest_device *totem = litest_current_device();
529 struct litest_device *touch;
530 struct libinput *li = totem->libinput;
531
532 touch = litest_add_device(li, LITEST_DELL_CANVAS_TOTEM_TOUCH);
533 litest_drain_events(li);
534
535 litest_tablet_proximity_in(totem, 50, 50, NULL);
536 libinput_dispatch(li);
537
538 litest_drain_events(li);
539
540 for (int i = 0; i < 3; i++) {
541 litest_touch_down(touch, 0, 51, 51);
542 litest_touch_move_to(touch, 0, 51, 50, 90, 80, 10);
543 litest_touch_up(touch, 0);
544
545 litest_assert_empty_queue(li);
546 }
547
548 litest_delete_device(touch);
549 }
550 END_TEST
551
START_TEST(totem_arbitration_outside_rect)552 START_TEST(totem_arbitration_outside_rect)
553 {
554 struct litest_device *totem = litest_current_device();
555 struct litest_device *touch;
556 struct libinput *li = totem->libinput;
557
558 touch = litest_add_device(li, LITEST_DELL_CANVAS_TOTEM_TOUCH);
559 litest_drain_events(li);
560
561 litest_tablet_proximity_in(totem, 50, 50, NULL);
562 libinput_dispatch(li);
563
564 litest_drain_events(li);
565
566 for (int i = 0; i < 3; i++) {
567 litest_touch_down(touch, 0, 81, 51);
568 litest_touch_move_to(touch, 0, 81, 50, 90, 80, 10);
569 litest_touch_up(touch, 0);
570 libinput_dispatch(li);
571
572 litest_assert_touch_sequence(li);
573 }
574
575 /* moving onto the totem is fine */
576 litest_touch_down(touch, 0, 81, 51);
577 litest_touch_move_to(touch, 0, 81, 50, 50, 50, 10);
578 litest_touch_up(touch, 0);
579 libinput_dispatch(li);
580
581 litest_assert_touch_sequence(li);
582
583 litest_delete_device(touch);
584 }
585 END_TEST
586
TEST_COLLECTION(totem)587 TEST_COLLECTION(totem)
588 {
589 litest_add("totem:tool", totem_type, LITEST_TOTEM, LITEST_ANY);
590 litest_add("totem:tool", totem_axes, LITEST_TOTEM, LITEST_ANY);
591 litest_add("totem:proximity", totem_proximity_in_out, LITEST_TOTEM, LITEST_ANY);
592 litest_add("totem:proximity", totem_proximity_in_on_init, LITEST_TOTEM, LITEST_ANY);
593 litest_add("totem:proximity", totem_proximity_out_on_suspend, LITEST_TOTEM, LITEST_ANY);
594
595 litest_add("totem:axes", totem_motion, LITEST_TOTEM, LITEST_ANY);
596 litest_add("totem:axes", totem_rotation, LITEST_TOTEM, LITEST_ANY);
597 litest_add("totem:axes", totem_size, LITEST_TOTEM, LITEST_ANY);
598 litest_add("totem:button", totem_button, LITEST_TOTEM, LITEST_ANY);
599 litest_add("totem:button", totem_button_down_on_init, LITEST_TOTEM, LITEST_ANY);
600 litest_add_no_device("totem:button", totem_button_up_on_delete);
601
602 litest_add("totem:arbitration", totem_arbitration_below, LITEST_TOTEM, LITEST_ANY);
603 litest_add("totem:arbitration", totem_arbitration_during, LITEST_TOTEM, LITEST_ANY);
604 litest_add("totem:arbitration", totem_arbitration_outside_rect, LITEST_TOTEM, LITEST_ANY);
605 }
606