[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