[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