[PATCH 4/4] compositor: implement new pointer surface protocol
Ander Conselvan de Oliveira
conselvan2 at gmail.com
Thu Feb 23 03:42:50 PST 2012
---
clients/window.c | 25 +++++++-
src/compositor.c | 180 ++++++++++++++++++++++++++++++++++++++++++++----------
src/compositor.h | 10 +++
3 files changed, 179 insertions(+), 36 deletions(-)
diff --git a/clients/window.c b/clients/window.c
index ac26f52..e503182 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -159,6 +159,7 @@ struct input {
struct wl_input_device *input_device;
struct window *pointer_focus;
struct window *keyboard_focus;
+ struct wl_surface *pointer_surface;
uint32_t current_pointer_image;
uint32_t modifiers;
int32_t sx, sy;
@@ -1875,10 +1876,12 @@ input_set_pointer_image(struct input *input, uint32_t time, int pointer)
struct display *display = input->display;
struct wl_buffer *buffer;
cairo_surface_t *surface;
+ int old_pointer;
if (pointer == input->current_pointer_image)
return;
+ old_pointer = input->current_pointer_image;
input->current_pointer_image = pointer;
surface = display->pointer_surfaces[pointer];
@@ -1886,9 +1889,20 @@ input_set_pointer_image(struct input *input, uint32_t time, int pointer)
return;
buffer = display_get_buffer_for_surface(display, surface);
- wl_input_device_attach(input->input_device, time, buffer,
- pointer_images[pointer].hotspot_x,
- pointer_images[pointer].hotspot_y);
+ if (old_pointer == POINTER_UNSET) {
+ wl_input_device_set_hotspot(input->input_device,
+ pointer_images[pointer].hotspot_x,
+ pointer_images[pointer].hotspot_y);
+ wl_surface_attach(input->pointer_surface, buffer, 0, 0);
+ }
+ else {
+ int dx = pointer_images[old_pointer].hotspot_x -
+ pointer_images[pointer].hotspot_x;
+ int dy = pointer_images[old_pointer].hotspot_y -
+ pointer_images[pointer].hotspot_y;
+
+ wl_surface_attach(input->pointer_surface, buffer, dx, dy);
+ }
}
struct wl_data_device *
@@ -2650,6 +2664,11 @@ display_add_input(struct display *d, uint32_t id)
input->input_device);
wl_data_device_add_listener(input->data_device,
&data_device_listener, input);
+
+ input->current_pointer_image = POINTER_UNSET;
+ input->pointer_surface = wl_compositor_create_surface(d->compositor);
+ wl_input_device_set_pointer_surface(input->input_device,
+ input->pointer_surface);
}
static void
diff --git a/src/compositor.c b/src/compositor.c
index 97f7c3e..a84f52f 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -929,6 +929,7 @@ weston_output_repaint(struct weston_output *output, int msecs)
overlap, surface_overlap;
int32_t width, height;
+ weston_compositor_update_cursor_sprites(ec);
weston_compositor_update_drag_surfaces(ec);
width = output->current->width +
@@ -1107,15 +1108,23 @@ weston_surface_assign_output(struct weston_surface *es)
}
}
+static struct weston_pointer_surface *
+device_client_pointer_surface(struct weston_input_device *device,
+ struct wl_client *client);
+
static void
surface_attach(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
{
struct weston_surface *es = resource->data;
+ struct weston_input_device *device = (struct weston_input_device *)
+ es->compositor->input_device;
struct weston_shell *shell = es->compositor->shell;
struct wl_buffer *buffer;
+ struct weston_pointer_surface *ps;
+
if (!buffer_resource && !es->output)
return;
@@ -1152,6 +1161,17 @@ surface_attach(struct wl_client *client,
buffer->width, buffer->height);
}
+ ps = device_client_pointer_surface(device, client);
+ if (ps && es == ps->surface) {
+ ps->hotspot_x -= sx;
+ ps->hotspot_y -= sy;
+
+ if (ps->surface == device->sprite) {
+ device->hotspot_x = ps->hotspot_x;
+ device->hotspot_y = ps->hotspot_y;
+ }
+ }
+
weston_buffer_attach(buffer, &es->surface);
}
@@ -1666,47 +1686,74 @@ notify_touch(struct wl_input_device *device, uint32_t time, int touch_id,
}
static void
-input_device_attach(struct wl_client *client,
- struct wl_resource *resource,
- uint32_t time,
- struct wl_resource *buffer_resource, int32_t x, int32_t y)
+pointer_surface_destroy(struct weston_pointer_surface *ps)
+{
+ if (!ps)
+ return;
+
+ if (ps->surface->output)
+ weston_surface_unmap(ps->surface);
+
+ ps->surface->pickable = 1;
+ wl_list_remove(&ps->link);
+ free(ps);
+}
+
+static void
+input_device_set_pointer_surface(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *surface_resource)
{
struct weston_input_device *device = resource->data;
- struct weston_compositor *compositor = device->compositor;
- struct wl_buffer *buffer;
+ struct weston_pointer_surface *ps;
+ struct weston_surface *es;
- if (time < device->input_device.pointer_focus_time)
- return;
- if (device->input_device.pointer_focus == NULL)
- return;
- if (device->input_device.pointer_focus->resource.client != client)
- return;
+ /* find if client has a previous pointer surface for this device */
+ ps = device_client_pointer_surface(device, client);
+ pointer_surface_destroy(ps);
- if (!buffer_resource && device->sprite->output) {
- wl_list_remove(&device->sprite->link);
- device->sprite->output = NULL;
- return;
- }
+ if (surface_resource) {
+ es = surface_resource->data;
+
+ ps = malloc(sizeof *ps);
+ ps->surface = es;
+ ps->hotspot_x = 0;
+ ps->hotspot_y = 0;
- if (!device->sprite->output) {
- wl_list_insert(&compositor->surface_list,
- &device->sprite->link);
- weston_surface_assign_output(device->sprite);
+ es->pickable = 0;
+ wl_list_insert(&device->pointer_surfaces, &ps->link);
}
+}
- buffer = buffer_resource->data;
- device->hotspot_x = x;
- device->hotspot_y = y;
- weston_surface_configure(device->sprite,
- device->input_device.x - device->hotspot_x,
- device->input_device.y - device->hotspot_y,
- buffer->width, buffer->height);
+static void
+input_device_set_hotspot(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t x, int32_t y)
+{
+ struct weston_input_device *device = resource->data;
+ struct weston_pointer_surface *ps;
+
+ ps = device_client_pointer_surface(device, client);
+ if (!ps)
+ return;
- weston_buffer_attach(buffer, &device->sprite->surface);
+ ps->hotspot_x = x;
+ ps->hotspot_y = y;
+
+ if (device->sprite == ps->surface) {
+ device->hotspot_x = x;
+ device->hotspot_y = y;
+
+ weston_surface_set_position(device->sprite,
+ device->input_device.x - x,
+ device->input_device.y - y);
+ weston_compositor_schedule_repaint(device->compositor);
+ }
}
const static struct wl_input_device_interface input_device_interface = {
- input_device_attach,
+ input_device_set_pointer_surface,
+ input_device_set_hotspot,
};
static void unbind_input_device(struct wl_resource *resource)
@@ -1737,7 +1784,8 @@ weston_input_device_init(struct weston_input_device *device,
wl_display_add_global(ec->wl_display, &wl_input_device_interface,
device, bind_input_device);
- device->sprite = weston_surface_create(ec);
+ wl_list_init(&device->pointer_surfaces);
+ device->sprite = NULL;
device->compositor = ec;
device->hotspot_x = 16;
@@ -1751,15 +1799,81 @@ weston_input_device_init(struct weston_input_device *device,
WL_EXPORT void
weston_input_device_release(struct weston_input_device *device)
{
+ struct weston_pointer_surface *ps, *tmp;
+
wl_list_remove(&device->link);
/* The global object is destroyed at wl_display_destroy() time. */
- if (device->sprite)
- destroy_surface(&device->sprite->surface.resource);
+ wl_list_for_each_safe(ps, tmp, &device->pointer_surfaces, link)
+ pointer_surface_destroy(ps);
wl_input_device_release(&device->input_device);
}
+static struct weston_pointer_surface *
+device_client_pointer_surface(struct weston_input_device *device,
+ struct wl_client *client)
+{
+ struct weston_pointer_surface *ps;
+
+ wl_list_for_each(ps, &device->pointer_surfaces, link)
+ if (ps->surface->surface.resource.client == client)
+ return ps;
+
+ return NULL;
+}
+
+static void
+device_update_cursor_sprite(struct wl_input_device *device,
+ struct weston_surface *surface)
+{
+ struct weston_input_device *wd = (struct weston_input_device *) device;
+ struct weston_pointer_surface *ps;
+ struct wl_client *client;
+
+ if (!surface)
+ return;
+
+ client = surface->surface.resource.client;
+
+ ps = device_client_pointer_surface(wd, client);
+ if (!ps)
+ return;
+
+ if (wd->sprite) {
+ if (client == wd->sprite->surface.resource.client)
+ return;
+
+ if (wd->sprite->output) {
+ weston_surface_damage_below(wd->sprite);
+ wd->sprite->output = NULL;
+ wl_list_remove(&wd->sprite->link);
+ }
+ }
+
+ wd->sprite = ps->surface;
+ wd->hotspot_x = ps->hotspot_x;
+ wd->hotspot_y = ps->hotspot_y;
+
+ if (!ps->surface->output) {
+ wl_list_insert(weston_compositor_top(wd->compositor),
+ &ps->surface->link);
+ weston_surface_set_position(ps->surface,
+ device->x - wd->hotspot_x,
+ device->y - wd->hotspot_y);
+ weston_surface_assign_output(ps->surface);
+ }
+}
+
+WL_EXPORT void
+weston_compositor_update_cursor_sprites(struct weston_compositor *ec)
+{
+ struct weston_surface *es = (struct weston_surface *)
+ ec->input_device->pointer_focus;
+
+ device_update_cursor_sprite(ec->input_device, es);
+}
+
static void
weston_input_update_drag_surface(struct wl_input_device *input_device,
int dx, int dy)
diff --git a/src/compositor.h b/src/compositor.h
index 4c82e79..130f4f6 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -79,6 +79,12 @@ struct weston_output {
void (*destroy)(struct weston_output *output);
};
+struct weston_pointer_surface {
+ struct weston_surface *surface;
+ int hotspot_x, hotspot_y;
+ struct wl_list link;
+};
+
struct weston_input_device {
struct wl_input_device input_device;
struct weston_compositor *compositor;
@@ -89,6 +95,8 @@ struct weston_input_device {
uint32_t modifier_state;
int hw_cursor;
+ struct wl_list pointer_surfaces;
+
uint32_t num_tp;
struct wl_surface *touch_focus;
struct wl_listener touch_focus_listener;
@@ -360,6 +368,8 @@ weston_compositor_wake(struct weston_compositor *compositor);
void
weston_compositor_activity(struct weston_compositor *compositor);
void
+weston_compositor_update_cursor_sprites(struct weston_compositor *compositor);
+void
weston_compositor_update_drag_surfaces(struct weston_compositor *compositor);
--
1.7.5.4
More information about the wayland-devel
mailing list