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.
Kristian Høgsberg 16 years ago
parent d1c58d60f6
commit 5ee1a60f1a
  1. 4
      Makefile.in
  2. 127
      egl-compositor.c
  3. 84
      evdev.c
  4. 72
      wayland.c
  5. 28
      wayland.h
  6. 5
      window.c

@ -35,7 +35,7 @@ egl-compositor : \
wayland-util.o wayland-util.o
egl-compositor : CFLAGS += @EGL_COMPOSITOR_CFLAGS@ 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 flower : flower.o wayland-glib.o cairo-util.o
gears : gears.o window.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 terminal : LDLIBS += -lutil
$(clients) : CFLAGS += @CLIENT_CFLAGS@ $(clients) : CFLAGS += @CLIENT_CFLAGS@
$(clients) : LDLIBS += @CLIENT_LIBS@ -L. -lwayland -lrt $(clients) : LDLIBS += -L. -lwayland @CLIENT_LIBS@ -lrt
install : $(libs) install : $(libs)
install -d @libdir@ @libdir@/pkgconfig install -d @libdir@ @libdir@/pkgconfig

@ -41,14 +41,22 @@
#include <xf86drmMode.h> #include <xf86drmMode.h>
#include <time.h> #include <time.h>
#include "wayland.h"
#include "cairo-util.h"
#include <GL/gl.h> #include <GL/gl.h>
#include <eagle.h> #include <eagle.h>
#include "wayland.h"
#include "cairo-util.h"
#include "egl-compositor.h"
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) #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 egl_compositor {
struct wl_compositor base; struct wl_compositor base;
EGLDisplay display; EGLDisplay display;
@ -58,11 +66,12 @@ struct egl_compositor {
struct wl_display *wl_display; struct wl_display *wl_display;
int gem_fd; int gem_fd;
int width, height; int width, height;
struct egl_surface *pointer;
struct egl_surface *background; struct egl_surface *background;
struct egl_surface *overlay; struct egl_surface *overlay;
double overlay_y, overlay_target, overlay_previous; double overlay_y, overlay_target, overlay_previous;
struct egl_input_device *input_device;
struct wl_list surface_list; struct wl_list surface_list;
/* Repaint state. */ /* Repaint state. */
@ -324,7 +333,10 @@ pointer_create(int x, int y, int width, int height)
cairo_fill(cr); cairo_fill(cr);
cairo_destroy(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); cairo_surface_destroy(surface);
@ -577,7 +589,7 @@ repaint(void *data)
draw_surface(ec->overlay); draw_surface(ec->overlay);
draw_surface(ec->pointer); draw_surface(ec->input_device->surface);
eglSwapBuffers(ec->display, ec->surface); eglSwapBuffers(ec->display, ec->surface);
ec->repaint_needed = 0; ec->repaint_needed = 0;
@ -727,15 +739,18 @@ notify_commit(struct wl_compositor *compositor)
} }
static struct egl_surface * 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; struct egl_surface *es;
es = container_of(ec->surface_list.prev, es = container_of(ec->surface_list.prev,
struct egl_surface, link); struct egl_surface, link);
while (&es->link != &ec->surface_list) { while (&es->link != &ec->surface_list) {
if (es->map.x <= x && x < es->map.x + es->map.width && if (es->map.x <= device->x &&
es->map.y <= y && y < es->map.y + es->map.height) device->x < es->map.x + es->map.width &&
es->map.y <= device->y &&
device->y < es->map.y + es->map.height)
return es; return es;
es = container_of(es->link.prev, es = container_of(es->link.prev,
@ -745,59 +760,53 @@ pick_surface(struct egl_compositor *ec, int32_t x, int32_t y)
return NULL; return NULL;
} }
static void void
notify_pointer_motion(struct wl_compositor *compositor, notify_motion(struct egl_input_device *device, int x, int y)
struct wl_object *source, int x, int y)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor;
struct egl_surface *es; struct egl_surface *es;
const int hotspot_x = 16, hotspot_y = 16; const int hotspot_x = 16, hotspot_y = 16;
int32_t sx, sy; int32_t sx, sy;
es = pick_surface(ec, x, y); es = pick_surface(device);
if (es) { if (es) {
sx = (x - es->map.x) * es->width / es->map.width; sx = (x - es->map.x) * es->width / es->map.width;
sy = (y - es->map.y) * es->height / es->map.height; 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); WL_INPUT_MOTION, x, y, sx, sy);
} }
ec->pointer->map.x = x - hotspot_x; device->x = x;
ec->pointer->map.y = y - hotspot_y; device->y = y;
schedule_repaint(ec); device->surface->map.x = x - hotspot_x;
device->surface->map.y = y - hotspot_y;
schedule_repaint(device->ec);
} }
static void void
notify_pointer_button(struct wl_compositor *compositor, notify_button(struct egl_input_device *device,
struct wl_object *source,
int32_t button, int32_t state) int32_t button, int32_t state)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor;
struct egl_surface *es; 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) { if (es) {
wl_list_remove(&es->link); 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? */ /* 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); WL_INPUT_BUTTON, button, state);
}
schedule_repaint(ec); schedule_repaint(device->ec);
}
} }
static void void
notify_key(struct wl_compositor *compositor, notify_key(struct egl_input_device *device,
struct wl_object *source, uint32_t key, uint32_t state) uint32_t key, uint32_t state)
{ {
struct egl_compositor *ec = (struct egl_compositor *) compositor; struct egl_compositor *ec = device->ec;
struct egl_surface *es; struct egl_surface *es;
if (key == KEY_ESC && state == 1) { if (key == KEY_ESC && state == 1) {
@ -813,7 +822,7 @@ notify_key(struct wl_compositor *compositor,
* effectively gives us click to focus behavior. */ * effectively gives us click to focus behavior. */
es = container_of(ec->surface_list.prev, es = container_of(ec->surface_list.prev,
struct egl_surface, link); 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); WL_INPUT_KEY, key, state);
} }
} }
@ -826,9 +835,6 @@ static const struct wl_compositor_interface interface = {
notify_surface_copy, notify_surface_copy,
notify_surface_damage, notify_surface_damage,
notify_commit, notify_commit,
notify_pointer_motion,
notify_pointer_button,
notify_key
}; };
static const char pointer_device_file[] = static const char pointer_device_file[] =
@ -836,27 +842,49 @@ static const char pointer_device_file[] =
static const char keyboard_device_file[] = static const char keyboard_device_file[] =
"/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-kbd"; "/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 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; 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"); path = getenv("WAYLAND_POINTER");
if (path == NULL) if (path == NULL)
path = pointer_device_file; path = pointer_device_file;
obj = wl_input_device_create(display, path); evdev_input_device_create(device, ec->wl_display, path);
if (obj != NULL)
wl_display_add_object(display, obj);
path = getenv("WAYLAND_KEYBOARD"); path = getenv("WAYLAND_KEYBOARD");
if (path == NULL) if (path == NULL)
path = keyboard_device_file; path = keyboard_device_file;
obj = wl_input_device_create(display, path); evdev_input_device_create(device, ec->wl_display, path);
if (obj != NULL) }
wl_display_add_object(display, obj);
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 static uint32_t
@ -1065,14 +1093,13 @@ egl_compositor_create(struct wl_display *display)
glOrtho(0, ec->width, ec->height, 0, 0, 1000.0); glOrtho(0, ec->width, ec->height, 0, 0, 1000.0);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
create_input_devices(display); create_input_devices(ec);
wl_list_init(&ec->surface_list); wl_list_init(&ec->surface_list);
filename = getenv("WAYLAND_BACKGROUND"); filename = getenv("WAYLAND_BACKGROUND");
if (filename == NULL) if (filename == NULL)
filename = "background.jpg"; filename = "background.jpg";
ec->background = background_create(filename, 1280, 800); 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 = overlay_create(0, ec->height, ec->width, 200);
ec->overlay_y = ec->height; ec->overlay_y = ec->height;
ec->overlay_target = ec->height; ec->overlay_target = ec->height;

@ -29,42 +29,28 @@
#include <linux/input.h> #include <linux/input.h>
#include "wayland.h" #include "wayland.h"
#include "egl-compositor.h"
struct wl_input_device { struct evdev_input_device {
struct wl_object base; struct egl_input_device *device;
struct wl_event_source *source; struct wl_event_source *source;
struct wl_display *display;
int fd;
int tool, new_x, new_y; int tool, new_x, new_y;
int32_t x, y, base_x, base_y; int base_x, base_y;
}; int fd;
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,
}; };
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; struct input_event ev[8], *e, *end;
int len, value, dx, dy, absolute_event; int len, value, dx, dy, absolute_event;
int x, y;
dx = 0; dx = 0;
dy = 0; dy = 0;
absolute_event = 0; absolute_event = 0;
egl_device_get_position(device->device, &x, &y);
len = read(fd, &ev, sizeof ev); len = read(fd, &ev, sizeof ev);
if (len < 0 || len % sizeof e[0] != 0) { 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) { switch (e->code) {
case ABS_X: case ABS_X:
if (device->new_x) { if (device->new_x) {
device->base_x = device->x - value; device->base_x = x - value;
device->new_x = 0; device->new_x = 0;
} }
device->x = device->base_x + value; x = device->base_x + value;
break; break;
case ABS_Y: case ABS_Y:
if (device->new_y) { if (device->new_y) {
device->base_y = device->y - value; device->base_y = y - value;
device->new_y = 0; device->new_y = 0;
} }
device->y = device->base_y + value; y = device->base_y + value;
break; break;
} }
break; break;
@ -133,54 +119,44 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data)
break; break;
case BTN_LEFT: case BTN_LEFT:
wl_display_post_button_event(device->display,
&device->base, 0, value);
break;
case BTN_RIGHT: case BTN_RIGHT:
wl_display_post_button_event(device->display,
&device->base, 2, value);
break;
case BTN_MIDDLE: case BTN_MIDDLE:
wl_display_post_button_event(device->display, case BTN_SIDE:
&device->base, 1, value); case BTN_EXTRA:
case BTN_FORWARD:
case BTN_BACK:
case BTN_TASK:
notify_button(device->device, e->code, value);
break; break;
default: default:
wl_display_post_key_event(device->display, notify_key(device->device, e->code, value);
&device->base, e->code, value);
break; break;
} }
} }
} }
if (dx != 0 || dy != 0) if (dx != 0 || dy != 0)
wl_display_post_relative_event(device->display, notify_motion(device->device, x + dx, y + dy);
&device->base, dx, dy);
if (absolute_event && device->tool) if (absolute_event && device->tool)
wl_display_post_absolute_event(device->display, notify_motion(device->device, x, y);
&device->base,
device->x, device->y);
} }
WL_EXPORT struct wl_object * struct evdev_input_device *
wl_input_device_create(struct wl_display *display, const char *path) 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; struct wl_event_loop *loop;
device = malloc(sizeof *device); device = malloc(sizeof *device);
if (device == NULL) if (device == NULL)
return NULL; return NULL;
device->base.interface = &input_device_interface;
device->display = display;
device->tool = 1; device->tool = 1;
device->x = 100;
device->y = 100;
device->new_x = 1; device->new_x = 1;
device->new_y = 1; device->new_y = 1;
device->device = master;
device->fd = open(path, O_RDONLY); device->fd = open(path, O_RDONLY);
if (device->fd < 0) { 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); loop = wl_display_get_event_loop(display);
device->source = wl_event_loop_add_fd(loop, device->fd, device->source = wl_event_loop_add_fd(loop, device->fd,
WL_EVENT_READABLE, WL_EVENT_READABLE,
wl_input_device_data, device); evdev_input_device_data, device);
if (device->source == NULL) { if (device->source == NULL) {
close(device->fd); close(device->fd);
free(device); free(device);
return NULL; return NULL;
} }
return &device->base; return device;
} }

@ -62,9 +62,6 @@ struct wl_display {
uint32_t id; uint32_t id;
struct wl_list global_list; struct wl_list global_list;
int32_t pointer_x;
int32_t pointer_y;
}; };
struct wl_surface { struct wl_surface {
@ -582,9 +579,6 @@ wl_display_create(void)
wl_list_init(&display->client_list); wl_list_init(&display->client_list);
wl_list_init(&display->global_list); wl_list_init(&display->global_list);
display->pointer_x = 100;
display->pointer_y = 100;
display->client_id_range = 256; /* Gah, arbitrary... */ display->client_id_range = 256; /* Gah, arbitrary... */
display->id = 1; display->id = 1;
@ -633,53 +627,35 @@ wl_surface_post_event(struct wl_surface *surface,
va_end(ap); va_end(ap);
} }
WL_EXPORT void struct wl_input_device {
wl_display_post_relative_event(struct wl_display *display, struct wl_object base;
struct wl_object *source, int dx, int dy) struct wl_display *display;
{ uint32_t button_state[16];
const struct wl_compositor_interface *interface; uint32_t button_count;
int32_t x, y;
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;
interface = display->compositor->interface; static const struct wl_method input_device_methods[] = {
interface->notify_pointer_motion(display->compositor, source, };
display->pointer_x, display->pointer_y);
}
WL_EXPORT void static const struct wl_event input_device_events[] = {
wl_display_post_button_event(struct wl_display *display, { "motion", "iiii" },
struct wl_object *source, int button, int state) { "button", "uu" },
{ { "key", "uu" },
const struct wl_compositor_interface *interface; };
interface = display->compositor->interface; static const struct wl_interface input_device_interface = {
interface->notify_pointer_button(display->compositor, source, "input_device", 1,
button, state); ARRAY_LENGTH(input_device_methods),
} input_device_methods,
ARRAY_LENGTH(input_device_events),
input_device_events,
};
WL_EXPORT void WL_EXPORT const struct wl_interface *
wl_display_post_key_event(struct wl_display *display, wl_input_device_get_interface(void)
struct wl_object *source, int key, int state)
{ {
const struct wl_compositor_interface *interface; return &input_device_interface;
interface = display->compositor->interface;
interface->notify_key(display->compositor, source, key, state);
} }
WL_EXPORT void WL_EXPORT void

@ -99,6 +99,7 @@ struct wl_object {
struct wl_surface; struct wl_surface;
struct wl_display; struct wl_display;
struct wl_input_device;
struct wl_map { struct wl_map {
int32_t x, y, width, height; 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_set_data(struct wl_surface *surface, void *data);
void *wl_surface_get_data(struct wl_surface *surface); 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_display *wl_display_create(void);
struct wl_event_loop *wl_display_get_event_loop(struct wl_display *display); 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); 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 int
wl_display_add_global(struct wl_display *display, struct wl_object *object); wl_display_add_global(struct wl_display *display, struct wl_object *object);
void const struct wl_interface *
wl_display_post_relative_event(struct wl_display *display, wl_input_device_get_interface(void);
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);
void void
wl_display_post_frame(struct wl_display *display, wl_display_post_frame(struct wl_display *display,
uint32_t frame, uint32_t msecs); uint32_t frame, uint32_t msecs);
@ -173,15 +162,6 @@ struct wl_compositor_interface {
int32_t x, int32_t y, int32_t x, int32_t y,
int32_t width, int32_t height); int32_t width, int32_t height);
uint32_t (*notify_commit)(struct wl_compositor *compositor); 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, void wl_display_set_compositor(struct wl_display *display,

@ -31,6 +31,7 @@
#include <cairo.h> #include <cairo.h>
#include <glib.h> #include <glib.h>
#include <linux/input.h>
#include "wayland-client.h" #include "wayland-client.h"
#include "wayland-glib.h" #include "wayland-glib.h"
@ -272,7 +273,7 @@ event_handler(struct wl_display *display,
location = LOCATION_OUTSIDE; location = LOCATION_OUTSIDE;
} }
if (button == 0 && state == 1) { if (button == BTN_LEFT && state == 1) {
switch (location) { switch (location) {
case LOCATION_INTERIOR: case LOCATION_INTERIOR:
window->drag_x = window->x - window->last_x; window->drag_x = window->x - window->last_x;
@ -288,7 +289,7 @@ event_handler(struct wl_display *display,
window->state = WINDOW_STABLE; window->state = WINDOW_STABLE;
break; break;
} }
} else if (button == 0 && state == 0) { } else if (button == BTN_LEFT && state == 0) {
window->state = WINDOW_STABLE; window->state = WINDOW_STABLE;
} }
} else if (opcode == 2) { } else if (opcode == 2) {

Loading…
Cancel
Save