layers: ignore destroyed layers

Fixes: #2858
This commit is contained in:
Consolatis 2025-06-26 17:31:55 +02:00
parent e5a236eef4
commit f3910746ba
4 changed files with 35 additions and 5 deletions

View file

@ -124,6 +124,9 @@ get_special(struct server *server, struct wlr_scene_node *node)
return "output->layer_popup_tree"; return "output->layer_popup_tree";
} }
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (!output->layer_tree[i]) {
continue;
}
if (node == &output->layer_tree[i]->node) { if (node == &output->layer_tree[i]->node) {
return get_layer_name(i); return get_layer_name(i);
} }

View file

@ -215,7 +215,9 @@ desktop_update_top_layer_visibility(struct server *server)
if (!output_is_usable(output)) { if (!output_is_usable(output)) {
continue; continue;
} }
wlr_scene_node_set_enabled(&output->layer_tree[top]->node, true); if (output->layer_tree[top]) {
wlr_scene_node_set_enabled(&output->layer_tree[top]->node, true);
}
} }
/* /*
@ -231,8 +233,10 @@ desktop_update_top_layer_visibility(struct server *server)
continue; continue;
} }
if (view->fullscreen && !(view->outputs & outputs_covered)) { if (view->fullscreen && !(view->outputs & outputs_covered)) {
wlr_scene_node_set_enabled( if (output->layer_tree[top]) {
&view->output->layer_tree[top]->node, false); wlr_scene_node_set_enabled(
&view->output->layer_tree[top]->node, false);
}
} }
outputs_covered |= view->outputs; outputs_covered |= view->outputs;
} }

View file

@ -43,6 +43,8 @@ static void
arrange_one_layer(const struct wlr_box *full_area, struct wlr_box *usable_area, arrange_one_layer(const struct wlr_box *full_area, struct wlr_box *usable_area,
struct wlr_scene_tree *tree, bool exclusive) struct wlr_scene_tree *tree, bool exclusive)
{ {
assert(tree);
struct wlr_scene_node *node; struct wlr_scene_node *node;
wl_list_for_each(node, &tree->children, link) { wl_list_for_each(node, &tree->children, link) {
/* /*
@ -90,6 +92,10 @@ layers_arrange(struct output *output)
for (int i = ARRAY_SIZE(output->layer_tree) - 1; i >= 0; i--) { for (int i = ARRAY_SIZE(output->layer_tree) - 1; i >= 0; i--) {
struct wlr_scene_tree *layer = output->layer_tree[i]; struct wlr_scene_tree *layer = output->layer_tree[i];
if (!layer) {
/* Might happen on output destroy */
continue;
}
/* /*
* Process exclusive-zone clients before non-exclusive-zone * Process exclusive-zone clients before non-exclusive-zone
@ -110,6 +116,10 @@ layers_arrange(struct output *output)
for (size_t i = 0; i < ARRAY_SIZE(output->layer_tree); i++) { for (size_t i = 0; i < ARRAY_SIZE(output->layer_tree); i++) {
struct wlr_scene_tree *layer = output->layer_tree[i]; struct wlr_scene_tree *layer = output->layer_tree[i];
if (!layer) {
/* Might happen on output destroy */
continue;
}
arrange_one_layer(&full_area, &usable_area, layer, /* exclusive */ false); arrange_one_layer(&full_area, &usable_area, layer, /* exclusive */ false);
/* Set node position to account for output layout change */ /* Set node position to account for output layout change */
@ -156,6 +166,10 @@ try_to_focus_next_layer_or_toplevel(struct server *server)
enum zwlr_layer_shell_v1_layer top = ZWLR_LAYER_SHELL_V1_LAYER_TOP; enum zwlr_layer_shell_v1_layer top = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
for (size_t i = overlay; i >= top; i--) { for (size_t i = overlay; i >= top; i--) {
struct wlr_scene_tree *tree = output->layer_tree[i]; struct wlr_scene_tree *tree = output->layer_tree[i];
if (!tree) {
/* Might happen on output destroy */
continue;
}
struct wlr_scene_node *node; struct wlr_scene_node *node;
/* /*
* In wlr_scene.c they were added at end of list so we * In wlr_scene.c they were added at end of list so we
@ -270,8 +284,11 @@ handle_surface_commit(struct wl_listener *listener, void *data)
/* Process layer change */ /* Process layer change */
if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) { if (committed & WLR_LAYER_SURFACE_V1_STATE_LAYER) {
wlr_scene_node_reparent(&layer->scene_layer_surface->tree->node, if (output->layer_tree[layer_surface->current.layer]) {
output->layer_tree[layer_surface->current.layer]); /* Might happen on output destroy */
wlr_scene_node_reparent(&layer->scene_layer_surface->tree->node,
output->layer_tree[layer_surface->current.layer]);
}
} }
/* Process keyboard-interactivity change */ /* Process keyboard-interactivity change */
if (committed & WLR_LAYER_SURFACE_V1_STATE_KEYBOARD_INTERACTIVITY) { if (committed & WLR_LAYER_SURFACE_V1_STATE_KEYBOARD_INTERACTIVITY) {
@ -597,6 +614,11 @@ handle_new_layer_surface(struct wl_listener *listener, void *data)
struct wlr_scene_tree *selected_layer = struct wlr_scene_tree *selected_layer =
output->layer_tree[layer_surface->current.layer]; output->layer_tree[layer_surface->current.layer];
if (!selected_layer) {
wlr_layer_surface_v1_destroy(layer_surface);
wlr_log(WLR_ERROR, "Targeted output by layer surface destroyed");
return;
}
surface->scene_layer_surface = wlr_scene_layer_surface_v1_create( surface->scene_layer_surface = wlr_scene_layer_surface_v1_create(
selected_layer, layer_surface); selected_layer, layer_surface);

View file

@ -175,6 +175,7 @@ output_destroy_notify(struct wl_listener *listener, void *data)
for (size_t i = 0; i < ARRAY_SIZE(output->layer_tree); i++) { for (size_t i = 0; i < ARRAY_SIZE(output->layer_tree); i++) {
wlr_scene_node_destroy(&output->layer_tree[i]->node); wlr_scene_node_destroy(&output->layer_tree[i]->node);
output->layer_tree[i] = NULL;
} }
wlr_scene_node_destroy(&output->layer_popup_tree->node); wlr_scene_node_destroy(&output->layer_popup_tree->node);
wlr_scene_node_destroy(&output->osd_tree->node); wlr_scene_node_destroy(&output->osd_tree->node);