• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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