[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