Unverified Commit 2a58d446 authored by Drew DeVault's avatar Drew DeVault Committed by GitHub
Browse files

Merge pull request #1136 from emersion/remove-unused-tablet-v2

Remove unused types/wlr_tablet_v2.c
parents 7f20ab64 4afd69bb
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L
#endif
#include <assert.h>
#include <libinput.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-server.h>
#include <types/wlr_tablet_v2.h>
#include <wlr/config.h>
#include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_tablet_tool.h>
#include <wlr/types/wlr_tablet_v2.h>
#include <wlr/util/log.h>
#include "tablet-unstable-v2-protocol.h"
struct wlr_tablet_seat_v2 {
struct wl_list link;
struct wlr_seat *wlr_seat;
struct wlr_tablet_manager_v2 *manager;
struct wl_list tablets; // wlr_tablet_v2_tablet::link
struct wl_list tools;
struct wl_list pads;
struct wl_list clients; //wlr_tablet_seat_v2_client::link;
struct wl_listener seat_destroy;
};
struct wlr_tablet_manager_client_v2 {
struct wl_list link;
struct wl_client *client;
struct wl_resource *resource;
struct wlr_tablet_manager_v2 *manager;
struct wl_listener client_destroy;
struct wl_list tablet_seats; // wlr_tablet_seat_client_v2::link
};
struct wlr_tablet_seat_client_v2 {
struct wl_list seat_link;
struct wl_list client_link;
struct wl_client *wl_client;
struct wl_resource *resource;
struct wlr_tablet_manager_client_v2 *client;
struct wlr_seat_client *seat;
struct wl_listener seat_client_destroy;
struct wl_list tools; //wlr_tablet_tool_client_v2::link
struct wl_list tablets; //wlr_tablet_client_v2::link
struct wl_list pads; //wlr_tablet_pad_client_v2::link
};
struct wlr_tablet_client_v2 {
struct wl_list seat_link; // wlr_tablet_seat_client_v2::tablet
struct wl_list tablet_link; // wlr_tablet_v2_tablet::clients
struct wl_client *client;
struct wl_resource *resource;
};
struct wlr_tablet_tool_client_v2 {
struct wl_list seat_link;
struct wl_list tool_link;
struct wl_client *client;
struct wl_resource *resource;
struct wlr_tablet_v2_tablet_tool *tool;
struct wlr_tablet_seat_client_v2 *seat;
uint32_t proximity_serial;
struct wl_event_source *frame_source;
};
struct wlr_tablet_pad_client_v2 {
struct wl_list seat_link;
struct wl_list pad_link;
struct wl_client *client;
struct wl_resource *resource;
struct wlr_tablet_v2_tablet_pad *pad;
uint32_t enter_serial;
uint32_t mode_serial;
uint32_t leave_serial;
size_t button_count;
size_t group_count;
struct wl_resource **groups;
size_t ring_count;
struct wl_resource **rings;
size_t strip_count;
struct wl_resource **strips;
};
struct tablet_pad_auxiliary_user_data {
struct wlr_tablet_pad_client_v2 *pad;
size_t index;
};
static struct zwp_tablet_v2_interface tablet_impl;
struct wlr_tablet_client_v2 *tablet_client_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwp_tablet_v2_interface,
&tablet_impl));
return wl_resource_get_user_data(resource);
}
void destroy_tablet_v2(struct wl_resource *resource) {
struct wlr_tablet_client_v2 *tablet = tablet_client_from_resource(resource);
if (!tablet) {
return;
}
wl_list_remove(&tablet->seat_link);
wl_list_remove(&tablet->tablet_link);
free(tablet);
wl_resource_set_user_data(resource, NULL);
}
static void handle_tablet_v2_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
static struct zwp_tablet_v2_interface tablet_impl = {
.destroy = handle_tablet_v2_destroy,
};
static void handle_wlr_seat_destroy(struct wl_listener *listener, void *data) {
struct wlr_tablet_seat_v2 *seat =
wl_container_of(listener, seat, seat_destroy);
wl_list_remove(&seat->link);
wl_list_remove(&seat->seat_destroy.link);
struct wlr_tablet_seat_client_v2 *client;
struct wlr_tablet_seat_client_v2 *tmp;
wl_list_for_each_safe(client, tmp, &seat->clients, seat_link) {
wlr_tablet_seat_client_v2_destroy(client->resource);
}
}
static struct wlr_tablet_seat_v2 *make_tablet_seat(
struct wlr_tablet_manager_v2 *manager,
struct wlr_seat *wlr_seat) {
struct wlr_tablet_seat_v2 *tablet_seat =
calloc(1, sizeof(struct wlr_tablet_seat_v2));
if (!tablet_seat) {
return NULL;
}
tablet_seat->manager = manager;
tablet_seat->wlr_seat = wlr_seat;
wl_list_init(&tablet_seat->clients);
wl_list_init(&tablet_seat->tablets);
wl_list_init(&tablet_seat->tools);
wl_list_init(&tablet_seat->pads);
tablet_seat->seat_destroy.notify = handle_wlr_seat_destroy;
wl_signal_add(&wlr_seat->events.destroy, &tablet_seat->seat_destroy);
wl_list_insert(&manager->seats, &tablet_seat->link);
return tablet_seat;
}
static struct wlr_tablet_seat_v2 *get_or_make_tablet_seat(
struct wlr_tablet_manager_v2 *manager,
struct wlr_seat *wlr_seat) {
struct wlr_tablet_seat_v2 *pos;
wl_list_for_each(pos, &manager->seats, link) {
if (pos->wlr_seat == wlr_seat) {
return pos;
}
}
return make_tablet_seat(manager, wlr_seat);
}
static void add_tablet_client(struct wlr_tablet_seat_client_v2 *seat,
struct wlr_tablet_v2_tablet *tablet) {
struct wlr_tablet_client_v2 *client =
calloc(1, sizeof(struct wlr_tablet_client_v2));
if (!client) {
return;
}
client->resource =
wl_resource_create(seat->wl_client, &zwp_tablet_v2_interface, 1, 0);
if (!client->resource) {
free(client);
return;
}
wl_resource_set_implementation(client->resource, &tablet_impl,
client, destroy_tablet_v2);
zwp_tablet_seat_v2_send_tablet_added(seat->resource, client->resource);
// Send the expected events
if (tablet->wlr_tool->name) {
zwp_tablet_v2_send_name(client->resource, tablet->wlr_tool->name);
}
zwp_tablet_v2_send_id(client->resource,
tablet->wlr_device->vendor, tablet->wlr_device->product);
for (size_t i = 0; i < tablet->wlr_tool->paths.length; ++i) {
zwp_tablet_v2_send_path(client->resource,
tablet->wlr_tool->paths.items[i]);
}
zwp_tablet_v2_send_done(client->resource);
client->client = seat->wl_client;
wl_list_insert(&seat->tablets, &client->seat_link);
wl_list_insert(&tablet->clients, &client->tablet_link);
}
static void handle_wlr_tablet_destroy(struct wl_listener *listener, void *data) {
struct wlr_tablet_v2_tablet *tablet =
wl_container_of(listener, tablet, tool_destroy);
struct wlr_tablet_client_v2 *pos;
struct wlr_tablet_client_v2 *tmp;
wl_list_for_each_safe(pos, tmp, &tablet->clients, tablet_link) {
// XXX: Add a timer/flag to destroy if client is slow?
zwp_tablet_v2_send_removed(pos->resource);
}
wl_list_remove(&tablet->clients);
wl_list_remove(&tablet->link);
wl_list_remove(&tablet->tool_destroy.link);
free(tablet);
}
static const struct wlr_surface_role pointer_cursor_surface_role = {
.name = "wl_pointer-cursor",
};
static void handle_tablet_tool_v2_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) {
struct wlr_tablet_tool_client_v2 *tool = tablet_tool_client_from_resource(resource);
if (!tool) {
return;
}
struct wlr_surface *surface = NULL;
if (surface_resource != NULL) {
surface = wlr_surface_from_resource(surface_resource);
if (!wlr_surface_set_role(surface, &pointer_cursor_surface_role, NULL,
surface_resource, WL_POINTER_ERROR_ROLE)) {
return;
}
}
struct wlr_tablet_v2_event_cursor evt = {
.surface = surface,
.serial = serial,
.hotspot_x = hotspot_x,
.hotspot_y = hotspot_y,
.seat_client = tool->seat->seat,
};
wl_signal_emit(&tool->tool->events.set_cursor, &evt);
}
static void handle_tablet_tool_v2_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
static struct zwp_tablet_tool_v2_interface tablet_tool_impl = {
.set_cursor = handle_tablet_tool_v2_set_cursor,
.destroy = handle_tablet_tool_v2_destroy,
};
static enum zwp_tablet_tool_v2_type tablet_type_from_wlr_type(
enum wlr_tablet_tool_type wlr_type) {
switch(wlr_type) {
case WLR_TABLET_TOOL_TYPE_PEN:
return ZWP_TABLET_TOOL_V2_TYPE_PEN;
case WLR_TABLET_TOOL_TYPE_ERASER:
return ZWP_TABLET_TOOL_V2_TYPE_ERASER;
case WLR_TABLET_TOOL_TYPE_BRUSH:
return ZWP_TABLET_TOOL_V2_TYPE_BRUSH;
case WLR_TABLET_TOOL_TYPE_PENCIL:
return ZWP_TABLET_TOOL_V2_TYPE_PENCIL;
case WLR_TABLET_TOOL_TYPE_AIRBRUSH:
return ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH;
case WLR_TABLET_TOOL_TYPE_MOUSE:
return ZWP_TABLET_TOOL_V2_TYPE_MOUSE;
case WLR_TABLET_TOOL_TYPE_LENS:
return ZWP_TABLET_TOOL_V2_TYPE_LENS;
}
assert(false && "Unreachable");
}
void destroy_tablet_tool_v2(struct wl_resource *resource) {
struct wlr_tablet_tool_client_v2 *client =
tablet_tool_client_from_resource(resource);
if (!client) {
return;
}
if (client->frame_source) {
wl_event_source_remove(client->frame_source);
}
if (client->tool && client->tool->current_client == client) {
client->tool->current_client = NULL;
}
wl_list_remove(&client->seat_link);
wl_list_remove(&client->tool_link);
free(client);
wl_resource_set_user_data(resource, NULL);
}
static void add_tablet_tool_client(struct wlr_tablet_seat_client_v2 *seat,
struct wlr_tablet_v2_tablet_tool *tool) {
struct wlr_tablet_tool_client_v2 *client =
calloc(1, sizeof(struct wlr_tablet_tool_client_v2));
if (!client) {
return;
}
client->tool = tool;
client->seat = seat;
client->resource =
wl_resource_create(seat->wl_client, &zwp_tablet_tool_v2_interface, 1, 0);
if (!client->resource) {
free(client);
return;
}
wl_resource_set_implementation(client->resource, &tablet_tool_impl,
client, destroy_tablet_tool_v2);
zwp_tablet_seat_v2_send_tool_added(seat->resource, client->resource);
// Send the expected events
if (tool->wlr_tool->hardware_serial) {
zwp_tablet_tool_v2_send_hardware_serial(
client->resource,
tool->wlr_tool->hardware_serial >> 32,
tool->wlr_tool->hardware_serial & 0xFFFFFFFF);
}
if (tool->wlr_tool->hardware_wacom) {
zwp_tablet_tool_v2_send_hardware_id_wacom(
client->resource,
tool->wlr_tool->hardware_wacom >> 32,
tool->wlr_tool->hardware_wacom & 0xFFFFFFFF);
}
zwp_tablet_tool_v2_send_type(client->resource,
tablet_type_from_wlr_type(tool->wlr_tool->type));
if (tool->wlr_tool->tilt) {
zwp_tablet_tool_v2_send_capability(client->resource,
ZWP_TABLET_TOOL_V2_CAPABILITY_TILT);
}
if (tool->wlr_tool->pressure) {
zwp_tablet_tool_v2_send_capability(client->resource,
ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE);
}
if (tool->wlr_tool->distance) {
zwp_tablet_tool_v2_send_capability(client->resource,
ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE);
}
if (tool->wlr_tool->rotation) {
zwp_tablet_tool_v2_send_capability(client->resource,
ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION);
}
if (tool->wlr_tool->slider) {
zwp_tablet_tool_v2_send_capability(client->resource,
ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER);
}
if (tool->wlr_tool->wheel) {
zwp_tablet_tool_v2_send_capability(client->resource,
ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL);
}
zwp_tablet_tool_v2_send_done(client->resource);
client->client = seat->wl_client;
wl_list_insert(&seat->tools, &client->seat_link);
wl_list_insert(&tool->clients, &client->tool_link);
}
struct wlr_tablet_v2_tablet *wlr_tablet_create(
struct wlr_tablet_manager_v2 *manager,
struct wlr_seat *wlr_seat,
struct wlr_input_device *wlr_device) {
assert(wlr_device->type == WLR_INPUT_DEVICE_TABLET_TOOL);
struct wlr_tablet_seat_v2 *seat = get_or_make_tablet_seat(manager, wlr_seat);
if (!seat) {
return NULL;
}
struct wlr_tablet_tool *tool = wlr_device->tablet_tool;
struct wlr_tablet_v2_tablet *tablet = calloc(1, sizeof(struct wlr_tablet_v2_tablet));
if (!tablet) {
return NULL;
}
tablet->wlr_tool = tool;
tablet->wlr_device = wlr_device;
wl_list_init(&tablet->clients);
tablet->tool_destroy.notify = handle_wlr_tablet_destroy;
wl_signal_add(&wlr_device->events.destroy, &tablet->tool_destroy);
wl_list_insert(&seat->tablets, &tablet->link);
// We need to create a tablet client for all clients on the seat
struct wlr_tablet_seat_client_v2 *pos;
wl_list_for_each(pos, &seat->clients, seat_link) {
// Tell the clients about the new tool
add_tablet_client(pos, tablet);
}
return tablet;
}
static void handle_wlr_tablet_tool_destroy(struct wl_listener *listener, void *data) {
struct wlr_tablet_v2_tablet_tool *tool =
wl_container_of(listener, tool, tool_destroy);
struct wlr_tablet_tool_client_v2 *pos;
struct wlr_tablet_tool_client_v2 *tmp;
wl_list_for_each_safe(pos, tmp, &tool->clients, tool_link) {
// XXX: Add a timer/flag to destroy if client is slow?
zwp_tablet_tool_v2_send_removed(pos->resource);
pos->tool = NULL;
}
wl_list_remove(&tool->clients);
wl_list_remove(&tool->link);
wl_list_remove(&tool->tool_destroy.link);
wl_list_remove(&tool->events.set_cursor.listener_list);
free(tool);
}
struct wlr_tablet_v2_tablet_tool *wlr_tablet_tool_create(
struct wlr_tablet_manager_v2 *manager,
struct wlr_seat *wlr_seat,
struct wlr_tablet_tool_tool *wlr_tool) {
struct wlr_tablet_seat_v2 *seat = get_or_make_tablet_seat(manager, wlr_seat);
if (!seat) {
return NULL;
}
struct wlr_tablet_v2_tablet_tool *tool =
calloc(1, sizeof(struct wlr_tablet_v2_tablet_tool));
if (!tool) {
return NULL;
}
tool->wlr_tool = wlr_tool;
wl_list_init(&tool->clients);
tool->tool_destroy.notify = handle_wlr_tablet_tool_destroy;
wl_signal_add(&wlr_tool->events.destroy, &tool->tool_destroy);
wl_list_insert(&seat->tools, &tool->link);
// We need to create a tablet client for all clients on the seat
struct wlr_tablet_seat_client_v2 *pos;
wl_list_for_each(pos, &seat->clients, seat_link) {
// Tell the clients about the new tool
add_tablet_tool_client(pos, tool);
}
wl_signal_init(&tool->events.set_cursor);
return tool;
}
static struct zwp_tablet_pad_v2_interface tablet_pad_impl;
struct wlr_tablet_pad_client_v2 *tablet_pad_client_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwp_tablet_pad_v2_interface,
&tablet_pad_impl));
return wl_resource_get_user_data(resource);
}
void destroy_tablet_pad_v2(struct wl_resource *resource) {
struct wlr_tablet_pad_client_v2 *pad =
tablet_pad_client_from_resource(resource);
if (!pad) {
return;
}
wl_list_remove(&pad->seat_link);
wl_list_remove(&pad->pad_link);
/* This isn't optimal, if the client destroys the resources in another
* order, it will be disconnected.
* But this makes things *way* easier for us, and (untested) I doubt
* clients will destroy it in another order.
*/
for (size_t i = 0; i < pad->group_count; ++i) {
if (pad->groups[i]) {
wl_resource_destroy(pad->groups[i]);
}
}
free(pad->groups);
for (size_t i = 0; i < pad->ring_count; ++i) {
if (pad->rings[i]) {
wl_resource_destroy(pad->rings[i]);
}
}
free(pad->rings);
for (size_t i = 0; i < pad->strip_count; ++i) {
if (pad->strips[i]) {
wl_resource_destroy(pad->strips[i]);
}
}
free(pad->strips);
free(pad);
wl_resource_set_user_data(resource, NULL);
}
static void handle_tablet_pad_v2_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
static void destroy_tablet_pad_ring_v2(struct wl_resource *resource) {
struct tablet_pad_auxiliary_user_data *aux = wl_resource_get_user_data(resource);
if (!aux) {
return;
}
aux->pad->rings[aux->index] = NULL;
free(aux);
wl_resource_set_user_data(resource, NULL);
}
static void handle_tablet_pad_ring_v2_set_feedback(struct wl_client *client,
struct wl_resource *resource, const char *description,
uint32_t serial) {
struct tablet_pad_auxiliary_user_data *aux = wl_resource_get_user_data(resource);
if (!aux) {
return;
}
struct wlr_tablet_v2_event_feedback evt = {
.serial = serial,
.description = description,
.index = aux->index
};
wl_signal_emit(&aux->pad->pad->events.ring_feedback, &evt);
}
static void handle_tablet_pad_ring_v2_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
static struct zwp_tablet_pad_ring_v2_interface tablet_pad_ring_impl = {
.set_feedback = handle_tablet_pad_ring_v2_set_feedback,
.destroy = handle_tablet_pad_ring_v2_destroy,
};
static void destroy_tablet_pad_strip_v2(struct wl_resource *resource) {
struct tablet_pad_auxiliary_user_data *aux = wl_resource_get_user_data(resource);
if (!aux) {
return;
}
aux->pad->strips[aux->index] = NULL;
free(aux);
wl_resource_set_user_data(resource, NULL);
}
static void handle_tablet_pad_strip_v2_set_feedback(struct wl_client *client,
struct wl_resource *resource, const char *description,
uint32_t serial) {
struct tablet_pad_auxiliary_user_data *aux = wl_resource_get_user_data(resource);
if (!aux) {
return;
}
struct wlr_tablet_v2_event_feedback evt = {
.serial = serial,
.description = description,
.index = aux->index
};
wl_signal_emit(&aux->pad->pad->events.strip_feedback, &evt);
}
static void handle_tablet_pad_strip_v2_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
static struct zwp_tablet_pad_strip_v2_interface tablet_pad_strip_impl = {
.set_feedback = handle_tablet_pad_strip_v2_set_feedback,
.destroy = handle_tablet_pad_strip_v2_destroy,
};
static void handle_tablet_pad_v2_set_feedback( struct wl_client *client,
struct wl_resource *resource, uint32_t button,
const char *description, uint32_t serial) {
struct wlr_tablet_pad_client_v2 *pad = tablet_pad_client_from_resource(resource);
if (!pad) {