From 808fd4186109960f687507fb326f43b3dae75078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 20 Jul 2010 17:06:19 -0400 Subject: [PATCH] Drop coordinates from buttons press, add timestamp to events --- clients/window.c | 157 ++++++++++++++++++++++++++++++--------------- clients/window.h | 3 +- compositor-drm.c | 10 +-- compositor-x11.c | 7 +- compositor.c | 56 ++++++++++------ compositor.h | 9 ++- wayland-client.h | 8 ++- wayland-protocol.c | 10 +-- 8 files changed, 169 insertions(+), 91 deletions(-) diff --git a/clients/window.c b/clients/window.c index 2a68a287..8f8b9e10 100644 --- a/clients/window.c +++ b/clients/window.c @@ -53,7 +53,6 @@ struct display { struct wl_display *display; struct wl_compositor *compositor; struct wl_output *output; - struct wl_input_device *input_device; struct rectangle screen_allocation; EGLDisplay dpy; EGLContext ctx; @@ -62,6 +61,7 @@ struct display { GMainLoop *loop; GSource *source; struct wl_list window_list; + struct wl_list input_list; char *device_name; cairo_surface_t *active_frame, *inactive_frame, *shadow; struct xkb_desc *xkb; @@ -79,10 +79,9 @@ struct window { int state; int fullscreen; int decoration; - struct wl_input_device *grab_device; - struct wl_input_device *keyboard_device; + struct input *grab_device; + struct input *keyboard_device; uint32_t name; - uint32_t modifiers; EGLImageKHR *image; cairo_surface_t *cairo_surface, *pending_surface; @@ -98,6 +97,16 @@ struct window { struct wl_list link; }; +struct input { + struct display *display; + struct wl_input_device *input_device; + struct window *pointer_focus; + struct window *keyboard_focus; + uint32_t modifiers; + int32_t x, y, sx, sy; + struct wl_list link; +}; + static void rounded_rect(cairo_t *cr, int x0, int y0, int x1, int y1, int radius) { @@ -302,15 +311,22 @@ enum window_state { static void window_handle_motion(void *data, struct wl_input_device *input_device, + uint32_t time, int32_t x, int32_t y, int32_t sx, int32_t sy) { - struct window *window = data; + struct input *input = data; + struct window *window = input->pointer_focus; + + input->x = x; + input->y = y; + input->sx = sx; + input->sy = sy; switch (window->state) { case WINDOW_MOVING: if (window->fullscreen) break; - if (window->grab_device != input_device) + if (window->grab_device != input) break; window->allocation.x = window->drag_x + x; window->allocation.y = window->drag_y + y; @@ -332,7 +348,7 @@ window_handle_motion(void *data, struct wl_input_device *input_device, case WINDOW_RESIZING_BOTTOM_RIGHT: if (window->fullscreen) break; - if (window->grab_device != input_device) + if (window->grab_device != input) break; if (window->state & WINDOW_RESIZING_LEFT) { window->allocation.x = x - window->drag_x + window->saved_allocation.x; @@ -357,26 +373,26 @@ window_handle_motion(void *data, struct wl_input_device *input_device, } static void window_handle_button(void *data, struct wl_input_device *input_device, - uint32_t button, uint32_t state, - int32_t x, int32_t y, int32_t sx, int32_t sy) + uint32_t time, uint32_t button, uint32_t state) { - struct window *window = data; + struct input *input = data; + struct window *window = input->pointer_focus; int grip_size = 8, vlocation, hlocation; - if (window->margin <= sx && sx < window->margin + grip_size) + if (window->margin <= input->sx && input->sx < window->margin + grip_size) hlocation = WINDOW_RESIZING_LEFT; - else if (sx < window->allocation.width - window->margin - grip_size) + else if (input->sx < window->allocation.width - window->margin - grip_size) hlocation = WINDOW_MOVING; - else if (sx < window->allocation.width - window->margin) + else if (input->sx < window->allocation.width - window->margin) hlocation = WINDOW_RESIZING_RIGHT; else hlocation = WINDOW_STABLE; - if (window->margin <= sy && sy < window->margin + grip_size) + if (window->margin <= input->sy && input->sy < window->margin + grip_size) vlocation = WINDOW_RESIZING_TOP; - else if (sy < window->allocation.height - window->margin - grip_size) + else if (input->sy < window->allocation.height - window->margin - grip_size) vlocation = WINDOW_MOVING; - else if (sy < window->allocation.height - window->margin) + else if (input->sy < window->allocation.height - window->margin) vlocation = WINDOW_RESIZING_BOTTOM; else vlocation = WINDOW_STABLE; @@ -384,10 +400,10 @@ static void window_handle_button(void *data, struct wl_input_device *input_devic if (button == BTN_LEFT && state == 1) { switch (hlocation | vlocation) { case WINDOW_MOVING: - window->drag_x = window->allocation.x - x; - window->drag_y = window->allocation.y - y; + window->drag_x = window->allocation.x - input->x; + window->drag_y = window->allocation.y - input->y; window->state = WINDOW_MOVING; - window->grab_device = input_device; + window->grab_device = input; break; case WINDOW_RESIZING_TOP: case WINDOW_RESIZING_BOTTOM: @@ -397,87 +413,102 @@ static void window_handle_button(void *data, struct wl_input_device *input_devic case WINDOW_RESIZING_TOP_RIGHT: case WINDOW_RESIZING_BOTTOM_LEFT: case WINDOW_RESIZING_BOTTOM_RIGHT: - window->drag_x = x; - window->drag_y = y; + window->drag_x = input->x; + window->drag_y = input->y; window->saved_allocation = window->allocation; window->state = hlocation | vlocation; - window->grab_device = input_device; + window->grab_device = input; break; default: window->state = WINDOW_STABLE; break; } } else if (button == BTN_LEFT && - state == 0 && window->grab_device == input_device) { + state == 0 && window->grab_device == input) { window->state = WINDOW_STABLE; } } static void window_handle_key(void *data, struct wl_input_device *input_device, - uint32_t key, uint32_t state) + uint32_t time, uint32_t key, uint32_t state) { - struct window *window = data; + struct input *input = data; + struct window *window = input->keyboard_focus; struct display *d = window->display; uint32_t code, sym, level; code = key + d->xkb->min_key_code; - if (window->keyboard_device != input_device) + if (window->keyboard_device != input) return; level = 0; - if (window->modifiers & WINDOW_MODIFIER_SHIFT && + if (input->modifiers & WINDOW_MODIFIER_SHIFT && XkbKeyGroupWidth(d->xkb, code, 0) > 1) level = 1; sym = XkbKeySymEntry(d->xkb, code, level, 0); if (state) - window->modifiers |= d->xkb->map->modmap[code]; + input->modifiers |= d->xkb->map->modmap[code]; else - window->modifiers &= ~d->xkb->map->modmap[code]; + input->modifiers &= ~d->xkb->map->modmap[code]; if (window->key_handler) (*window->key_handler)(window, key, sym, state, - window->modifiers, window->user_data); + input->modifiers, window->user_data); } static void window_handle_pointer_focus(void *data, struct wl_input_device *input_device, - struct wl_surface *surface) + uint32_t time, struct wl_surface *surface) { + struct input *input = data; + + if (surface) + input->pointer_focus = wl_surface_get_user_data(surface); + else + input->pointer_focus = NULL; } static void window_handle_keyboard_focus(void *data, struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, struct wl_array *keys) { - struct window *window = data; - struct display *d = window->display; + struct input *input = data; + struct window *window = input->keyboard_focus; + struct display *d = input->display; uint32_t *k, *end; - if (window->keyboard_device == input_device && surface != window->surface) + window = input->keyboard_focus; + if (window) { window->keyboard_device = NULL; - else if (window->keyboard_device == NULL && surface == window->surface) - window->keyboard_device = input_device; - else - return; - - if (window->keyboard_device) { - end = keys->data + keys->size; - for (k = keys->data; k < end; k++) - window->modifiers |= d->xkb->map->modmap[*k]; - } else { - window->modifiers = 0; + if (window->keyboard_focus_handler) + (*window->keyboard_focus_handler)(window, NULL, + window->user_data); } - if (window->keyboard_focus_handler) - (*window->keyboard_focus_handler)(window, - window->keyboard_device, - window->user_data); + if (surface) + input->keyboard_focus = wl_surface_get_user_data(surface); + else + input->keyboard_focus = NULL; + + end = keys->data + keys->size; + for (k = keys->data; k < end; k++) + input->modifiers |= d->xkb->map->modmap[*k]; + + window = input->keyboard_focus; + if (window) { + window->keyboard_device = input; + if (window->keyboard_focus_handler) + (*window->keyboard_focus_handler)(window, + window->keyboard_device, + window->user_data); + } } static const struct wl_input_device_listener input_device_listener = { @@ -668,11 +699,9 @@ window_create(struct display *display, const char *title, window->state = WINDOW_STABLE; window->decoration = 1; + wl_surface_set_user_data(window->surface, window); wl_list_insert(display->window_list.prev, &window->link); - wl_input_device_add_listener(display->input_device, - &input_device_listener, window); - return window; } @@ -746,6 +775,26 @@ static const struct wl_output_listener output_listener = { display_handle_geometry, }; +static void +display_add_input(struct display *d, struct wl_object *object) +{ + struct input *input; + + input = malloc(sizeof *input); + if (input == NULL) + return; + + memset(input, 0, sizeof *input); + input->display = d; + input->input_device = (struct wl_input_device *) object; + input->pointer_focus = NULL; + input->keyboard_focus = NULL; + wl_list_insert(d->input_list.prev, &input->link); + + wl_input_device_add_listener(input->input_device, + &input_device_listener, input); +} + static void display_handle_global(struct wl_display *display, struct wl_object *object, void *data) @@ -759,7 +808,7 @@ display_handle_global(struct wl_display *display, d->output = (struct wl_output *) object; wl_output_add_listener(d->output, &output_listener, d); } else if (wl_object_implements(object, "input_device", 1)) { - d->input_device =(struct wl_input_device *) object; + display_add_input(d, object); } } @@ -855,6 +904,8 @@ display_create(int *argc, char **argv[], const GOptionEntry *option_entries) return NULL; } + wl_list_init(&d->input_list); + /* Set up listener so we'll catch all events. */ wl_display_add_global_listener(d->display, display_handle_global, d); diff --git a/clients/window.h b/clients/window.h index f020acee..f3ab19b6 100644 --- a/clients/window.h +++ b/clients/window.h @@ -33,6 +33,7 @@ struct rectangle { }; struct display; +struct input; struct display * display_create(int *argc, char **argv[], const GOptionEntry *option_entries); @@ -67,7 +68,7 @@ typedef void (*window_acknowledge_handler_t)(struct window *window, uint32_t key typedef void (*window_key_handler_t)(struct window *window, uint32_t key, uint32_t unicode, uint32_t state, uint32_t modifiers, void *data); typedef void (*window_keyboard_focus_handler_t)(struct window *window, - struct wl_input_device *device, void *data); + struct input *device, void *data); struct window * window_create(struct display *display, const char *title, diff --git a/compositor-drm.c b/compositor-drm.c index 1fb4c21d..6a930650 100644 --- a/compositor-drm.c +++ b/compositor-drm.c @@ -87,6 +87,7 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) struct input_event ev[8], *e, *end; int len, value, dx, dy, absolute_event; int x, y; + uint32_t time; c = (struct drm_compositor *) device->master->base.ec; if (!c->vt_active) @@ -109,6 +110,7 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) for (e = ev; e < end; e++) { /* Get the signed value, earlier kernels had this as unsigned */ value = e->value; + time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; switch (e->type) { case EV_REL: @@ -173,21 +175,21 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) case BTN_BACK: case BTN_TASK: notify_button(&device->master->base, - e->code, value); + time, e->code, value); break; default: notify_key(&device->master->base, - e->code, value); + time, e->code, value); break; } } } if (dx != 0 || dy != 0) - notify_motion(&device->master->base, x + dx, y + dy); + notify_motion(&device->master->base, time, x + dx, y + dy); if (absolute_event && device->tool) - notify_motion(&device->master->base, x, y); + notify_motion(&device->master->base, time, x, y); } static struct evdev_input_device * diff --git a/compositor-x11.c b/compositor-x11.c index 46f6a765..76ee7449 100644 --- a/compositor-x11.c +++ b/compositor-x11.c @@ -511,27 +511,30 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data) case XCB_KEY_PRESS: key_press = (xcb_key_press_event_t *) event; notify_key(c->base.input_device, - key_press->detail - 8, 1); + key_press->time, key_press->detail - 8, 1); break; case XCB_KEY_RELEASE: key_press = (xcb_key_press_event_t *) event; notify_key(c->base.input_device, - key_press->detail - 8, 0); + key_press->time, key_press->detail - 8, 0); break; case XCB_BUTTON_PRESS: button_press = (xcb_button_press_event_t *) event; notify_button(c->base.input_device, + button_press->time, button_press->detail + BTN_LEFT - 1, 1); break; case XCB_BUTTON_RELEASE: button_press = (xcb_button_press_event_t *) event; notify_button(c->base.input_device, + button_press->time, button_press->detail + BTN_LEFT - 1, 0); break; case XCB_MOTION_NOTIFY: motion_notify = (xcb_motion_notify_event_t *) event; notify_motion(c->base.input_device, + motion_notify->time, motion_notify->event_x, motion_notify->event_y); break; diff --git a/compositor.c b/compositor.c index 824bf0d0..ac2960e2 100644 --- a/compositor.c +++ b/compositor.c @@ -549,7 +549,8 @@ wlsc_surface_transform(struct wlsc_surface *surface, static void wlsc_input_device_set_keyboard_focus(struct wlsc_input_device *device, - struct wlsc_surface *surface) + struct wlsc_surface *surface, + uint32_t time) { if (device->keyboard_focus == surface) return; @@ -558,20 +559,22 @@ wlsc_input_device_set_keyboard_focus(struct wlsc_input_device *device, (!surface || device->keyboard_focus->base.client != surface->base.client)) wl_surface_post_event(&device->keyboard_focus->base, &device->base, - WL_INPUT_KEYBOARD_FOCUS, NULL, &device->keys); + WL_INPUT_KEYBOARD_FOCUS, + time, NULL, &device->keys); if (surface) wl_surface_post_event(&surface->base, &device->base, WL_INPUT_KEYBOARD_FOCUS, - &surface->base, &device->keys); + time, &surface->base, &device->keys); device->keyboard_focus = surface; } static void wlsc_input_device_set_pointer_focus(struct wlsc_input_device *device, - struct wlsc_surface *surface) + struct wlsc_surface *surface, + uint32_t time) { if (device->pointer_focus == surface) return; @@ -580,11 +583,13 @@ wlsc_input_device_set_pointer_focus(struct wlsc_input_device *device, (!surface || device->pointer_focus->base.client != surface->base.client)) wl_surface_post_event(&device->pointer_focus->base, &device->base, - WL_INPUT_POINTER_FOCUS, NULL); + WL_INPUT_POINTER_FOCUS, + time, NULL); if (surface) wl_surface_post_event(&surface->base, &device->base, - WL_INPUT_POINTER_FOCUS, &surface->base); + WL_INPUT_POINTER_FOCUS, + time, &surface->base); device->pointer_focus = surface; } @@ -612,7 +617,7 @@ pick_surface(struct wlsc_input_device *device, int32_t *sx, int32_t *sy) } void -notify_motion(struct wlsc_input_device *device, int x, int y) +notify_motion(struct wlsc_input_device *device, uint32_t time, int x, int y) { struct wlsc_surface *es; struct wlsc_compositor *ec = device->ec; @@ -635,11 +640,11 @@ notify_motion(struct wlsc_input_device *device, int x, int y) device->y = y; es = pick_surface(device, &sx, &sy); - wlsc_input_device_set_pointer_focus(device, es); - + wlsc_input_device_set_pointer_focus(device, es, time); + if (es) wl_surface_post_event(&es->base, &device->base, - WL_INPUT_MOTION, x, y, sx, sy); + WL_INPUT_MOTION, time, x, y, sx, sy); wlsc_matrix_init(&device->sprite->matrix); wlsc_matrix_scale(&device->sprite->matrix, 64, 64, 1); @@ -651,28 +656,26 @@ notify_motion(struct wlsc_input_device *device, int x, int y) void notify_button(struct wlsc_input_device *device, - int32_t button, int32_t state) + uint32_t time, int32_t button, int32_t state) { struct wlsc_surface *surface; struct wlsc_compositor *compositor = device->ec; - int32_t sx, sy; - surface = pick_surface(device, &sx, &sy); + surface = device->pointer_focus; if (surface) { if (state) { wlsc_surface_raise(surface); device->grab++; device->grab_surface = surface; wlsc_input_device_set_keyboard_focus(device, - surface); + surface, time); } else { device->grab--; } /* FIXME: Swallow click on raise? */ wl_surface_post_event(&surface->base, &device->base, - WL_INPUT_BUTTON, button, state, - device->x, device->y, sx, sy); + WL_INPUT_BUTTON, time, button, state); wlsc_compositor_schedule_repaint(compositor); } @@ -680,7 +683,7 @@ notify_button(struct wlsc_input_device *device, void notify_key(struct wlsc_input_device *device, - uint32_t key, uint32_t state) + uint32_t time, uint32_t key, uint32_t state) { struct wlsc_compositor *compositor = device->ec; uint32_t *k, *end; @@ -726,8 +729,18 @@ notify_key(struct wlsc_input_device *device, if (device->keyboard_focus != NULL) wl_surface_post_event(&device->keyboard_focus->base, - &device->base, - WL_INPUT_KEY, key, state); + &device->base, + WL_INPUT_KEY, time, key, state); +} + +static uint32_t +get_time(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + return tv.tv_sec * 1000 + tv.tv_usec / 1000; } static void @@ -738,16 +751,17 @@ handle_surface_destroy(struct wlsc_listener *listener, container_of(listener, struct wlsc_input_device, listener); struct wlsc_surface *focus; int32_t sx, sy; + uint32_t time = get_time(); if (device->grab_surface == surface) { device->grab_surface = NULL; device->grab = 0; } if (device->keyboard_focus == surface) - wlsc_input_device_set_keyboard_focus(device, NULL); + wlsc_input_device_set_keyboard_focus(device, NULL, time); if (device->pointer_focus == surface) { focus = pick_surface(device, &sx, &sy); - wlsc_input_device_set_pointer_focus(device, focus); + wlsc_input_device_set_pointer_focus(device, focus, time); fprintf(stderr, "lost pointer focus surface, reverting to %p\n", focus); } } diff --git a/compositor.h b/compositor.h index 362a8c58..0129c84d 100644 --- a/compositor.h +++ b/compositor.h @@ -124,11 +124,14 @@ struct wlsc_surface { }; void -notify_motion(struct wlsc_input_device *device, int x, int y); +notify_motion(struct wlsc_input_device *device, + uint32_t time, int x, int y); void -notify_button(struct wlsc_input_device *device, int32_t button, int32_t state); +notify_button(struct wlsc_input_device *device, + uint32_t time, int32_t button, int32_t state); void -notify_key(struct wlsc_input_device *device, uint32_t key, uint32_t state); +notify_key(struct wlsc_input_device *device, + uint32_t time, uint32_t key, uint32_t state); void wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs); diff --git a/wayland-client.h b/wayland-client.h index ca4a515c..be77a0e0 100644 --- a/wayland-client.h +++ b/wayland-client.h @@ -120,19 +120,23 @@ struct wl_input_device; struct wl_input_device_listener { void (*motion)(void *data, struct wl_input_device *input_device, + uint32_t time, int32_t x, int32_t y, int32_t sx, int32_t sy); void (*button)(void *data, struct wl_input_device *input_device, - uint32_t button, uint32_t state, - int32_t x, int32_t y, int32_t sx, int32_t sy); + uint32_t time, + uint32_t button, uint32_t state); void (*key)(void *data, struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state); void (*pointer_focus)(void *data, struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface); void (*keyboard_focus)(void *data, struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, struct wl_array *keys); }; diff --git a/wayland-protocol.c b/wayland-protocol.c index 19e5db74..5a989d46 100644 --- a/wayland-protocol.c +++ b/wayland-protocol.c @@ -73,11 +73,11 @@ WL_EXPORT const struct wl_interface wl_surface_interface = { static const struct wl_message input_device_events[] = { - { "motion", "iiii" }, - { "button", "uuiiii" }, - { "key", "uu" }, - { "pointer_focus", "o" }, - { "keyboard_focus", "oa" }, + { "motion", "uiiii" }, + { "button", "uuu" }, + { "key", "uuu" }, + { "pointer_focus", "uo" }, + { "keyboard_focus", "uoa" }, }; WL_EXPORT const struct wl_interface wl_input_device_interface = {