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