diff --git a/include/layers.h b/include/layers.h index 489bf9e2..6f98d41d 100644 --- a/include/layers.h +++ b/include/layers.h @@ -11,6 +11,8 @@ struct seat; struct lab_layer_surface { struct wlr_scene_layer_surface_v1 *scene_layer_surface; struct server *server; + struct output *output; + struct wlr_scene_tree *tree; bool mapped; diff --git a/src/layers.c b/src/layers.c index 9583b7f7..e52ea3c4 100644 --- a/src/layers.c +++ b/src/layers.c @@ -45,6 +45,13 @@ arrange_one_layer(const struct wlr_box *full_area, struct wlr_box *usable_area, { struct wlr_scene_node *node; wl_list_for_each(node, &tree->children, link) { + /* + * Could be null during destruction when called from + * handle_node_destroy() + */ + if (!node->data) { + continue; + } struct lab_layer_surface *surface = node_layer_surface_from_node(node); struct wlr_scene_layer_surface_v1 *scene = surface->scene_layer_surface; if (!scene->layer_surface->initialized) { @@ -119,6 +126,7 @@ handle_output_destroy(struct wl_listener *listener, void *data) struct lab_layer_surface *layer = wl_container_of(listener, layer, output_destroy); layer->scene_layer_surface->layer_surface->output = NULL; + layer->output = NULL; wlr_layer_surface_v1_destroy(layer->scene_layer_surface->layer_surface); } @@ -312,6 +320,16 @@ handle_node_destroy(struct wl_listener *listener, void *data) * focus to. */ + /* + * Nullify node descriptor early to avoid functions such as + * arrange_one_layer() trying to dereference it. + */ + layer->tree->node.data = NULL; + + if (layer->output) { + output_update_usable_area(layer->output); + } + wl_list_remove(&layer->map.link); wl_list_remove(&layer->unmap.link); wl_list_remove(&layer->surface_commit.link); @@ -327,9 +345,6 @@ handle_unmap(struct wl_listener *listener, void *data) struct lab_layer_surface *layer = wl_container_of(listener, layer, unmap); struct wlr_layer_surface_v1 *layer_surface = layer->scene_layer_surface->layer_surface; - if (layer_surface->output) { - output_update_usable_area(layer_surface->output->data); - } struct seat *seat = &layer->server->seat; if (seat->focused_layer == layer_surface) { try_to_focus_next_layer_or_toplevel(layer->server); @@ -552,6 +567,7 @@ handle_new_layer_surface(struct wl_listener *listener, void *data) struct lab_layer_surface *surface = znew(*surface); struct output *output = layer_surface->output->data; + surface->output = output; wlr_fractional_scale_v1_notify_scale(layer_surface->surface, output->wlr_output->scale); @@ -566,6 +582,7 @@ handle_new_layer_surface(struct wl_listener *listener, void *data) wlr_log(WLR_ERROR, "could not create layer surface"); return; } + surface->tree = surface->scene_layer_surface->tree; /* In support of IME popup */ layer_surface->surface->data = surface->scene_layer_surface->tree; diff --git a/src/node.c b/src/node.c index 328c0eb9..e60c13eb 100644 --- a/src/node.c +++ b/src/node.c @@ -11,7 +11,7 @@ descriptor_destroy(struct node_descriptor *node_descriptor) return; } wl_list_remove(&node_descriptor->destroy.link); - free(node_descriptor); + zfree(node_descriptor); } static void