From 31d78ff497865f5b0442f14adeac8987e1b7273d Mon Sep 17 00:00:00 2001 From: nyorain Date: Thu, 10 Aug 2017 12:42:35 +0200 Subject: [PATCH] Fix wlr_surface destruction bug --- examples/compositor.h | 4 ++++ examples/compositor/wl_compositor.c | 11 ++++++----- include/wlr/types/wlr_surface.h | 6 ++++-- types/wlr_surface.c | 5 ++--- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/examples/compositor.h b/examples/compositor.h index 4649a8d3..2847808f 100644 --- a/examples/compositor.h +++ b/examples/compositor.h @@ -14,6 +14,10 @@ struct wl_compositor_state { void wl_compositor_init(struct wl_display *display, struct wl_compositor_state *state, struct wlr_renderer *renderer); +struct wlr_surface; +void wl_compositor_surface_destroyed(struct wl_compositor_state *compositor, + struct wlr_surface *surface); + struct wl_shell_state { struct wl_global *wl_global; struct wl_list wl_resources; diff --git a/examples/compositor/wl_compositor.c b/examples/compositor/wl_compositor.c index 89d23d6a..66c069ba 100644 --- a/examples/compositor/wl_compositor.c +++ b/examples/compositor/wl_compositor.c @@ -6,9 +6,8 @@ #include "compositor.h" static void destroy_surface_listener(struct wl_listener *listener, void *data) { - struct wl_compositor_state *state; - struct wlr_surface *surface = data; - state = wl_container_of(listener, state, destroy_surface_listener); + struct wlr_surface *surface = wl_resource_get_user_data(data); + struct wl_compositor_state *state = surface->compositor_data; struct wl_resource *res = NULL; wl_list_for_each(res, &state->surfaces, link) { @@ -25,8 +24,11 @@ static void wl_compositor_create_surface(struct wl_client *client, struct wl_resource *surface_resource = wl_resource_create(client, &wl_surface_interface, wl_resource_get_version(resource), id); struct wlr_surface *surface = wlr_surface_create(surface_resource, state->renderer); + surface->compositor_data = state; + surface->compositor_listener.notify = &destroy_surface_listener; + wl_resource_add_destroy_listener(surface_resource, &surface->compositor_listener); + wl_list_insert(&state->surfaces, wl_resource_get_link(surface_resource)); - wl_signal_add(&surface->signals.destroy, &state->destroy_surface_listener); } static void wl_compositor_create_region(struct wl_client *client, @@ -73,7 +75,6 @@ void wl_compositor_init(struct wl_display *display, &wl_compositor_interface, 4, state, wl_compositor_bind); state->wl_global = wl_global; state->renderer = renderer; - state->destroy_surface_listener.notify = destroy_surface_listener; wl_list_init(&state->wl_resources); wl_list_init(&state->surfaces); } diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index b80b1de4..a195798f 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -37,15 +37,17 @@ struct wlr_surface { float surface_to_buffer_matrix[16]; struct { - struct wl_signal destroy; struct wl_signal commit; } signals; struct wl_list frame_callback_list; // wl_surface.frame + + struct wl_listener compositor_listener; // destroy listener used by compositor + void *compositor_data; }; struct wlr_renderer; struct wlr_surface *wlr_surface_create(struct wl_resource *res, - struct wlr_renderer *renderer); + struct wlr_renderer *renderer); #endif diff --git a/types/wlr_surface.c b/types/wlr_surface.c index d20436ef..ff83db83 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -161,13 +161,13 @@ const struct wl_surface_interface surface_interface = { static void destroy_surface(struct wl_resource *resource) { struct wlr_surface *surface = wl_resource_get_user_data(resource); - wl_signal_emit(&surface->signals.destroy, surface); - wlr_texture_destroy(surface->texture); + wlr_texture_destroy(surface->texture); struct wlr_frame_callback *cb, *next; wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link) { wl_resource_destroy(cb->resource); } + free(surface); } @@ -177,7 +177,6 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res, surface->texture = wlr_render_texture_init(renderer); surface->resource = res; wl_signal_init(&surface->signals.commit); - wl_signal_init(&surface->signals.destroy); wl_list_init(&surface->frame_callback_list); wl_resource_set_implementation(res, &surface_interface, surface, destroy_surface);