Drop coordinates from buttons press, add timestamp to events
authorKristian Høgsberg <krh@bitplanet.net>
Tue, 20 Jul 2010 21:06:19 +0000 (17:06 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 20 Jul 2010 21:06:19 +0000 (17:06 -0400)
clients/window.c
clients/window.h
compositor-drm.c
compositor-x11.c
compositor.c
compositor.h
wayland-client.h
wayland-protocol.c

index 2a68a28..8f8b9e1 100644 (file)
@@ -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;
 }
 
@@ -747,6 +776,26 @@ static const struct wl_output_listener output_listener = {
 };
 
 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);
index f020ace..f3ab19b 100644 (file)
@@ -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,
index 1fb4c21..6a93065 100644 (file)
@@ -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 *
index 46f6a76..76ee744 100644 (file)
@@ -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;
index 824bf0d..ac2960e 100644 (file)
@@ -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);
        }
 }
index 362a8c5..0129c84 100644 (file)
@@ -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);
index ca4a515..be77a0e 100644 (file)
@@ -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);
 };
index 19e5db7..5a989d4 100644 (file)
@@ -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 = {