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;
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;
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;
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)
{
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;
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;
}
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;
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:
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 = {
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;
}
};
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)
{
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);
}
}
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);
};
struct display;
+struct input;
struct display *
display_create(int *argc, char **argv[], const GOptionEntry *option_entries);
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,
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)
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:
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 *
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;
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;
(!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;
(!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;
}
}
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;
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);
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);
}
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;
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
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);
}
}
};
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);
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);
};
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 = {