[PATCH weston 4/5] Make use of new wl_cursors
Ander Conselvan de Oliveira
conselvan2 at gmail.com
Wed Jul 25 03:57:34 PDT 2012
Hi Daniel,
On 07/23/2012 09:55 PM, Daniel Stone wrote:
> 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(-)
>
[snip]
> diff --git a/src/compositor.c b/src/compositor.c
> index 132f09f..92abab1 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
[snip]
> @@ -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);
> }
It would be better to have an appropriate es->configure set for every
surface used as a cursor and avoid doing this check for every single
attach in every single surface. This can be done in cursor_new and we
should fail if the surface already has es->configure set.
> @@ -2177,103 +2281,32 @@ notify_touch(struct wl_seat *seat, uint32_t time, int touch_id,
[snip]
> -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;
You are effectively allowing any client to hide the cursor at any moment
regardless of where the focus is.
> -
> - 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;
Removing this makes it possible to make any surface a cursor, such as a
fullscreen shell surface. We don't want that.
Anyway, this whole logic is there because the protocol allows a client
to change the cursor surface if it has focus or is the owner of the
current pointer surface. That is the reason for the
if (surface && surface != seat->sprite)
check. This way, a client that lost the focus can still update the
hotspot. If you changes, this is not possible anymore.
Cheers,
Ander
> - }
> }
>
> - 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.
> */
>
More information about the wayland-devel
mailing list