diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c index 98f26fc6c..6afac865b 100644 --- a/src/compositor/meta-window-actor-wayland.c +++ b/src/compositor/meta-window-actor-wayland.c @@ -144,10 +144,33 @@ meta_window_actor_wayland_update_regions (MetaWindowActor *actor) { } +static void +meta_window_actor_wayland_dispose (GObject *object) +{ + MetaWindowActor *window_actor = META_WINDOW_ACTOR (object); + MetaSurfaceActor *surface_actor = + meta_window_actor_get_surface (window_actor); + GList *children; + GList *l; + + children = clutter_actor_get_children (CLUTTER_ACTOR (window_actor)); + for (l = children; l; l = l->next) + { + ClutterActor *child_actor = l->data; + + if (META_IS_SURFACE_ACTOR_WAYLAND (child_actor) && + child_actor != CLUTTER_ACTOR (surface_actor)) + clutter_actor_remove_child (CLUTTER_ACTOR (window_actor), child_actor); + } + + G_OBJECT_CLASS (meta_window_actor_wayland_parent_class)->dispose (object); +} + static void meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass) { MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor; window_actor_class->frame_complete = meta_window_actor_wayland_frame_complete; @@ -157,6 +180,8 @@ meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass) window_actor_class->queue_destroy = meta_window_actor_wayland_queue_destroy; window_actor_class->set_frozen = meta_window_actor_wayland_set_frozen; window_actor_class->update_regions = meta_window_actor_wayland_update_regions; + + object_class->dispose = meta_window_actor_wayland_dispose; } static void diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c index 24d5c0a53..542d97ca1 100644 --- a/src/wayland/meta-wayland-subsurface.c +++ b/src/wayland/meta-wayland-subsurface.c @@ -292,7 +292,8 @@ unparent_actor (MetaWaylandSurface *surface) return; parent_actor = clutter_actor_get_parent (actor); - clutter_actor_remove_child (parent_actor, actor); + if (parent_actor) + clutter_actor_remove_child (parent_actor, actor); } static void @@ -490,6 +491,7 @@ surface_handle_parent_surface_destroyed (struct wl_listener *listener, surface, sub.parent_destroy_listener); + g_node_unlink (surface->subsurface_branch_node); surface->sub.parent = NULL; } diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index ca6bd98cd..13d0f9184 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -1328,13 +1328,6 @@ meta_wayland_surface_notify_unmapped (MetaWaylandSurface *surface) g_signal_emit (surface, surface_signals[SURFACE_UNMAPPED], 0); } -static void -unlink_note (GNode *node, - gpointer data) -{ - g_node_unlink (node); -} - static void wl_surface_destructor (struct wl_resource *resource) { @@ -1383,14 +1376,7 @@ wl_surface_destructor (struct wl_resource *resource) if (surface->wl_subsurface) wl_resource_destroy (surface->wl_subsurface); - if (surface->subsurface_branch_node) - { - g_node_children_foreach (surface->subsurface_branch_node, - G_TRAVERSE_NON_LEAVES, - unlink_note, - NULL); - g_clear_pointer (&surface->subsurface_branch_node, g_node_destroy); - } + g_clear_pointer (&surface->subsurface_branch_node, g_node_destroy); g_hash_table_destroy (surface->shortcut_inhibited_seats); diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index 1319c74e3..b87cb9aee 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -185,6 +185,12 @@ surface_from_xdg_toplevel_resource (struct wl_resource *resource) return surface_from_xdg_surface_resource (resource); } +static MetaWaylandXdgPopup * +meta_wayland_xdg_popup_from_surface (MetaWaylandSurface *surface) +{ + return META_WAYLAND_XDG_POPUP (surface->role); +} + static void meta_wayland_xdg_surface_reset (MetaWaylandXdgSurface *xdg_surface) { @@ -1059,6 +1065,7 @@ finish_popup_setup (MetaWaylandXdgPopup *xdg_popup) xdg_popup->setup.parent_surface = NULL; xdg_popup->setup.grab_seat = NULL; + xdg_popup->dismissed_by_client = FALSE; if (!meta_wayland_surface_get_window (parent_surface)) { @@ -1128,6 +1135,37 @@ finish_popup_setup (MetaWaylandXdgPopup *xdg_popup) } } +static void +dismiss_invalid_popup (MetaWaylandXdgPopup *xdg_popup) +{ + if (xdg_popup->popup) + { + while (TRUE) + { + MetaWaylandSurface *top_popup_surface; + MetaWaylandXdgPopup *top_xdg_popup; + + top_popup_surface = + meta_wayland_popup_get_top_popup (xdg_popup->popup); + if (!top_popup_surface) + break; + + top_xdg_popup = meta_wayland_xdg_popup_from_surface (top_popup_surface); + + xdg_popup_send_popup_done (top_xdg_popup->resource); + meta_wayland_popup_destroy (top_xdg_popup->popup); + + if (top_xdg_popup == xdg_popup) + break; + } + } + else + { + xdg_popup_send_popup_done (xdg_popup->resource); + meta_wayland_xdg_popup_unmap (xdg_popup); + } +} + static void meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role, MetaWaylandSurfaceState *pending) @@ -1208,7 +1246,7 @@ meta_wayland_xdg_popup_post_apply_state (MetaWaylandSurfaceRole *surface_role, { g_warning ("Buggy client caused popup to be placed outside of " "parent window"); - dismiss_popup (xdg_popup); + dismiss_invalid_popup (xdg_popup); } } @@ -1248,6 +1286,9 @@ meta_wayland_xdg_popup_configure (MetaWaylandShellSurface *shell_surface, int geometry_scale; int x, y; + if (!xdg_popup->resource) + return; + /* If the parent surface was destroyed, its window will be destroyed * before the popup receives the parent-destroy signal. This means that * the popup may potentially get temporary focus until itself is destroyed.