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