Does toytoolkit really need to support animated cursors?

If so it would be nice to animate the normal cursor, too, and perhaps
demonstrate code reuse for this.


On Tue, Feb 2, 2016 at 9:28 PM, Peter Hutterer <[email protected]>
wrote:

> From: Stephen Chandler Paul <[email protected]>
>
> Again, a lot of this is code that has been reused from the cursor code
> for pointers.
>
> Co-authored-by: Peter Hutterer <[email protected]>
> Signed-off-by: Stephen Chandler Paul <[email protected]>
> Signed-off-by: Peter Hutterer <[email protected]>
> ---
>  clients/window.c | 138
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  clients/window.h |  13 ++++--
>  2 files changed, 145 insertions(+), 6 deletions(-)
>
> diff --git a/clients/window.c b/clients/window.c
> index 37c703b..26c2593 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -159,6 +159,12 @@ struct tablet_tool {
>         struct tablet *current_tablet;
>         struct window *focus;
>         struct widget *focus_widget;
> +       uint32_t enter_serial;
> +       uint32_t cursor_serial;
> +       int current_cursor;
> +       struct wl_surface *cursor_surface;
> +       uint32_t cursor_anim_start;
> +       struct wl_callback *cursor_frame_cb;
>
>         enum zwp_tablet_tool_v1_type type;
>         uint64_t serial;
> @@ -332,6 +338,7 @@ struct widget {
>         int opaque;
>         int tooltip_count;
>         int default_cursor;
> +       int default_tablet_cursor;
>         /* If this is set to false then no cairo surface will be
>          * created before redrawing the surface. This is useful if the
>          * redraw handler is going to do completely custom rendering
> @@ -1676,6 +1683,7 @@ widget_create(struct window *window, struct surface
> *surface, void *data)
>         widget->tooltip = NULL;
>         widget->tooltip_count = 0;
>         widget->default_cursor = CURSOR_LEFT_PTR;
> +       widget->default_tablet_cursor = CURSOR_LEFT_PTR;
>         widget->use_cairo = 1;
>
>         return widget;
> @@ -1734,6 +1742,12 @@ widget_set_default_cursor(struct widget *widget,
> int cursor)
>  }
>
>  void
> +widget_set_default_tablet_cursor(struct widget *widget, int cursor)
> +{
> +       widget->default_tablet_cursor = cursor;
> +}
> +
> +void
>  widget_get_allocation(struct widget *widget, struct rectangle *allocation)
>  {
>         *allocation = widget->allocation;
> @@ -5667,6 +5681,117 @@ tablet_tool_handle_removed(void *data, struct
> zwp_tablet_tool_v1 *zwp_tablet_too
>         zwp_tablet_tool_v1_destroy(zwp_tablet_tool_v1);
>  }
>
> +static const struct wl_callback_listener
> tablet_tool_cursor_surface_listener;
> +
> +static void
> +tablet_tool_set_cursor_image_index(struct tablet_tool *tool, int index)
> +{
> +       struct wl_buffer *buffer;
> +       struct wl_cursor *cursor;
> +       struct wl_cursor_image *image;
> +
> +       cursor = tool->input->display->cursors[tool->current_cursor];
> +       if (index >= (int)cursor->image_count) {
> +               fprintf(stderr, "cursor index out of range\n");
> +               return;
> +       }
> +
> +       image = cursor->images[index];
> +       buffer = wl_cursor_image_get_buffer(image);
> +       if (!buffer)
> +               return;
> +
> +       wl_surface_attach(tool->cursor_surface, buffer, 0, 0);
> +       wl_surface_damage(tool->cursor_surface, 0, 0,
> +                         image->width, image->height);
> +       wl_surface_commit(tool->cursor_surface);
> +       zwp_tablet_tool_v1_set_cursor(tool->tool, tool->enter_serial,
> +                                     tool->cursor_surface,
> +                                     image->hotspot_x, image->hotspot_y);
> +}
> +
> +static void
> +tablet_tool_surface_frame_callback(void *data, struct wl_callback
> *callback,
> +                                  uint32_t time)
> +{
> +       struct tablet_tool *tool = data;
> +       struct wl_cursor *cursor;
> +       int i;
> +
> +       if (callback) {
> +               assert(callback == tool->cursor_frame_cb);
> +               wl_callback_destroy(callback);
> +               tool->cursor_frame_cb = NULL;
> +       }
> +
> +       if (tool->current_cursor == CURSOR_BLANK) {
> +               zwp_tablet_tool_v1_set_cursor(tool->tool,
> tool->enter_serial,
> +                                             NULL, 0, 0);
> +               return;
> +       }
> +
> +       if (tool->current_cursor == CURSOR_UNSET)
> +               return;
> +
> +       cursor = tool->input->display->cursors[tool->current_cursor];
> +       if (!cursor)
> +               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. */
> +       if (time == 0)
> +               tool->cursor_anim_start = 0;
> +       else if (tool->cursor_anim_start == 0)
> +               tool->cursor_anim_start = time;
> +
> +       if (time == 0 || tool->cursor_anim_start == 0)
> +               i = 0;
> +       else
> +               i = wl_cursor_frame(cursor, time -
> tool->cursor_anim_start);
> +
> +       if (cursor->image_count > 1) {
> +               tool->cursor_frame_cb =
> +                       wl_surface_frame(tool->cursor_surface);
> +               wl_callback_add_listener(tool->cursor_frame_cb,
> +
> &tablet_tool_cursor_surface_listener,
> +                                        tool);
> +       }
> +
> +       tablet_tool_set_cursor_image_index(tool, i);
> +}
> +
> +static const struct wl_callback_listener
> tablet_tool_cursor_surface_listener =  {
> +       tablet_tool_surface_frame_callback,
> +};
> +
> +void
> +tablet_tool_set_cursor_image(struct tablet_tool *tool, int cursor)
> +{
> +       bool force = false;
> +
> +       if (tool->enter_serial > tool->cursor_serial)
> +               force = true;
> +
> +       if (!force && cursor == tool->current_cursor)
> +               return;
> +
> +       tool->current_cursor = cursor;
> +       tool->cursor_serial = tool->enter_serial;
> +
> +       if (!tool->cursor_frame_cb) {
> +               tablet_tool_surface_frame_callback(tool, NULL, 0);
> +       } else if (force) {
> +               /* The current frame callback may be stuck if, for
> instance,
> +                * the set cursor request was processed by the server after
> +                * this client lost the focus. In this case the cursor
> surface
> +                * might not be mapped and the frame callback wouldn't ever
> +                * complete. Send a set_cursor and attach to try to map the
> +                * cursor surface again so that the callback will finish
> +                */
> +               tablet_tool_set_cursor_image_index(tool, 0);
> +       }
> +}
> +
>  static void
>  tablet_tool_set_focus_widget(struct tablet_tool *tool, struct window
> *window,
>                              wl_fixed_t sx, wl_fixed_t sy)
> @@ -5707,6 +5832,7 @@ tablet_tool_handle_proximity_in(void *data,
>
>         tool->focus = window;
>         tool->current_tablet = tablet;
> +       tool->enter_serial = serial;
>  }
>
>  static void
> @@ -5751,6 +5877,7 @@ tablet_tool_handle_motion(void *data, struct
> zwp_tablet_tool_v1 *zwp_tablet_tool
>         double sy = wl_fixed_to_double(y);
>         struct window *window = tool->focus;
>         struct widget *widget;
> +       int cursor;
>
>         if (!window)
>                 return;
> @@ -5765,9 +5892,14 @@ tablet_tool_handle_motion(void *data, struct
> zwp_tablet_tool_v1 *zwp_tablet_tool
>         tablet_tool_set_focus_widget(tool, window, sx, sy);
>         widget = tool->focus_widget;
>         if (widget && widget->tablet_tool_motion_handler) {
> -               widget->tablet_tool_motion_handler(widget, tool, sx, sy,
> -                                                  widget->user_data);
> +               cursor = widget->tablet_tool_motion_handler(widget, tool,
> +                                                           sx, sy,
> +
>  widget->user_data);
> +       } else {
> +               cursor = widget->default_tablet_cursor;
>         }
> +
> +       tablet_tool_set_cursor_image(tool, cursor);
>  }
>
>  static void
> @@ -5908,6 +6040,8 @@ tablet_tool_added(void *data, struct
> zwp_tablet_seat_v1 *zwp_tablet_seat1,
>
>         tool->tool = id;
>         tool->input = input;
> +       tool->cursor_surface =
> +               wl_compositor_create_surface(input->display->compositor);
>  }
>
>  static const struct zwp_tablet_seat_v1_listener tablet_seat_listener = {
> diff --git a/clients/window.h b/clients/window.h
> index 86f0366..903abf0 100644
> --- a/clients/window.h
> +++ b/clients/window.h
> @@ -275,10 +275,10 @@ typedef void (*widget_axis_handler_t)(struct widget
> *widget,
>                                       uint32_t axis,
>                                       wl_fixed_t value,
>                                       void *data);
> -typedef void (*widget_tablet_tool_motion_handler_t)(struct widget *widget,
> -                                                   struct tablet_tool
> *tool,
> -                                                   float x, float y,
> -                                                   void *data);
> +typedef int (*widget_tablet_tool_motion_handler_t)(struct widget *widget,
> +                                                  struct tablet_tool
> *tool,
> +                                                  float x, float y,
> +                                                  void *data);
>  typedef void (*widget_tablet_tool_down_handler_t)(struct widget *widget,
>                                                   struct tablet_tool *tool,
>                                                   void *data);
> @@ -533,6 +533,8 @@ widget_destroy(struct widget *widget);
>  void
>  widget_set_default_cursor(struct widget *widget, int cursor);
>  void
> +widget_set_default_tablet_cursor(struct widget *widget, int cursor);
> +void
>  widget_get_allocation(struct widget *widget, struct rectangle
> *allocation);
>
>  void
> @@ -750,4 +752,7 @@ tablet_tool_get_serial(struct tablet_tool *tool);
>  uint64_t
>  tablet_tool_get_hwid(struct tablet_tool *tool);
>
> +void
> +tablet_tool_set_cursor_image(struct tablet_tool *tool, int cursor);
> +
>  #endif
> --
> 2.5.0
>
> _______________________________________________
> wayland-devel mailing list
> [email protected]
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to