[gtk: 12/16] wayland: Fix top-most-popup check



commit 11dbc384abea77fba55a40bf06d4176ce19eaa3d
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sun Feb 16 16:24:12 2020 +0100

    wayland: Fix top-most-popup check
    
    We can map a non-grabbing popup wherever, it's just the grabbing
    popup-chain that needs to be ensured not to break any ordering rules.
    
    Fix this by managing two lists; one of open popups, and another for
    grabbing ones.

 gdk/wayland/gdkdisplay-wayland.h |  1 +
 gdk/wayland/gdksurface-wayland.c | 32 +++++++++++++++++++++++++++-----
 2 files changed, 28 insertions(+), 5 deletions(-)
---
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index 1da3e36fe8..aa5797a331 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -127,6 +127,7 @@ struct _GdkWaylandDisplay
   GList *orphan_dialogs;
 
   GList *current_popups;
+  GList *current_grabbing_popups;
 
   struct wl_cursor_theme *cursor_theme;
   gchar *cursor_theme_name;
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index c29331441d..267943799e 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -2184,6 +2184,21 @@ create_dynamic_positioner (GdkSurface *surface)
   g_assert_not_reached ();
 }
 
+static gboolean
+can_map_grabbing_popup (GdkSurface *surface,
+                        GdkSurface *parent)
+{
+  GdkDisplay *display = gdk_surface_get_display (surface);
+  GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
+  GdkSurface *top_most_popup;
+
+  if (!display_wayland->current_grabbing_popups)
+    return TRUE;
+
+  top_most_popup = g_list_first (display_wayland->current_grabbing_popups)->data;
+  return top_most_popup == parent;
+}
+
 static void
 gdk_wayland_surface_create_xdg_popup (GdkSurface     *surface,
                                       GdkSurface     *parent,
@@ -2210,13 +2225,11 @@ gdk_wayland_surface_create_xdg_popup (GdkSurface     *surface,
       g_warning ("Can't map popup, already mapped");
       return;
     }
+
   if (grab_input_seat &&
-      ((display->current_popups &&
-        g_list_last (display->current_popups)->data != parent) ||
-       (!display->current_popups &&
-        !is_realized_toplevel (parent))))
+      !can_map_grabbing_popup (surface, parent))
     {
-      g_warning ("Tried to map a popup with a non-top most parent");
+      g_warning ("Tried to map a grabbing popup with a non-top most parent");
       return;
     }
 
@@ -2291,6 +2304,11 @@ gdk_wayland_surface_create_xdg_popup (GdkSurface     *surface,
 
   impl->popup_parent = parent;
   display->current_popups = g_list_append (display->current_popups, surface);
+  if (grab_input_seat)
+    {
+      display->current_grabbing_popups =
+        g_list_prepend (display->current_grabbing_popups, surface);
+    }
 }
 
 static GdkWaylandSeat *
@@ -2490,6 +2508,8 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
           impl->display_server.xdg_popup = NULL;
           display_wayland->current_popups =
             g_list_remove (display_wayland->current_popups, surface);
+          display_wayland->current_grabbing_popups =
+            g_list_remove (display_wayland->current_grabbing_popups, surface);
         }
       if (impl->display_server.xdg_surface)
         {
@@ -2512,6 +2532,8 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
           impl->display_server.zxdg_popup_v6 = NULL;
           display_wayland->current_popups =
             g_list_remove (display_wayland->current_popups, surface);
+          display_wayland->current_grabbing_popups =
+            g_list_remove (display_wayland->current_grabbing_popups, surface);
         }
       if (impl->display_server.zxdg_surface_v6)
         {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]