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 <peter.hutterer@who-t.net> and
Bastian Farkas <bfarkas@de.adit-jv.com>.

Signed-off-by: Michael Olbrich <m.olbrich@pengutronix.de>
This commit is contained in:
Michael Olbrich 2021-01-20 09:05:45 +01:00 committed by Daniel Stone
parent f95c2986dd
commit 03596a9d06
6 changed files with 514 additions and 0 deletions

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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')