On Wed, Feb 03, 2016 at 03:28:05PM +1000, Peter Hutterer wrote:
> From: Stephen Chandler Paul <[email protected]>
> 
> Introduces two new structs, weston_tablet and weston_tablet_tool with the
> respective information as it's used on the protocol.
> 
> Note that tools are independent of tablets, many tools can be used across
> multiple tablets.
> 
> The nesting on the protocol level requires a global tablet manager, a tablet
> seat nested into weston_seat. The list of tablets and tools are also part of
> the weston_seat.
> 
> Most functions are stubs except for the actual tablet and tablet tool
> creation and removal.
> 
> Co-authored-by: Peter Hutterer <[email protected]>
> Signed-off-by: Stephen Chandler Paul <[email protected]>
> Signed-off-by: Peter Hutterer <[email protected]>
> ---
> Changes since v1:
> - fixed freeing of tablets and tools, previous version caused the occasional
>   segfault when a client released the resource. Split now into unlinking the
>   tablet (during destroy) and actual freeing (during resource cleanup)
> - shared code for initialization of tablets/tools, was duplicated before
> 
>  Makefile.am           |  13 +-
>  configure.ac          |   2 +-
>  src/compositor.c      |   1 +
>  src/compositor.h      |  98 ++++++++++++
>  src/input.c           | 416 
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/libinput-device.c | 187 +++++++++++++++++++++++
>  src/libinput-device.h |   4 +-
>  7 files changed, 716 insertions(+), 5 deletions(-)
> 
> diff --git a/Makefile.am b/Makefile.am
> index 623621d..d5b4aae 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -126,7 +126,9 @@ nodist_weston_SOURCES =                                   
> \
>       protocol/scaler-protocol.c                      \
>       protocol/scaler-server-protocol.h               \
>       protocol/linux-dmabuf-unstable-v1-protocol.c    \
> -     protocol/linux-dmabuf-unstable-v1-server-protocol.h
> +     protocol/linux-dmabuf-unstable-v1-server-protocol.h             \
> +     protocol/tablet-unstable-v1-protocol.c                          \
> +     protocol/tablet-unstable-v1-server-protocol.h
>  
>  BUILT_SOURCES += $(nodist_weston_SOURCES)
>  
> @@ -570,7 +572,9 @@ nodist_libtoytoolkit_la_SOURCES =                 \
>       protocol/xdg-shell-unstable-v5-protocol.c                       \
>       protocol/xdg-shell-unstable-v5-client-protocol.h                \
>       protocol/ivi-application-protocol.c             \
> -     protocol/ivi-application-client-protocol.h
> +     protocol/ivi-application-client-protocol.h      \
> +     protocol/tablet-unstable-v1-protocol.c          \
> +     protocol/tablet-unstable-v1-client-protocol.h
>  
>  BUILT_SOURCES += $(nodist_libtoytoolkit_la_SOURCES)
>  
> @@ -779,7 +783,10 @@ BUILT_SOURCES +=                                 \
>       protocol/ivi-hmi-controller-protocol.c          \
>       protocol/ivi-hmi-controller-client-protocol.h   \
>       protocol/ivi-application-protocol.c             \
> -     protocol/ivi-application-client-protocol.h
> +     protocol/ivi-application-client-protocol.h      \
> +     protocol/tablet-unstable-v1-protocol.c          \
> +     protocol/tablet-unstable-v1-client-protocol.h
> +

nit: Sneaky newline.

>  
>  westondatadir = $(datadir)/weston
>  dist_westondata_DATA =                               \
> diff --git a/configure.ac b/configure.ac
> index 107c155..e45d74c 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -178,7 +178,7 @@ if test x$enable_drm_compositor = xyes; then
>  fi
>  
>  
> -PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 0.8.0])
> +PKG_CHECK_MODULES(LIBINPUT_BACKEND, [libinput >= 1.1.901])
>  PKG_CHECK_MODULES(COMPOSITOR, [$COMPOSITOR_MODULES])
>  
>  PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.0],
> diff --git a/src/compositor.c b/src/compositor.c
> index 98efb4c..cbdb14c 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -4769,6 +4769,7 @@ weston_compositor_create(struct wl_display *display, 
> void *user_data)
>       wl_list_init(&ec->touch_binding_list);
>       wl_list_init(&ec->axis_binding_list);
>       wl_list_init(&ec->debug_binding_list);
> +     wl_list_init(&ec->tablet_manager_resource_list);
>  
>       weston_plane_init(&ec->primary_plane, ec, 0, 0);
>       weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
> diff --git a/src/compositor.h b/src/compositor.h
> index 58ae94b..3c67ffe 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -38,6 +38,7 @@ extern "C" {
>  
>  #define WL_HIDE_DEPRECATED
>  #include <wayland-server.h>
> +#include <tablet-unstable-v1-server-protocol.h>
>  
>  #include "version.h"
>  #include "matrix.h"
> @@ -404,6 +405,34 @@ struct weston_touch {
>       uint32_t grab_time;
>  };
>  
> +struct weston_tablet_tool {
> +     struct weston_seat *seat;
> +     enum zwp_tablet_tool_v1_type type;
> +
> +     struct wl_list resource_list;
> +
> +     struct wl_list link;
> +
> +     uint64_t serial;
> +     uint64_t hwid;

Isn't this wacom specific?

> +     uint32_t capabilities;
> +};
> +
> +struct weston_tablet {
> +     struct weston_seat *seat;
> +     struct evdev_device *device;
> +
> +     struct wl_list resource_list;
> +
> +     struct wl_list link;
> +
> +     char *name;
> +     uint32_t vid;
> +     uint32_t pid;
> +     const char *path;
> +     struct weston_output *output;
> +};
> +
>  void
>  weston_pointer_motion_to_abs(struct weston_pointer *pointer,
>                            struct weston_pointer_motion_event *event,
> @@ -477,6 +506,16 @@ weston_touch_start_grab(struct weston_touch *device,
>  void
>  weston_touch_end_grab(struct weston_touch *touch);
>  
> +struct weston_tablet *
> +weston_tablet_create(void);
> +void
> +weston_tablet_destroy(struct weston_tablet *tablet);
> +
> +struct weston_tablet_tool *
> +weston_tablet_tool_create(void);
> +void
> +weston_tablet_tool_destroy(struct weston_tablet_tool *tool);
> +
>  void
>  wl_data_device_set_keyboard_focus(struct weston_seat *seat);
>  
> @@ -563,6 +602,8 @@ struct weston_seat {
>       struct weston_pointer *pointer_state;
>       struct weston_keyboard *keyboard_state;
>       struct weston_touch *touch_state;
> +     struct wl_list tablet_list;
> +     struct wl_list tablet_tool_list;
>       int pointer_device_count;
>       int keyboard_device_count;
>       int touch_device_count;
> @@ -588,6 +629,8 @@ struct weston_seat {
>  
>       struct input_method *input_method;
>       char *seat_name;
> +
> +     struct wl_list tablet_seat_resource_list;
>  };
>  
>  enum {
> @@ -787,6 +830,9 @@ struct weston_compositor {
>  
>       void *user_data;
>       void (*exit)(struct weston_compositor *c);
> +
> +     struct wl_global *tablet_manager;
> +     struct wl_list tablet_manager_resource_list;
>  };
>  
>  struct weston_buffer {
> @@ -1195,6 +1241,47 @@ void
>  notify_touch_cancel(struct weston_seat *seat);
>  
>  void
> +notify_tablet_added(struct weston_tablet *tablet);
> +
> +void
> +notify_tablet_tool_added(struct weston_tablet_tool *tool);
> +
> +void
> +notify_tablet_tool_proximity_in(struct weston_tablet_tool *tool,
> +                             uint32_t time,
> +                             struct weston_tablet *tablet);
> +void
> +notify_tablet_tool_proximity_out(struct weston_tablet_tool *tool,
> +                              uint32_t time);
> +void
> +notify_tablet_tool_motion(struct weston_tablet_tool *tool,
> +                       uint32_t time,
> +                       wl_fixed_t x, wl_fixed_t y);
> +void
> +notify_tablet_tool_pressure(struct weston_tablet_tool *tool,
> +                         uint32_t time, uint32_t pressure);
> +void
> +notify_tablet_tool_distance(struct weston_tablet_tool *tool,
> +                         uint32_t time, uint32_t distance);
> +void
> +notify_tablet_tool_tilt(struct weston_tablet_tool *tool,
> +                     uint32_t time, int32_t tilt_x, int32_t tilt_y);
> +void
> +notify_tablet_tool_button(struct weston_tablet_tool *tool,
> +                       uint32_t time,
> +                       uint32_t button,
> +                       enum zwp_tablet_tool_v1_button_state state);
> +void
> +notify_tablet_tool_up(struct weston_tablet_tool *tool,
> +                   uint32_t time);
> +void
> +notify_tablet_tool_down(struct weston_tablet_tool *tool,
> +                     uint32_t time);
> +void
> +notify_tablet_tool_frame(struct weston_tablet_tool *tool,
> +                      uint32_t time);
> +
> +void
>  weston_layer_entry_insert(struct weston_layer_entry *list,
>                         struct weston_layer_entry *entry);
>  void
> @@ -1512,6 +1599,14 @@ void
>  weston_seat_init_touch(struct weston_seat *seat);
>  void
>  weston_seat_release_touch(struct weston_seat *seat);
> +struct weston_tablet *
> +weston_seat_add_tablet(struct weston_seat *seat);
> +struct weston_tablet_tool *
> +weston_seat_add_tablet_tool(struct weston_seat *seat);
> +void
> +weston_seat_release_tablet_tool(struct weston_tablet_tool *tablet_tool);
> +void
> +weston_seat_release_tablet(struct weston_tablet *tablet);
>  void
>  weston_seat_repick(struct weston_seat *seat);
>  void
> @@ -1525,6 +1620,9 @@ weston_compositor_xkb_init(struct weston_compositor *ec,
>  void
>  weston_compositor_xkb_destroy(struct weston_compositor *ec);
>  
> +void
> +weston_tablet_manager_init(struct weston_compositor *ec);
> +
>  /* String literal of spaces, the same width as the timestamp. */
>  #define STAMP_SPACE "               "
>  
> diff --git a/src/input.c b/src/input.c
> index 2539fa7..0b43fd8 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -828,6 +828,57 @@ weston_touch_destroy(struct weston_touch *touch)
>       free(touch);
>  }
>  
> +WL_EXPORT struct weston_tablet *
> +weston_tablet_create(void)
> +{
> +     struct weston_tablet *tablet;
> +
> +     tablet = zalloc(sizeof *tablet);
> +     if (tablet == NULL)
> +             return NULL;
> +
> +     wl_list_init(&tablet->resource_list);
> +
> +     return tablet;
> +}
> +
> +WL_EXPORT void
> +weston_tablet_destroy(struct weston_tablet *tablet)
> +{
> +     struct wl_resource *resource;
> +
> +     wl_resource_for_each(resource, &tablet->resource_list)
> +             zwp_tablet_v1_send_removed(resource);
> +
> +     wl_list_remove(&tablet->link);
> +}
> +
> +WL_EXPORT struct weston_tablet_tool *
> +weston_tablet_tool_create(void)
> +{
> +     struct weston_tablet_tool *tool;
> +
> +     tool = zalloc(sizeof *tool);
> +     if (tool == NULL)
> +             return NULL;
> +
> +     wl_list_init(&tool->resource_list);
> +
> +     return tool;
> +}
> +
> +WL_EXPORT void
> +weston_tablet_tool_destroy(struct weston_tablet_tool *tool)
> +{
> +     struct wl_resource *resource, *tmp;
> +
> +     wl_resource_for_each_safe(resource, tmp, &tool->resource_list)
> +             zwp_tablet_tool_v1_send_removed(resource);

No reason to use the _safe() version here.

> +
> +     wl_list_remove(&tool->link);
> +}
> +

nit: Extra newline

> +
>  static void
>  seat_send_updated_caps(struct weston_seat *seat)
>  {
> @@ -1913,6 +1964,237 @@ pointer_cursor_surface_get_label(struct 
> weston_surface *surface,
>  }
>  
>  static void
> +tablet_destroy(struct wl_client *client, struct wl_resource *resource)
> +{
> +     wl_resource_destroy(resource);
> +}
> +
> +static const struct zwp_tablet_v1_interface tablet_interface = {
> +     tablet_destroy,
> +};
> +
> +static void
> +send_tablet_added(struct weston_tablet *tablet,
> +               struct wl_resource *tablet_seat_resource,
> +               struct wl_resource *tablet_resource)
> +{
> +     zwp_tablet_seat_v1_send_tablet_added(tablet_seat_resource, 
> tablet_resource);
> +     zwp_tablet_v1_send_name(tablet_resource, tablet->name);
> +     zwp_tablet_v1_send_id(tablet_resource, tablet->vid, tablet->pid);
> +     zwp_tablet_v1_send_path(tablet_resource, tablet->path);
> +     zwp_tablet_v1_send_done(tablet_resource);
> +}
> +
> +static void
> +tablet_unbind_resource(struct wl_resource *resource)
> +{
> +     struct weston_tablet *tablet;
> +
> +     tablet = wl_resource_get_user_data(resource);
> +
> +     wl_list_remove(wl_resource_get_link(resource));
> +
> +     if (wl_list_empty(&tablet->resource_list)) {
> +             free(tablet->name);
> +             free(tablet);
> +     }
> +}
> +
> +static void
> +tablet_add_resource(struct weston_tablet *tablet,
> +                 struct wl_client *client,
> +                 struct wl_resource *tablet_seat_resource)
> +{
> +     struct wl_resource *tablet_resource;
> +
> +     tablet_resource = wl_resource_create(client,
> +                                          &zwp_tablet_v1_interface,
> +                                          1, 0);

The version should be inherited from tablet_seat.

> +
> +     wl_list_insert(&tablet->resource_list,
> +                    wl_resource_get_link(tablet_resource));
> +     wl_resource_set_implementation(tablet_resource,
> +                                    &tablet_interface,
> +                                    tablet,
> +                                    tablet_unbind_resource);
> +
> +     wl_resource_set_user_data(tablet_resource, tablet);
> +     send_tablet_added(tablet, tablet_seat_resource, tablet_resource);
> +}
> +
> +WL_EXPORT void
> +notify_tablet_added(struct weston_tablet *tablet)
> +{
> +     struct wl_resource *tablet_seat_resource;
> +     struct weston_seat *seat = tablet->seat;
> +
> +     wl_resource_for_each(tablet_seat_resource,
> +                          &seat->tablet_seat_resource_list) {
> +             tablet_add_resource(tablet,
> +                                 
> wl_resource_get_client(tablet_seat_resource),
> +                                 tablet_seat_resource);
> +     }
> +}
> +
> +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)
> +{
> +}
> +
> +static void
> +tablet_tool_destroy(struct wl_client *client, struct wl_resource *resource)
> +{
> +     wl_resource_destroy(resource);
> +}
> +
> +static const struct zwp_tablet_tool_v1_interface tablet_tool_interface = {
> +     tablet_tool_set_cursor,
> +     tablet_tool_destroy,
> +};
> +
> +static void
> +send_tool_added(struct weston_tablet_tool *tool,
> +             struct wl_resource *tool_seat_resource,
> +             struct wl_resource *tool_resource)
> +{
> +     uint32_t caps, cap;

nit: missing newline

> +     zwp_tablet_seat_v1_send_tool_added(tool_seat_resource, tool_resource);
> +     zwp_tablet_tool_v1_send_type(tool_resource, tool->type);
> +     zwp_tablet_tool_v1_send_hardware_serial(tool_resource,
> +                                             tool->serial >> 32,
> +                                             tool->serial & 0xFFFFFFFF);
> +     zwp_tablet_tool_v1_send_hardware_id_wacom(tool_resource,
> +                                               tool->hwid >> 32,
> +                                               tool->hwid & 0xFFFFFFFF);

What if the tool is not a wacom tool?

> +     caps = tool->capabilities;
> +     while (caps != 0) {
> +             cap = ffs(caps) - 1;
> +             zwp_tablet_tool_v1_send_capability(tool_resource, cap);
> +             caps &= ~(1 << cap);
> +     }
> +
> +     zwp_tablet_tool_v1_send_done(tool_resource);
> +}
> +
> +static void
> +tablet_tool_unbind_resource(struct wl_resource *resource)
> +{
> +     struct weston_tablet_tool *tool;
> +
> +     tool = wl_resource_get_user_data(resource);
> +
> +     wl_list_remove(wl_resource_get_link(resource));
> +
> +     if (wl_list_empty(&tool->resource_list)) {
> +             free(tool);
> +     }
> +}
> +
> +static void
> +tablet_tool_add_resource(struct weston_tablet_tool *tool,
> +                      struct wl_client *client,
> +                      struct wl_resource *tablet_seat_resource)
> +{
> +     struct wl_resource *tool_resource;
> +
> +     tool_resource = wl_resource_create(client,
> +                                        &zwp_tablet_tool_v1_interface,
> +                                        1, 0);

Should inherit the version here as well.

> +
> +     wl_list_insert(&tool->resource_list,
> +                    wl_resource_get_link(tool_resource));
> +     wl_resource_set_implementation(tool_resource,
> +                                    &tablet_tool_interface,
> +                                    tool,
> +                                    tablet_tool_unbind_resource);
> +
> +     wl_resource_set_user_data(tool_resource, tool);
> +     send_tool_added(tool, tablet_seat_resource, tool_resource);
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_added(struct weston_tablet_tool *tool)
> +{
> +     struct wl_resource *tablet_seat_resource;
> +     struct weston_seat *seat = tool->seat;
> +     struct wl_client *client;
> +
> +     wl_resource_for_each(tablet_seat_resource,
> +                          &seat->tablet_seat_resource_list) {
> +             client = wl_resource_get_client(tablet_seat_resource);
> +             tablet_tool_add_resource(tool, client,
> +                                      tablet_seat_resource);
> +     }
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_proximity_in(struct weston_tablet_tool *tool,
> +                              uint32_t time,
> +                              struct weston_tablet *tablet)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_proximity_out(struct weston_tablet_tool *tool,
> +                              uint32_t time)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_motion(struct weston_tablet_tool *tool,
> +                       uint32_t time,
> +                       wl_fixed_t x, wl_fixed_t y)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_pressure(struct weston_tablet_tool *tool,
> +                         uint32_t time, uint32_t pressure)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_distance(struct weston_tablet_tool *tool,
> +                         uint32_t time, uint32_t distance)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_tilt(struct weston_tablet_tool *tool,
> +                     uint32_t time, int32_t tilt_x, int32_t tilt_y)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_button(struct weston_tablet_tool *tool,
> +                       uint32_t time,
> +                       uint32_t button,
> +                       enum zwp_tablet_tool_v1_button_state state)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_down(struct weston_tablet_tool *tool,
> +                     uint32_t time)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_up(struct weston_tablet_tool *tool,
> +                   uint32_t time)
> +{
> +}
> +
> +WL_EXPORT void
> +notify_tablet_tool_frame(struct weston_tablet_tool *tool,
> +                      uint32_t time)
> +{
> +}
> +
> +
> +static void
>  pointer_cursor_surface_configure(struct weston_surface *es,
>                                int32_t dx, int32_t dy)
>  {
> @@ -2597,6 +2879,20 @@ weston_seat_release_pointer(struct weston_seat *seat)
>  }
>  
>  WL_EXPORT void
> +weston_seat_release_tablet_tool(struct weston_tablet_tool *tool)
> +{
> +     /* FIXME: nothing is calling this function yet, tools are only
> +        released on shutdown when the seat goes away */
> +     weston_tablet_tool_destroy(tool);
> +}
> +
> +WL_EXPORT void
> +weston_seat_release_tablet(struct weston_tablet *tablet)
> +{
> +     weston_tablet_destroy(tablet);
> +}
> +
> +WL_EXPORT void
>  weston_seat_init_touch(struct weston_seat *seat)
>  {
>       struct weston_touch *touch;
> @@ -2619,6 +2915,39 @@ weston_seat_init_touch(struct weston_seat *seat)
>       seat_send_updated_caps(seat);
>  }
>  
> +WL_EXPORT struct weston_tablet *
> +weston_seat_add_tablet(struct weston_seat *seat)
> +{
> +     struct weston_tablet *tablet;
> +
> +     weston_tablet_manager_init(seat->compositor);
> +
> +     tablet = weston_tablet_create();
> +     if (tablet == NULL)
> +             return NULL;
> +
> +     tablet->seat = seat;
> +
> +     return tablet;
> +}
> +
> +WL_EXPORT struct weston_tablet_tool *
> +weston_seat_add_tablet_tool(struct weston_seat *seat)
> +{
> +     struct weston_tablet_tool *tool;
> +
> +     weston_tablet_manager_init(seat->compositor);
> +
> +     tool = weston_tablet_tool_create();
> +     if (tool == NULL)
> +             return NULL;
> +
> +     wl_list_init(&tool->resource_list);
> +     tool->seat = seat;
> +
> +     return tool;
> +}
> +
>  WL_EXPORT void
>  weston_seat_release_touch(struct weston_seat *seat)
>  {
> @@ -2643,6 +2972,9 @@ weston_seat_init(struct weston_seat *seat, struct 
> weston_compositor *ec,
>       wl_list_init(&seat->drag_resource_list);
>       wl_signal_init(&seat->destroy_signal);
>       wl_signal_init(&seat->updated_caps_signal);
> +     wl_list_init(&seat->tablet_seat_resource_list);
> +     wl_list_init(&seat->tablet_list);
> +     wl_list_init(&seat->tablet_tool_list);
>  
>       seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
>                                       seat, bind_seat);
> @@ -2661,6 +2993,9 @@ weston_seat_init(struct weston_seat *seat, struct 
> weston_compositor *ec,
>  WL_EXPORT void
>  weston_seat_release(struct weston_seat *seat)
>  {
> +     struct weston_tablet *tablet, *tmp;
> +     struct weston_tablet_tool *tool, *tmp_tool;
> +
>       wl_list_remove(&seat->link);
>  
>       if (seat->saved_kbd_focus)
> @@ -2672,6 +3007,10 @@ weston_seat_release(struct weston_seat *seat)
>               weston_keyboard_destroy(seat->keyboard_state);
>       if (seat->touch_state)
>               weston_touch_destroy(seat->touch_state);
> +     wl_list_for_each_safe(tablet, tmp, &seat->tablet_list, link)
> +             weston_tablet_destroy(tablet);
> +     wl_list_for_each_safe(tool, tmp_tool, &seat->tablet_tool_list, link)
> +             weston_tablet_tool_destroy(tool);
>  
>       free (seat->seat_name);
>  
> @@ -2745,3 +3084,80 @@ weston_seat_get_touch(struct weston_seat *seat)
>  
>       return NULL;
>  }
> +
> +static void
> +tablet_seat_destroy(struct wl_client *client, struct wl_resource *resource)
> +{
> +}
> +
> +static const struct zwp_tablet_seat_v1_interface tablet_seat_interface = {
> +     tablet_seat_destroy,
> +};
> +
> +static void
> +tablet_manager_get_tablet_seat(struct wl_client *client, struct wl_resource 
> *resource,
> +                            uint32_t id, struct wl_resource *seat_resource)
> +{
> +     struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
> +     struct wl_resource *cr;
> +     struct weston_tablet *tablet;
> +     struct weston_tablet_tool *tool;
> +
> +     cr = wl_resource_create(client, &zwp_tablet_seat_v1_interface,
> +                             wl_resource_get_version(resource), id);
> +     if (cr == NULL) {
> +             wl_client_post_no_memory(client);
> +             return;
> +     }
> +
> +     /* store the resource in the weston_seat */
> +     wl_list_insert(&seat->tablet_seat_resource_list, 
> wl_resource_get_link(cr));
> +     wl_resource_set_implementation(cr, &tablet_seat_interface, seat,
> +                                    unbind_resource);
> +
> +     /* Notify client of any tablets already connected to the system */
> +     wl_list_for_each(tablet, &seat->tablet_list, link)
> +             tablet_add_resource(tablet, client, cr);
> +
> +     /* Notify client of any tools already known */
> +     wl_list_for_each(tool, &seat->tablet_tool_list, link)
> +             tablet_tool_add_resource(tool, client, cr);
> +}
> +
> +static void
> +tablet_manager_destroy(struct wl_client *client, struct wl_resource 
> *resource)
> +{
> +
> +}
> +
> +static const struct zwp_tablet_manager_v1_interface tablet_manager_interface 
> = {
> +     tablet_manager_get_tablet_seat,
> +     tablet_manager_destroy,
> +};
> +
> +static void
> +bind_tablet_manager(struct wl_client *client, void *data, uint32_t version,
> +                 uint32_t id)
> +{
> +     struct weston_compositor *compositor = data;
> +     struct wl_resource *resource;
> +
> +     resource = wl_resource_create(client, &zwp_tablet_manager_v1_interface,
> +                                   MIN(version, 1), id);
> +     wl_resource_set_implementation(resource, &tablet_manager_interface,
> +                                    data, unbind_resource);
> +     wl_list_insert(&compositor->tablet_manager_resource_list,
> +                    wl_resource_get_link(resource));
> +}
> +
> +WL_EXPORT void
> +weston_tablet_manager_init(struct weston_compositor *compositor)
> +{
> +     if (compositor->tablet_manager)
> +             return;
> +
> +     compositor->tablet_manager = wl_global_create(compositor->wl_display,
> +                                                   
> &zwp_tablet_manager_v1_interface,
> +                                                   1, compositor,
> +                                                   bind_tablet_manager);
> +}
> diff --git a/src/libinput-device.c b/src/libinput-device.c
> index 99b2916..be41091 100644
> --- a/src/libinput-device.c
> +++ b/src/libinput-device.c
> @@ -40,6 +40,14 @@
>  #include "libinput-device.h"
>  #include "shared/helpers.h"
>  
> +struct tablet_output_listener {
> +     struct wl_listener base;
> +     struct wl_list tablet_list;
> +};
> +
> +static bool
> +tablet_bind_output(struct weston_tablet *tablet, struct weston_output 
> *output);
> +
>  void
>  evdev_led_update(struct evdev_device *device, enum weston_led weston_leds)
>  {
> @@ -348,6 +356,79 @@ handle_touch_frame(struct libinput_device 
> *libinput_device,
>       notify_touch_frame(seat);
>  }
>  
> +static void
> +handle_tablet_proximity(struct libinput_device *libinput_device,
> +                     struct libinput_event_tablet_tool *proximity_event)
> +{
> +     struct evdev_device *device;
> +     struct weston_tablet *tablet;
> +     struct weston_tablet_tool *tool;
> +     struct libinput_tablet_tool *libinput_tool;
> +     enum libinput_tablet_tool_type libinput_tool_type;
> +     uint32_t serial, type;
> +     uint32_t time;
> +     bool create = true;
> +
> +     device = libinput_device_get_user_data(libinput_device);
> +     time = libinput_event_tablet_tool_get_time(proximity_event);
> +     libinput_tool = libinput_event_tablet_tool_get_tool(proximity_event);
> +     serial = libinput_tablet_tool_get_serial(libinput_tool);
> +     libinput_tool_type = libinput_tablet_tool_get_type(libinput_tool);
> +
> +     tool = libinput_tablet_tool_get_user_data(libinput_tool);
> +     tablet = device->tablet;
> +
> +     if (libinput_event_tablet_tool_get_proximity_state(proximity_event) ==
> +         LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT) {
> +             notify_tablet_tool_proximity_out(tool, time);
> +             return;
> +     }
> +
> +     switch (libinput_tool_type) {
> +     case LIBINPUT_TABLET_TOOL_TYPE_PEN:
> +             type = ZWP_TABLET_TOOL_V1_TYPE_PEN;
> +             break;
> +     case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
> +             type = ZWP_TABLET_TOOL_V1_TYPE_ERASER;
> +             break;
> +     default:
> +             fprintf(stderr, "Unknown libinput tool type %d\n",
> +                     libinput_tool_type);
> +             return;
> +     }
> +

nit: would be clearer if you set create = false; here.

> +     wl_list_for_each(tool, &device->seat->tablet_tool_list, link) {
> +             if (tool->serial == serial && tool->type == type) {

What about the case where serial == 0, but they are different tools?

> +                     create = false;
> +                     break;
> +             }
> +     }
> +
> +     if (create) {
> +             tool = weston_seat_add_tablet_tool(device->seat);

OOM check?

> +             tool->serial = serial;
> +             tool->hwid = libinput_tablet_tool_get_tool_id(libinput_tool);
> +             tool->type = type;
> +             tool->capabilities = 0;
> +
> +             if (libinput_tablet_tool_has_distance(libinput_tool))
> +                 tool->capabilities |= 1 << 
> ZWP_TABLET_TOOL_V1_CAPABILITY_DISTANCE;
> +             if (libinput_tablet_tool_has_pressure(libinput_tool))
> +                 tool->capabilities |= 1 << 
> ZWP_TABLET_TOOL_V1_CAPABILITY_PRESSURE;
> +             if (libinput_tablet_tool_has_tilt(libinput_tool))
> +                 tool->capabilities |= 1 << 
> ZWP_TABLET_TOOL_V1_CAPABILITY_TILT;
> +
> +             wl_list_insert(&device->seat->tablet_tool_list, &tool->link);
> +             notify_tablet_tool_added(tool);
> +
> +             libinput_tablet_tool_set_user_data(libinput_tool, tool);
> +     }
> +
> +     notify_tablet_tool_proximity_in(tool, time, tablet);
> +     /* FIXME: we should send axis updates  here */
> +     notify_tablet_tool_frame(tool, time);
> +}
> +
>  int
>  evdev_device_process_event(struct libinput_event *event)
>  {
> @@ -397,6 +478,10 @@ evdev_device_process_event(struct libinput_event *event)
>               handle_touch_frame(libinput_device,
>                                  libinput_event_get_touch_event(event));
>               break;
> +     case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY:
> +             handle_tablet_proximity(libinput_device,
> +                             libinput_event_get_tablet_tool_event(event));
> +             break;
>       default:
>               handled = 0;
>               weston_log("unknown libinput event %d\n",
> @@ -552,6 +637,102 @@ configure_device(struct evdev_device *device)
>       evdev_device_set_calibration(device);
>  }
>  
> +static void
> +bind_unbound_tablets(struct wl_listener *listener_base, void *data)
> +{
> +     struct tablet_output_listener *listener =
> +             wl_container_of(listener_base, listener, base);
> +     struct weston_tablet *tablet, *tmp;
> +
> +     wl_list_for_each_safe(tablet, tmp, &listener->tablet_list, link) {
> +             if (tablet_bind_output(tablet, data)) {
> +                     wl_list_remove(&tablet->link);
> +                     wl_list_insert(&tablet->seat->tablet_list,
> +                                    &tablet->link);
> +                     tablet->device->seat_caps |= EVDEV_SEAT_TABLET;
> +                     notify_tablet_added(tablet);
> +             }
> +     }
> +
> +     if (wl_list_empty(&listener->tablet_list)) {
> +             wl_list_remove(&listener_base->link);
> +             free(listener);
> +     }
> +}
> +
> +static bool
> +tablet_bind_output(struct weston_tablet *tablet, struct weston_output 
> *output)
> +{
> +     struct wl_list *output_list = &tablet->seat->compositor->output_list;
> +     struct weston_compositor *compositor = tablet->seat->compositor;
> +     struct tablet_output_listener *listener;
> +     struct wl_listener *listener_base;
> +
> +     if (output) {
> +             tablet->output = output;
> +     } else if (!wl_list_empty(output_list)) {
> +             /* Find the first available display */
> +             wl_list_for_each(output, output_list, link)
> +                     break;
> +             tablet->output = output;
> +     }
> +
> +     if (tablet->output)
> +             return true;
> +
> +     listener_base = wl_signal_get(&compositor->output_created_signal,
> +                                   bind_unbound_tablets);
> +     if (listener_base == NULL) {
> +             listener = zalloc(sizeof(*listener));
> +
> +             wl_list_init(&listener->tablet_list);
> +
> +             listener_base = &listener->base;
> +             listener_base->notify = bind_unbound_tablets;
> +
> +             wl_signal_add(&compositor->output_created_signal,
> +                           listener_base);
> +     } else {
> +             listener = wl_container_of(listener_base, listener, base);
> +     }
> +
> +     wl_list_insert(&listener->tablet_list, &tablet->link);
> +     return false;
> +}
> +
> +static void
> +evdev_device_init_tablet(struct evdev_device *device,
> +                      struct libinput_device *libinput_device,
> +                      struct weston_seat *seat)
> +{
> +     struct weston_tablet *tablet;
> +     struct udev_device *udev_device;
> +
> +     tablet = weston_seat_add_tablet(seat);

OOM check?


Jonas

> +     tablet->name = strdup(libinput_device_get_name(libinput_device));
> +     tablet->vid = libinput_device_get_id_vendor(libinput_device);
> +     tablet->pid = libinput_device_get_id_product(libinput_device);
> +
> +     udev_device = libinput_device_get_udev_device(libinput_device);
> +     if (udev_device) {
> +             tablet->path = udev_device_get_devnode(udev_device);
> +             udev_device_unref(udev_device);
> +     }
> +
> +     /* If we can successfully bind the tablet to an output, then
> +      * it's ready to get added to the seat's tablet list, otherwise
> +      * it will get added when an appropriate output is available */
> +     if (tablet_bind_output(tablet, NULL)) {
> +             wl_list_insert(&seat->tablet_list, &tablet->link);
> +             device->seat_caps |= EVDEV_SEAT_TABLET;
> +
> +             notify_tablet_added(tablet);
> +     }
> +
> +     device->tablet = tablet;
> +     tablet->device = device;
> +}
> +
>  struct evdev_device *
>  evdev_device_create(struct libinput_device *libinput_device,
>                   struct weston_seat *seat)
> @@ -581,6 +762,10 @@ evdev_device_create(struct libinput_device 
> *libinput_device,
>               weston_seat_init_touch(seat);
>               device->seat_caps |= EVDEV_SEAT_TOUCH;
>       }
> +     if (libinput_device_has_capability(libinput_device,
> +                                        LIBINPUT_DEVICE_CAP_TABLET_TOOL)) {
> +             evdev_device_init_tablet(device, libinput_device, seat);
> +     }
>  
>       libinput_device_set_user_data(libinput_device, device);
>       libinput_device_ref(libinput_device);
> @@ -599,6 +784,8 @@ evdev_device_destroy(struct evdev_device *device)
>               weston_seat_release_keyboard(device->seat);
>       if (device->seat_caps & EVDEV_SEAT_TOUCH)
>               weston_seat_release_touch(device->seat);
> +     if (device->seat_caps & EVDEV_SEAT_TABLET)
> +             weston_seat_release_tablet(device->tablet);
>  
>       if (device->output)
>               wl_list_remove(&device->output_destroy_listener.link);
> diff --git a/src/libinput-device.h b/src/libinput-device.h
> index a3848ca..e082291 100644
> --- a/src/libinput-device.h
> +++ b/src/libinput-device.h
> @@ -37,7 +37,8 @@
>  enum evdev_device_seat_capability {
>       EVDEV_SEAT_POINTER = (1 << 0),
>       EVDEV_SEAT_KEYBOARD = (1 << 1),
> -     EVDEV_SEAT_TOUCH = (1 << 2)
> +     EVDEV_SEAT_TOUCH = (1 << 2),
> +     EVDEV_SEAT_TABLET = (1 << 3)
>  };
>  
>  struct evdev_device {
> @@ -47,6 +48,7 @@ struct evdev_device {
>       struct wl_list link;
>       struct weston_output *output;
>       struct wl_listener output_destroy_listener;
> +     struct weston_tablet *tablet;
>       char *devnode;
>       char *output_name;
>       int fd;
> -- 
> 2.5.0
> 
> _______________________________________________
> wayland-devel mailing list
> [email protected]
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to