[PATCH weston 05/13] tablet: handle tablet cursors in the compositor

Bill Spitzak spitzak at gmail.com
Fri Nov 6 15:24:37 PST 2015


This looks like you are having the compositor maintain several cursors per
seat, and switching them when different tools are used.

That is wrong. The client is responsible for setting the cursor. Any cursor
changes by the compositor will only lead to flashing or blinking or other
incorrect renderings, in cases where the compositor chooses a cursor that
is not equal to the current cursor and also not equal to the cursor the
client actually wants. That is why wayland does not set cursors on enter
events, and why it should not set the cursor here either.

Strong NAK

On Thu, Nov 5, 2015 at 8:31 PM, Peter Hutterer <peter.hutterer at who-t.net>
wrote:

> From: Stephen Chandler Paul <thatslyude at gmail.com>
>
> The tablet is given a separate cursor. Most tablet interaction is an
> absolute
> interaction and shouldn't need a cursor at all, but usually the cursor is
> used
> to indicate the type of virtual tool currently assigned.
>
> Co-authored-by: Peter Hutterer <peter.hutterer at who-t.net>
> Signed-off-by: Stephen Chandler Paul <thatslyude at gmail.com>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
>  src/compositor.c |   6 +++
>  src/compositor.h |  13 +++++
>  src/input.c      | 157
> ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 175 insertions(+), 1 deletion(-)
>
> diff --git a/src/compositor.c b/src/compositor.c
> index 8eadf8c..7777291 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -1759,6 +1759,7 @@ weston_view_unmap(struct weston_view *view)
>                 struct weston_pointer *pointer =
> weston_seat_get_pointer(seat);
>                 struct weston_keyboard *keyboard =
>                         weston_seat_get_keyboard(seat);
> +               struct weston_tablet_tool *tool;
>
>                 if (keyboard && keyboard->focus == view->surface)
>                         weston_keyboard_set_focus(keyboard, NULL);
> @@ -1766,6 +1767,11 @@ weston_view_unmap(struct weston_view *view)
>                         weston_pointer_clear_focus(pointer);
>                 if (touch && touch->focus == view)
>                         weston_touch_set_focus(touch, NULL);
> +
> +               wl_list_for_each(tool, &seat->tablet_tool_list, link) {
> +                       if (tool->focus == view)
> +                               weston_tablet_tool_set_focus(tool, NULL,
> 0);
> +               }
>         }
>  }
>
> diff --git a/src/compositor.h b/src/compositor.h
> index ce084c8..2eaadf4 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -432,6 +432,12 @@ struct weston_tablet_tool {
>
>         int button_count;
>         bool tip_is_down;
> +
> +       int32_t hotspot_x, hotspot_y;
> +       struct weston_view *sprite;
> +       struct wl_listener sprite_destroy_listener;
> +
> +       wl_fixed_t x, y;
>  };
>
>  struct weston_tablet {
> @@ -531,6 +537,13 @@ void
>  weston_tablet_tool_end_grab(struct weston_tablet_tool *tool);
>
>  void
> +weston_tablet_tool_clamp(struct weston_tablet_tool *tool,
> +                        wl_fixed_t *fx, wl_fixed_t *fy);
> +void
> +weston_tablet_tool_cursor_move(struct weston_tablet_tool *tool,
> +                              wl_fixed_t x, wl_fixed_t y);
> +
> +void
>  wl_data_device_set_keyboard_focus(struct weston_seat *seat);
>
>  int
> diff --git a/src/input.c b/src/input.c
> index 6139b31..69806e2 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -781,7 +781,13 @@ static void
>  default_grab_tablet_tool_proximity_out(struct weston_tablet_tool_grab
> *grab,
>                                        uint32_t time)
>  {
> -       weston_tablet_tool_set_focus(grab->tool, NULL, time);
> +       struct weston_tablet_tool *tool = grab->tool;
> +
> +       weston_tablet_tool_set_focus(tool, NULL, time);
> +
> +       /* Hide the cursor */
> +       if (weston_surface_is_mapped(tool->sprite->surface))
> +               weston_surface_unmap(tool->sprite->surface);
>  }
>
>  static void
> @@ -796,6 +802,8 @@ default_grab_tablet_tool_motion(struct
> weston_tablet_tool_grab *grab,
>         struct wl_resource *resource;
>         struct wl_list *resource_list = &tool->focus_resource_list;
>
> +       weston_tablet_tool_cursor_move(tool, x, y);
> +
>         current_view = weston_compositor_pick_view(tool->seat->compositor,
>                                                    x, y, &sx, &sy);
>         if (current_view != tool->focus)
> @@ -933,6 +941,29 @@ static struct weston_tablet_tool_grab_interface
> default_tablet_tool_grab_interfa
>         default_grab_tablet_tool_cancel,
>  };
>
> +static void
> +tablet_tool_unmap_sprite(struct weston_tablet_tool *tool)
> +{
> +       if (weston_surface_is_mapped(tool->sprite->surface))
> +               weston_surface_unmap(tool->sprite->surface);
> +
> +       wl_list_remove(&tool->sprite_destroy_listener.link);
> +       tool->sprite->surface->configure = NULL;
> +       tool->sprite->surface->configure_private = NULL;
> +       weston_view_destroy(tool->sprite);
> +       tool->sprite = NULL;
> +}
> +
> +static void
> +tablet_tool_handle_sprite_destroy(struct wl_listener *listener, void
> *data)
> +{
> +       struct weston_tablet_tool *tool =
> +               container_of(listener, struct weston_tablet_tool,
> +                            sprite_destroy_listener);
> +
> +       tool->sprite = NULL;
> +}
> +
>  WL_EXPORT struct weston_tablet_tool *
>  weston_tablet_tool_create(void)
>  {
> @@ -945,6 +976,9 @@ weston_tablet_tool_create(void)
>         wl_list_init(&tool->resource_list);
>         wl_list_init(&tool->focus_resource_list);
>
> +       wl_list_init(&tool->sprite_destroy_listener.link);
> +       tool->sprite_destroy_listener.notify =
> tablet_tool_handle_sprite_destroy;
> +
>         wl_list_init(&tool->focus_view_listener.link);
>         tool->focus_view_listener.notify =
> tablet_tool_focus_view_destroyed;
>
> @@ -963,6 +997,9 @@ weston_tablet_tool_destroy(struct weston_tablet_tool
> *tool)
>  {
>         struct wl_resource *resource, *tmp;
>
> +       if (tool->sprite)
> +               tablet_tool_unmap_sprite(tool);
> +
>         wl_resource_for_each_safe(resource, tmp, &tool->resource_list)
>                 zwp_tablet_tool1_send_removed(resource);
>
> @@ -970,6 +1007,48 @@ weston_tablet_tool_destroy(struct weston_tablet_tool
> *tool)
>         free(tool);
>  }
>
> +WL_EXPORT void
> +weston_tablet_tool_clamp(struct weston_tablet_tool *tool,
> +                        wl_fixed_t *fx, wl_fixed_t *fy)
> +{
> +       struct weston_output *output = tool->current_tablet->output;
> +       int x, y;
> +
> +       x = wl_fixed_to_int(*fx);
> +       y = wl_fixed_to_int(*fy);
> +
> +       if (x < output->x)
> +               *fx = wl_fixed_from_int(output->x);
> +       else if (x >= output->x + output->width)
> +               *fx = wl_fixed_from_int(output->x + output->width - 1);
> +
> +       if (y < output->y)
> +               *fy = wl_fixed_from_int(output->y);
> +       else if (y >= output->y + output->height)
> +               *fy = wl_fixed_from_int(output->y + output->height - 1);
> +}
> +
> +WL_EXPORT void
> +weston_tablet_tool_cursor_move(struct weston_tablet_tool *tool,
> +                              wl_fixed_t x,
> +                              wl_fixed_t y)
> +{
> +       int32_t ix, iy;
> +
> +       weston_tablet_tool_clamp(tool, &x, &y);
> +       tool->x = x;
> +       tool->y = y;
> +
> +       ix = wl_fixed_to_int(x);
> +       iy = wl_fixed_to_int(y);
> +
> +       if (tool->sprite) {
> +               weston_view_set_position(tool->sprite,
> +                                        ix - tool->hotspot_x,
> +                                        iy - tool->hotspot_y);
> +               weston_view_schedule_repaint(tool->sprite);
> +       }
> +}
>
>  static void
>  seat_send_updated_caps(struct weston_seat *seat)
> @@ -2034,10 +2113,86 @@ notify_tablet_added(struct weston_tablet *tablet)
>  }
>
>  static void
> +tablet_tool_cursor_surface_configure(struct weston_surface *es,
> +                                    int32_t dx, int32_t dy)
> +{
> +       struct weston_tablet_tool *tool = es->configure_private;
> +       int x, y;
> +
> +       if (es->width == 0)
> +               return;
> +
> +       assert(es == tool->sprite->surface);
> +
> +       tool->hotspot_x -= dx;
> +       tool->hotspot_y -= dy;
> +
> +       x = wl_fixed_to_int(tool->x) - tool->hotspot_x;
> +       y = wl_fixed_to_int(tool->y) - tool->hotspot_y;
> +
> +       weston_view_set_position(tool->sprite, x, y);
> +
> +       empty_region(&es->pending.input);
> +       empty_region(&es->input);
> +
> +       if (!weston_surface_is_mapped(es)) {
> +               weston_layer_entry_insert(
> +                       &es->compositor->cursor_layer.view_list,
> +                       &tool->sprite->layer_link);
> +               weston_view_update_transform(tool->sprite);
> +       }
> +}
> +
> +static void
>  tablet_tool_set_cursor(struct wl_client *client, struct wl_resource
> *resource,
>                        uint32_t serial, struct wl_resource
> *surface_resource,
>                        int32_t hotspot_x, int32_t hotspot_y)
>  {
> +       struct weston_tablet_tool *tool =
> wl_resource_get_user_data(resource);
> +       struct weston_surface *surface = NULL;
> +
> +       if (surface_resource)
> +               surface = wl_resource_get_user_data(surface_resource);
> +
> +       if (tool->focus == NULL)
> +               return;
> +
> +       /* tablet->focus->surface->resource can be NULL. Surfaces like the
> +        * black_surface used in shell.c for fullscreen don't have
> +        * a resource, but can still have focus */
> +       if (tool->focus->surface->resource == NULL)
> +               return;
> +
> +       if (wl_resource_get_client(tool->focus->surface->resource) !=
> client)
> +               return;
> +
> +       if (tool->focus_serial - serial > UINT32_MAX / 2)
> +               return;
> +
> +       if (surface && tool->sprite && surface != tool->sprite->surface &&
> +           surface->configure) {
> +               wl_resource_post_error(surface->resource,
> +                                      WL_DISPLAY_ERROR_INVALID_OBJECT,
> +                                      "surface->configure already set");
> +               return;
> +       }
> +
> +       if (tool->sprite)
> +               tablet_tool_unmap_sprite(tool);
> +
> +       if (!surface)
> +               return;
> +
> +       wl_signal_add(&surface->destroy_signal,
> +                     &tool->sprite_destroy_listener);
> +       surface->configure = tablet_tool_cursor_surface_configure;
> +       surface->configure_private = tool;
> +       tool->sprite = weston_view_create(surface);
> +       tool->hotspot_x = hotspot_x;
> +       tool->hotspot_y = hotspot_y;
> +
> +       if (surface->buffer_ref.buffer)
> +               tablet_tool_cursor_surface_configure(surface, 0, 0);
>  }
>
>  static void
> --
> 2.4.3
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20151106/5baed102/attachment-0001.html>


More information about the wayland-devel mailing list