[PATCH weston 5/5] window: Implement animated cursors (using pointer surfaces)

Kristian Høgsberg hoegsberg at gmail.com
Fri Jun 15 08:05:12 PDT 2012


On Fri, Jun 15, 2012 at 05:27:36PM +0300, Ander Conselvan de Oliveira wrote:
> Since the introduction of pointer.set_cursor(), it is possible for a
> client to set the surface containing the pointer image and get frame
> callbacks on it thus allowing a clear implementation of animated
> cursors.
> 
> This also makes the busy cursor hack of using frame callbacks on the
> busy surface unnecessary.
> ---
>  clients/desktop-shell.c |   32 -------------------------
>  clients/window.c        |   59 +++++++++++++++++++++++++++++++++++++++++++----
>  clients/window.h        |    3 --
>  3 files changed, 54 insertions(+), 40 deletions(-)
> 
> diff --git a/clients/desktop-shell.c b/clients/desktop-shell.c
> index 5a81b2c..6c73a5c 100644
> --- a/clients/desktop-shell.c
> +++ b/clients/desktop-shell.c
> @@ -767,42 +767,10 @@ background_create(struct desktop *desktop)
>  	return background;
>  }
>  
> -static const struct wl_callback_listener busy_cursor_listener;
> -
> -static void
> -busy_cursor_frame_callback(void *data,
> -			   struct wl_callback *callback, uint32_t time)
> -{
> -	struct input *input = data;
> -	struct display *display = input_get_display(input);
> -	struct desktop *desktop = display_get_user_data(display);
> -	struct wl_surface *surface;
> -	int index;
> -
> -	if (callback)
> -		wl_callback_destroy(callback);
> -	if (input_get_focus_widget(input) != desktop->busy_widget)
> -		return;
> -
> -	/* FIXME: Get frame duration and number of frames from cursor. */
> -	index = (time / 100) % 8;
> -	input_set_pointer_image_index(input, CURSOR_WATCH, index);
> -
> -	surface = window_get_wl_surface(desktop->busy_window);
> -	callback = wl_surface_frame(surface);
> -	wl_callback_add_listener(callback, &busy_cursor_listener, input);
> -}
> -
> -static const struct wl_callback_listener busy_cursor_listener = {
> -	busy_cursor_frame_callback
> -};
> -
>  static int
>  busy_surface_enter_handler(struct widget *widget, struct input *input,
>  			   float x, float y, void *data)
>  {
> -	busy_cursor_frame_callback(input, NULL, 0);
> -
>  	return CURSOR_WATCH;
>  }
>  
> diff --git a/clients/window.c b/clients/window.c
> index 57443d9..436f862 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -189,6 +189,8 @@ struct input {
>  	struct window *pointer_focus;
>  	struct window *keyboard_focus;
>  	int current_cursor;
> +	uint32_t cursor_anim_start;
> +	struct wl_callback *cursor_frame_cb;
>  	struct wl_surface *pointer_surface;
>  	uint32_t modifiers;
>  	uint32_t pointer_enter_serial;
> @@ -2274,14 +2276,14 @@ static const struct wl_data_device_listener data_device_listener = {
>  	data_device_selection
>  };
>  
> -void
> -input_set_pointer_image_index(struct input *input, int pointer, int index)
> +static void
> +input_set_pointer_image_index(struct input *input, int index)
>  {
>  	struct wl_buffer *buffer;
>  	struct wl_cursor *cursor;
>  	struct wl_cursor_image *image;
>  
> -	cursor = input->display->cursors[pointer];
> +	cursor = input->display->cursors[input->current_cursor];
>  	if (!cursor)
>  		return;
>  
> @@ -2295,7 +2297,6 @@ input_set_pointer_image_index(struct input *input, int pointer, int index)
>  	if (!buffer)
>  		return;
>  
> -	input->current_cursor = pointer;
>  	wl_pointer_set_cursor(input->pointer, input->display->serial,
>  			      input->pointer_surface,
>  			      image->hotspot_x, image->hotspot_y);
> @@ -2304,13 +2305,61 @@ input_set_pointer_image_index(struct input *input, int pointer, int index)
>  			  image->width, image->height);
>  }
>  
> +static const struct wl_callback_listener pointer_surface_listener;
> +
> +static void
> +pointer_surface_frame_callback(void *data, struct wl_callback *callback,
> +			       uint32_t time)
> +{
> +	struct input *input = data;
> +	struct wl_cursor *cursor =
> +		input->display->cursors[input->current_cursor];
> +	int i;
> +
> +	if (callback) {
> +		assert(callback == input->cursor_frame_cb);
> +		wl_callback_destroy(callback);
> +		input->cursor_frame_cb = NULL;
> +	}
> +
> +	if (input->current_cursor == CURSOR_UNSET)
> +		return;
> +
> +	/* FIXME We don't have the current time on the first call so we set
> +	 * the animation start to the time of the first frame callback. */

Better to check for callback == NULL to detect first frame (0 is a
valid timestamp).  On the other hand, does it even matter?  Just
always pass in the timestamp, and the animation will just start from a
random frame.  Anyway, committed the patch as is, we can tweak this
later.

Kristian

> +	if (time == 0)
> +		input->cursor_anim_start = 0;
> +	else if (input->cursor_anim_start == 0)
> +		input->cursor_anim_start = time;
> +
> +	if (time == 0 || input->cursor_anim_start == 0)
> +		i = 0;
> +	else
> +		i = wl_cursor_frame(cursor, time - input->cursor_anim_start);
> +
> +	input_set_pointer_image_index(input, i);
> +
> +	if (cursor->image_count == 1)
> +		return;
> +
> +	input->cursor_frame_cb = wl_surface_frame(input->pointer_surface);
> +	wl_callback_add_listener(input->cursor_frame_cb,
> +				 &pointer_surface_listener, input);
> +}
> +
> +static const struct wl_callback_listener pointer_surface_listener = {
> +	pointer_surface_frame_callback
> +};
> +
>  void
>  input_set_pointer_image(struct input *input, int pointer)
>  {
>  	if (pointer == input->current_cursor)
>  		return;
>  
> -	input_set_pointer_image_index(input, pointer, 0);
> +	input->current_cursor = pointer;
> +	if (!input->cursor_frame_cb)
> +		pointer_surface_frame_callback(input, NULL, 0);
>  }
>  
>  struct wl_data_device *
> diff --git a/clients/window.h b/clients/window.h
> index 8b8e816..da3815b 100644
> --- a/clients/window.h
> +++ b/clients/window.h
> @@ -368,9 +368,6 @@ void
>  input_set_pointer_image(struct input *input, int pointer);
>  
>  void
> -input_set_pointer_image_index(struct input *input, int pointer, int index);
> -
> -void
>  input_get_position(struct input *input, int32_t *x, int32_t *y);
>  
>  #define MOD_SHIFT_MASK		0x01
> -- 
> 1.7.4.1
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list