[PATCH weston 4/5] Make use of new wl_cursors
Daniel Stone
daniel at fooishbar.org
Mon Jul 23 11:55:00 PDT 2012
Port the existing manual (and somewhat fragile) cursor-handling code to
the new wl_cursor interface.
Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
clients/window.c | 6 +-
src/compositor.c | 378 ++++++++++++++++++++----------------------------------
src/compositor.h | 16 ++-
src/shell.c | 34 ++++-
4 files changed, 183 insertions(+), 251 deletions(-)
diff --git a/clients/window.c b/clients/window.c
index 93299e1..2a7010a 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -2372,12 +2372,12 @@ input_set_pointer_image_index(struct input *input, int index)
if (!buffer)
return;
- wl_pointer_set_cursor(input->pointer, input->display->serial,
- input->pointer_surface,
- image->hotspot_x, image->hotspot_y);
wl_surface_attach(input->pointer_surface, buffer, 0, 0);
wl_surface_damage(input->pointer_surface, 0, 0,
image->width, image->height);
+ wl_pointer_set_cursor(input->pointer, input->display->serial,
+ input->pointer_surface,
+ image->hotspot_x, image->hotspot_y);
}
static const struct wl_callback_listener pointer_surface_listener;
diff --git a/src/compositor.c b/src/compositor.c
index 132f09f..92abab1 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1109,8 +1109,6 @@ weston_output_repaint(struct weston_output *output, int msecs)
pixman_region32_t opaque, new_damage, output_damage;
int32_t width, height;
- weston_compositor_update_drag_surfaces(ec);
-
width = output->current->width +
output->border.left + output->border.right;
height = output->current->height +
@@ -1381,6 +1379,28 @@ weston_surface_assign_output(struct weston_surface *es)
weston_surface_update_output_mask(es, mask);
}
+/**
+ * If the surface we just reconfigured is current for any cursor, update
+ * the cursor and signal.
+ */
+static void
+check_cursor_configure(struct weston_surface *es, int32_t dx, int32_t dy)
+{
+ struct weston_seat *seat;
+ struct weston_cursor *cursor;
+
+ wl_list_for_each(seat, &es->compositor->seat_list, link) {
+ wl_list_for_each(cursor, &seat->cursor_list, link) {
+ if (cursor->cursor->icon != &es->surface)
+ continue;
+ empty_region(&es->input);
+ cursor->cursor->hotspot_x -= dx;
+ cursor->cursor->hotspot_y -= dy;
+ wl_signal_emit(&cursor->cursor->update_signal, cursor->cursor);
+ }
+ }
+}
+
static void
surface_attach(struct wl_client *client,
struct wl_resource *resource,
@@ -1394,8 +1414,13 @@ surface_attach(struct wl_client *client,
weston_surface_attach(&es->surface, buffer);
- if (buffer && es->configure)
+ if (!buffer)
+ return;
+
+ if (es->configure)
es->configure(es, sx, sy);
+
+ check_cursor_configure(es, sx, sy);
}
static void
@@ -1432,7 +1457,7 @@ surface_frame(struct wl_client *client,
wl_resource_post_no_memory(resource);
return;
}
-
+
cb->resource.object.interface = &wl_callback_interface;
cb->resource.object.id = callback;
cb->resource.destroy = destroy_frame_callback;
@@ -1656,9 +1681,6 @@ idle_handler(void *data)
return 1;
}
-static void
-weston_seat_update_drag_surface(struct wl_seat *seat, int dx, int dy);
-
static void
clip_pointer_motion(struct weston_seat *seat, wl_fixed_t *fx, wl_fixed_t *fy)
{
@@ -1707,10 +1729,6 @@ notify_motion(struct wl_seat *seat, uint32_t time, wl_fixed_t x, wl_fixed_t y)
clip_pointer_motion(ws, &x, &y);
- weston_seat_update_drag_surface(seat,
- x - seat->pointer->x,
- y - seat->pointer->y);
-
seat->pointer->x = x;
seat->pointer->y = y;
@@ -1727,13 +1745,103 @@ notify_motion(struct wl_seat *seat, uint32_t time, wl_fixed_t x, wl_fixed_t y)
interface = seat->pointer->grab->interface;
interface->motion(seat->pointer->grab, time,
seat->pointer->grab->x, seat->pointer->grab->y);
+}
+
+static void
+cursor_unmap(struct weston_cursor *cursor)
+{
+ if (!cursor->sprite)
+ return;
+
+ if (weston_surface_is_mapped(cursor->sprite))
+ weston_surface_unmap(cursor->sprite);
+ cursor->sprite = NULL;
+ wl_list_remove(&cursor->sprite_destroy_listener.link);
+}
+
+static void
+cursor_destroy(struct wl_listener *listener, void *data)
+{
+ struct weston_cursor *cursor =
+ container_of(listener, struct weston_cursor,
+ cursor_destroy_listener);
+
+ cursor_unmap(cursor);
+ wl_list_remove(&cursor->link);
+ free(cursor);
+}
+
+static void
+cursor_sprite_destroy(struct wl_listener *listener, void *data)
+{
+ struct weston_cursor *cursor =
+ container_of(listener, struct weston_cursor,
+ sprite_destroy_listener);
+
+ cursor->cursor->icon = NULL;
+ cursor->sprite = NULL;
+}
+
+static void
+cursor_update(struct wl_listener *listener, void *data)
+{
+ struct wl_cursor *wl_cursor = data;
+ struct weston_surface *icon = (struct weston_surface *) wl_cursor->icon;
+ struct weston_cursor *cursor =
+ container_of(listener, struct weston_cursor, update_listener);
+ int32_t ix, iy;
+ unsigned int has_changed = (icon != cursor->sprite);
- if (ws->sprite) {
- weston_surface_set_position(ws->sprite,
- ix - ws->hotspot_x,
- iy - ws->hotspot_y);
- weston_compositor_schedule_repaint(ec);
+ ix = wl_fixed_to_int(wl_cursor->x) - wl_cursor->hotspot_x;
+ iy = wl_fixed_to_int(wl_cursor->y) - wl_cursor->hotspot_y;
+
+ if (has_changed && cursor->sprite) {
+ if (weston_surface_is_mapped(cursor->sprite))
+ weston_surface_unmap(cursor->sprite);
+ wl_list_remove(&cursor->sprite_destroy_listener.link);
+ }
+
+ cursor->sprite = icon;
+
+ if (!cursor->sprite)
+ return;
+
+ weston_surface_set_position(icon, ix, iy);
+ if (has_changed) {
+ wl_signal_add(&icon->surface.resource.destroy_signal,
+ &cursor->sprite_destroy_listener);
+ wl_list_insert(&icon->compositor->cursor_layer.surface_list,
+ &icon->layer_link);
+ }
+ if (!weston_surface_is_mapped(icon) && icon->buffer) {
+ weston_surface_configure(icon, ix, iy, icon->buffer->width,
+ icon->buffer->height);
+ weston_surface_assign_output(icon);
}
+ weston_compositor_schedule_repaint(cursor->seat->compositor);
+}
+
+static void
+cursor_new(struct wl_listener *listener, void *data)
+{
+ struct weston_cursor *cursor;
+ struct weston_seat *seat =
+ container_of(listener, struct weston_seat, cursor_listener);
+
+ cursor = malloc(sizeof *cursor);
+ if (!cursor)
+ return;
+
+ cursor->seat = seat;
+ cursor->cursor = data;
+ cursor->sprite = NULL;
+ cursor->update_listener.notify = cursor_update;
+ wl_signal_add(&cursor->cursor->update_signal, &cursor->update_listener);
+ cursor->sprite_destroy_listener.notify = cursor_sprite_destroy;
+ cursor->cursor_destroy_listener.notify = cursor_destroy;
+ wl_signal_add(&cursor->cursor->destroy_signal,
+ &cursor->cursor_destroy_listener);
+ wl_list_insert(&seat->cursor_list, &cursor->link);
}
WL_EXPORT void
@@ -1963,10 +2071,6 @@ notify_pointer_focus(struct wl_seat *seat, struct weston_output *output,
struct weston_compositor *compositor = ws->compositor;
if (output) {
- weston_seat_update_drag_surface(seat,
- x - seat->pointer->x,
- y - seat->pointer->y);
-
seat->pointer->x = x;
seat->pointer->y = y;
compositor->focus = 1;
@@ -2177,103 +2281,32 @@ notify_touch(struct wl_seat *seat, uint32_t time, int touch_id,
}
static void
-pointer_handle_sprite_destroy(struct wl_listener *listener, void *data)
-{
- struct weston_seat *seat = container_of(listener, struct weston_seat,
- sprite_destroy_listener);
-
- seat->sprite = NULL;
-}
-
-static void
-pointer_cursor_surface_configure(struct weston_surface *es,
- int32_t dx, int32_t dy)
-{
- struct weston_seat *seat = es->private;
- int x, y;
-
- assert(es == seat->sprite);
-
- seat->hotspot_x -= dx;
- seat->hotspot_y -= dy;
-
- x = wl_fixed_to_int(seat->seat.pointer->x) - seat->hotspot_x;
- y = wl_fixed_to_int(seat->seat.pointer->y) - seat->hotspot_y;
-
- weston_surface_configure(seat->sprite, x, y,
- es->buffer->width, es->buffer->height);
-
- empty_region(&es->input);
-
- if (!weston_surface_is_mapped(es)) {
- wl_list_insert(&es->compositor->cursor_layer.surface_list,
- &es->layer_link);
- weston_surface_assign_output(es);
- }
-}
-
-static void
-pointer_unmap_sprite(struct weston_seat *seat)
-{
- if (weston_surface_is_mapped(seat->sprite))
- weston_surface_unmap(seat->sprite);
-
- wl_list_remove(&seat->sprite_destroy_listener.link);
- seat->sprite->configure = NULL;
- seat->sprite->private = NULL;
- seat->sprite = NULL;
-}
-
-static void
pointer_set_cursor(struct wl_client *client, struct wl_resource *resource,
uint32_t serial, struct wl_resource *surface_resource,
int32_t x, int32_t y)
{
struct weston_seat *seat = resource->data;
- struct weston_surface *surface = NULL;
-
- if (surface_resource)
- surface = container_of(surface_resource->data,
- struct weston_surface, surface);
+ struct weston_surface *surface;
- if (serial < seat->seat.pointer->focus_serial)
+ if (!surface_resource) {
+ wl_pointer_set_cursor_icon(&seat->pointer, NULL, 0, 0);
return;
-
- if (surface && surface != seat->sprite) {
- if (seat->seat.pointer->focus == NULL)
- return;
- if (seat->seat.pointer->focus->resource.client != client)
- return;
-
- if (surface->configure) {
- wl_resource_post_error(&surface->surface.resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "surface->configure already "
- "set");
- return;
- }
}
- if (seat->sprite)
- pointer_unmap_sprite(seat);
+ surface = container_of(surface_resource->data,
+ struct weston_surface, surface);
- if (!surface)
+ if (serial < seat->seat.pointer->focus_serial)
return;
- wl_signal_add(&surface->surface.resource.destroy_signal,
- &seat->sprite_destroy_listener);
+ if (seat->seat.pointer->focus == NULL ||
+ seat->seat.pointer->focus->resource.client != client)
+ return;
- surface->configure = pointer_cursor_surface_configure;
- surface->private = seat;
empty_region(&surface->input);
- seat->sprite = surface;
- seat->hotspot_x = x;
- seat->hotspot_y = y;
-
- weston_surface_set_position(surface,
- wl_fixed_to_int(seat->seat.pointer->x) - x,
- wl_fixed_to_int(seat->seat.pointer->y) - y);
+ wl_pointer_set_cursor_icon(&seat->pointer, &surface->surface,
+ x, y);
}
static const struct wl_pointer_interface pointer_interface = {
@@ -2399,17 +2432,6 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
wl_seat_send_capabilities(resource, caps);
}
-static void
-device_handle_new_drag_icon(struct wl_listener *listener, void *data)
-{
- struct weston_seat *seat;
-
- seat = container_of(listener, struct weston_seat,
- new_drag_icon_listener);
-
- weston_seat_update_drag_surface(&seat->seat, 0, 0);
-}
-
static void weston_compositor_xkb_init(struct weston_compositor *ec,
struct xkb_rule_names *names)
{
@@ -2602,8 +2624,9 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
wl_display_add_global(ec->wl_display, &wl_seat_interface, seat,
bind_seat);
- seat->sprite = NULL;
- seat->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
+ wl_list_init(&seat->cursor_list);
+ seat->cursor_listener.notify = cursor_new;
+ wl_signal_add(&seat->seat.cursor_signal, &seat->cursor_listener);
seat->compositor = ec;
seat->hotspot_x = 16;
@@ -2616,10 +2639,6 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec)
wl_list_insert(ec->seat_list.prev, &seat->link);
- seat->new_drag_icon_listener.notify = device_handle_new_drag_icon;
- wl_signal_add(&seat->seat.drag_icon_signal,
- &seat->new_drag_icon_listener);
-
clipboard_create(seat);
}
@@ -2629,9 +2648,6 @@ weston_seat_release(struct weston_seat *seat)
wl_list_remove(&seat->link);
/* The global object is destroyed at wl_display_destroy() time. */
- if (seat->sprite)
- pointer_unmap_sprite(seat);
-
if (seat->xkb_state.state != NULL)
xkb_state_unref(seat->xkb_state.state);
xkb_info_destroy(&seat->xkb_info);
@@ -2640,124 +2656,6 @@ weston_seat_release(struct weston_seat *seat)
}
static void
-drag_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
-{
- weston_surface_configure(es,
- es->geometry.x + sx, es->geometry.y + sy,
- es->buffer->width, es->buffer->height);
-}
-
-static int
-device_setup_new_drag_surface(struct weston_seat *ws,
- struct weston_surface *surface)
-{
- struct wl_seat *seat = &ws->seat;
-
- if (surface->configure) {
- wl_resource_post_error(&surface->surface.resource,
- WL_DISPLAY_ERROR_INVALID_OBJECT,
- "surface->configure already set");
- return 0;
- }
-
- ws->drag_surface = surface;
-
- weston_surface_set_position(ws->drag_surface,
- wl_fixed_to_double(seat->pointer->x),
- wl_fixed_to_double(seat->pointer->y));
-
- surface->configure = drag_surface_configure;
-
- wl_signal_add(&surface->surface.resource.destroy_signal,
- &ws->drag_surface_destroy_listener);
-
- return 1;
-}
-
-static void
-device_release_drag_surface(struct weston_seat *seat)
-{
- seat->drag_surface->configure = NULL;
- undef_region(&seat->drag_surface->input);
- wl_list_remove(&seat->drag_surface_destroy_listener.link);
- seat->drag_surface = NULL;
-}
-
-static void
-device_map_drag_surface(struct weston_seat *seat)
-{
- struct wl_list *list;
-
- if (weston_surface_is_mapped(seat->drag_surface) ||
- !seat->drag_surface->buffer)
- return;
-
- if (seat->sprite && weston_surface_is_mapped(seat->sprite))
- list = &seat->sprite->layer_link;
- else
- list = &seat->compositor->cursor_layer.surface_list;
-
- wl_list_insert(list, &seat->drag_surface->layer_link);
- weston_surface_assign_output(seat->drag_surface);
- empty_region(&seat->drag_surface->input);
-}
-
-static void
-weston_seat_update_drag_surface(struct wl_seat *seat,
- int dx, int dy)
-{
- int surface_changed = 0;
- struct weston_seat *ws = (struct weston_seat *) seat;
-
- if (!ws->drag_surface && !seat->drag_surface)
- return;
-
- if (ws->drag_surface && seat->drag_surface &&
- (&ws->drag_surface->surface.resource !=
- &seat->drag_surface->resource))
- /* between calls to this funcion we got a new drag_surface */
- surface_changed = 1;
-
- if (!seat->drag_surface || surface_changed) {
- device_release_drag_surface(ws);
- if (!surface_changed)
- return;
- }
-
- if (!ws->drag_surface || surface_changed) {
- struct weston_surface *surface = (struct weston_surface *)
- seat->drag_surface;
- if (!device_setup_new_drag_surface(ws, surface))
- return;
- }
-
- /* the client may not have attached a buffer to the drag surface
- * when we setup it up, so check if map is needed on every update */
- device_map_drag_surface(ws);
-
- /* the client may have attached a buffer with a different size to
- * the drag surface, causing the input region to be reset */
- if (region_is_undefined(&ws->drag_surface->input))
- empty_region(&ws->drag_surface->input);
-
- if (!dx && !dy)
- return;
-
- weston_surface_set_position(ws->drag_surface,
- ws->drag_surface->geometry.x + wl_fixed_to_double(dx),
- ws->drag_surface->geometry.y + wl_fixed_to_double(dy));
-}
-
-WL_EXPORT void
-weston_compositor_update_drag_surfaces(struct weston_compositor *compositor)
-{
- struct weston_seat *seat;
-
- wl_list_for_each(seat, &compositor->seat_list, link)
- weston_seat_update_drag_surface(&seat->seat, 0, 0);
-}
-
-static void
bind_output(struct wl_client *client,
void *data, uint32_t version, uint32_t id)
{
diff --git a/src/compositor.h b/src/compositor.h
index 22c0174..41623e5 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -203,6 +203,16 @@ struct weston_xkb_info {
xkb_led_index_t scroll_led;
};
+struct weston_cursor {
+ struct wl_cursor *cursor;
+ struct weston_seat *seat;
+ struct weston_surface *sprite;
+ struct wl_listener sprite_destroy_listener;
+ struct wl_listener cursor_destroy_listener;
+ struct wl_listener update_listener;
+ struct wl_list link;
+};
+
struct weston_seat {
struct wl_seat seat;
struct wl_pointer pointer;
@@ -212,9 +222,9 @@ struct weston_seat {
struct wl_touch touch;
int has_touch;
+ struct wl_list cursor_list;
struct weston_compositor *compositor;
- struct weston_surface *sprite;
- struct wl_listener sprite_destroy_listener;
+ struct wl_listener cursor_listener;
struct weston_surface *drag_surface;
struct wl_listener drag_surface_destroy_listener;
int32_t hotspot_x, hotspot_y;
@@ -556,8 +566,6 @@ void
weston_compositor_wake(struct weston_compositor *compositor);
void
weston_compositor_activity(struct weston_compositor *compositor);
-void
-weston_compositor_update_drag_surfaces(struct weston_compositor *compositor);
struct weston_binding;
diff --git a/src/shell.c b/src/shell.c
index 344c690..264c9de 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -774,6 +774,11 @@ noop_grab_focus(struct wl_pointer_grab *grab,
struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
{
grab->focus = NULL;
+
+ grab->pointer->cursor.x = grab->pointer->x;
+ grab->pointer->cursor.y = grab->pointer->y;
+ wl_signal_emit(&grab->pointer->cursor.update_signal,
+ &grab->pointer->cursor);
}
static void
@@ -795,7 +800,9 @@ move_grab_motion(struct wl_pointer_grab *grab,
weston_surface_configure(es, dx, dy,
es->geometry.width, es->geometry.height);
- weston_compositor_schedule_repaint(es->compositor);
+ pointer->cursor.x = pointer->x;
+ pointer->cursor.y = pointer->y;
+ wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
}
static void
@@ -810,7 +817,6 @@ move_grab_button(struct wl_pointer_grab *grab,
if (pointer->button_count == 0 &&
state == WL_POINTER_BUTTON_STATE_RELEASED) {
shell_grab_end(shell_grab);
- wl_pointer_end_grab(pointer);
free(grab);
}
}
@@ -826,11 +832,9 @@ busy_cursor_grab_focus(struct wl_pointer_grab *base,
struct wl_surface *surface, int32_t x, int32_t y)
{
struct shell_grab *grab = (struct shell_grab *) base;
- struct wl_pointer *pointer = base->pointer;
if (grab->grab.focus != surface) {
shell_grab_end(grab);
- wl_pointer_end_grab(pointer);
free(grab);
}
}
@@ -839,6 +843,11 @@ static void
busy_cursor_grab_motion(struct wl_pointer_grab *grab,
uint32_t time, int32_t x, int32_t y)
{
+ struct wl_pointer *pointer = grab->pointer;
+
+ pointer->cursor.x = pointer->x;
+ pointer->cursor.y = pointer->y;
+ wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
}
static void
@@ -1093,6 +1102,10 @@ resize_grab_motion(struct wl_pointer_grab *grab,
shsurf->client->send_configure(shsurf->surface,
resize->edges, width, height);
+
+ pointer->cursor.x = pointer->x;
+ pointer->cursor.y = pointer->y;
+ wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
}
static void
@@ -1552,17 +1565,26 @@ popup_grab_focus(struct wl_pointer_grab *grab,
wl_fixed_from_int(0));
grab->focus = NULL;
}
+
+ pointer->cursor.x = pointer->x;
+ pointer->cursor.y = pointer->y;
+ wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
}
static void
popup_grab_motion(struct wl_pointer_grab *grab,
uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
{
+ struct wl_pointer *pointer = grab->pointer;
struct wl_resource *resource;
resource = grab->pointer->focus_resource;
if (resource)
wl_pointer_send_motion(resource, time, sx, sy);
+
+ pointer->cursor.x = pointer->x;
+ pointer->cursor.y = pointer->y;
+ wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
}
static void
@@ -2266,6 +2288,10 @@ rotate_grab_motion(struct wl_pointer_grab *grab,
surface->geometry.y + dposy);
}
+ pointer->cursor.x = pointer->x;
+ pointer->cursor.y = pointer->y;
+ wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
+
/* Repaint implies weston_surface_update_transform(), which
* lazily applies the damage due to rotation update.
*/
--
1.7.10.4
More information about the wayland-devel
mailing list