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