From eb17ee1c26bb5faf08d50264dbe5fcfc79e0666c Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Mon, 5 Sep 2016 17:53:38 +0200 Subject: [PATCH] wayland: unmap popup along with its toplevel If an application umaps the toplevel from its popup callback, this can lead to a protocol error. Make sure we mark popup parent and use that to check if their parent is the toplevel being unmapped in which case we shall unmap the popup first to avoid the protocol error. Bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=770906 --- gdk/wayland/gdkwindow-wayland.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index ccd3bc4f32..be9bf9890e 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -132,6 +132,7 @@ struct _GdkWindowImplWayland unsigned int awaiting_frame : 1; GdkWindowTypeHint hint; GdkWindow *transient_for; + GdkWindow *popup_parent; PositionMethod position_method; cairo_surface_t *staging_cairo_surface; @@ -2009,6 +2010,7 @@ gdk_wayland_window_create_xdg_popup (GdkWindow *window, wl_surface_commit (impl->display_server.wl_surface); + impl->popup_parent = parent; display->current_popups = g_list_append (display->current_popups, window); } @@ -2329,6 +2331,28 @@ unmap_subsurface (GdkWindow *window) impl->display_server.wl_subsurface = NULL; } +static void +unmap_popups_for_window (GdkWindow *window) +{ + GdkWaylandDisplay *display_wayland; + GList *l; + + display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window)); + for (l = display_wayland->current_popups; l; l = l->next) + { + GdkWindow *popup = l->data; + GdkWindowImplWayland *popup_impl = GDK_WINDOW_IMPL_WAYLAND (popup->impl); + + if (popup_impl->popup_parent == window) + { + g_warning ("Tried to unmap the parent of a popup"); + gdk_window_hide (popup); + + return; + } + } +} + static void gdk_wayland_window_hide_surface (GdkWindow *window) { @@ -2337,6 +2361,8 @@ gdk_wayland_window_hide_surface (GdkWindow *window) unset_transient_for_exported (window); + unmap_popups_for_window (window); + if (impl->display_server.wl_surface) { if (impl->dummy_egl_surface)