[PATCH v2 weston 01/13] tablet: Add initial tablet support to weston

Jonas Ã…dahl jadahl at gmail.com
Sat Apr 30 09:57:21 UTC 2016


On Wed, Feb 03, 2016 at 03:28:05PM +1000, Peter Hutterer wrote:
> From: Stephen Chandler Paul <thatslyude at gmail.com>
> 
> 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 <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>
> ---
> 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
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list