From 5d37b14116e61d5f21f72cdfbd979fe92e17e295 Mon Sep 17 00:00:00 2001 From: emersion Date: Thu, 3 May 2018 20:22:51 +0100 Subject: [PATCH] data-device: make sure resources are correctly destroyed --- include/types/wlr_data_device.h | 3 +- include/wlr/types/wlr_data_device.h | 8 +++++ types/data_device/wlr_data_device.c | 52 ++++++++++++++++++++++++----- types/data_device/wlr_data_offer.c | 4 +-- types/data_device/wlr_data_source.c | 5 ++- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/include/types/wlr_data_device.h b/include/types/wlr_data_device.h index 4aa53dc0..ee423f80 100644 --- a/include/types/wlr_data_device.h +++ b/include/types/wlr_data_device.h @@ -18,7 +18,8 @@ struct wlr_data_offer *data_offer_create(struct wl_client *client, void data_offer_update_action(struct wlr_data_offer *offer); struct wlr_client_data_source *client_data_source_create( - struct wl_client *client, uint32_t version, uint32_t id); + struct wl_client *client, uint32_t version, uint32_t id, + struct wl_list *resource_list); struct wlr_client_data_source *client_data_source_from_resource( struct wl_resource *resource); struct wlr_data_offer *data_source_send_offer(struct wlr_data_source *source, diff --git a/include/wlr/types/wlr_data_device.h b/include/wlr/types/wlr_data_device.h index 6fb41c29..80d4bc8b 100644 --- a/include/wlr/types/wlr_data_device.h +++ b/include/wlr/types/wlr_data_device.h @@ -15,8 +15,16 @@ wlr_touch_grab_interface wlr_data_device_touch_drag_interface; struct wlr_data_device_manager { struct wl_global *global; + struct wl_list wl_resources; + struct wl_list data_sources; struct wl_listener display_destroy; + + struct { + struct wl_signal destroy; + } events; + + void *data; }; struct wlr_data_offer { diff --git a/types/data_device/wlr_data_device.c b/types/data_device/wlr_data_device.c index fffb2f1b..70ba3bfa 100644 --- a/types/data_device/wlr_data_device.c +++ b/types/data_device/wlr_data_device.c @@ -11,6 +11,8 @@ #include "types/wlr_data_device.h" #include "util/signal.h" +#define DATA_DEVICE_MANAGER_VERSION 3 + static const struct wl_data_device_interface data_device_impl; static struct wlr_seat_client *seat_client_from_data_device_resource( @@ -83,7 +85,7 @@ static const struct wl_data_device_interface data_device_impl = { .release = data_device_release, }; -static void data_device_destroy(struct wl_resource *resource) { +static void data_device_handle_resource_destroy(struct wl_resource *resource) { wl_list_remove(wl_resource_get_link(resource)); } @@ -164,6 +166,15 @@ void wlr_seat_set_selection(struct wlr_seat *seat, } +static const struct wl_data_device_manager_interface data_device_manager_impl; + +static struct wlr_data_device_manager *data_device_manager_from_resource( + struct wl_resource *resource) { + assert(wl_resource_instance_of(resource, &wl_data_device_manager_interface, + &data_device_manager_impl)); + return wl_resource_get_user_data(resource); +} + static void data_device_manager_get_data_device(struct wl_client *client, struct wl_resource *manager_resource, uint32_t id, struct wl_resource *seat_resource) { @@ -178,13 +189,17 @@ static void data_device_manager_get_data_device(struct wl_client *client, return; } wl_resource_set_implementation(resource, &data_device_impl, seat_client, - &data_device_destroy); + &data_device_handle_resource_destroy); wl_list_insert(&seat_client->data_devices, wl_resource_get_link(resource)); } static void data_device_manager_create_data_source(struct wl_client *client, - struct wl_resource *resource, uint32_t id) { - client_data_source_create(client, wl_resource_get_version(resource), id); + struct wl_resource *manager_resource, uint32_t id) { + struct wlr_data_device_manager *manager = + data_device_manager_from_resource(manager_resource); + + client_data_source_create(client, wl_resource_get_version(manager_resource), + id, &manager->data_sources); } static const struct wl_data_device_manager_interface @@ -193,8 +208,15 @@ static const struct wl_data_device_manager_interface .get_data_device = data_device_manager_get_data_device, }; +static void data_device_manager_handle_resource_destroy( + struct wl_resource *resource) { + wl_list_remove(wl_resource_get_link(resource)); +} + static void data_device_manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) { + struct wlr_data_device_manager *manager = data; + struct wl_resource *resource = wl_resource_create(client, &wl_data_device_manager_interface, version, id); @@ -202,18 +224,26 @@ static void data_device_manager_bind(struct wl_client *client, wl_client_post_no_memory(client); return; } - wl_resource_set_implementation(resource, &data_device_manager_impl, - NULL, NULL); + manager, data_device_manager_handle_resource_destroy); + + wl_list_insert(&manager->wl_resources, wl_resource_get_link(resource)); } void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) { if (!manager) { return; } + wlr_signal_emit_safe(&manager->events.destroy, manager); wl_list_remove(&manager->display_destroy.link); - // TODO: free wl_resources wl_global_destroy(manager->global); + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe(resource, tmp, &manager->wl_resources) { + wl_resource_destroy(resource); + } + wl_resource_for_each_safe(resource, tmp, &manager->data_sources) { + wl_resource_destroy(resource); + } free(manager); } @@ -232,11 +262,15 @@ struct wlr_data_device_manager *wlr_data_device_manager_create( return NULL; } + wl_list_init(&manager->wl_resources); + wl_list_init(&manager->data_sources); + wl_signal_init(&manager->events.destroy); + manager->global = wl_global_create(display, &wl_data_device_manager_interface, - 3, NULL, data_device_manager_bind); + DATA_DEVICE_MANAGER_VERSION, manager, data_device_manager_bind); if (!manager->global) { - wlr_log(L_ERROR, "could not create data device manager wl global"); + wlr_log(L_ERROR, "could not create data device manager wl_global"); free(manager); return NULL; } diff --git a/types/data_device/wlr_data_offer.c b/types/data_device/wlr_data_offer.c index dfaf054c..a5ea9183 100644 --- a/types/data_device/wlr_data_offer.c +++ b/types/data_device/wlr_data_offer.c @@ -145,7 +145,7 @@ static void data_offer_set_actions(struct wl_client *client, data_offer_update_action(offer); } -static void data_offer_resource_destroy(struct wl_resource *resource) { +static void data_offer_handle_resource_destroy(struct wl_resource *resource) { struct wlr_data_offer *offer = data_offer_from_resource(resource); if (!offer->source) { @@ -208,7 +208,7 @@ struct wlr_data_offer *data_offer_create(struct wl_client *client, return NULL; } wl_resource_set_implementation(offer->resource, &data_offer_impl, offer, - data_offer_resource_destroy); + data_offer_handle_resource_destroy); offer->source_destroy.notify = handle_offer_source_destroyed; wl_signal_add(&source->events.destroy, &offer->source_destroy); diff --git a/types/data_device/wlr_data_source.c b/types/data_device/wlr_data_source.c index 7c554d35..bf638f5a 100644 --- a/types/data_device/wlr_data_source.c +++ b/types/data_device/wlr_data_source.c @@ -245,11 +245,13 @@ static void data_source_handle_resource_destroy(struct wl_resource *resource) { struct wlr_client_data_source *source = client_data_source_from_resource(resource); wlr_data_source_finish(&source->source); + wl_list_remove(wl_resource_get_link(source->resource)); free(source); } struct wlr_client_data_source *client_data_source_create( - struct wl_client *client, uint32_t version, uint32_t id) { + struct wl_client *client, uint32_t version, uint32_t id, + struct wl_list *resource_list) { struct wlr_client_data_source *source = calloc(1, sizeof(struct wlr_client_data_source)); if (source == NULL) { @@ -265,6 +267,7 @@ struct wlr_client_data_source *client_data_source_create( } wl_resource_set_implementation(source->resource, &data_source_impl, source, data_source_handle_resource_destroy); + wl_list_insert(resource_list, wl_resource_get_link(source->resource)); source->impl.accept = client_data_source_accept; source->impl.send = client_data_source_send;