On Wed, Jan 29, 2014 at 11:55:37AM +1000, Peter Hutterer wrote: > Simply prints the various events to make it easier to check what's coming out > of libinput. Works for --udev (the default) or for --device /dev/input/event0. > Example output: > > event7 DEVICE_ADDED seat0 default > event8 DEVICE_ADDED seat0 default > event4 POINTER_BUTTON +1.35s 272 pressed > event5 POINTER_MOTION +2.31s -3.00/ 2.00 > > Time is displayed relative to the starting time. > > Note: statically linked for easier debugging, but we don't distribute it > (yet) anyway. > > Signed-off-by: Peter Hutterer <[email protected]>
Neat tool! This and the other 4, Reviewed-by: Jonas Ådahl <[email protected]> > --- > Makefile.am | 2 +- > configure.ac | 3 +- > tools/.gitignore | 1 + > tools/Makefile.am | 7 + > tools/event-debug.c | 453 > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 5 files changed, 464 insertions(+), 2 deletions(-) > create mode 100644 tools/.gitignore > create mode 100644 tools/Makefile.am > create mode 100644 tools/event-debug.c > > diff --git a/Makefile.am b/Makefile.am > index 07bfcd4..08bf7ce 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -1,3 +1,3 @@ > -SUBDIRS = src doc test > +SUBDIRS = src doc test tools > > ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} > diff --git a/configure.ac b/configure.ac > index 7281bb4..44729a9 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -87,5 +87,6 @@ AC_CONFIG_FILES([Makefile > src/Makefile > src/libinput.pc > src/libinput-version.h > - test/Makefile]) > + test/Makefile > + tools/Makefile]) > AC_OUTPUT > diff --git a/tools/.gitignore b/tools/.gitignore > new file mode 100644 > index 0000000..2cdd654 > --- /dev/null > +++ b/tools/.gitignore > @@ -0,0 +1 @@ > +event-debug > diff --git a/tools/Makefile.am b/tools/Makefile.am > new file mode 100644 > index 0000000..9c29f56 > --- /dev/null > +++ b/tools/Makefile.am > @@ -0,0 +1,7 @@ > +noinst_PROGRAMS = event-debug > + > +AM_CPPFLAGS = -I$(top_srcdir)/src > + > +event_debug_SOURCES = event-debug.c > +event_debug_LDADD = ../src/libinput.la > +event_debug_LDFLAGS = -static > diff --git a/tools/event-debug.c b/tools/event-debug.c > new file mode 100644 > index 0000000..53e92b0 > --- /dev/null > +++ b/tools/event-debug.c > @@ -0,0 +1,453 @@ > +/* > + * Copyright © 2014 Red Hat, Inc. > + * > + * Permission to use, copy, modify, distribute, and sell this software and > + * its documentation for any purpose is hereby granted without fee, provided > + * that the above copyright notice appear in all copies and that both that > + * copyright notice and this permission notice appear in supporting > + * documentation, and that the name of the copyright holders not be used in > + * advertising or publicity pertaining to distribution of the software > + * without specific, written prior permission. The copyright holders make > + * no representations about the suitability of this software for any > + * purpose. It is provided "as is" without express or implied warranty. > + * > + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS > + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND > + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY > + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER > + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF > + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN > + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > + */ > + > +#define _GNU_SOURCE > +#include <errno.h> > +#include <fcntl.h> > +#include <getopt.h> > +#include <poll.h> > +#include <stdio.h> > +#include <signal.h> > +#include <string.h> > +#include <time.h> > +#include <unistd.h> > +#include <linux/input.h> > +#include <sys/ioctl.h> > +#include <sys/signalfd.h> > + > +#include <libinput.h> > + > +static enum { > + MODE_UDEV, > + MODE_DEVICE, > +} mode = MODE_UDEV; > +static const char *device; > +static const char *seat = "seat0"; > +static struct udev *udev; > +uint32_t start_time; > + > +static void > +usage(void) > +{ > + printf("Usage: %s [--udev [<seat>]|--device /dev/input/event0]\n" > + "--udev <seat>.... Use udev device discovery (default).\n" > + " Specifying a seat ID is optional.\n" > + "--device /path/to/device .... open the given device only\n", > + program_invocation_short_name); > +} > + > +static int > +parse_args(int argc, char **argv) > +{ > + while (1) { > + int c; > + int option_index = 0; > + static struct option opts[] = { > + { "device", 1, 0, 'd' }, > + { "udev", 0, 0, 'u' }, > + { "help", 0, 0, 'h' }, > + { 0, 0, 0, 0} > + }; > + > + c = getopt_long(argc, argv, "h", opts, &option_index); > + if (c == -1) > + break; > + > + switch(c) { > + case 'h': /* --help */ > + usage(); > + exit(0); > + case 'd': /* --device */ > + mode = MODE_DEVICE; > + if (!optarg) { > + usage(); > + return 1; > + } > + device = optarg; > + break; > + case 'u': /* --udev */ > + mode = MODE_UDEV; > + if (optarg) > + seat = optarg; > + break; > + default: > + usage(); > + return 1; > + } > + > + } > + > + if (optind < argc) { > + usage(); > + return 1; > + } > + > + return 0; > +} > + > +static int > +open_restricted(const char *path, int flags, void *user_data) > +{ > + int fd = open(path, flags); > + int clockid = CLOCK_MONOTONIC; > + > + if (fd >= 0 && ioctl(fd, EVIOCSCLOCKID, &clockid) < 0) > + fprintf(stderr, "Changing clock on %s failed, timestamps " > + "will be off\n", path); > + > + return fd < 0 ? -errno : fd; > +} > + > +static void > +close_restricted(int fd, void *user_data) > +{ > + close(fd); > +} > + > +static void get_current_screen_dimensions(struct libinput_device *device, > + int *width, > + int *height, > + void *user_data) > +{ > + /* display absdata in % of the screen */ > + *width = 100; > + *height = 100; > +} > + > +const static struct libinput_interface interface = { > + .open_restricted = open_restricted, > + .close_restricted = close_restricted, > + .get_current_screen_dimensions = get_current_screen_dimensions, > +}; > + > +static int > +open_udev(struct libinput **li) > +{ > + udev = udev_new(); > + if (!udev) { > + fprintf(stderr, "Failed to initialize udev\n"); > + return 1; > + } > + > + *li = libinput_create_from_udev(&interface, NULL, udev, seat); > + if (!*li) { > + fprintf(stderr, "Failed to initialize context from udev\n"); > + return 1; > + } > + > + return 0; > +} > + > +static int > +open_device(struct libinput **li, const char *path) > +{ > + *li = libinput_create_from_path(&interface, NULL, path); > + if (!*li) { > + fprintf(stderr, "Failed to initialize context from %s\n", path); > + return 1; > + } > + return 0; > +} > + > +static void > +print_event_header(struct libinput_event *ev) > +{ > + struct libinput_device *dev = libinput_event_get_device(ev); > + const char *type; > + > + switch(libinput_event_get_type(ev)) { > + case LIBINPUT_EVENT_NONE: > + abort(); > + case LIBINPUT_EVENT_DEVICE_ADDED: > + type = "DEVICE_ADDED"; > + break; > + case LIBINPUT_EVENT_DEVICE_REMOVED: > + type = "DEVICE_REMOVED"; > + break; > + case LIBINPUT_EVENT_KEYBOARD_KEY: > + type = "KEYBOARD_KEY"; > + break; > + case LIBINPUT_EVENT_POINTER_MOTION: > + type = "POINTER_MOTION"; > + break; > + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: > + type = "POINTER_MOTION_ABSOLUTE"; > + break; > + case LIBINPUT_EVENT_POINTER_BUTTON: > + type = "POINTER_BUTTON"; > + break; > + case LIBINPUT_EVENT_POINTER_AXIS: > + type = "POINTER_AXIS"; > + break; > + case LIBINPUT_EVENT_TOUCH_TOUCH: > + type = "TOUCH_TOUCH"; > + break; > + case LIBINPUT_EVENT_TOUCH_FRAME: > + type = "TOUCH_FRAME"; > + break; > + } > + > + printf("%-7s %s ", libinput_device_get_sysname(dev), type); > +} > + > +static void > +print_event_time(uint32_t time) > +{ > + printf("%+6.2fs ", (time - start_time) / 1000.0); > +} > + > +static void > +print_device_notify(struct libinput_event *ev) > +{ > + struct libinput_device *dev = libinput_event_get_device(ev); > + struct libinput_seat *seat = libinput_device_get_seat(dev); > + > + printf("%s %s\n", > + libinput_seat_get_physical_name(seat), > + libinput_seat_get_logical_name(seat)); > +} > + > +static void > +print_key_event(struct libinput_event *ev) > +{ > + struct libinput_event_keyboard *k = > libinput_event_get_keyboard_event(ev); > + enum libinput_keyboard_key_state state; > + > + print_event_time(libinput_event_keyboard_get_time(k)); > + state = libinput_event_keyboard_get_key_state(k); > + printf("%d %s\n", > + libinput_event_keyboard_get_key(k), > + state == LIBINPUT_KEYBOARD_KEY_STATE_PRESSED ? "pressed" : > "released"); > +} > + > +static void > +print_motion_event(struct libinput_event *ev) > +{ > + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); > + li_fixed_t x = libinput_event_pointer_get_dx(p), > + y = libinput_event_pointer_get_dy(p); > + > + print_event_time(libinput_event_pointer_get_time(p)); > + > + printf("%6.2f/%6.2f\n", > + li_fixed_to_double(x), > + li_fixed_to_double(y)); > +} > + > +static void > +print_absmotion_event(struct libinput_event *ev) > +{ > + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); > + li_fixed_t x = libinput_event_pointer_get_absolute_x(p), > + y = libinput_event_pointer_get_absolute_y(p); > + > + print_event_time(libinput_event_pointer_get_time(p)); > + printf("%6.2f/%6.2f\n", > + li_fixed_to_double(x), > + li_fixed_to_double(y)); > +} > + > +static void > +print_button_event(struct libinput_event *ev) > +{ > + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); > + enum libinput_pointer_button_state state; > + > + print_event_time(libinput_event_pointer_get_time(p)); > + > + state = libinput_event_pointer_get_button_state(p); > + printf("%3d %s\n", > + libinput_event_pointer_get_button(p), > + state == LIBINPUT_POINTER_BUTTON_STATE_PRESSED ? "pressed" : > "released"); > +} > + > +static void > +print_axis_event(struct libinput_event *ev) > +{ > + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); > + enum libinput_pointer_axis axis = libinput_event_pointer_get_axis(p); > + const char *ax; > + li_fixed_t val; > + > + switch (axis) { > + case LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL: > + ax = "vscroll"; > + break; > + case LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL: > + ax = "hscroll"; > + break; > + default: > + abort(); > + } > + > + print_event_time(libinput_event_pointer_get_time(p)); > + val = libinput_event_pointer_get_axis_value(p); > + printf("%s %.2f\n", > + ax, li_fixed_to_double(val)); > +} > + > +static void > +print_touch_frame_event(struct libinput_event *ev) > +{ > + struct libinput_event_touch *t = libinput_event_get_touch_event(ev); > + > + print_event_time(libinput_event_touch_get_time(t)); > + printf("\n"); > +} > + > +static void > +print_touch_event(struct libinput_event *ev) > +{ > + struct libinput_event_touch *t = libinput_event_get_touch_event(ev); > + li_fixed_t x = libinput_event_touch_get_x(t), > + y = libinput_event_touch_get_y(t); > + const char *type; > + > + switch (libinput_event_touch_get_touch_type(t)) { > + case LIBINPUT_TOUCH_TYPE_DOWN: type = "down"; break; > + case LIBINPUT_TOUCH_TYPE_UP: type = "up"; break; > + case LIBINPUT_TOUCH_TYPE_MOTION: type = "motion"; break; > + case LIBINPUT_TOUCH_TYPE_CANCEL: type = "cancel"; break; > + default: > + abort(); > + } > + > + print_event_time(libinput_event_touch_get_time(t)); > + > + printf("%6s %u %5.2f/%5.2f\n", > + type, > + libinput_event_touch_get_slot(t), > + li_fixed_to_double(x), > + li_fixed_to_double(y)); > +} > + > +static int > +handle_and_print_events(struct libinput *li) > +{ > + int rc = -1; > + struct libinput_event *ev; > + > + libinput_dispatch(li); > + while ((ev = libinput_get_event(li))) { > + print_event_header(ev); > + > + switch (libinput_event_get_type(ev)) { > + case LIBINPUT_EVENT_NONE: > + abort(); > + case LIBINPUT_EVENT_DEVICE_ADDED: > + case LIBINPUT_EVENT_DEVICE_REMOVED: > + print_device_notify(ev); > + break; > + case LIBINPUT_EVENT_KEYBOARD_KEY: > + print_key_event(ev); > + break; > + case LIBINPUT_EVENT_POINTER_MOTION: > + print_motion_event(ev); > + break; > + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: > + print_absmotion_event(ev); > + break; > + case LIBINPUT_EVENT_POINTER_BUTTON: > + print_button_event(ev); > + break; > + case LIBINPUT_EVENT_POINTER_AXIS: > + print_axis_event(ev); > + break; > + case LIBINPUT_EVENT_TOUCH_TOUCH: > + print_touch_event(ev); > + break; > + case LIBINPUT_EVENT_TOUCH_FRAME: > + print_touch_frame_event(ev); > + break; > + } > + > + libinput_event_destroy(ev); > + libinput_dispatch(li); > + rc = 0; > + } > + return rc; > +} > + > +void > +mainloop(struct libinput *li) > +{ > + struct pollfd fds[2]; > + sigset_t mask; > + > + fds[0].fd = libinput_get_fd(li); > + fds[0].events = POLLIN; > + fds[0].revents = 0; > + > + sigemptyset(&mask); > + sigaddset(&mask, SIGINT); > + > + fds[1].fd = signalfd(-1, &mask, SFD_NONBLOCK); > + fds[1].events = POLLIN; > + fds[1].revents = 0; > + > + if (fds[1].fd == -1 || > + sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { > + fprintf(stderr, "Failed to set up signal handling (%s)\n", > + strerror(errno)); > + } > + > + /* Handle already-pending device added events */ > + if (handle_and_print_events(li)) > + fprintf(stderr, "Expected device added events on startup but > got none. " > + "Maybe you don't have the right > permissions?\n"); > + > + while (poll(fds, 2, -1) > -1) { > + if (fds[1].revents) > + break; > + > + handle_and_print_events(li); > + } > +} > + > +int > +main(int argc, char **argv) > +{ > + struct libinput *li; > + struct timespec tp; > + > + if (parse_args(argc, argv)) > + return 1; > + > + if (mode == MODE_UDEV) { > + if (open_udev(&li)) > + return 1; > + } else if (mode == MODE_DEVICE) { > + if (open_device(&li, device)) > + return 1; > + } else > + abort(); > + > + clock_gettime(CLOCK_MONOTONIC, &tp); > + start_time = tp.tv_sec * 1000 + tp.tv_nsec / 1000000; > + > + mainloop(li); > + > + if (udev) > + udev_unref(udev); > + > + return 0; > +} > -- > 1.8.4.2 > > _______________________________________________ > wayland-devel mailing list > [email protected] > http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
