Destroy xdg_popups when its parent is destroyed

Fixes: #2845
This commit is contained in:
Consolatis 2025-06-18 17:40:04 +02:00 committed by Johan Malm
parent a8df2487b2
commit 30248e1ba3
4 changed files with 35 additions and 0 deletions

View file

@ -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;
struct output *output;

View file

@ -314,6 +314,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
@ -377,6 +393,12 @@ handle_popup_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);
@ -565,6 +587,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;
surface->output = output;

View file

@ -73,6 +73,12 @@ static void
handle_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);

View file

@ -345,6 +345,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;