Fix wlr_surface destruction bug

This commit is contained in:
nyorain 2017-08-10 12:42:35 +02:00
parent 073dff63da
commit 31d78ff497
4 changed files with 16 additions and 10 deletions

View file

@ -14,6 +14,10 @@ struct wl_compositor_state {
void wl_compositor_init(struct wl_display *display, void wl_compositor_init(struct wl_display *display,
struct wl_compositor_state *state, struct wlr_renderer *renderer); 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_shell_state {
struct wl_global *wl_global; struct wl_global *wl_global;
struct wl_list wl_resources; struct wl_list wl_resources;

View file

@ -6,9 +6,8 @@
#include "compositor.h" #include "compositor.h"
static void destroy_surface_listener(struct wl_listener *listener, void *data) { static void destroy_surface_listener(struct wl_listener *listener, void *data) {
struct wl_compositor_state *state; struct wlr_surface *surface = wl_resource_get_user_data(data);
struct wlr_surface *surface = data; struct wl_compositor_state *state = surface->compositor_data;
state = wl_container_of(listener, state, destroy_surface_listener);
struct wl_resource *res = NULL; struct wl_resource *res = NULL;
wl_list_for_each(res, &state->surfaces, link) { 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, struct wl_resource *surface_resource = wl_resource_create(client,
&wl_surface_interface, wl_resource_get_version(resource), id); &wl_surface_interface, wl_resource_get_version(resource), id);
struct wlr_surface *surface = wlr_surface_create(surface_resource, state->renderer); 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_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, 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); &wl_compositor_interface, 4, state, wl_compositor_bind);
state->wl_global = wl_global; state->wl_global = wl_global;
state->renderer = renderer; state->renderer = renderer;
state->destroy_surface_listener.notify = destroy_surface_listener;
wl_list_init(&state->wl_resources); wl_list_init(&state->wl_resources);
wl_list_init(&state->surfaces); wl_list_init(&state->surfaces);
} }

View file

@ -37,15 +37,17 @@ struct wlr_surface {
float surface_to_buffer_matrix[16]; float surface_to_buffer_matrix[16];
struct { struct {
struct wl_signal destroy;
struct wl_signal commit; struct wl_signal commit;
} signals; } signals;
struct wl_list frame_callback_list; // wl_surface.frame 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_renderer;
struct wlr_surface *wlr_surface_create(struct wl_resource *res, struct wlr_surface *wlr_surface_create(struct wl_resource *res,
struct wlr_renderer *renderer); struct wlr_renderer *renderer);
#endif #endif

View file

@ -161,13 +161,13 @@ const struct wl_surface_interface surface_interface = {
static void destroy_surface(struct wl_resource *resource) { static void destroy_surface(struct wl_resource *resource) {
struct wlr_surface *surface = wl_resource_get_user_data(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; struct wlr_frame_callback *cb, *next;
wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link) { wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link) {
wl_resource_destroy(cb->resource); wl_resource_destroy(cb->resource);
} }
free(surface); free(surface);
} }
@ -177,7 +177,6 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
surface->texture = wlr_render_texture_init(renderer); surface->texture = wlr_render_texture_init(renderer);
surface->resource = res; surface->resource = res;
wl_signal_init(&surface->signals.commit); wl_signal_init(&surface->signals.commit);
wl_signal_init(&surface->signals.destroy);
wl_list_init(&surface->frame_callback_list); wl_list_init(&surface->frame_callback_list);
wl_resource_set_implementation(res, &surface_interface, wl_resource_set_implementation(res, &surface_interface,
surface, destroy_surface); surface, destroy_surface);