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.
This commit is contained in:
Kristian Høgsberg 2008-12-11 23:18:45 -05:00
parent d1c58d60f6
commit 5ee1a60f1a
6 changed files with 145 additions and 185 deletions

View File

@ -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

View File

@ -41,14 +41,22 @@
#include <xf86drmMode.h>
#include <time.h>
#include "wayland.h"
#include "cairo-util.h"
#include <GL/gl.h>
#include <eagle.h>
#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;

84
evdev.c
View File

@ -29,42 +29,28 @@
#include <linux/input.h>
#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;
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;
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;
}

View File

@ -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)
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;
};
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,
};
WL_EXPORT const struct wl_interface *
wl_input_device_get_interface(void)
{
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;
interface = display->compositor->interface;
interface->notify_pointer_motion(display->compositor, source,
display->pointer_x, display->pointer_y);
}
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;
interface = display->compositor->interface;
interface->notify_pointer_button(display->compositor, source,
button, state);
}
WL_EXPORT void
wl_display_post_key_event(struct wl_display *display,
struct wl_object *source, int key, int state)
{
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

View File

@ -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,

View File

@ -31,6 +31,7 @@
#include <cairo.h>
#include <glib.h>
#include <linux/input.h>
#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) {