[PATCH wayland 06/10] Add cursor object representing the visible pointer
Ander Conselvan de Oliveira
conselvan2 at gmail.com
Wed Jul 25 03:45:01 PDT 2012
On 07/23/2012 09:54 PM, Daniel Stone wrote:
> The wl_cursor object represents a visible on-screen cursor, with
> co-ordinates and a surface image. Add hooks for compositors to be able
> to discover new cursors and be informed when they change, and have the
> core implementation track the location.
I like the idea of having wl_cursor with position and hotspot but there
is a few problems with the implementation.
First, the drag icon should not replace the pointer cursor but be a
surface displayed under it. And if we just make that a separate cursor,
the whole saved cursor logic can be dropped.
Also, having to emit the cursor update signal on every single grab is
leading to a lot of code duplication. Is there a reason it can't be done
inside notify_* in weston? The drag cursor would be updated on the drag
grab though, since it would be a separate cursor.
And maybe the cursor.update_signal is not necessary. If all the cursor
are in a list, they could be updated on weston_output_repaint() before
redoing the surface list.
Cheers,
Ander
> Signed-off-by: Daniel Stone <daniel at fooishbar.org>
> ---
> src/data-device.c | 30 +++++++++++++++++-----
> src/wayland-server.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++---
> src/wayland-server.h | 27 ++++++++++++++++++--
> 3 files changed, 115 insertions(+), 11 deletions(-)
>
> diff --git a/src/data-device.c b/src/data-device.c
> index 82020af..c19e14f 100644
> --- a/src/data-device.c
> +++ b/src/data-device.c
> @@ -212,6 +212,12 @@ drag_grab_focus(struct wl_pointer_grab *grab,
> &seat->drag_focus_listener);
> seat->drag_focus_resource = resource;
> grab->focus = surface;
> +
> + seat->pointer->cursor.icon = seat->drag_cursor.icon;
> + seat->pointer->cursor.x = seat->pointer->x;
> + seat->pointer->cursor.y = seat->pointer->y;
> + wl_signal_emit(&seat->pointer->cursor.update_signal,
> + &seat->pointer->cursor);
> }
>
> static void
> @@ -223,6 +229,11 @@ drag_grab_motion(struct wl_pointer_grab *grab,
> if (seat->drag_focus_resource)
> wl_data_device_send_motion(seat->drag_focus_resource,
> time, x, y);
> +
> + seat->pointer->cursor.x = seat->pointer->x;
> + seat->pointer->cursor.y = seat->pointer->y;
> + wl_signal_emit(&seat->pointer->cursor.update_signal,
> + &seat->pointer->cursor);
> }
>
> static void
> @@ -231,14 +242,15 @@ data_device_end_drag_grab(struct wl_seat *seat)
> struct wl_resource *surface_resource;
> struct wl_surface_interface *implementation;
>
> - if (seat->drag_surface) {
> - surface_resource = &seat->drag_surface->resource;
> + if (seat->drag_cursor.icon) {
> + surface_resource = &seat->drag_cursor.icon->resource;
> implementation = (struct wl_surface_interface *)
> surface_resource->object.implementation;
>
> implementation->attach(surface_resource->client,
> surface_resource, NULL, 0, 0);
> wl_list_remove(&seat->drag_icon_listener.link);
> + seat->drag_cursor.icon = NULL;
> }
>
> drag_grab_focus(&seat->drag_grab, NULL,
> @@ -247,7 +259,7 @@ data_device_end_drag_grab(struct wl_seat *seat)
> wl_pointer_end_grab(seat->pointer);
>
> seat->drag_data_source = NULL;
> - seat->drag_surface = NULL;
> + seat->drag_cursor.icon = NULL;
> seat->drag_client = NULL;
> }
>
> @@ -292,7 +304,12 @@ destroy_data_device_icon(struct wl_listener *listener, void *data)
> struct wl_seat *seat = container_of(listener, struct wl_seat,
> drag_icon_listener);
>
> - seat->drag_surface = NULL;
> + if (seat->pointer->cursor.icon == seat->drag_cursor.icon) {
> + seat->pointer->cursor.icon = NULL;
> + wl_signal_emit(&seat->pointer->cursor.update_signal,
> + &seat->pointer->cursor);
> + }
> + seat->drag_cursor.icon = NULL;
> }
>
> static void
> @@ -322,11 +339,12 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
> }
>
> if (icon_resource) {
> - seat->drag_surface = icon_resource->data;
> + seat->drag_cursor.icon = icon_resource->data;
> + seat->drag_cursor.hotspot_x = 0;
> + seat->drag_cursor.hotspot_y = 0;
> seat->drag_icon_listener.notify = destroy_data_device_icon;
> wl_signal_add(&icon_resource->destroy_signal,
> &seat->drag_icon_listener);
> - wl_signal_emit(&seat->drag_icon_signal, icon_resource);
> }
>
> wl_pointer_set_focus(seat->pointer, NULL,
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index 88e8433..f9d2522 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -519,6 +519,13 @@ default_grab_focus(struct wl_pointer_grab *grab,
> return;
>
> wl_pointer_set_focus(pointer, surface, x, y);
> +
> + pointer->cursor.icon = pointer->saved_cursor.icon;
> + pointer->cursor.hotspot_x = pointer->saved_cursor.hotspot_x;
> + pointer->cursor.hotspot_y = pointer->saved_cursor.hotspot_y;
> + pointer->cursor.x = pointer->x;
> + pointer->cursor.y = pointer->y;
> + wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
> }
>
> static void
> @@ -526,10 +533,15 @@ default_grab_motion(struct wl_pointer_grab *grab,
> uint32_t time, wl_fixed_t x, wl_fixed_t y)
> {
> struct wl_resource *resource;
> + struct wl_pointer *pointer = grab->pointer;
>
> - resource = grab->pointer->focus_resource;
> + resource = pointer->focus_resource;
> if (resource)
> wl_pointer_send_motion(resource, time, x, y);
> +
> + pointer->cursor.x = pointer->x;
> + pointer->cursor.y = pointer->y;
> + wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
> }
>
> static void
> @@ -627,6 +639,47 @@ static const struct wl_keyboard_grab_interface
> default_grab_modifiers,
> };
>
> +static void
> +saved_cursor_destroy_listener(struct wl_listener *listener, void *data)
> +{
> + struct wl_pointer *pointer =
> + container_of(listener, struct wl_pointer, icon_listener);
> +
> + if (pointer->cursor.icon == pointer->saved_cursor.icon) {
> + pointer->cursor.icon = NULL;
> + wl_signal_emit(&pointer->cursor.update_signal,
> + &pointer->cursor);
> + }
> +
> + pointer->saved_cursor.icon = NULL;
> +}
> +
> +WL_EXPORT void
> +wl_pointer_set_cursor_icon(struct wl_pointer *pointer,
> + struct wl_surface *cursor,
> + int32_t hotspot_x,
> + int32_t hotspot_y)
> +{
> + if (pointer->saved_cursor.icon)
> + wl_list_remove(&pointer->icon_listener.link);
> +
> + pointer->saved_cursor.icon = cursor;
> + if (cursor)
> + wl_signal_add(&cursor->resource.destroy_signal,
> + &pointer->icon_listener);
> + pointer->saved_cursor.hotspot_x = hotspot_x;
> + pointer->saved_cursor.hotspot_y = hotspot_y;
> +
> + /* Grabs will set their own cursor. */
> + if (pointer->grab != &pointer->default_grab)
> + return;
> +
> + pointer->cursor.icon = pointer->saved_cursor.icon;
> + pointer->cursor.hotspot_x = pointer->saved_cursor.hotspot_x;
> + pointer->cursor.hotspot_y = pointer->saved_cursor.hotspot_y;
> + wl_signal_emit(&pointer->cursor.update_signal, &pointer->cursor);
> +}
> +
> WL_EXPORT void
> wl_pointer_init(struct wl_pointer *pointer)
> {
> @@ -638,6 +691,10 @@ wl_pointer_init(struct wl_pointer *pointer)
> pointer->grab = &pointer->default_grab;
> wl_signal_init(&pointer->focus_signal);
>
> + pointer->icon_listener.notify = saved_cursor_destroy_listener;
> + wl_signal_init(&pointer->cursor.update_signal);
> + wl_signal_init(&pointer->cursor.destroy_signal);
> +
> /* FIXME: Pick better co-ords. */
> pointer->x = wl_fixed_from_int(100);
> pointer->y = wl_fixed_from_int(100);
> @@ -649,6 +706,10 @@ wl_pointer_release(struct wl_pointer *pointer)
> /* XXX: What about pointer->resource_list? */
> if (pointer->focus_resource)
> wl_list_remove(&pointer->focus_listener.link);
> + if (pointer->saved_cursor.icon)
> + wl_list_remove(&pointer->icon_listener.link);
> + wl_signal_emit(&pointer->cursor.destroy_signal,
> + &pointer->cursor);
> }
>
> WL_EXPORT void
> @@ -700,7 +761,7 @@ wl_seat_init(struct wl_seat *seat)
> wl_list_init(&seat->base_resource_list);
> wl_signal_init(&seat->selection_signal);
> wl_list_init(&seat->drag_resource_list);
> - wl_signal_init(&seat->drag_icon_signal);
> + wl_signal_init(&seat->cursor_signal);
> }
>
> WL_EXPORT void
> @@ -742,8 +803,10 @@ wl_seat_set_pointer(struct wl_seat *seat, struct wl_pointer *pointer)
> return;
>
> seat->pointer = pointer;
> - if (pointer)
> + if (pointer) {
> pointer->seat = seat;
> + wl_signal_emit(&seat->cursor_signal, &pointer->cursor);
> + }
>
> seat_send_updated_caps(seat);
> }
> diff --git a/src/wayland-server.h b/src/wayland-server.h
> index f092145..f7a0957 100644
> --- a/src/wayland-server.h
> +++ b/src/wayland-server.h
> @@ -239,6 +239,19 @@ struct wl_data_source {
> void (*cancel)(struct wl_data_source *source);
> };
>
> +struct wl_cursor {
> + struct wl_signal update_signal;
> + struct wl_signal destroy_signal;
> +
> + struct wl_surface *icon;
> +
> + wl_fixed_t x;
> + wl_fixed_t y;
> +
> + int32_t hotspot_x;
> + int32_t hotspot_y;
> +};
> +
> struct wl_pointer {
> struct wl_seat *seat;
>
> @@ -260,6 +273,10 @@ struct wl_pointer {
> struct wl_surface *current;
> wl_fixed_t current_x, current_y;
>
> + struct wl_cursor cursor;
> + struct wl_cursor saved_cursor;
> + struct wl_listener icon_listener;
> +
> uint32_t button_count;
> };
>
> @@ -307,6 +324,8 @@ struct wl_seat {
> struct wl_keyboard *keyboard;
> struct wl_touch *touch;
>
> + struct wl_signal cursor_signal;
> +
> uint32_t selection_serial;
> struct wl_data_source *selection_data_source;
> struct wl_listener selection_data_source_listener;
> @@ -320,9 +339,8 @@ struct wl_seat {
> struct wl_resource *drag_focus_resource;
> struct wl_listener drag_focus_listener;
> struct wl_pointer_grab drag_grab;
> - struct wl_surface *drag_surface;
> + struct wl_cursor drag_cursor;
> struct wl_listener drag_icon_listener;
> - struct wl_signal drag_icon_signal;
> };
>
> /*
> @@ -389,6 +407,11 @@ wl_pointer_start_grab(struct wl_pointer *pointer,
> struct wl_pointer_grab *grab);
> void
> wl_pointer_end_grab(struct wl_pointer *pointer);
> +void
> +wl_pointer_set_cursor_icon(struct wl_pointer *pointer,
> + struct wl_surface *cursor,
> + wl_fixed_t hotspot_x,
> + wl_fixed_t hotspot_y);
>
> void
> wl_keyboard_init(struct wl_keyboard *keyboard);
>
More information about the wayland-devel
mailing list