diff --git a/include/types/wlr_tablet_v2.h b/include/types/wlr_tablet_v2.h new file mode 100644 index 00000000..21e2d962 --- /dev/null +++ b/include/types/wlr_tablet_v2.h @@ -0,0 +1,20 @@ +#ifndef TYPES_WLR_TABLET_V2_H +#define TYPES_WLR_TABLET_V2_H + +#include "tablet-unstable-v2-protocol.h" +#include +#include + + +struct wlr_tablet_client_v2 *tablet_client_from_resource(struct wl_resource *resource); +void destroy_tablet_v2(struct wl_resource *resource); + +void destroy_tablet_pad_v2(struct wl_resource *resource); +struct wlr_tablet_pad_client_v2 *tablet_pad_client_from_resource(struct wl_resource *resource); + +void destroy_tablet_tool_v2(struct wl_resource *resource); +struct wlr_tablet_tool_client_v2 *tablet_tool_client_from_resource(struct wl_resource *resource); + +struct wlr_tablet_seat_client_v2 *tablet_seat_client_from_resource(struct wl_resource *resource); +static void wlr_tablet_seat_client_v2_destroy(struct wl_resource *resource); +#endif /* TYPES_WLR_TABLET_V2_H */ diff --git a/types/wlr_tablet_v2.c b/types/wlr_tablet_v2.c index 5dec1c5d..781e52f9 100644 --- a/types/wlr_tablet_v2.c +++ b/types/wlr_tablet_v2.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -104,18 +105,23 @@ struct tablet_pad_auxiliary_user_data { static struct zwp_tablet_v2_interface tablet_impl; -static struct wlr_tablet_client_v2 *tablet_client_from_resource(struct wl_resource *resource) { +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); } -static void destroy_tablet_v2(struct wl_resource *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, @@ -127,33 +133,6 @@ static struct zwp_tablet_v2_interface tablet_impl = { .destroy = handle_tablet_v2_destroy, }; -static void destroy_tablet_seat_client(struct wlr_tablet_seat_client_v2 *client) { - /* This is only called when the seat or client gets destroyed. - * The client is liable to make a request on a deleted resource either - * way, so we don't do the removed->destroy process, but just remove - * all structs immediatly. - */ - struct wlr_tablet_client_v2 *tablet; - struct wlr_tablet_client_v2 *tmp_tablet; - wl_list_for_each_safe(tablet, tmp_tablet, &client->tablets, seat_link) { - wl_resource_destroy(tablet->resource); - } - - struct wlr_tablet_pad_client_v2 *pad; - struct wlr_tablet_pad_client_v2 *tmp_pad; - wl_list_for_each_safe(pad, tmp_pad, &client->pads, seat_link) { - wl_resource_destroy(pad->resource); - } - - struct wlr_tablet_tool_client_v2 *tool; - struct wlr_tablet_tool_client_v2 *tmp_tool; - wl_list_for_each_safe(tool, tmp_tool, &client->tools, seat_link) { - wl_resource_destroy(tool->resource); - } - - wl_resource_destroy(client->resource); -} - 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); @@ -163,13 +142,8 @@ static void handle_wlr_seat_destroy(struct wl_listener *listener, void *data) { struct wlr_tablet_seat_client_v2 *client; struct wlr_tablet_seat_client_v2 *tmp; - - /* wl_seat doesn't have a removed event/destroy request, so we can just - * destroy all attached tablet_seat_clients -> tablet_v2 resources. - * The client can call requests on gone resources either way - */ wl_list_for_each_safe(client, tmp, &seat->clients, seat_link) { - destroy_tablet_seat_client(client); + wlr_tablet_seat_client_v2_destroy(client->resource); } } @@ -271,7 +245,7 @@ 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 = wl_resource_get_user_data(resource); + struct wlr_tablet_tool_client_v2 *tool = tablet_tool_client_from_resource(resource); if (!tool) { return; } @@ -327,9 +301,13 @@ static enum zwp_tablet_tool_v2_type tablet_type_from_wlr_type( assert(false && "Unreachable"); } -static void destroy_tablet_tool(struct wl_resource *resource) { +void destroy_tablet_tool_v2(struct wl_resource *resource) { struct wlr_tablet_tool_client_v2 *client = - wl_resource_get_user_data(resource); + tablet_tool_client_from_resource(resource); + + if (!client) { + return; + } if (client->frame_source) { wl_event_source_remove(client->frame_source); @@ -342,6 +320,8 @@ static void destroy_tablet_tool(struct wl_resource *resource) { 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, @@ -361,7 +341,7 @@ static void add_tablet_tool_client(struct wlr_tablet_seat_client_v2 *seat, return; } wl_resource_set_implementation(client->resource, &tablet_tool_impl, - client, destroy_tablet_tool); + client, destroy_tablet_tool_v2); zwp_tablet_seat_v2_send_tool_added(seat->resource, client->resource); // Send the expected events @@ -506,17 +486,21 @@ struct wlr_tablet_v2_tablet_tool *wlr_tablet_tool_create( static struct zwp_tablet_pad_v2_interface tablet_pad_impl; -static struct wlr_tablet_pad_client_v2 *tablet_pad_client_from_resource(struct wl_resource *resource) { +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); } -static void destroy_tablet_pad_v2(struct wl_resource *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); @@ -547,6 +531,7 @@ static void destroy_tablet_pad_v2(struct wl_resource *resource) { free(pad->strips); free(pad); + wl_resource_set_user_data(resource, NULL); } static void handle_tablet_pad_v2_destroy(struct wl_client *client, @@ -633,7 +618,10 @@ static struct zwp_tablet_pad_strip_v2_interface tablet_pad_strip_impl = { 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_v2_tablet_pad *pad = wl_resource_get_user_data(resource); + struct wlr_tablet_pad_client_v2 *pad = tablet_pad_client_from_resource(resource); + if (!pad) { + return; + } struct wlr_tablet_v2_event_feedback evt = { .serial = serial, @@ -641,7 +629,7 @@ static void handle_tablet_pad_v2_set_feedback( struct wl_client *client, .description = description, }; - wl_signal_emit(&pad->events.button_feedback, &evt); + wl_signal_emit(&pad->pad->events.button_feedback, &evt); } static struct zwp_tablet_pad_v2_interface tablet_pad_impl = { @@ -891,31 +879,49 @@ static struct zwp_tablet_seat_v2_interface seat_impl = { .destroy = tablet_seat_destroy, }; -static struct wlr_tablet_seat_client_v2 *tablet_seat_from_resource ( +struct wlr_tablet_seat_client_v2 *tablet_seat_client_from_resource( struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &zwp_tablet_seat_v2_interface, &seat_impl)); return wl_resource_get_user_data(resource); } -static void wlr_tablet_seat_client_v2_destroy(struct wl_resource *resource) { - struct wlr_tablet_seat_client_v2 *seat = tablet_seat_from_resource(resource); +void wlr_tablet_seat_client_v2_destroy(struct wl_resource *resource) { + struct wlr_tablet_seat_client_v2 *seat = tablet_seat_client_from_resource(resource); + if (!seat) { + return; + } - /* XXX: Evaluate whether we should have a way to access structs */ - wl_list_remove(&seat->tools); - wl_list_remove(&seat->tablets); - wl_list_remove(&seat->pads); + struct wlr_tablet_client_v2 *tablet; + struct wlr_tablet_client_v2 *tmp_tablet; + wl_list_for_each_safe(tablet, tmp_tablet, &seat->tablets, seat_link) { + destroy_tablet_v2(tablet->resource); + } + + struct wlr_tablet_pad_client_v2 *pad; + struct wlr_tablet_pad_client_v2 *tmp_pad; + wl_list_for_each_safe(pad, tmp_pad, &seat->pads, seat_link) { + destroy_tablet_pad_v2(pad->resource); + } + + struct wlr_tablet_tool_client_v2 *tool; + struct wlr_tablet_tool_client_v2 *tmp_tool; + wl_list_for_each_safe(tool, tmp_tool, &seat->tools, seat_link) { + destroy_tablet_tool_v2(tool->resource); + } wl_list_remove(&seat->seat_link); wl_list_remove(&seat->client_link); + wl_list_remove(&seat->seat_client_destroy.link); free(seat); + wl_resource_set_user_data(resource, NULL); } static void handle_seat_client_destroy(struct wl_listener *listener, void *data) { struct wlr_tablet_seat_client_v2 *seat = wl_container_of(listener, seat, seat_client_destroy); - destroy_tablet_seat_client(seat); + wlr_tablet_seat_client_v2_destroy(seat->resource); } static void tablet_manager_destroy(struct wl_client *client, @@ -1426,3 +1432,9 @@ bool wlr_surface_accepts_tablet_v2(struct wlr_tablet_v2_tablet *tablet, return false; } + +struct wlr_tablet_tool_client_v2 *tablet_tool_client_from_resource(struct wl_resource *resource) { + assert(wl_resource_instance_of(resource, &zwp_tablet_tool_v2_interface, + &tablet_tool_impl)); + return wl_resource_get_user_data(resource); +}