From 2888dbf597a77224e623fd7ddabd2088738e769c Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Tue, 10 Oct 2023 21:51:58 +0100 Subject: [PATCH] layers: arrange layers on destroy ...rather than unmap because that is the approach of sway and it also avoids wshowkeys crashing. Fixes: #1153 --- include/layers.h | 2 ++ src/layers.c | 23 ++++++++++++++++++++--- src/node.c | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/layers.h b/include/layers.h index d64c434f..6d76f859 100644 --- a/include/layers.h +++ b/include/layers.h @@ -10,6 +10,8 @@ struct output; 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 f812a016..6e3b7b55 100644 --- a/src/layers.c +++ b/src/layers.c @@ -43,6 +43,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->current.exclusive_zone != exclusive) { @@ -101,6 +108,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); } @@ -196,6 +204,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); @@ -211,9 +229,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) { seat_set_focus_layer(seat, NULL); @@ -376,6 +391,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; struct wlr_scene_tree *selected_layer = output->layer_tree[layer_surface->current.layer]; @@ -387,6 +403,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; node_descriptor_create(&surface->scene_layer_surface->tree->node, LAB_NODE_DESC_LAYER_SURFACE, surface); diff --git a/src/node.c b/src/node.c index 84ca3f6c..daae6d46 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