From 03596a9d065ccb38059c9b782e1d4cd4eaf5a59e Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Wed, 20 Jan 2021 09:05:45 +0100 Subject: [PATCH] libweston: Add initial tablet support to weston Introduces three new structs, weston_tablet and weston_tablet_tool for the respective devices, with the respective information as it's used on the protocol. And weston_tablet_tool_id to track the tools of a tablet. 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. This is based on patches from Peter Hutterer and Bastian Farkas . Signed-off-by: Michael Olbrich --- include/libweston/libweston.h | 34 +++ libweston/backend.h | 42 ++++ libweston/compositor.c | 1 + libweston/input.c | 407 +++++++++++++++++++++++++++++++++ libweston/libweston-internal.h | 28 +++ libweston/meson.build | 2 + 6 files changed, 514 insertions(+) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index d872f7b4c..1aa146e14 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -842,6 +842,33 @@ struct weston_touch { struct wl_list timestamps_list; }; +struct weston_tablet_tool { + struct weston_seat *seat; + uint32_t type; + + struct wl_list resource_list; + + struct wl_list link; + + uint64_t serial; + uint64_t hwid; + uint32_t capabilities; +}; + +struct weston_tablet { + struct weston_seat *seat; + + struct wl_list resource_list; + struct wl_list tool_list; + + struct wl_list link; + + char *name; + uint32_t vid; + uint32_t pid; + const char *path; +}; + struct weston_coord_global weston_pointer_motion_to_abs(struct weston_pointer *pointer, struct weston_pointer_motion_event *event); @@ -1026,6 +1053,10 @@ struct weston_seat { struct input_method *input_method; char *seat_name; + + struct wl_list tablet_list; + struct wl_list tablet_tool_list; + struct wl_list tablet_seat_resource_list; }; enum { @@ -1307,6 +1338,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; + /* Whether to let the compositor run without any input device. */ bool require_input; diff --git a/libweston/backend.h b/libweston/backend.h index 425a478d2..cbf9f3c57 100644 --- a/libweston/backend.h +++ b/libweston/backend.h @@ -256,4 +256,46 @@ notify_touch_calibrator_cancel(struct weston_touch_device *device); void notify_touch_calibrator_frame(struct weston_touch_device *device); +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, + const struct timespec *time, + struct weston_tablet *tablet); +void +notify_tablet_tool_proximity_out(struct weston_tablet_tool *tool, + const struct timespec *time); +void +notify_tablet_tool_motion(struct weston_tablet_tool *tool, + const struct timespec *time, + wl_fixed_t x, wl_fixed_t y); +void +notify_tablet_tool_pressure(struct weston_tablet_tool *tool, + const struct timespec *time, uint32_t pressure); +void +notify_tablet_tool_distance(struct weston_tablet_tool *tool, + const struct timespec *time, uint32_t distance); +void +notify_tablet_tool_tilt(struct weston_tablet_tool *tool, + const struct timespec *time, + int32_t tilt_x, int32_t tilt_y); +void +notify_tablet_tool_button(struct weston_tablet_tool *tool, + const struct timespec *time, + uint32_t button, + uint32_t state_w); +void +notify_tablet_tool_up(struct weston_tablet_tool *tool, + const struct timespec *time); +void +notify_tablet_tool_down(struct weston_tablet_tool *tool, + const struct timespec *time); +void +notify_tablet_tool_frame(struct weston_tablet_tool *tool, + const struct timespec *time); + #endif diff --git a/libweston/compositor.c b/libweston/compositor.c index 82e6102c5..82363d291 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -8535,6 +8535,7 @@ weston_compositor_create(struct wl_display *display, 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); wl_list_init(&ec->plugin_api_list); diff --git a/libweston/input.c b/libweston/input.c index 6cd26bc34..1365502aa 100644 --- a/libweston/input.c +++ b/libweston/input.c @@ -48,6 +48,7 @@ #include "relative-pointer-unstable-v1-server-protocol.h" #include "pointer-constraints-unstable-v1-server-protocol.h" #include "input-timestamps-unstable-v1-server-protocol.h" +#include "tablet-unstable-v2-server-protocol.h" enum pointer_constraint_type { POINTER_CONSTRAINT_TYPE_LOCK, @@ -1401,6 +1402,75 @@ 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); + wl_list_init(&tablet->tool_list); + + return tablet; +} + +WL_EXPORT void +weston_tablet_destroy(struct weston_tablet *tablet) +{ + struct wl_resource *resource; + struct weston_tablet_tool *tool, *tmptool; + + wl_resource_for_each(resource, &tablet->resource_list) { + zwp_tablet_v2_send_removed(resource); + wl_resource_set_user_data(resource, NULL); + } + + /* Remove the tablet from the list */ + wl_list_remove(&tablet->link); + + /* Remove any local tools */ + wl_list_for_each_safe(tool, tmptool, &tablet->tool_list, link) + weston_seat_release_tablet_tool(tool); + + if (wl_list_empty(&tablet->resource_list)) { + free(tablet->name); + free(tablet); + } +} + +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_v2_send_removed(resource); + wl_resource_set_user_data(resource, NULL); + } + + wl_list_remove(&tool->link); + wl_list_remove(&tool->resource_list); + free(tool); +} + + static void seat_send_updated_caps(struct weston_seat *seat) { @@ -2689,6 +2759,208 @@ pointer_cursor_surface_get_label(struct weston_surface *surface, return snprintf(buf, len, "cursor"); } +static void +tablet_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static const struct zwp_tablet_v2_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_v2_send_tablet_added(tablet_seat_resource, tablet_resource); + zwp_tablet_v2_send_name(tablet_resource, tablet->name); + zwp_tablet_v2_send_id(tablet_resource, tablet->vid, tablet->pid); + zwp_tablet_v2_send_path(tablet_resource, tablet->path); + zwp_tablet_v2_send_done(tablet_resource); +} + +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_v2_interface, + 1, 0); + + wl_list_insert(&tablet->resource_list, + wl_resource_get_link(tablet_resource)); + wl_resource_set_implementation(tablet_resource, + &tablet_interface, + 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_v2_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; + zwp_tablet_seat_v2_send_tool_added(tool_seat_resource, tool_resource); + zwp_tablet_tool_v2_send_type(tool_resource, tool->type); + zwp_tablet_tool_v2_send_hardware_serial(tool_resource, + tool->serial >> 32, + tool->serial & 0xFFFFFFFF); + zwp_tablet_tool_v2_send_hardware_id_wacom(tool_resource, + tool->hwid >> 32, + tool->hwid & 0xFFFFFFFF); + caps = tool->capabilities; + while (caps != 0) { + cap = ffs(caps) - 1; + zwp_tablet_tool_v2_send_capability(tool_resource, cap); + caps &= ~(1 << cap); + } + + zwp_tablet_tool_v2_send_done(tool_resource); +} + +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_v2_interface, + 1, 0); + + wl_list_insert(&tool->resource_list, + wl_resource_get_link(tool_resource)); + wl_resource_set_implementation(tool_resource, + &tablet_tool_interface, + 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, + const struct timespec *time, + struct weston_tablet *tablet) +{ +} + +WL_EXPORT void +notify_tablet_tool_proximity_out(struct weston_tablet_tool *tool, + const struct timespec *time) +{ +} + +WL_EXPORT void +notify_tablet_tool_motion(struct weston_tablet_tool *tool, + const struct timespec *time, + wl_fixed_t x, wl_fixed_t y) +{ +} + +WL_EXPORT void +notify_tablet_tool_pressure(struct weston_tablet_tool *tool, + const struct timespec *time, uint32_t pressure) +{ +} + +WL_EXPORT void +notify_tablet_tool_distance(struct weston_tablet_tool *tool, + const struct timespec *time, uint32_t distance) +{ +} + +WL_EXPORT void +notify_tablet_tool_tilt(struct weston_tablet_tool *tool, + const struct timespec *time, + wl_fixed_t tilt_x, wl_fixed_t tilt_y) +{ +} + +WL_EXPORT void +notify_tablet_tool_button(struct weston_tablet_tool *tool, + const struct timespec *time, + uint32_t button, + enum zwp_tablet_tool_v2_button_state state) +{ +} + +WL_EXPORT void +notify_tablet_tool_down(struct weston_tablet_tool *tool, + const struct timespec *time) +{ +} + +WL_EXPORT void +notify_tablet_tool_up(struct weston_tablet_tool *tool, + const struct timespec *time) +{ +} + +WL_EXPORT void +notify_tablet_tool_frame(struct weston_tablet_tool *tool, + const struct timespec *time) +{ +} + + static void pointer_cursor_surface_committed(struct weston_surface *es, struct weston_coord_surface new_origin) @@ -3410,6 +3682,18 @@ weston_seat_release_pointer(struct weston_seat *seat) } } +WL_EXPORT void +weston_seat_release_tablet_tool(struct weston_tablet_tool *tool) +{ + weston_tablet_tool_destroy(tool); +} + +WL_EXPORT void +weston_seat_release_tablet(struct weston_tablet *tablet) +{ + weston_tablet_destroy(tablet); +} + WL_EXPORT int weston_seat_init_touch(struct weston_seat *seat) { @@ -3435,6 +3719,39 @@ weston_seat_init_touch(struct weston_seat *seat) return 0; } +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) { @@ -3459,6 +3776,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, MIN(wl_seat_interface.version, 7), @@ -3479,6 +3799,8 @@ WL_EXPORT void weston_seat_release(struct weston_seat *seat) { struct wl_resource *resource; + struct weston_tablet *tablet, *tmp; + struct weston_tablet_tool *tool, *tmp_tool; wl_resource_for_each(resource, &seat->base_resource_list) { wl_resource_set_user_data(resource, NULL); @@ -3502,6 +3824,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); @@ -3640,6 +3966,87 @@ 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_v2_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_v2_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 local tools already known */ + wl_list_for_each(tool, &tablet->tool_list, link) + tablet_tool_add_resource(tool, client, cr); + } + + /* Notify client of any global 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_v2_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_v2_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_v2_interface, + 1, compositor, + bind_tablet_manager); +} + /** Sets the keyboard focus to the given surface * * \param surface the surface to focus on diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index ce39441f6..ee3aa78d6 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -300,6 +300,15 @@ weston_seat_release_pointer(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_update_keymap(struct weston_seat *seat, struct xkb_keymap *keymap); @@ -349,6 +358,25 @@ weston_touch_start_drag(struct weston_touch *touch, bool weston_touch_device_can_calibrate(struct weston_touch_device *device); +/* weston_tablet */ + +void +weston_tablet_manager_init(struct weston_compositor *ec); + +struct weston_tablet * +weston_tablet_create(void); + +void +weston_tablet_destroy(struct weston_tablet *tablet); + +/* weston_tablet_tool */ + +struct weston_tablet_tool * +weston_tablet_tool_create(void); + +void +weston_tablet_tool_destroy(struct weston_tablet_tool *tool); + /* weston_surface */ pixman_box32_t weston_surface_to_buffer_rect(struct weston_surface *surface, diff --git a/libweston/meson.build b/libweston/meson.build index f4143c79d..0a1d1fccf 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -73,6 +73,8 @@ srcs_libweston = [ weston_direct_display_server_protocol_h, weston_output_capture_protocol_c, weston_output_capture_server_protocol_h, + tablet_unstable_v2_protocol_c, + tablet_unstable_v2_server_protocol_h, ] subdir('desktop')