diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index b1364e8c6..69f610217 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -1021,6 +1021,12 @@ xdg_popup_destructor (struct wl_resource *resource) { MetaWaylandSurface *surface = wl_resource_get_user_data (resource); + if (surface->popup.parent) + { + wl_list_remove (&surface->popup.parent_destroy_listener.link); + surface->popup.parent = NULL; + } + if (surface->popup.popup) meta_wayland_popup_dismiss (surface->popup.popup); @@ -1038,6 +1044,20 @@ static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = { xdg_popup_destroy, }; +static void +handle_popup_parent_destroyed (struct wl_listener *listener, void *data) +{ + MetaWaylandSurface *surface = + wl_container_of (listener, surface, popup.parent_destroy_listener); + + wl_resource_post_error (surface->xdg_popup, + XDG_POPUP_ERROR_NOT_THE_TOPMOST_POPUP, + "destroyed popup not top most popup"); + surface->popup.parent = NULL; + + destroy_window (surface); +} + static void handle_popup_destroyed (struct wl_listener *listener, void *data) { @@ -1130,6 +1150,11 @@ xdg_shell_get_xdg_popup (struct wl_client *client, surface->xdg_popup = popup_resource; surface->xdg_shell_resource = resource; + surface->popup.parent = parent_surf; + surface->popup.parent_destroy_listener.notify = handle_popup_parent_destroyed; + wl_resource_add_destroy_listener (parent_surf->resource, + &surface->popup.parent_destroy_listener); + window = meta_window_wayland_new (display, surface); meta_window_move_frame (window, FALSE, parent_surf->window->rect.x + x, diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 0f13dfd16..9f8b9de1a 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -102,8 +102,11 @@ struct _MetaWaylandSurface /* xdg_popup */ struct { - MetaWaylandPopup *popup; - struct wl_listener destroy_listener; + MetaWaylandSurface *parent; + struct wl_listener parent_destroy_listener; + + MetaWaylandPopup *popup; + struct wl_listener destroy_listener; } popup; /* wl_subsurface stuff. */