From fb8e59dd4b505dee7bba2a4a2ff6d6a97988b7f6 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Wed, 18 Jun 2025 17:40:04 +0200 Subject: [PATCH] Destroy xdg_popups when its parent is destroyed Backport of 30248e1ba3b651b70f9cf525945e084fd88bfae4 --- include/layers.h | 1 + src/layers.c | 23 +++++++++++++++++++++++ src/xdg-popup.c | 6 ++++++ src/xdg.c | 5 +++++ 4 files changed, 35 insertions(+) diff --git a/include/layers.h b/include/layers.h index 489bf9e2..a47d916e 100644 --- a/include/layers.h +++ b/include/layers.h @@ -9,6 +9,7 @@ struct output; struct seat; struct lab_layer_surface { + struct wlr_layer_surface_v1 *layer_surface; struct wlr_scene_layer_surface_v1 *scene_layer_surface; struct server *server; diff --git a/src/layers.c b/src/layers.c index 9b4dcdc8..4072bc7e 100644 --- a/src/layers.c +++ b/src/layers.c @@ -302,6 +302,22 @@ handle_node_destroy(struct wl_listener *listener, void *data) { struct lab_layer_surface *layer = wl_container_of(listener, layer, node_destroy); + + /* + * Important: + * + * We can no longer access layer->scene_layer_surface anymore + * because it has already been free'd by wlroots. + * Set it to NULL to run into a proper crash rather than accessing + * random free'd memory. + */ + layer->scene_layer_surface = NULL; + + struct wlr_xdg_popup *popup, *tmp; + wl_list_for_each_safe(popup, tmp, &layer->layer_surface->popups, link) { + wlr_xdg_popup_destroy(popup); + } + /* * TODO: Determine if this layer is being used by an exclusive client. * If it is, try and find another layer owned by this client to pass @@ -358,6 +374,12 @@ popup_handle_destroy(struct wl_listener *listener, void *data) { struct lab_layer_popup *popup = wl_container_of(listener, popup, destroy); + + struct wlr_xdg_popup *_popup, *tmp; + wl_list_for_each_safe(_popup, tmp, &popup->wlr_popup->base->popups, link) { + wlr_xdg_popup_destroy(_popup); + } + wl_list_remove(&popup->destroy.link); wl_list_remove(&popup->new_popup.link); wl_list_remove(&popup->reposition.link); @@ -546,6 +568,7 @@ handle_new_layer_surface(struct wl_listener *listener, void *data) } struct lab_layer_surface *surface = znew(*surface); + surface->layer_surface = layer_surface; struct output *output = layer_surface->output->data; diff --git a/src/xdg-popup.c b/src/xdg-popup.c index 454bfead..ee71d608 100644 --- a/src/xdg-popup.c +++ b/src/xdg-popup.c @@ -73,6 +73,12 @@ static void handle_xdg_popup_destroy(struct wl_listener *listener, void *data) { struct xdg_popup *popup = wl_container_of(listener, popup, destroy); + + struct wlr_xdg_popup *_popup, *tmp; + wl_list_for_each_safe(_popup, tmp, &popup->wlr_popup->base->popups, link) { + wlr_xdg_popup_destroy(_popup); + } + wl_list_remove(&popup->destroy.link); wl_list_remove(&popup->new_popup.link); wl_list_remove(&popup->reposition.link); diff --git a/src/xdg.c b/src/xdg.c index 5bb8fa17..f7969b9c 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -326,6 +326,11 @@ handle_destroy(struct wl_listener *listener, void *data) struct xdg_toplevel_view *xdg_toplevel_view = xdg_toplevel_view_from_view(view); + struct wlr_xdg_popup *popup, *tmp; + wl_list_for_each_safe(popup, tmp, &xdg_toplevel_view->xdg_surface->popups, link) { + wlr_xdg_popup_destroy(popup); + } + xdg_toplevel_view->xdg_surface->data = NULL; xdg_toplevel_view->xdg_surface = NULL;