data-device: make sure resources are correctly destroyed

This commit is contained in:
emersion 2018-05-03 20:22:51 +01:00
parent 7843a48432
commit 5d37b14116
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
5 changed files with 59 additions and 13 deletions

View file

@ -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); void data_offer_update_action(struct wlr_data_offer *offer);
struct wlr_client_data_source *client_data_source_create( 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 wlr_client_data_source *client_data_source_from_resource(
struct wl_resource *resource); struct wl_resource *resource);
struct wlr_data_offer *data_source_send_offer(struct wlr_data_source *source, struct wlr_data_offer *data_source_send_offer(struct wlr_data_source *source,

View file

@ -15,8 +15,16 @@ wlr_touch_grab_interface wlr_data_device_touch_drag_interface;
struct wlr_data_device_manager { struct wlr_data_device_manager {
struct wl_global *global; struct wl_global *global;
struct wl_list wl_resources;
struct wl_list data_sources;
struct wl_listener display_destroy; struct wl_listener display_destroy;
struct {
struct wl_signal destroy;
} events;
void *data;
}; };
struct wlr_data_offer { struct wlr_data_offer {

View file

@ -11,6 +11,8 @@
#include "types/wlr_data_device.h" #include "types/wlr_data_device.h"
#include "util/signal.h" #include "util/signal.h"
#define DATA_DEVICE_MANAGER_VERSION 3
static const struct wl_data_device_interface data_device_impl; static const struct wl_data_device_interface data_device_impl;
static struct wlr_seat_client *seat_client_from_data_device_resource( 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, .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)); 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, static void data_device_manager_get_data_device(struct wl_client *client,
struct wl_resource *manager_resource, uint32_t id, struct wl_resource *manager_resource, uint32_t id,
struct wl_resource *seat_resource) { struct wl_resource *seat_resource) {
@ -178,13 +189,17 @@ static void data_device_manager_get_data_device(struct wl_client *client,
return; return;
} }
wl_resource_set_implementation(resource, &data_device_impl, seat_client, 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)); wl_list_insert(&seat_client->data_devices, wl_resource_get_link(resource));
} }
static void data_device_manager_create_data_source(struct wl_client *client, static void data_device_manager_create_data_source(struct wl_client *client,
struct wl_resource *resource, uint32_t id) { struct wl_resource *manager_resource, uint32_t id) {
client_data_source_create(client, wl_resource_get_version(resource), 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 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, .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, static void data_device_manager_bind(struct wl_client *client,
void *data, uint32_t version, uint32_t id) { void *data, uint32_t version, uint32_t id) {
struct wlr_data_device_manager *manager = data;
struct wl_resource *resource = wl_resource_create(client, struct wl_resource *resource = wl_resource_create(client,
&wl_data_device_manager_interface, &wl_data_device_manager_interface,
version, id); version, id);
@ -202,18 +224,26 @@ static void data_device_manager_bind(struct wl_client *client,
wl_client_post_no_memory(client); wl_client_post_no_memory(client);
return; return;
} }
wl_resource_set_implementation(resource, &data_device_manager_impl, 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) { void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) {
if (!manager) { if (!manager) {
return; return;
} }
wlr_signal_emit_safe(&manager->events.destroy, manager);
wl_list_remove(&manager->display_destroy.link); wl_list_remove(&manager->display_destroy.link);
// TODO: free wl_resources
wl_global_destroy(manager->global); 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); free(manager);
} }
@ -232,11 +262,15 @@ struct wlr_data_device_manager *wlr_data_device_manager_create(
return NULL; return NULL;
} }
wl_list_init(&manager->wl_resources);
wl_list_init(&manager->data_sources);
wl_signal_init(&manager->events.destroy);
manager->global = manager->global =
wl_global_create(display, &wl_data_device_manager_interface, 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) { 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); free(manager);
return NULL; return NULL;
} }

View file

@ -145,7 +145,7 @@ static void data_offer_set_actions(struct wl_client *client,
data_offer_update_action(offer); 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); struct wlr_data_offer *offer = data_offer_from_resource(resource);
if (!offer->source) { if (!offer->source) {
@ -208,7 +208,7 @@ struct wlr_data_offer *data_offer_create(struct wl_client *client,
return NULL; return NULL;
} }
wl_resource_set_implementation(offer->resource, &data_offer_impl, offer, 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; offer->source_destroy.notify = handle_offer_source_destroyed;
wl_signal_add(&source->events.destroy, &offer->source_destroy); wl_signal_add(&source->events.destroy, &offer->source_destroy);

View file

@ -245,11 +245,13 @@ static void data_source_handle_resource_destroy(struct wl_resource *resource) {
struct wlr_client_data_source *source = struct wlr_client_data_source *source =
client_data_source_from_resource(resource); client_data_source_from_resource(resource);
wlr_data_source_finish(&source->source); wlr_data_source_finish(&source->source);
wl_list_remove(wl_resource_get_link(source->resource));
free(source); free(source);
} }
struct wlr_client_data_source *client_data_source_create( 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 = struct wlr_client_data_source *source =
calloc(1, sizeof(struct wlr_client_data_source)); calloc(1, sizeof(struct wlr_client_data_source));
if (source == NULL) { 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, wl_resource_set_implementation(source->resource, &data_source_impl,
source, data_source_handle_resource_destroy); 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.accept = client_data_source_accept;
source->impl.send = client_data_source_send; source->impl.send = client_data_source_send;