1 /*
2 * Copyright © 2014 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 <errno.h>
27 #include <inttypes.h>
28 #include <getopt.h>
29 #include <poll.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <time.h>
35 #include <unistd.h>
36 #include "linux/input.h"
37
38 #include <libinput.h>
39 #include <libevdev/libevdev.h>
40
41 #include "libinput-version.h"
42 #include "util-strings.h"
43 #include "util-macros.h"
44 #include "shared.h"
45
46 static uint32_t start_time;
47 static const uint32_t screen_width = 100;
48 static const uint32_t screen_height = 100;
49 static struct tools_options options;
50 static bool show_keycodes;
51 static volatile sig_atomic_t stop = 0;
52 static bool be_quiet = false;
53
54 #define printq(...) ({ if (!be_quiet) printf(__VA_ARGS__); })
55
56 static void
print_event_header(struct libinput_event * ev)57 print_event_header(struct libinput_event *ev)
58 {
59 /* use for pointer value only, do not dereference */
60 static void *last_device = NULL;
61 struct libinput_device *dev = libinput_event_get_device(ev);
62 const char *type = NULL;
63 char prefix;
64
65 switch(libinput_event_get_type(ev)) {
66 case LIBINPUT_EVENT_NONE:
67 abort();
68 case LIBINPUT_EVENT_DEVICE_ADDED:
69 type = "DEVICE_ADDED";
70 break;
71 case LIBINPUT_EVENT_DEVICE_REMOVED:
72 type = "DEVICE_REMOVED";
73 break;
74 case LIBINPUT_EVENT_KEYBOARD_KEY:
75 type = "KEYBOARD_KEY";
76 break;
77 case LIBINPUT_EVENT_POINTER_MOTION:
78 type = "POINTER_MOTION";
79 break;
80 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
81 type = "POINTER_MOTION_ABSOLUTE";
82 break;
83 case LIBINPUT_EVENT_POINTER_BUTTON:
84 type = "POINTER_BUTTON";
85 break;
86 case LIBINPUT_EVENT_POINTER_AXIS:
87 type = "POINTER_AXIS";
88 break;
89 case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
90 type = "POINTER_SCROLL_WHEEL";
91 break;
92 case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
93 type = "POINTER_SCROLL_FINGER";
94 break;
95 case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
96 type = "POINTER_SCROLL_CONTINUOUS";
97 break;
98 case LIBINPUT_EVENT_TOUCH_DOWN:
99 type = "TOUCH_DOWN";
100 break;
101 case LIBINPUT_EVENT_TOUCH_MOTION:
102 type = "TOUCH_MOTION";
103 break;
104 case LIBINPUT_EVENT_TOUCH_UP:
105 type = "TOUCH_UP";
106 break;
107 case LIBINPUT_EVENT_TOUCH_CANCEL:
108 type = "TOUCH_CANCEL";
109 break;
110 case LIBINPUT_EVENT_TOUCH_FRAME:
111 type = "TOUCH_FRAME";
112 break;
113 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
114 type = "GESTURE_SWIPE_BEGIN";
115 break;
116 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
117 type = "GESTURE_SWIPE_UPDATE";
118 break;
119 case LIBINPUT_EVENT_GESTURE_SWIPE_END:
120 type = "GESTURE_SWIPE_END";
121 break;
122 case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
123 type = "GESTURE_PINCH_BEGIN";
124 break;
125 case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
126 type = "GESTURE_PINCH_UPDATE";
127 break;
128 case LIBINPUT_EVENT_GESTURE_PINCH_END:
129 type = "GESTURE_PINCH_END";
130 break;
131 case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
132 type = "GESTURE_HOLD_BEGIN";
133 break;
134 case LIBINPUT_EVENT_GESTURE_HOLD_END:
135 type = "GESTURE_HOLD_END";
136 break;
137 case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
138 type = "TABLET_TOOL_AXIS";
139 break;
140 case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
141 type = "TABLET_TOOL_PROXIMITY";
142 break;
143 case LIBINPUT_EVENT_TABLET_TOOL_TIP:
144 type = "TABLET_TOOL_TIP";
145 break;
146 case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
147 type = "TABLET_TOOL_BUTTON";
148 break;
149 case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
150 type = "TABLET_PAD_BUTTON";
151 break;
152 case LIBINPUT_EVENT_TABLET_PAD_RING:
153 type = "TABLET_PAD_RING";
154 break;
155 case LIBINPUT_EVENT_TABLET_PAD_STRIP:
156 type = "TABLET_PAD_STRIP";
157 break;
158 case LIBINPUT_EVENT_TABLET_PAD_KEY:
159 type = "TABLET_PAD_KEY";
160 break;
161 case LIBINPUT_EVENT_SWITCH_TOGGLE:
162 type = "SWITCH_TOGGLE";
163 break;
164 }
165
166 prefix = (last_device != dev) ? '-' : ' ';
167
168 printq("%c%-7s %-23s ",
169 prefix,
170 libinput_device_get_sysname(dev),
171 type);
172
173 last_device = dev;
174 }
175
176 static void
print_event_time(uint32_t time)177 print_event_time(uint32_t time)
178 {
179 printq("%+6.3fs ", start_time ? (time - start_time) / 1000.0 : 0);
180 }
181
182 static inline void
print_device_options(struct libinput_device * dev)183 print_device_options(struct libinput_device *dev)
184 {
185 uint32_t scroll_methods, click_methods;
186
187 if (libinput_device_config_tap_get_finger_count(dev)) {
188 printq(" tap");
189 if (libinput_device_config_tap_get_drag_lock_enabled(dev))
190 printq("(dl on)");
191 else
192 printq("(dl off)");
193 }
194 if (libinput_device_config_left_handed_is_available(dev))
195 printq(" left");
196 if (libinput_device_config_scroll_has_natural_scroll(dev))
197 printq(" scroll-nat");
198 if (libinput_device_config_calibration_has_matrix(dev))
199 printq(" calib");
200
201 scroll_methods = libinput_device_config_scroll_get_methods(dev);
202 if (scroll_methods != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) {
203 printq(" scroll");
204 if (scroll_methods & LIBINPUT_CONFIG_SCROLL_2FG)
205 printq("-2fg");
206 if (scroll_methods & LIBINPUT_CONFIG_SCROLL_EDGE)
207 printq("-edge");
208 if (scroll_methods & LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)
209 printq("-button");
210 }
211
212 click_methods = libinput_device_config_click_get_methods(dev);
213 if (click_methods != LIBINPUT_CONFIG_CLICK_METHOD_NONE) {
214 printq(" click");
215 if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS)
216 printq("-buttonareas");
217 if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER)
218 printq("-clickfinger");
219 }
220
221 if (libinput_device_config_dwt_is_available(dev)) {
222 if (libinput_device_config_dwt_get_enabled(dev) ==
223 LIBINPUT_CONFIG_DWT_ENABLED)
224 printq(" dwt-on");
225 else
226 printq(" dwt-off)");
227 }
228
229 if (libinput_device_has_capability(dev,
230 LIBINPUT_DEVICE_CAP_TABLET_PAD)) {
231 int nbuttons, nstrips, nrings, ngroups;
232
233 nbuttons = libinput_device_tablet_pad_get_num_buttons(dev);
234 nstrips = libinput_device_tablet_pad_get_num_strips(dev);
235 nrings = libinput_device_tablet_pad_get_num_rings(dev);
236 ngroups = libinput_device_tablet_pad_get_num_mode_groups(dev);
237
238 printq(" buttons:%d strips:%d rings:%d mode groups:%d",
239 nbuttons,
240 nstrips,
241 nrings,
242 ngroups);
243 }
244 }
245
246 static void
print_device_notify(struct libinput_event * ev)247 print_device_notify(struct libinput_event *ev)
248 {
249 struct libinput_device *dev = libinput_event_get_device(ev);
250 struct libinput_seat *seat = libinput_device_get_seat(dev);
251 struct libinput_device_group *group;
252 double w, h;
253 static int next_group_id = 0;
254 intptr_t group_id;
255
256 group = libinput_device_get_device_group(dev);
257 group_id = (intptr_t)libinput_device_group_get_user_data(group);
258 if (!group_id) {
259 group_id = ++next_group_id;
260 libinput_device_group_set_user_data(group, (void*)group_id);
261 }
262
263 printq("%-33s %5s %7s group%-2d",
264 libinput_device_get_name(dev),
265 libinput_seat_get_physical_name(seat),
266 libinput_seat_get_logical_name(seat),
267 (int)group_id);
268
269 printq(" cap:");
270 if (libinput_device_has_capability(dev,
271 LIBINPUT_DEVICE_CAP_KEYBOARD))
272 printq("k");
273 if (libinput_device_has_capability(dev,
274 LIBINPUT_DEVICE_CAP_POINTER))
275 printq("p");
276 if (libinput_device_has_capability(dev,
277 LIBINPUT_DEVICE_CAP_TOUCH))
278 printq("t");
279 if (libinput_device_has_capability(dev,
280 LIBINPUT_DEVICE_CAP_GESTURE))
281 printq("g");
282 if (libinput_device_has_capability(dev,
283 LIBINPUT_DEVICE_CAP_TABLET_TOOL))
284 printq("T");
285 if (libinput_device_has_capability(dev,
286 LIBINPUT_DEVICE_CAP_TABLET_PAD))
287 printq("P");
288 if (libinput_device_has_capability(dev,
289 LIBINPUT_DEVICE_CAP_SWITCH))
290 printq("S");
291
292 if (libinput_device_get_size(dev, &w, &h) == 0)
293 printq(" size %.0fx%.0fmm", w, h);
294
295 if (libinput_device_has_capability(dev,
296 LIBINPUT_DEVICE_CAP_TOUCH))
297 printq(" ntouches %d", libinput_device_touch_get_touch_count(dev));
298
299 if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED)
300 print_device_options(dev);
301
302 printq("\n");
303
304 }
305
306 static void
print_key_event(struct libinput_event * ev)307 print_key_event(struct libinput_event *ev)
308 {
309 struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
310 enum libinput_key_state state;
311 uint32_t key;
312 const char *keyname;
313
314 print_event_time(libinput_event_keyboard_get_time(k));
315 state = libinput_event_keyboard_get_key_state(k);
316
317 key = libinput_event_keyboard_get_key(k);
318 if (!show_keycodes && (key >= KEY_ESC && key < KEY_ZENKAKUHANKAKU)) {
319 keyname = "***";
320 key = -1;
321 } else {
322 keyname = libevdev_event_code_get_name(EV_KEY, key);
323 keyname = keyname ? keyname : "???";
324 }
325 printq("%s (%d) %s\n",
326 keyname,
327 key,
328 state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
329 }
330
331 static void
print_motion_event(struct libinput_event * ev)332 print_motion_event(struct libinput_event *ev)
333 {
334 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
335 double x = libinput_event_pointer_get_dx(p);
336 double y = libinput_event_pointer_get_dy(p);
337 double ux = libinput_event_pointer_get_dx_unaccelerated(p);
338 double uy = libinput_event_pointer_get_dy_unaccelerated(p);
339
340 print_event_time(libinput_event_pointer_get_time(p));
341
342 printq("%6.2f/%6.2f (%+6.2f/%+6.2f)\n", x, y, ux, uy);
343 }
344
345 static void
print_absmotion_event(struct libinput_event * ev)346 print_absmotion_event(struct libinput_event *ev)
347 {
348 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
349 double x = libinput_event_pointer_get_absolute_x_transformed(
350 p, screen_width);
351 double y = libinput_event_pointer_get_absolute_y_transformed(
352 p, screen_height);
353
354 print_event_time(libinput_event_pointer_get_time(p));
355 printq("%6.2f/%6.2f\n", x, y);
356 }
357
358 static void
print_pointer_button_event(struct libinput_event * ev)359 print_pointer_button_event(struct libinput_event *ev)
360 {
361 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
362 enum libinput_button_state state;
363 const char *buttonname;
364 int button;
365
366 print_event_time(libinput_event_pointer_get_time(p));
367
368 button = libinput_event_pointer_get_button(p);
369 buttonname = libevdev_event_code_get_name(EV_KEY, button);
370
371 state = libinput_event_pointer_get_button_state(p);
372 printq("%s (%d) %s, seat count: %u\n",
373 buttonname ? buttonname : "???",
374 button,
375 state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
376 libinput_event_pointer_get_seat_button_count(p));
377 }
378
379 static void
print_tablet_axes(struct libinput_event_tablet_tool * t)380 print_tablet_axes(struct libinput_event_tablet_tool *t)
381 {
382 struct libinput_tablet_tool *tool = libinput_event_tablet_tool_get_tool(t);
383 double x, y;
384 double dist, pressure;
385 double rotation, slider, wheel;
386 double delta;
387 double major, minor;
388
389 #define changed_sym(ev, ax) \
390 (libinput_event_tablet_tool_##ax##_has_changed(ev) ? "*" : "")
391
392 x = libinput_event_tablet_tool_get_x(t);
393 y = libinput_event_tablet_tool_get_y(t);
394 printq("\t%.2f%s/%.2f%s",
395 x, changed_sym(t, x),
396 y, changed_sym(t, y));
397
398 if (libinput_tablet_tool_has_tilt(tool)) {
399 x = libinput_event_tablet_tool_get_tilt_x(t);
400 y = libinput_event_tablet_tool_get_tilt_y(t);
401 printq("\ttilt: %.2f%s/%.2f%s",
402 x, changed_sym(t, tilt_x),
403 y, changed_sym(t, tilt_y));
404 }
405
406 if (libinput_tablet_tool_has_distance(tool) ||
407 libinput_tablet_tool_has_pressure(tool)) {
408 dist = libinput_event_tablet_tool_get_distance(t);
409 pressure = libinput_event_tablet_tool_get_pressure(t);
410 if (dist)
411 printq("\tdistance: %.2f%s",
412 dist, changed_sym(t, distance));
413 else
414 printq("\tpressure: %.2f%s",
415 pressure, changed_sym(t, pressure));
416 }
417
418 if (libinput_tablet_tool_has_rotation(tool)) {
419 rotation = libinput_event_tablet_tool_get_rotation(t);
420 printq("\trotation: %6.2f%s",
421 rotation, changed_sym(t, rotation));
422 }
423
424 if (libinput_tablet_tool_has_slider(tool)) {
425 slider = libinput_event_tablet_tool_get_slider_position(t);
426 printq("\tslider: %.2f%s",
427 slider, changed_sym(t, slider));
428 }
429
430 if (libinput_tablet_tool_has_wheel(tool)) {
431 wheel = libinput_event_tablet_tool_get_wheel_delta(t);
432 delta = libinput_event_tablet_tool_get_wheel_delta_discrete(t);
433 printq("\twheel: %.2f%s (%d)",
434 wheel, changed_sym(t, wheel),
435 (int)delta);
436 }
437
438 if (libinput_tablet_tool_has_size(tool)) {
439 major = libinput_event_tablet_tool_get_size_major(t);
440 minor = libinput_event_tablet_tool_get_size_minor(t);
441 printq("\tsize: %.2f%s/%.2f%s",
442 major, changed_sym(t, size_major),
443 minor, changed_sym(t, size_minor));
444 }
445 }
446
447 static void
print_tablet_tip_event(struct libinput_event * ev)448 print_tablet_tip_event(struct libinput_event *ev)
449 {
450 struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev);
451 enum libinput_tablet_tool_tip_state state;
452
453 print_event_time(libinput_event_tablet_tool_get_time(t));
454
455 print_tablet_axes(t);
456
457 state = libinput_event_tablet_tool_get_tip_state(t);
458 printq(" %s\n", state == LIBINPUT_TABLET_TOOL_TIP_DOWN ? "down" : "up");
459 }
460
461 static void
print_tablet_button_event(struct libinput_event * ev)462 print_tablet_button_event(struct libinput_event *ev)
463 {
464 struct libinput_event_tablet_tool *p = libinput_event_get_tablet_tool_event(ev);
465 enum libinput_button_state state;
466 const char *buttonname;
467 int button;
468
469 print_event_time(libinput_event_tablet_tool_get_time(p));
470
471 button = libinput_event_tablet_tool_get_button(p);
472 buttonname = libevdev_event_code_get_name(EV_KEY, button);
473
474 state = libinput_event_tablet_tool_get_button_state(p);
475 printq("%3d (%s) %s, seat count: %u\n",
476 button,
477 buttonname ? buttonname : "???",
478 state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
479 libinput_event_tablet_tool_get_seat_button_count(p));
480 }
481
482 static void
print_pointer_axis_event(struct libinput_event * ev)483 print_pointer_axis_event(struct libinput_event *ev)
484 {
485 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
486 double v = 0, h = 0, v120 = 0, h120 = 0;
487 const char *have_vert = "",
488 *have_horiz = "";
489 const char *source = "invalid";
490 enum libinput_pointer_axis axis;
491 enum libinput_event_type type;
492
493 type = libinput_event_get_type(ev);
494
495 switch (type) {
496 case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
497 source = "wheel";
498 break;
499 case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
500 source = "finger";
501 break;
502 case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
503 source = "continuous";
504 break;
505 default:
506 abort();
507 break;
508 }
509
510 axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
511 if (libinput_event_pointer_has_axis(p, axis)) {
512 v = libinput_event_pointer_get_scroll_value(p, axis);
513 if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL)
514 v120 = libinput_event_pointer_get_scroll_value_v120(p, axis);
515 have_vert = "*";
516 }
517 axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
518 if (libinput_event_pointer_has_axis(p, axis)) {
519 h = libinput_event_pointer_get_scroll_value(p, axis);
520 if (type == LIBINPUT_EVENT_POINTER_SCROLL_WHEEL)
521 h120 = libinput_event_pointer_get_scroll_value_v120(p, axis);
522 have_horiz = "*";
523 }
524
525 print_event_time(libinput_event_pointer_get_time(p));
526 printq("vert %.2f/%.1f%s horiz %.2f/%.1f%s (%s)\n",
527 v, v120, have_vert,
528 h, h120, have_horiz, source);
529 }
530
531 static void
print_tablet_axis_event(struct libinput_event * ev)532 print_tablet_axis_event(struct libinput_event *ev)
533 {
534 struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev);
535
536 print_event_time(libinput_event_tablet_tool_get_time(t));
537 print_tablet_axes(t);
538 printq("\n");
539 }
540
541 static void
print_proximity_event(struct libinput_event * ev)542 print_proximity_event(struct libinput_event *ev)
543 {
544 struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev);
545 struct libinput_tablet_tool *tool = libinput_event_tablet_tool_get_tool(t);
546 enum libinput_tablet_tool_proximity_state state;
547 const char *tool_str,
548 *state_str;
549
550 switch (libinput_tablet_tool_get_type(tool)) {
551 case LIBINPUT_TABLET_TOOL_TYPE_PEN:
552 tool_str = "pen";
553 break;
554 case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
555 tool_str = "eraser";
556 break;
557 case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
558 tool_str = "brush";
559 break;
560 case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
561 tool_str = "pencil";
562 break;
563 case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
564 tool_str = "airbrush";
565 break;
566 case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
567 tool_str = "mouse";
568 break;
569 case LIBINPUT_TABLET_TOOL_TYPE_LENS:
570 tool_str = "lens";
571 break;
572 case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
573 tool_str = "totem";
574 break;
575 default:
576 abort();
577 }
578
579 state = libinput_event_tablet_tool_get_proximity_state(t);
580
581 print_event_time(libinput_event_tablet_tool_get_time(t));
582
583 if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN) {
584 print_tablet_axes(t);
585 state_str = "proximity-in";
586 } else if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) {
587 print_tablet_axes(t);
588 state_str = "proximity-out";
589 } else {
590 abort();
591 }
592
593 printq("\t%-8s (%#" PRIx64 ", id %#" PRIx64 ") %s ",
594 tool_str,
595 libinput_tablet_tool_get_serial(tool),
596 libinput_tablet_tool_get_tool_id(tool),
597 state_str);
598
599 if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN) {
600 printq("\taxes:");
601 if (libinput_tablet_tool_has_distance(tool))
602 printq("d");
603 if (libinput_tablet_tool_has_pressure(tool))
604 printq("p");
605 if (libinput_tablet_tool_has_tilt(tool))
606 printq("t");
607 if (libinput_tablet_tool_has_rotation(tool))
608 printq("r");
609 if (libinput_tablet_tool_has_slider(tool))
610 printq("s");
611 if (libinput_tablet_tool_has_wheel(tool))
612 printq("w");
613 if (libinput_tablet_tool_has_size(tool))
614 printq("S");
615
616 printq("\tbtn:");
617 if (libinput_tablet_tool_has_button(tool, BTN_TOUCH))
618 printq("T");
619 if (libinput_tablet_tool_has_button(tool, BTN_STYLUS))
620 printq("S");
621 if (libinput_tablet_tool_has_button(tool, BTN_STYLUS2))
622 printq("S2");
623 if (libinput_tablet_tool_has_button(tool, BTN_LEFT))
624 printq("L");
625 if (libinput_tablet_tool_has_button(tool, BTN_MIDDLE))
626 printq("M");
627 if (libinput_tablet_tool_has_button(tool, BTN_RIGHT))
628 printq("R");
629 if (libinput_tablet_tool_has_button(tool, BTN_SIDE))
630 printq("Sd");
631 if (libinput_tablet_tool_has_button(tool, BTN_EXTRA))
632 printq("Ex");
633 if (libinput_tablet_tool_has_button(tool, BTN_0))
634 printq("0");
635 }
636
637 printq("\n");
638 }
639
640 static void
print_touch_event(struct libinput_event * ev)641 print_touch_event(struct libinput_event *ev)
642 {
643 struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
644 enum libinput_event_type type = libinput_event_get_type(ev);
645
646 print_event_time(libinput_event_touch_get_time(t));
647
648 if (type != LIBINPUT_EVENT_TOUCH_FRAME) {
649 printq("%d (%d)",
650 libinput_event_touch_get_slot(t),
651 libinput_event_touch_get_seat_slot(t));
652 }
653
654 if (type == LIBINPUT_EVENT_TOUCH_DOWN ||
655 type == LIBINPUT_EVENT_TOUCH_MOTION) {
656 double x = libinput_event_touch_get_x_transformed(t, screen_width);
657 double y = libinput_event_touch_get_y_transformed(t, screen_height);
658 double xmm = libinput_event_touch_get_x(t);
659 double ymm = libinput_event_touch_get_y(t);
660
661 printq(" %5.2f/%5.2f (%5.2f/%5.2fmm)", x, y, xmm, ymm);
662 }
663
664 printq("\n");
665 }
666
667 static void
print_gesture_event_without_coords(struct libinput_event * ev)668 print_gesture_event_without_coords(struct libinput_event *ev)
669 {
670 struct libinput_event_gesture *t = libinput_event_get_gesture_event(ev);
671 int finger_count = libinput_event_gesture_get_finger_count(t);
672 int cancelled = 0;
673 enum libinput_event_type type;
674
675 type = libinput_event_get_type(ev);
676
677 if (type == LIBINPUT_EVENT_GESTURE_SWIPE_END ||
678 type == LIBINPUT_EVENT_GESTURE_PINCH_END ||
679 type == LIBINPUT_EVENT_GESTURE_HOLD_END)
680 cancelled = libinput_event_gesture_get_cancelled(t);
681
682 print_event_time(libinput_event_gesture_get_time(t));
683 printq("%d%s\n", finger_count, cancelled ? " cancelled" : "");
684 }
685
686 static void
print_gesture_event_with_coords(struct libinput_event * ev)687 print_gesture_event_with_coords(struct libinput_event *ev)
688 {
689 struct libinput_event_gesture *t = libinput_event_get_gesture_event(ev);
690 double dx = libinput_event_gesture_get_dx(t);
691 double dy = libinput_event_gesture_get_dy(t);
692 double dx_unaccel = libinput_event_gesture_get_dx_unaccelerated(t);
693 double dy_unaccel = libinput_event_gesture_get_dy_unaccelerated(t);
694
695 print_event_time(libinput_event_gesture_get_time(t));
696
697 printq("%d %5.2f/%5.2f (%5.2f/%5.2f unaccelerated)",
698 libinput_event_gesture_get_finger_count(t),
699 dx, dy, dx_unaccel, dy_unaccel);
700
701 if (libinput_event_get_type(ev) ==
702 LIBINPUT_EVENT_GESTURE_PINCH_UPDATE) {
703 double scale = libinput_event_gesture_get_scale(t);
704 double angle = libinput_event_gesture_get_angle_delta(t);
705
706 printq(" %5.2f @ %5.2f\n", scale, angle);
707 } else {
708 printq("\n");
709 }
710 }
711
712 static void
print_tablet_pad_button_event(struct libinput_event * ev)713 print_tablet_pad_button_event(struct libinput_event *ev)
714 {
715 struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
716 struct libinput_tablet_pad_mode_group *group;
717 enum libinput_button_state state;
718 unsigned int button, mode;
719
720 print_event_time(libinput_event_tablet_pad_get_time(p));
721
722 button = libinput_event_tablet_pad_get_button_number(p),
723 state = libinput_event_tablet_pad_get_button_state(p);
724 mode = libinput_event_tablet_pad_get_mode(p);
725 printq("%3d %s (mode %d)",
726 button,
727 state == LIBINPUT_BUTTON_STATE_PRESSED ? "pressed" : "released",
728 mode);
729
730 group = libinput_event_tablet_pad_get_mode_group(p);
731 if (libinput_tablet_pad_mode_group_button_is_toggle(group, button))
732 printq(" <mode toggle>");
733
734 printq("\n");
735 }
736
737 static void
print_tablet_pad_ring_event(struct libinput_event * ev)738 print_tablet_pad_ring_event(struct libinput_event *ev)
739 {
740 struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
741 const char *source = "<invalid>";
742 unsigned int mode;
743
744 print_event_time(libinput_event_tablet_pad_get_time(p));
745
746 switch (libinput_event_tablet_pad_get_ring_source(p)) {
747 case LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER:
748 source = "finger";
749 break;
750 case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
751 source = "unknown";
752 break;
753 }
754
755 mode = libinput_event_tablet_pad_get_mode(p);
756 printq("ring %d position %.2f (source %s) (mode %d)\n",
757 libinput_event_tablet_pad_get_ring_number(p),
758 libinput_event_tablet_pad_get_ring_position(p),
759 source,
760 mode);
761 }
762
763 static void
print_tablet_pad_strip_event(struct libinput_event * ev)764 print_tablet_pad_strip_event(struct libinput_event *ev)
765 {
766 struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
767 const char *source = "<invalid>";
768 unsigned int mode;
769
770 print_event_time(libinput_event_tablet_pad_get_time(p));
771
772 switch (libinput_event_tablet_pad_get_strip_source(p)) {
773 case LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER:
774 source = "finger";
775 break;
776 case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
777 source = "unknown";
778 break;
779 }
780
781 mode = libinput_event_tablet_pad_get_mode(p);
782 printq("strip %d position %.2f (source %s) (mode %d)\n",
783 libinput_event_tablet_pad_get_strip_number(p),
784 libinput_event_tablet_pad_get_strip_position(p),
785 source,
786 mode);
787 }
788
789 static void
print_tablet_pad_key_event(struct libinput_event * ev)790 print_tablet_pad_key_event(struct libinput_event *ev)
791 {
792 struct libinput_event_tablet_pad *p = libinput_event_get_tablet_pad_event(ev);
793 enum libinput_key_state state;
794 uint32_t key;
795 const char *keyname;
796
797 print_event_time(libinput_event_tablet_pad_get_time(p));
798
799 key = libinput_event_tablet_pad_get_key(p);
800 if (!show_keycodes && (key >= KEY_ESC && key < KEY_ZENKAKUHANKAKU)) {
801 keyname = "***";
802 key = -1;
803 } else {
804 keyname = libevdev_event_code_get_name(EV_KEY, key);
805 keyname = keyname ? keyname : "???";
806 }
807 state = libinput_event_tablet_pad_get_key_state(p);
808 printq("%s (%d) %s\n",
809 keyname,
810 key,
811 state == LIBINPUT_KEY_STATE_PRESSED ? "pressed" : "released");
812 }
813
814
815 static void
print_switch_event(struct libinput_event * ev)816 print_switch_event(struct libinput_event *ev)
817 {
818 struct libinput_event_switch *sw = libinput_event_get_switch_event(ev);
819 enum libinput_switch_state state;
820 const char *which;
821
822 print_event_time(libinput_event_switch_get_time(sw));
823
824 switch (libinput_event_switch_get_switch(sw)) {
825 case LIBINPUT_SWITCH_LID:
826 which = "lid";
827 break;
828 case LIBINPUT_SWITCH_TABLET_MODE:
829 which = "tablet-mode";
830 break;
831 default:
832 abort();
833 }
834
835 state = libinput_event_switch_get_switch_state(sw);
836
837 printq("switch %s state %d\n", which, state);
838 }
839
840 static int
handle_and_print_events(struct libinput * li)841 handle_and_print_events(struct libinput *li)
842 {
843 int rc = -1;
844 struct libinput_event *ev;
845
846 tools_dispatch(li);
847 while ((ev = libinput_get_event(li))) {
848 enum libinput_event_type type = libinput_event_get_type(ev);
849
850 if (type != LIBINPUT_EVENT_POINTER_AXIS)
851 print_event_header(ev);
852
853 switch (type) {
854 case LIBINPUT_EVENT_NONE:
855 abort();
856 case LIBINPUT_EVENT_DEVICE_ADDED:
857 print_device_notify(ev);
858 tools_device_apply_config(libinput_event_get_device(ev),
859 &options);
860 break;
861 case LIBINPUT_EVENT_DEVICE_REMOVED:
862 print_device_notify(ev);
863 break;
864 case LIBINPUT_EVENT_KEYBOARD_KEY:
865 print_key_event(ev);
866 break;
867 case LIBINPUT_EVENT_POINTER_MOTION:
868 print_motion_event(ev);
869 break;
870 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
871 print_absmotion_event(ev);
872 break;
873 case LIBINPUT_EVENT_POINTER_BUTTON:
874 print_pointer_button_event(ev);
875 break;
876 case LIBINPUT_EVENT_POINTER_AXIS:
877 /* ignore */
878 break;
879 case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
880 case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
881 case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
882 print_pointer_axis_event(ev);
883 break;
884 case LIBINPUT_EVENT_TOUCH_DOWN:
885 case LIBINPUT_EVENT_TOUCH_MOTION:
886 case LIBINPUT_EVENT_TOUCH_UP:
887 case LIBINPUT_EVENT_TOUCH_CANCEL:
888 case LIBINPUT_EVENT_TOUCH_FRAME:
889 print_touch_event(ev);
890 break;
891 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
892 print_gesture_event_without_coords(ev);
893 break;
894 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
895 print_gesture_event_with_coords(ev);
896 break;
897 case LIBINPUT_EVENT_GESTURE_SWIPE_END:
898 print_gesture_event_without_coords(ev);
899 break;
900 case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
901 print_gesture_event_without_coords(ev);
902 break;
903 case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
904 print_gesture_event_with_coords(ev);
905 break;
906 case LIBINPUT_EVENT_GESTURE_PINCH_END:
907 print_gesture_event_without_coords(ev);
908 break;
909 case LIBINPUT_EVENT_GESTURE_HOLD_BEGIN:
910 print_gesture_event_without_coords(ev);
911 break;
912 case LIBINPUT_EVENT_GESTURE_HOLD_END:
913 print_gesture_event_without_coords(ev);
914 break;
915 case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
916 print_tablet_axis_event(ev);
917 break;
918 case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
919 print_proximity_event(ev);
920 break;
921 case LIBINPUT_EVENT_TABLET_TOOL_TIP:
922 print_tablet_tip_event(ev);
923 break;
924 case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
925 print_tablet_button_event(ev);
926 break;
927 case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
928 print_tablet_pad_button_event(ev);
929 break;
930 case LIBINPUT_EVENT_TABLET_PAD_RING:
931 print_tablet_pad_ring_event(ev);
932 break;
933 case LIBINPUT_EVENT_TABLET_PAD_STRIP:
934 print_tablet_pad_strip_event(ev);
935 break;
936 case LIBINPUT_EVENT_TABLET_PAD_KEY:
937 print_tablet_pad_key_event(ev);
938 break;
939 case LIBINPUT_EVENT_SWITCH_TOGGLE:
940 print_switch_event(ev);
941 break;
942 }
943
944 libinput_event_destroy(ev);
945 rc = 0;
946 }
947 return rc;
948 }
949
950 static void
sighandler(int signal,siginfo_t * siginfo,void * userdata)951 sighandler(int signal, siginfo_t *siginfo, void *userdata)
952 {
953 stop = 1;
954 }
955
956 static void
mainloop(struct libinput * li)957 mainloop(struct libinput *li)
958 {
959 struct pollfd fds;
960
961 fds.fd = libinput_get_fd(li);
962 fds.events = POLLIN;
963 fds.revents = 0;
964
965 /* Handle already-pending device added events */
966 if (handle_and_print_events(li))
967 fprintf(stderr, "Expected device added events on startup but got none. "
968 "Maybe you don't have the right permissions?\n");
969
970 /* time offset starts with our first received event */
971 if (poll(&fds, 1, -1) > -1) {
972 struct timespec tp;
973
974 clock_gettime(CLOCK_MONOTONIC, &tp);
975 start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000;
976 do {
977 handle_and_print_events(li);
978 } while (!stop && poll(&fds, 1, -1) > -1);
979 }
980
981 printf("\n");
982 }
983
984 static void
usage(void)985 usage(void) {
986 printf("Usage: libinput debug-events [options] [--udev <seat>|--device /dev/input/event0 ...]\n");
987 }
988
989 int
main(int argc,char ** argv)990 main(int argc, char **argv)
991 {
992 struct libinput *li;
993 enum tools_backend backend = BACKEND_NONE;
994 const char *seat_or_devices[60] = {NULL};
995 size_t ndevices = 0;
996 bool grab = false;
997 bool verbose = false;
998 struct sigaction act;
999
1000 tools_init_options(&options);
1001
1002 while (1) {
1003 int c;
1004 int option_index = 0;
1005 enum {
1006 OPT_DEVICE = 1,
1007 OPT_UDEV,
1008 OPT_GRAB,
1009 OPT_VERBOSE,
1010 OPT_SHOW_KEYCODES,
1011 OPT_QUIET,
1012 };
1013 static struct option opts[] = {
1014 CONFIGURATION_OPTIONS,
1015 { "help", no_argument, 0, 'h' },
1016 { "show-keycodes", no_argument, 0, OPT_SHOW_KEYCODES },
1017 { "device", required_argument, 0, OPT_DEVICE },
1018 { "udev", required_argument, 0, OPT_UDEV },
1019 { "grab", no_argument, 0, OPT_GRAB },
1020 { "verbose", no_argument, 0, OPT_VERBOSE },
1021 { "quiet", no_argument, 0, OPT_QUIET },
1022 { 0, 0, 0, 0}
1023 };
1024
1025 c = getopt_long(argc, argv, "h", opts, &option_index);
1026 if (c == -1)
1027 break;
1028
1029 switch(c) {
1030 case '?':
1031 exit(EXIT_INVALID_USAGE);
1032 break;
1033 case 'h':
1034 usage();
1035 exit(EXIT_SUCCESS);
1036 break;
1037 case OPT_SHOW_KEYCODES:
1038 show_keycodes = true;
1039 break;
1040 case OPT_QUIET:
1041 be_quiet = true;
1042 break;
1043 case OPT_DEVICE:
1044 if (backend == BACKEND_UDEV ||
1045 ndevices >= ARRAY_LENGTH(seat_or_devices)) {
1046 usage();
1047 return EXIT_INVALID_USAGE;
1048
1049 }
1050 backend = BACKEND_DEVICE;
1051 seat_or_devices[ndevices++] = optarg;
1052 break;
1053 case OPT_UDEV:
1054 if (backend == BACKEND_DEVICE ||
1055 ndevices >= ARRAY_LENGTH(seat_or_devices)) {
1056 usage();
1057 return EXIT_INVALID_USAGE;
1058
1059 }
1060 backend = BACKEND_UDEV;
1061 seat_or_devices[0] = optarg;
1062 ndevices = 1;
1063 break;
1064 case OPT_GRAB:
1065 grab = true;
1066 break;
1067 case OPT_VERBOSE:
1068 verbose = true;
1069 break;
1070 default:
1071 if (tools_parse_option(c, optarg, &options) != 0) {
1072 usage();
1073 return EXIT_INVALID_USAGE;
1074 }
1075 break;
1076 }
1077
1078 }
1079
1080 if (optind < argc) {
1081 if (backend == BACKEND_UDEV) {
1082 usage();
1083 return EXIT_INVALID_USAGE;
1084 }
1085 backend = BACKEND_DEVICE;
1086 do {
1087 if (ndevices >= ARRAY_LENGTH(seat_or_devices)) {
1088 usage();
1089 return EXIT_INVALID_USAGE;
1090 }
1091 seat_or_devices[ndevices++] = argv[optind];
1092 } while(++optind < argc);
1093 } else if (backend == BACKEND_NONE) {
1094 backend = BACKEND_UDEV;
1095 seat_or_devices[0] = "seat0";
1096 }
1097
1098 memset(&act, 0, sizeof(act));
1099 act.sa_sigaction = sighandler;
1100 act.sa_flags = SA_SIGINFO;
1101
1102 if (sigaction(SIGINT, &act, NULL) == -1) {
1103 fprintf(stderr, "Failed to set up signal handling (%s)\n",
1104 strerror(errno));
1105 return EXIT_FAILURE;
1106 }
1107
1108 if (verbose)
1109 printf("libinput version: %s\n", LIBINPUT_VERSION);
1110
1111 li = tools_open_backend(backend, seat_or_devices, verbose, &grab);
1112 if (!li)
1113 return EXIT_FAILURE;
1114
1115 mainloop(li);
1116
1117 libinput_unref(li);
1118
1119 return EXIT_SUCCESS;
1120 }
1121