From 5ee1a60f1a03b3176332f6d4f27744d0dfdb0601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 11 Dec 2008 23:18:45 -0500 Subject: [PATCH] Rewrite input event delivery path. Instead of having the input driver push the events into the core server, only to have the server call back out to the compositor hooks, the driver now just calls the compositor directly. The input drivers are always dependent on the type of compositor anyway so there was no point in passing the events through the server. Now the server is only involved when it's time to actually send the events to the clients. --- Makefile.in | 4 +- egl-compositor.c | 129 ++++++++++++++++++++++++++++------------------- evdev.c | 84 +++++++++++------------------- wayland.c | 72 +++++++++----------------- wayland.h | 28 ++-------- window.c | 5 +- 6 files changed, 141 insertions(+), 181 deletions(-) diff --git a/Makefile.in b/Makefile.in index a5540f0a..b0d60538 100644 --- a/Makefile.in +++ b/Makefile.in @@ -35,7 +35,7 @@ egl-compositor : \ wayland-util.o egl-compositor : CFLAGS += @EGL_COMPOSITOR_CFLAGS@ -egl-compositor : LDLIBS += @EGL_COMPOSITOR_LIBS@ -L. -lwayland-server -rdynamic -lrt +egl-compositor : LDLIBS += -L. -lwayland-server @EGL_COMPOSITOR_LIBS@ -rdynamic -lrt flower : flower.o wayland-glib.o cairo-util.o gears : gears.o window.o wayland-glib.o cairo-util.o @@ -45,7 +45,7 @@ terminal : terminal.o window.o wayland-glib.o cairo-util.o terminal : LDLIBS += -lutil $(clients) : CFLAGS += @CLIENT_CFLAGS@ -$(clients) : LDLIBS += @CLIENT_LIBS@ -L. -lwayland -lrt +$(clients) : LDLIBS += -L. -lwayland @CLIENT_LIBS@ -lrt install : $(libs) install -d @libdir@ @libdir@/pkgconfig diff --git a/egl-compositor.c b/egl-compositor.c index 069d6756..77b9fbb7 100644 --- a/egl-compositor.c +++ b/egl-compositor.c @@ -41,14 +41,22 @@ #include #include -#include "wayland.h" -#include "cairo-util.h" - #include #include +#include "wayland.h" +#include "cairo-util.h" +#include "egl-compositor.h" + #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) +struct egl_input_device { + struct wl_object base; + int32_t x, y; + struct egl_compositor *ec; + struct egl_surface *surface; +}; + struct egl_compositor { struct wl_compositor base; EGLDisplay display; @@ -58,11 +66,12 @@ struct egl_compositor { struct wl_display *wl_display; int gem_fd; int width, height; - struct egl_surface *pointer; struct egl_surface *background; struct egl_surface *overlay; double overlay_y, overlay_target, overlay_previous; + struct egl_input_device *input_device; + struct wl_list surface_list; /* Repaint state. */ @@ -324,7 +333,10 @@ pointer_create(int x, int y, int width, int height) cairo_fill(cr); cairo_destroy(cr); - es = egl_surface_create_from_cairo_surface(surface, x, y, width, height); + es = egl_surface_create_from_cairo_surface(surface, + x - hotspot_x, + y - hotspot_y, + width, height); cairo_surface_destroy(surface); @@ -577,7 +589,7 @@ repaint(void *data) draw_surface(ec->overlay); - draw_surface(ec->pointer); + draw_surface(ec->input_device->surface); eglSwapBuffers(ec->display, ec->surface); ec->repaint_needed = 0; @@ -727,15 +739,18 @@ notify_commit(struct wl_compositor *compositor) } static struct egl_surface * -pick_surface(struct egl_compositor *ec, int32_t x, int32_t y) +pick_surface(struct egl_input_device *device) { + struct egl_compositor *ec = device->ec; struct egl_surface *es; es = container_of(ec->surface_list.prev, struct egl_surface, link); while (&es->link != &ec->surface_list) { - if (es->map.x <= x && x < es->map.x + es->map.width && - es->map.y <= y && y < es->map.y + es->map.height) + if (es->map.x <= device->x && + device->x < es->map.x + es->map.width && + es->map.y <= device->y && + device->y < es->map.y + es->map.height) return es; es = container_of(es->link.prev, @@ -745,59 +760,53 @@ pick_surface(struct egl_compositor *ec, int32_t x, int32_t y) return NULL; } -static void -notify_pointer_motion(struct wl_compositor *compositor, - struct wl_object *source, int x, int y) +void +notify_motion(struct egl_input_device *device, int x, int y) { - struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_surface *es; const int hotspot_x = 16, hotspot_y = 16; int32_t sx, sy; - es = pick_surface(ec, x, y); + es = pick_surface(device); if (es) { sx = (x - es->map.x) * es->width / es->map.width; sy = (y - es->map.y) * es->height / es->map.height; - wl_surface_post_event(es->wl_surface, source, + wl_surface_post_event(es->wl_surface, &device->base, WL_INPUT_MOTION, x, y, sx, sy); } - ec->pointer->map.x = x - hotspot_x; - ec->pointer->map.y = y - hotspot_y; - schedule_repaint(ec); + device->x = x; + device->y = y; + device->surface->map.x = x - hotspot_x; + device->surface->map.y = y - hotspot_y; + + schedule_repaint(device->ec); } -static void -notify_pointer_button(struct wl_compositor *compositor, - struct wl_object *source, - int32_t button, int32_t state) +void +notify_button(struct egl_input_device *device, + int32_t button, int32_t state) { - struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_surface *es; - const int hotspot_x = 16, hotspot_y = 16; - int x, y; - x = ec->pointer->map.x + hotspot_x; - y = ec->pointer->map.y + hotspot_y; - - es = pick_surface(ec, x, y); + es = pick_surface(device); if (es) { wl_list_remove(&es->link); - wl_list_insert(ec->surface_list.prev, &es->link); + wl_list_insert(device->ec->surface_list.prev, &es->link); /* FIXME: Swallow click on raise? */ - wl_surface_post_event(es->wl_surface, source, + wl_surface_post_event(es->wl_surface, &device->base, WL_INPUT_BUTTON, button, state); - } - schedule_repaint(ec); + schedule_repaint(device->ec); + } } -static void -notify_key(struct wl_compositor *compositor, - struct wl_object *source, uint32_t key, uint32_t state) +void +notify_key(struct egl_input_device *device, + uint32_t key, uint32_t state) { - struct egl_compositor *ec = (struct egl_compositor *) compositor; + struct egl_compositor *ec = device->ec; struct egl_surface *es; if (key == KEY_ESC && state == 1) { @@ -813,7 +822,7 @@ notify_key(struct wl_compositor *compositor, * effectively gives us click to focus behavior. */ es = container_of(ec->surface_list.prev, struct egl_surface, link); - wl_surface_post_event(es->wl_surface, source, + wl_surface_post_event(es->wl_surface, &device->base, WL_INPUT_KEY, key, state); } } @@ -826,9 +835,6 @@ static const struct wl_compositor_interface interface = { notify_surface_copy, notify_surface_damage, notify_commit, - notify_pointer_motion, - notify_pointer_button, - notify_key }; static const char pointer_device_file[] = @@ -836,27 +842,49 @@ static const char pointer_device_file[] = static const char keyboard_device_file[] = "/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-kbd"; +struct evdev_input_device * +evdev_input_device_create(struct egl_input_device *device, + struct wl_display *display, const char *path); + +void +egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y); + static void -create_input_devices(struct wl_display *display) +create_input_devices(struct egl_compositor *ec) { - struct wl_object *obj; + struct egl_input_device *device; const char *path; + device = malloc(sizeof *device); + if (device == NULL) + return; + + device->base.interface = wl_input_device_get_interface(); + wl_display_add_object(ec->wl_display, &device->base); + ec->input_device = device; + device->x = 100; + device->y = 100; + device->surface = pointer_create(device->x, device->y, 64, 64); + device->ec = ec; + path = getenv("WAYLAND_POINTER"); if (path == NULL) path = pointer_device_file; - obj = wl_input_device_create(display, path); - if (obj != NULL) - wl_display_add_object(display, obj); + evdev_input_device_create(device, ec->wl_display, path); path = getenv("WAYLAND_KEYBOARD"); if (path == NULL) path = keyboard_device_file; - obj = wl_input_device_create(display, path); - if (obj != NULL) - wl_display_add_object(display, obj); + evdev_input_device_create(device, ec->wl_display, path); +} + +void +egl_device_get_position(struct egl_input_device *device, int32_t *x, int32_t *y) +{ + *x = device->x; + *y = device->y; } static uint32_t @@ -1065,14 +1093,13 @@ egl_compositor_create(struct wl_display *display) glOrtho(0, ec->width, ec->height, 0, 0, 1000.0); glMatrixMode(GL_MODELVIEW); - create_input_devices(display); + create_input_devices(ec); wl_list_init(&ec->surface_list); filename = getenv("WAYLAND_BACKGROUND"); if (filename == NULL) filename = "background.jpg"; ec->background = background_create(filename, 1280, 800); - ec->pointer = pointer_create(100, 100, 64, 64); ec->overlay = overlay_create(0, ec->height, ec->width, 200); ec->overlay_y = ec->height; ec->overlay_target = ec->height; diff --git a/evdev.c b/evdev.c index b73ca9d7..77f82fd0 100644 --- a/evdev.c +++ b/evdev.c @@ -29,42 +29,28 @@ #include #include "wayland.h" +#include "egl-compositor.h" -struct wl_input_device { - struct wl_object base; +struct evdev_input_device { + struct egl_input_device *device; struct wl_event_source *source; - struct wl_display *display; - int fd; int tool, new_x, new_y; - int32_t x, y, base_x, base_y; -}; - -static const struct wl_method input_device_methods[] = { -}; - -static const struct wl_event input_device_events[] = { - { "motion", "iiii" }, - { "button", "uu" }, - { "key", "uu" }, -}; - -static const struct wl_interface input_device_interface = { - "input_device", 1, - ARRAY_LENGTH(input_device_methods), - input_device_methods, - ARRAY_LENGTH(input_device_events), - input_device_events, + int base_x, base_y; + int fd; }; -static void wl_input_device_data(int fd, uint32_t mask, void *data) +static void evdev_input_device_data(int fd, uint32_t mask, void *data) { - struct wl_input_device *device = data; + struct evdev_input_device *device = data; struct input_event ev[8], *e, *end; int len, value, dx, dy, absolute_event; + int x, y; dx = 0; dy = 0; absolute_event = 0; + egl_device_get_position(device->device, &x, &y); + len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { @@ -96,17 +82,17 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) switch (e->code) { case ABS_X: if (device->new_x) { - device->base_x = device->x - value; + device->base_x = x - value; device->new_x = 0; } - device->x = device->base_x + value; + x = device->base_x + value; break; case ABS_Y: if (device->new_y) { - device->base_y = device->y - value; + device->base_y = y - value; device->new_y = 0; } - device->y = device->base_y + value; + y = device->base_y + value; break; } break; @@ -133,54 +119,44 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) break; case BTN_LEFT: - wl_display_post_button_event(device->display, - &device->base, 0, value); - break; - case BTN_RIGHT: - wl_display_post_button_event(device->display, - &device->base, 2, value); - break; - case BTN_MIDDLE: - wl_display_post_button_event(device->display, - &device->base, 1, value); + case BTN_SIDE: + case BTN_EXTRA: + case BTN_FORWARD: + case BTN_BACK: + case BTN_TASK: + notify_button(device->device, e->code, value); break; default: - wl_display_post_key_event(device->display, - &device->base, e->code, value); + notify_key(device->device, e->code, value); break; } } } if (dx != 0 || dy != 0) - wl_display_post_relative_event(device->display, - &device->base, dx, dy); + notify_motion(device->device, x + dx, y + dy); if (absolute_event && device->tool) - wl_display_post_absolute_event(device->display, - &device->base, - device->x, device->y); + notify_motion(device->device, x, y); } -WL_EXPORT struct wl_object * -wl_input_device_create(struct wl_display *display, const char *path) +struct evdev_input_device * +evdev_input_device_create(struct egl_input_device *master, + struct wl_display *display, const char *path) { - struct wl_input_device *device; + struct evdev_input_device *device; struct wl_event_loop *loop; device = malloc(sizeof *device); if (device == NULL) return NULL; - device->base.interface = &input_device_interface; - device->display = display; device->tool = 1; - device->x = 100; - device->y = 100; device->new_x = 1; device->new_y = 1; + device->device = master; device->fd = open(path, O_RDONLY); if (device->fd < 0) { @@ -192,12 +168,12 @@ wl_input_device_create(struct wl_display *display, const char *path) loop = wl_display_get_event_loop(display); device->source = wl_event_loop_add_fd(loop, device->fd, WL_EVENT_READABLE, - wl_input_device_data, device); + evdev_input_device_data, device); if (device->source == NULL) { close(device->fd); free(device); return NULL; } - return &device->base; + return device; } diff --git a/wayland.c b/wayland.c index 4f41ebd3..85301ab7 100644 --- a/wayland.c +++ b/wayland.c @@ -62,9 +62,6 @@ struct wl_display { uint32_t id; struct wl_list global_list; - - int32_t pointer_x; - int32_t pointer_y; }; struct wl_surface { @@ -582,9 +579,6 @@ wl_display_create(void) wl_list_init(&display->client_list); wl_list_init(&display->global_list); - display->pointer_x = 100; - display->pointer_y = 100; - display->client_id_range = 256; /* Gah, arbitrary... */ display->id = 1; @@ -633,53 +627,35 @@ wl_surface_post_event(struct wl_surface *surface, va_end(ap); } -WL_EXPORT void -wl_display_post_relative_event(struct wl_display *display, - struct wl_object *source, int dx, int dy) -{ - const struct wl_compositor_interface *interface; - - display->pointer_x += dx; - display->pointer_y += dy; - - interface = display->compositor->interface; - interface->notify_pointer_motion(display->compositor, source, - display->pointer_x, display->pointer_y); -} - -WL_EXPORT void -wl_display_post_absolute_event(struct wl_display *display, - struct wl_object *source, int x, int y) -{ - const struct wl_compositor_interface *interface; - - display->pointer_x = x; - display->pointer_y = y; +struct wl_input_device { + struct wl_object base; + struct wl_display *display; + uint32_t button_state[16]; + uint32_t button_count; + int32_t x, y; +}; - interface = display->compositor->interface; - interface->notify_pointer_motion(display->compositor, source, - display->pointer_x, display->pointer_y); -} +static const struct wl_method input_device_methods[] = { +}; -WL_EXPORT void -wl_display_post_button_event(struct wl_display *display, - struct wl_object *source, int button, int state) -{ - const struct wl_compositor_interface *interface; +static const struct wl_event input_device_events[] = { + { "motion", "iiii" }, + { "button", "uu" }, + { "key", "uu" }, +}; - interface = display->compositor->interface; - interface->notify_pointer_button(display->compositor, source, - button, state); -} +static const struct wl_interface input_device_interface = { + "input_device", 1, + ARRAY_LENGTH(input_device_methods), + input_device_methods, + ARRAY_LENGTH(input_device_events), + input_device_events, +}; -WL_EXPORT void -wl_display_post_key_event(struct wl_display *display, - struct wl_object *source, int key, int state) +WL_EXPORT const struct wl_interface * +wl_input_device_get_interface(void) { - const struct wl_compositor_interface *interface; - - interface = display->compositor->interface; - interface->notify_key(display->compositor, source, key, state); + return &input_device_interface; } WL_EXPORT void diff --git a/wayland.h b/wayland.h index 61258339..cc19ab3a 100644 --- a/wayland.h +++ b/wayland.h @@ -99,6 +99,7 @@ struct wl_object { struct wl_surface; struct wl_display; +struct wl_input_device; struct wl_map { int32_t x, y, width, height; @@ -107,9 +108,6 @@ struct wl_map { void wl_surface_set_data(struct wl_surface *surface, void *data); void *wl_surface_get_data(struct wl_surface *surface); -struct wl_object * -wl_input_device_create(struct wl_display *display, const char *path); - struct wl_display *wl_display_create(void); struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display); int wl_display_add_socket(struct wl_display *display, const char *name, size_t name_size); @@ -120,18 +118,9 @@ wl_display_add_object(struct wl_display *display, struct wl_object *object); int wl_display_add_global(struct wl_display *display, struct wl_object *object); -void -wl_display_post_relative_event(struct wl_display *display, - struct wl_object *source, int dx, int dy); -void -wl_display_post_absolute_event(struct wl_display *display, - struct wl_object *source, int x, int y); -void -wl_display_post_button_event(struct wl_display *display, - struct wl_object *source, int button, int state); -void -wl_display_post_key_event(struct wl_display *display, - struct wl_object *source, int key, int state); +const struct wl_interface * +wl_input_device_get_interface(void); + void wl_display_post_frame(struct wl_display *display, uint32_t frame, uint32_t msecs); @@ -173,15 +162,6 @@ struct wl_compositor_interface { int32_t x, int32_t y, int32_t width, int32_t height); uint32_t (*notify_commit)(struct wl_compositor *compositor); - void (*notify_pointer_motion)(struct wl_compositor *compositor, - struct wl_object *source, - int32_t x, int32_t y); - void (*notify_pointer_button)(struct wl_compositor *compositor, - struct wl_object *source, - int32_t button, int32_t state); - void (*notify_key)(struct wl_compositor *compositor, - struct wl_object *source, - uint32_t key, uint32_t state); }; void wl_display_set_compositor(struct wl_display *display, diff --git a/window.c b/window.c index 6b42322a..c44d29bd 100644 --- a/window.c +++ b/window.c @@ -31,6 +31,7 @@ #include #include +#include #include "wayland-client.h" #include "wayland-glib.h" @@ -272,7 +273,7 @@ event_handler(struct wl_display *display, location = LOCATION_OUTSIDE; } - if (button == 0 && state == 1) { + if (button == BTN_LEFT && state == 1) { switch (location) { case LOCATION_INTERIOR: window->drag_x = window->x - window->last_x; @@ -288,7 +289,7 @@ event_handler(struct wl_display *display, window->state = WINDOW_STABLE; break; } - } else if (button == 0 && state == 0) { + } else if (button == BTN_LEFT && state == 0) { window->state = WINDOW_STABLE; } } else if (opcode == 2) {