diff options
Diffstat (limited to 'tools/libinput-debug-gui.c')
-rw-r--r-- | tools/libinput-debug-gui.c | 903 |
1 files changed, 903 insertions, 0 deletions
diff --git a/tools/libinput-debug-gui.c b/tools/libinput-debug-gui.c new file mode 100644 index 00000000..fa685275 --- /dev/null +++ b/tools/libinput-debug-gui.c @@ -0,0 +1,903 @@ +/* + * Copyright © 2014 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#include <config.h> + +#include <linux/input.h> + +#include <cairo.h> +#include <errno.h> +#include <fcntl.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <gtk/gtk.h> +#include <glib.h> + +#include <libinput.h> +#include <libinput-util.h> + +#include "shared.h" + +#define clip(val_, min_, max_) min((max_), max((min_), (val_))) + +struct tools_context context; + +struct touch { + int active; + int x, y; +}; + +struct point { + double x, y; +}; + +struct window { + GtkWidget *win; + GtkWidget *area; + int width, height; /* of window */ + + /* sprite position */ + double x, y; + + /* abs position */ + int absx, absy; + + /* scroll bar positions */ + double vx, vy; + double hx, hy; + + /* touch positions */ + struct touch touches[32]; + + /* l/m/r mouse buttons */ + int l, m, r; + + /* touchpad swipe */ + struct { + int nfingers; + double x, y; + } swipe; + + struct { + int nfingers; + double scale; + double angle; + double x, y; + } pinch; + + struct { + double x, y; + double x_in, y_in; + double x_down, y_down; + double x_up, y_up; + double pressure; + double distance; + double tilt_x, tilt_y; + + /* these are for the delta coordinates, but they're not + * deltas, they are converted into abs positions */ + size_t ndeltas; + struct point deltas[64]; + } tool; + + struct libinput_device *devices[50]; +}; + +LIBINPUT_ATTRIBUTE_PRINTF(1, 2) +static int +error(const char *fmt, ...) +{ + va_list args; + fprintf(stderr, "error: "); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + return EXIT_FAILURE; +} + +LIBINPUT_ATTRIBUTE_PRINTF(1, 2) +static void +msg(const char *fmt, ...) +{ + va_list args; + printf("info: "); + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +static inline void +draw_gestures(struct window *w, cairo_t *cr) +{ + int i; + int offset; + + /* swipe */ + cairo_save(cr); + cairo_translate(cr, w->swipe.x, w->swipe.y); + for (i = 0; i < w->swipe.nfingers; i++) { + cairo_set_source_rgb(cr, .8, .8, .4); + cairo_arc(cr, (i - 2) * 40, 0, 20, 0, 2 * M_PI); + cairo_fill(cr); + } + + for (i = 0; i < 4; i++) { /* 4 fg max */ + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_arc(cr, (i - 2) * 40, 0, 20, 0, 2 * M_PI); + cairo_stroke(cr); + } + cairo_restore(cr); + + /* pinch */ + cairo_save(cr); + offset = w->pinch.scale * 100; + cairo_translate(cr, w->pinch.x, w->pinch.y); + cairo_rotate(cr, w->pinch.angle * M_PI/180.0); + if (w->pinch.nfingers > 0) { + cairo_set_source_rgb(cr, .4, .4, .8); + cairo_arc(cr, offset, -offset, 20, 0, 2 * M_PI); + cairo_arc(cr, -offset, offset, 20, 0, 2 * M_PI); + cairo_fill(cr); + } + + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_arc(cr, offset, -offset, 20, 0, 2 * M_PI); + cairo_stroke(cr); + cairo_arc(cr, -offset, offset, 20, 0, 2 * M_PI); + cairo_stroke(cr); + + cairo_restore(cr); + +} + +static inline void +draw_scrollbars(struct window *w, cairo_t *cr) +{ + cairo_set_source_rgb(cr, .4, .8, 0); + + cairo_save(cr); + cairo_rectangle(cr, w->vx - 10, w->vy - 20, 20, 40); + cairo_rectangle(cr, w->hx - 20, w->hy - 10, 40, 20); + cairo_fill(cr); + cairo_restore(cr); +} + +static inline void +draw_touchpoints(struct window *w, cairo_t *cr) +{ + struct touch *t; + + cairo_set_source_rgb(cr, .8, .2, .2); + + ARRAY_FOR_EACH(w->touches, t) { + cairo_save(cr); + cairo_arc(cr, t->x, t->y, 10, 0, 2 * M_PI); + cairo_fill(cr); + cairo_restore(cr); + } +} + +static inline void +draw_abs_pointer(struct window *w, cairo_t *cr) +{ + cairo_set_source_rgb(cr, .2, .4, .8); + + cairo_save(cr); + cairo_arc(cr, w->absx, w->absy, 10, 0, 2 * M_PI); + cairo_fill(cr); + cairo_restore(cr); +} + +static inline void +draw_buttons(struct window *w, cairo_t *cr) +{ + cairo_save(cr); + if (w->l || w->m || w->r) { + cairo_set_source_rgb(cr, .2, .8, .8); + if (w->l) + cairo_rectangle(cr, w->width/2 - 100, w->height - 200, 70, 30); + if (w->m) + cairo_rectangle(cr, w->width/2 - 20, w->height - 200, 40, 30); + if (w->r) + cairo_rectangle(cr, w->width/2 + 30, w->height - 200, 70, 30); + cairo_fill(cr); + } + + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_rectangle(cr, w->width/2 - 100, w->height - 200, 70, 30); + cairo_rectangle(cr, w->width/2 - 20, w->height - 200, 40, 30); + cairo_rectangle(cr, w->width/2 + 30, w->height - 200, 70, 30); + cairo_stroke(cr); + cairo_restore(cr); +} + +static inline void +draw_tablet(struct window *w, cairo_t *cr) +{ + double x, y; + int first, last; + size_t mask; + int i; + + /* tablet tool, square for prox-in location */ + cairo_save(cr); + cairo_set_source_rgb(cr, .8, .8, .8); + if (w->tool.x_in && w->tool.y_in) { + cairo_rectangle(cr, w->tool.x_in - 15, w->tool.y_in - 15, 30, 30); + cairo_stroke(cr); + cairo_restore(cr); + cairo_save(cr); + } + + if (w->tool.x_down && w->tool.y_down) { + cairo_rectangle(cr, w->tool.x_down - 10, w->tool.y_down - 10, 20, 20); + cairo_stroke(cr); + cairo_restore(cr); + cairo_save(cr); + } + + if (w->tool.x_up && w->tool.y_up) { + cairo_rectangle(cr, w->tool.x_up - 10, w->tool.y_up - 10, 20, 20); + cairo_stroke(cr); + cairo_restore(cr); + cairo_save(cr); + } + + if (w->tool.pressure) + cairo_set_source_rgb(cr, .8, .8, .2); + + cairo_translate(cr, w->tool.x, w->tool.y); + cairo_scale(cr, 1.0 + w->tool.tilt_x/30.0, 1.0 + w->tool.tilt_y/30.0); + cairo_arc(cr, 0, 0, + 1 + 10 * max(w->tool.pressure, w->tool.distance), + 0, 2 * M_PI); + cairo_fill(cr); + cairo_restore(cr); + + /* tablet deltas */ + mask = ARRAY_LENGTH(w->tool.deltas); + first = max(w->tool.ndeltas + 1, mask) - mask; + last = w->tool.ndeltas; + + cairo_save(cr); + cairo_set_source_rgb(cr, .8, .8, .2); + + x = w->tool.deltas[first % mask].x; + y = w->tool.deltas[first % mask].y; + cairo_move_to(cr, x, y); + + for (i = first + 1; i < last; i++) { + x = w->tool.deltas[i % mask].x; + y = w->tool.deltas[i % mask].y; + cairo_line_to(cr, x, y); + } + + cairo_stroke(cr); + +} + +static inline void +draw_pointer(struct window *w, cairo_t *cr) +{ + /* draw pointer sprite */ + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_save(cr); + cairo_move_to(cr, w->x, w->y); + cairo_rel_line_to(cr, 10, 15); + cairo_rel_line_to(cr, -10, 0); + cairo_rel_line_to(cr, 0, -15); + cairo_fill(cr); + cairo_restore(cr); +} + +static inline void +draw_background(struct window *w, cairo_t *cr) +{ + int x1, x2, y1, y2, x3, y3, x4, y4; + int cols; + + /* 10px and 5px grids */ + cairo_save(cr); + cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); + x1 = w->width/2 - 200; + y1 = w->height/2 - 200; + x2 = w->width/2 + 200; + y2 = w->height/2 - 200; + for (cols = 1; cols < 10; cols++) { + cairo_move_to(cr, x1 + 10 * cols, y1); + cairo_rel_line_to(cr, 0, 100); + cairo_move_to(cr, x1, y1 + 10 * cols); + cairo_rel_line_to(cr, 100, 0); + + cairo_move_to(cr, x2 + 5 * cols, y2); + cairo_rel_line_to(cr, 0, 50); + cairo_move_to(cr, x2, y2 + 5 * cols); + cairo_rel_line_to(cr, 50, 0); + } + + /* 3px horiz/vert bar codes */ + x3 = w->width/2 - 200; + y3 = w->height/2 + 200; + x4 = w->width/2 + 200; + y4 = w->height/2 + 100; + for (cols = 0; cols < 50; cols++) { + cairo_move_to(cr, x3 + 3 * cols, y3); + cairo_rel_line_to(cr, 0, 20); + + cairo_move_to(cr, x4, y4 + 3 * cols); + cairo_rel_line_to(cr, 20, 0); + } + cairo_stroke(cr); +} + +static gboolean +draw(GtkWidget *widget, cairo_t *cr, gpointer data) +{ + struct window *w = data; + + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_rectangle(cr, 0, 0, w->width, w->height); + cairo_fill(cr); + + draw_background(w, cr); + + draw_gestures(w, cr); + draw_scrollbars(w, cr); + draw_touchpoints(w, cr); + draw_abs_pointer(w, cr); + draw_buttons(w, cr); + draw_tablet(w, cr); + draw_pointer(w, cr); + + return TRUE; +} + +static void +map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data) +{ + struct window *w = data; + GdkDisplay *display; + GdkWindow *window; + + gtk_window_get_size(GTK_WINDOW(widget), &w->width, &w->height); + + w->x = w->width/2; + w->y = w->height/2; + + w->vx = w->width/2; + w->vy = w->height/2; + w->hx = w->width/2; + w->hy = w->height/2; + + w->swipe.x = w->width/2; + w->swipe.y = w->height/2; + + w->pinch.scale = 1.0; + w->pinch.x = w->width/2; + w->pinch.y = w->height/2; + + g_signal_connect(G_OBJECT(w->area), "draw", G_CALLBACK(draw), w); + + window = gdk_event_get_window(event); + display = gdk_window_get_display(window); + + gdk_window_set_cursor(gtk_widget_get_window(w->win), + gdk_cursor_new_for_display(display, + GDK_BLANK_CURSOR)); +} + +static void +window_init(struct window *w) +{ + memset(w, 0, sizeof(*w)); + + w->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_widget_set_events(w->win, 0); + gtk_window_set_title(GTK_WINDOW(w->win), "libinput debugging tool"); + gtk_window_set_default_size(GTK_WINDOW(w->win), 1024, 768); + gtk_window_maximize(GTK_WINDOW(w->win)); + gtk_window_set_resizable(GTK_WINDOW(w->win), TRUE); + gtk_widget_realize(w->win); + g_signal_connect(G_OBJECT(w->win), "map-event", G_CALLBACK(map_event_cb), w); + g_signal_connect(G_OBJECT(w->win), "delete-event", G_CALLBACK(gtk_main_quit), NULL); + + w->area = gtk_drawing_area_new(); + gtk_widget_set_events(w->area, 0); + gtk_container_add(GTK_CONTAINER(w->win), w->area); + gtk_widget_show_all(w->win); +} + +static void +window_cleanup(struct window *w) +{ + struct libinput_device **dev; + ARRAY_FOR_EACH(w->devices, dev) { + if (*dev) + libinput_device_unref(*dev); + } +} + +static void +change_ptraccel(struct window *w, double amount) +{ + struct libinput_device **dev; + + ARRAY_FOR_EACH(w->devices, dev) { + double speed; + enum libinput_config_status status; + + if (*dev == NULL) + continue; + + if (!libinput_device_config_accel_is_available(*dev)) + continue; + + speed = libinput_device_config_accel_get_speed(*dev); + speed = clip(speed + amount, -1, 1); + + status = libinput_device_config_accel_set_speed(*dev, speed); + + if (status != LIBINPUT_CONFIG_STATUS_SUCCESS) { + msg("%s: failed to change accel to %.2f (%s)\n", + libinput_device_get_name(*dev), + speed, + libinput_config_status_to_str(status)); + } else { + printf("%s: speed is %.2f\n", + libinput_device_get_name(*dev), + speed); + } + + } +} + +static void +handle_event_device_notify(struct libinput_event *ev) +{ + struct tools_context *context; + struct libinput_device *dev = libinput_event_get_device(ev); + struct libinput *li; + struct window *w; + const char *type; + size_t i; + + if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED) + type = "added"; + else + type = "removed"; + + msg("%s %-30s %s\n", + libinput_device_get_sysname(dev), + libinput_device_get_name(dev), + type); + + li = libinput_event_get_context(ev); + context = libinput_get_user_data(li); + w = context->user_data; + + tools_device_apply_config(libinput_event_get_device(ev), + &context->options); + + if (libinput_event_get_type(ev) == LIBINPUT_EVENT_DEVICE_ADDED) { + for (i = 0; i < ARRAY_LENGTH(w->devices); i++) { + if (w->devices[i] == NULL) { + w->devices[i] = libinput_device_ref(dev); + break; + } + } + } else { + for (i = 0; i < ARRAY_LENGTH(w->devices); i++) { + if (w->devices[i] == dev) { + libinput_device_unref(w->devices[i]); + w->devices[i] = NULL; + break; + } + } + } +} + +static void +handle_event_motion(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); + double dx = libinput_event_pointer_get_dx(p), + dy = libinput_event_pointer_get_dy(p); + + w->x += dx; + w->y += dy; + w->x = clip(w->x, 0.0, w->width); + w->y = clip(w->y, 0.0, w->height); +} + +static void +handle_event_absmotion(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); + double x = libinput_event_pointer_get_absolute_x_transformed(p, w->width), + y = libinput_event_pointer_get_absolute_y_transformed(p, w->height); + + w->absx = x; + w->absy = y; +} + +static void +handle_event_touch(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_touch *t = libinput_event_get_touch_event(ev); + int slot = libinput_event_touch_get_seat_slot(t); + struct touch *touch; + double x, y; + + if (slot == -1 || slot >= (int) ARRAY_LENGTH(w->touches)) + return; + + touch = &w->touches[slot]; + + if (libinput_event_get_type(ev) == LIBINPUT_EVENT_TOUCH_UP) { + touch->active = 0; + return; + } + + x = libinput_event_touch_get_x_transformed(t, w->width), + y = libinput_event_touch_get_y_transformed(t, w->height); + + touch->active = 1; + touch->x = (int)x; + touch->y = (int)y; +} + +static void +handle_event_axis(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); + double value; + + if (libinput_event_pointer_has_axis(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { + value = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + w->vy += value; + w->vy = clip(w->vy, 0, w->height); + } + + if (libinput_event_pointer_has_axis(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { + value = libinput_event_pointer_get_axis_value(p, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + w->hx += value; + w->hx = clip(w->hx, 0, w->width); + } +} + +static int +handle_event_keyboard(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_keyboard *k = libinput_event_get_keyboard_event(ev); + unsigned int key = libinput_event_keyboard_get_key(k); + + if (libinput_event_keyboard_get_key_state(k) == + LIBINPUT_KEY_STATE_RELEASED) + return 0; + + switch(key) { + case KEY_ESC: + return 1; + case KEY_UP: + change_ptraccel(w, 0.1); + break; + case KEY_DOWN: + change_ptraccel(w, -0.1); + break; + default: + break; + } + + return 0; +} + +static void +handle_event_button(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev); + unsigned int button = libinput_event_pointer_get_button(p); + int is_press; + + is_press = libinput_event_pointer_get_button_state(p) == LIBINPUT_BUTTON_STATE_PRESSED; + + switch (button) { + case BTN_LEFT: + w->l = is_press; + break; + case BTN_RIGHT: + w->r = is_press; + break; + case BTN_MIDDLE: + w->m = is_press; + break; + } + +} + +static void +handle_event_swipe(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_gesture *g = libinput_event_get_gesture_event(ev); + int nfingers; + double dx, dy; + + nfingers = libinput_event_gesture_get_finger_count(g); + + switch (libinput_event_get_type(ev)) { + case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: + w->swipe.nfingers = nfingers; + w->swipe.x = w->width/2; + w->swipe.y = w->height/2; + break; + case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: + dx = libinput_event_gesture_get_dx(g); + dy = libinput_event_gesture_get_dy(g); + w->swipe.x += dx; + w->swipe.y += dy; + break; + case LIBINPUT_EVENT_GESTURE_SWIPE_END: + w->swipe.nfingers = 0; + w->swipe.x = w->width/2; + w->swipe.y = w->height/2; + break; + default: + abort(); + } +} + +static void +handle_event_pinch(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_gesture *g = libinput_event_get_gesture_event(ev); + int nfingers; + double dx, dy; + + nfingers = libinput_event_gesture_get_finger_count(g); + + switch (libinput_event_get_type(ev)) { + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + w->pinch.nfingers = nfingers; + w->pinch.x = w->width/2; + w->pinch.y = w->height/2; + break; + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + dx = libinput_event_gesture_get_dx(g); + dy = libinput_event_gesture_get_dy(g); + w->pinch.x += dx; + w->pinch.y += dy; + w->pinch.scale = libinput_event_gesture_get_scale(g); + w->pinch.angle += libinput_event_gesture_get_angle_delta(g); + break; + case LIBINPUT_EVENT_GESTURE_PINCH_END: + w->pinch.nfingers = 0; + w->pinch.x = w->width/2; + w->pinch.y = w->height/2; + w->pinch.angle = 0.0; + w->pinch.scale = 1.0; + break; + default: + abort(); + } +} + +static void +handle_event_tablet(struct libinput_event *ev, struct window *w) +{ + struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev); + double x, y; + struct point point; + int idx; + const int mask = ARRAY_LENGTH(w->tool.deltas); + + x = libinput_event_tablet_tool_get_x_transformed(t, w->width); + y = libinput_event_tablet_tool_get_y_transformed(t, w->height); + + switch (libinput_event_get_type(ev)) { + case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: + if (libinput_event_tablet_tool_get_proximity_state(t) == + LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) { + w->tool.x_in = 0; + w->tool.y_in = 0; + w->tool.x_down = 0; + w->tool.y_down = 0; + w->tool.x_up = 0; + w->tool.y_up = 0; + } else { + w->tool.x_in = x; + w->tool.y_in = y; + w->tool.ndeltas = 0; + w->tool.deltas[0].x = w->width/2; + w->tool.deltas[0].y = w->height/2; + } + break; + case LIBINPUT_EVENT_TABLET_TOOL_TIP: + w->tool.pressure = libinput_event_tablet_tool_get_pressure(t); + w->tool.distance = libinput_event_tablet_tool_get_distance(t); + w->tool.tilt_x = libinput_event_tablet_tool_get_tilt_x(t); + w->tool.tilt_y = libinput_event_tablet_tool_get_tilt_y(t); + if (libinput_event_tablet_tool_get_tip_state(t) == + LIBINPUT_TABLET_TOOL_TIP_DOWN) { + w->tool.x_down = x; + w->tool.y_down = y; + } else { + w->tool.x_up = x; + w->tool.y_up = y; + } + /* fallthrough */ + case LIBINPUT_EVENT_TABLET_TOOL_AXIS: + w->tool.x = x; + w->tool.y = y; + w->tool.pressure = libinput_event_tablet_tool_get_pressure(t); + w->tool.distance = libinput_event_tablet_tool_get_distance(t); + w->tool.tilt_x = libinput_event_tablet_tool_get_tilt_x(t); + w->tool.tilt_y = libinput_event_tablet_tool_get_tilt_y(t); + + /* Add the delta to the last position and store them as abs + * coordinates */ + idx = w->tool.ndeltas % mask; + point = w->tool.deltas[idx]; + + idx = (w->tool.ndeltas + 1) % mask; + point.x += libinput_event_tablet_tool_get_dx(t); + point.y += libinput_event_tablet_tool_get_dy(t); + w->tool.deltas[idx] = point; + w->tool.ndeltas++; + break; + case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: + break; + default: + abort(); + } +} + +static gboolean +handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data) +{ + struct libinput *li = data; + struct tools_context *context = libinput_get_user_data(li); + struct window *w = context->user_data; + struct libinput_event *ev; + + libinput_dispatch(li); + + while ((ev = libinput_get_event(li))) { + switch (libinput_event_get_type(ev)) { + case LIBINPUT_EVENT_NONE: + abort(); + case LIBINPUT_EVENT_DEVICE_ADDED: + case LIBINPUT_EVENT_DEVICE_REMOVED: + handle_event_device_notify(ev); + break; + case LIBINPUT_EVENT_POINTER_MOTION: + handle_event_motion(ev, w); + break; + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + handle_event_absmotion(ev, w); + break; + case LIBINPUT_EVENT_TOUCH_DOWN: + case LIBINPUT_EVENT_TOUCH_MOTION: + case LIBINPUT_EVENT_TOUCH_UP: + handle_event_touch(ev, w); + break; + case LIBINPUT_EVENT_POINTER_AXIS: + handle_event_axis(ev, w); + break; + case LIBINPUT_EVENT_TOUCH_CANCEL: + case LIBINPUT_EVENT_TOUCH_FRAME: + break; + case LIBINPUT_EVENT_POINTER_BUTTON: + handle_event_button(ev, w); + break; + case LIBINPUT_EVENT_KEYBOARD_KEY: + if (handle_event_keyboard(ev, w)) { + libinput_event_destroy(ev); + gtk_main_quit(); + return FALSE; + } + break; + case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: + case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: + case LIBINPUT_EVENT_GESTURE_SWIPE_END: + handle_event_swipe(ev, w); + break; + case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: + case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: + case LIBINPUT_EVENT_GESTURE_PINCH_END: + handle_event_pinch(ev, w); + break; + case LIBINPUT_EVENT_TABLET_TOOL_AXIS: + case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: + case LIBINPUT_EVENT_TABLET_TOOL_TIP: + case LIBINPUT_EVENT_TABLET_TOOL_BUTTON: + handle_event_tablet(ev, w); + break; + case LIBINPUT_EVENT_TABLET_PAD_BUTTON: + case LIBINPUT_EVENT_TABLET_PAD_RING: + case LIBINPUT_EVENT_TABLET_PAD_STRIP: + break; + case LIBINPUT_EVENT_SWITCH_TOGGLE: + break; + } + + libinput_event_destroy(ev); + libinput_dispatch(li); + } + gtk_widget_queue_draw(w->area); + + return TRUE; +} + +static void +sockets_init(struct libinput *li) +{ + GIOChannel *c = g_io_channel_unix_new(libinput_get_fd(li)); + + g_io_channel_set_encoding(c, NULL, NULL); + g_io_add_watch(c, G_IO_IN, handle_event_libinput, li); +} + +int +main(int argc, char **argv) +{ + struct window w; + struct libinput *li; + struct udev *udev; + + gtk_init(&argc, &argv); + + tools_init_context(&context); + + if (tools_parse_args(argc, argv, &context) != 0) + return 1; + + udev = udev_new(); + if (!udev) + error("Failed to initialize udev\n"); + + context.user_data = &w; + li = tools_open_backend(&context); + if (!li) + return 1; + + window_init(&w); + sockets_init(li); + handle_event_libinput(NULL, 0, li); + + gtk_main(); + + window_cleanup(&w); + libinput_unref(li); + udev_unref(udev); + + return 0; +} |