2 * Copyright © 2014 Red Hat, Inc.
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 #include <linux/input.h>
34 #include <sys/ioctl.h>
35 #include <sys/signalfd.h>
43 static const char *device;
44 static const char *seat = "seat0";
45 static struct udev *udev;
51 printf("Usage: %s [--udev [<seat>]|--device /dev/input/event0]\n"
52 "--udev <seat>.... Use udev device discovery (default).\n"
53 " Specifying a seat ID is optional.\n"
54 "--device /path/to/device .... open the given device only\n",
55 program_invocation_short_name);
59 parse_args(int argc, char **argv)
64 static struct option opts[] = {
65 { "device", 1, 0, 'd' },
66 { "udev", 0, 0, 'u' },
67 { "help", 0, 0, 'h' },
71 c = getopt_long(argc, argv, "h", opts, &option_index);
76 case 'h': /* --help */
79 case 'd': /* --device */
87 case 'u': /* --udev */
108 open_restricted(const char *path, int flags, void *user_data)
110 int fd = open(path, flags);
111 int clockid = CLOCK_MONOTONIC;
113 if (fd >= 0 && ioctl(fd, EVIOCSCLOCKID, &clockid) < 0)
114 fprintf(stderr, "Changing clock on %s failed, timestamps "
115 "will be off\n", path);
117 return fd < 0 ? -errno : fd;
121 close_restricted(int fd, void *user_data)
126 static void get_current_screen_dimensions(struct libinput_device *device,
131 /* display absdata in % of the screen */
136 const static struct libinput_interface interface = {
137 .open_restricted = open_restricted,
138 .close_restricted = close_restricted,
139 .get_current_screen_dimensions = get_current_screen_dimensions,
143 open_udev(struct libinput **li)
147 fprintf(stderr, "Failed to initialize udev\n");
151 *li = libinput_create_from_udev(&interface, NULL, udev, seat);
153 fprintf(stderr, "Failed to initialize context from udev\n");
161 open_device(struct libinput **li, const char *path)
163 *li = libinput_create_from_path(&interface, NULL, path);
165 fprintf(stderr, "Failed to initialize context from %s\n", path);
172 print_event_header(struct libinput_event *ev)
174 struct libinput_device *dev = libinput_event_get_device(ev);
177 switch(libinput_event_get_type(ev)) {
178 case LIBINPUT_EVENT_NONE:
180 case LIBINPUT_EVENT_DEVICE_ADDED:
181 type = "DEVICE_ADDED";
183 case LIBINPUT_EVENT_DEVICE_REMOVED:
184 type = "DEVICE_REMOVED";
186 case LIBINPUT_EVENT_KEYBOARD_KEY:
187 type = "KEYBOARD_KEY";
189 case LIBINPUT_EVENT_POINTER_MOTION:
190 type = "POINTER_MOTION";
192 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
193 type = "POINTER_MOTION_ABSOLUTE";
195 case LIBINPUT_EVENT_POINTER_BUTTON:
196 type = "POINTER_BUTTON";
198 case LIBINPUT_EVENT_POINTER_AXIS:
199 type = "POINTER_AXIS";
201 case LIBINPUT_EVENT_TOUCH_TOUCH:
202 type = "TOUCH_TOUCH";
204 case LIBINPUT_EVENT_TOUCH_FRAME:
205 type = "TOUCH_FRAME";
209 printf("%-7s %s ", libinput_device_get_sysname(dev), type);
213 print_event_time(uint32_t time)
215 printf("%+6.2fs ", (time - start_time) / 1000.0);
219 print_device_notify(struct libinput_event *ev)
221 struct libinput_device *dev = libinput_event_get_device(ev);
222 struct libinput_seat *seat = libinput_device_get_seat(dev);
225 libinput_seat_get_physical_name(seat),
226 libinput_seat_get_logical_name(seat));
230 print_key_event(struct libinput_event *ev)
232 struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev);
233 enum libinput_keyboard_key_state state;
235 print_event_time(libinput_event_keyboard_get_time(k));
236 state = libinput_event_keyboard_get_key_state(k);
238 libinput_event_keyboard_get_key(k),
239 state == LIBINPUT_KEYBOARD_KEY_STATE_PRESSED ? "pressed" : "released");
243 print_motion_event(struct libinput_event *ev)
245 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
246 li_fixed_t x = libinput_event_pointer_get_dx(p),
247 y = libinput_event_pointer_get_dy(p);
249 print_event_time(libinput_event_pointer_get_time(p));
251 printf("%6.2f/%6.2f\n",
252 li_fixed_to_double(x),
253 li_fixed_to_double(y));
257 print_absmotion_event(struct libinput_event *ev)
259 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
260 li_fixed_t x = libinput_event_pointer_get_absolute_x(p),
261 y = libinput_event_pointer_get_absolute_y(p);
263 print_event_time(libinput_event_pointer_get_time(p));
264 printf("%6.2f/%6.2f\n",
265 li_fixed_to_double(x),
266 li_fixed_to_double(y));
270 print_button_event(struct libinput_event *ev)
272 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
273 enum libinput_pointer_button_state state;
275 print_event_time(libinput_event_pointer_get_time(p));
277 state = libinput_event_pointer_get_button_state(p);
279 libinput_event_pointer_get_button(p),
280 state == LIBINPUT_POINTER_BUTTON_STATE_PRESSED ? "pressed" : "released");
284 print_axis_event(struct libinput_event *ev)
286 struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
287 enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p);
292 case LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL:
295 case LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL:
302 print_event_time(libinput_event_pointer_get_time(p));
303 val = libinput_event_pointer_get_axis_value(p);
305 ax, li_fixed_to_double(val));
309 print_touch_frame_event(struct libinput_event *ev)
311 struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
313 print_event_time(libinput_event_touch_get_time(t));
318 print_touch_event(struct libinput_event *ev)
320 struct libinput_event_touch *t = libinput_event_get_touch_event(ev);
321 li_fixed_t x = libinput_event_touch_get_x(t),
322 y = libinput_event_touch_get_y(t);
325 switch (libinput_event_touch_get_touch_type(t)) {
326 case LIBINPUT_TOUCH_TYPE_DOWN: type = "down"; break;
327 case LIBINPUT_TOUCH_TYPE_UP: type = "up"; break;
328 case LIBINPUT_TOUCH_TYPE_MOTION: type = "motion"; break;
329 case LIBINPUT_TOUCH_TYPE_CANCEL: type = "cancel"; break;
334 print_event_time(libinput_event_touch_get_time(t));
336 printf("%6s %u %5.2f/%5.2f\n",
338 libinput_event_touch_get_slot(t),
339 li_fixed_to_double(x),
340 li_fixed_to_double(y));
344 handle_and_print_events(struct libinput *li)
347 struct libinput_event *ev;
349 libinput_dispatch(li);
350 while ((ev = libinput_get_event(li))) {
351 print_event_header(ev);
353 switch (libinput_event_get_type(ev)) {
354 case LIBINPUT_EVENT_NONE:
356 case LIBINPUT_EVENT_DEVICE_ADDED:
357 case LIBINPUT_EVENT_DEVICE_REMOVED:
358 print_device_notify(ev);
360 case LIBINPUT_EVENT_KEYBOARD_KEY:
363 case LIBINPUT_EVENT_POINTER_MOTION:
364 print_motion_event(ev);
366 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
367 print_absmotion_event(ev);
369 case LIBINPUT_EVENT_POINTER_BUTTON:
370 print_button_event(ev);
372 case LIBINPUT_EVENT_POINTER_AXIS:
373 print_axis_event(ev);
375 case LIBINPUT_EVENT_TOUCH_TOUCH:
376 print_touch_event(ev);
378 case LIBINPUT_EVENT_TOUCH_FRAME:
379 print_touch_frame_event(ev);
383 libinput_event_destroy(ev);
384 libinput_dispatch(li);
391 mainloop(struct libinput *li)
393 struct pollfd fds[2];
396 fds[0].fd = libinput_get_fd(li);
397 fds[0].events = POLLIN;
401 sigaddset(&mask, SIGINT);
403 fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK);
404 fds[1].events = POLLIN;
407 if (fds[1].fd == -1 ||
408 sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
409 fprintf(stderr, "Failed to set up signal handling (%s)\n",
413 /* Handle already-pending device added events */
414 if (handle_and_print_events(li))
415 fprintf(stderr, "Expected device added events on startup but got none. "
416 "Maybe you don't have the right permissions?\n");
418 while (poll(fds, 2, -1) > -1) {
422 handle_and_print_events(li);
429 main(int argc, char **argv)
434 if (parse_args(argc, argv))
437 if (mode == MODE_UDEV) {
440 } else if (mode == MODE_DEVICE) {
441 if (open_device(&li, device))
446 clock_gettime(CLOCK_MONOTONIC, &tp);
447 start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000;