• 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_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