[gtk/wip/matthiasc/popup5: 123/130] x11: Implement popup surfaces



commit e96bfbfb3ef491eb59e033c00ed8b5aa7afa2244
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Apr 22 15:22:33 2019 +0000

    x11: Implement popup surfaces
    
    Make them use o-r windows, and move
    with their parent.
    
    We do a sort-of ok job on stacking order
    here - whenever the parent window gets a
    ConfigureNotify, we just restack all popups
    directly on top of their parent. This is good
    enough to keep popups on top of their parent
    while we drag it around, and it gets the popup
    to disappear when raising another window on
    top of the parent.

 gdk/x11/gdkdisplay-x11.c | 10 +++++--
 gdk/x11/gdkprivate-x11.h |  2 ++
 gdk/x11/gdksurface-x11.c | 78 +++++++++++++++++++++++++++++++++++++++---------
 gdk/x11/gdksurface-x11.h |  5 ++++
 4 files changed, 79 insertions(+), 16 deletions(-)
---
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 5b3f7c74cd..7fd21ccb0d 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -985,8 +985,12 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
            }
          if (!is_substructure)
            {
-             surface->x = event->configure.x;
-             surface->y = event->configure.y;
+              if (surface->x != event->configure.x ||
+                  surface->y != event->configure.y)
+                {
+                  surface->x = event->configure.x;
+                  surface->y = event->configure.y;
+                }
 
               if (surface_impl->unscaled_width != xevent->xconfigure.width ||
                   surface_impl->unscaled_height != xevent->xconfigure.height)
@@ -1007,6 +1011,8 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
                  if (surface->resize_count == 0)
                    _gdk_x11_moveresize_configure_done (display, surface);
                }
+
+              gdk_x11_surface_update_popups (surface);
            }
         }
       break;
diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h
index 2e2b420560..5539d51ba1 100644
--- a/gdk/x11/gdkprivate-x11.h
+++ b/gdk/x11/gdkprivate-x11.h
@@ -227,6 +227,8 @@ void _gdk_x11_cursor_display_finalize (GdkDisplay *display);
 
 void _gdk_x11_surface_register_dnd (GdkSurface *window);
 
+void gdk_x11_surface_update_popups (GdkSurface *surface);
+
 GdkDrag        * _gdk_x11_surface_drag_begin (GdkSurface          *window,
                                               GdkDevice          *device,
                                               GdkContentProvider *content,
diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c
index e9d6a7129c..e695c09e5d 100644
--- a/gdk/x11/gdksurface-x11.c
+++ b/gdk/x11/gdksurface-x11.c
@@ -425,12 +425,20 @@ gdk_x11_surface_end_frame (GdkSurface *surface)
 static void
 gdk_x11_surface_finalize (GObject *object)
 {
+  GdkSurface *surface;
   GdkX11Surface *impl;
 
   g_return_if_fail (GDK_IS_X11_SURFACE (object));
 
+  surface = GDK_SURFACE (object);
   impl = GDK_X11_SURFACE (object);
 
+  if (surface->parent)
+    {
+      GdkX11Surface *parent_impl = GDK_X11_SURFACE (surface->parent);
+      parent_impl->popups = g_list_remove (parent_impl->popups, surface);
+    }
+
   if (impl->toplevel->in_frame)
     unhook_surface_changed (GDK_SURFACE (impl));
 
@@ -842,7 +850,8 @@ _gdk_x11_display_create_surface (GdkDisplay     *display,
   xattributes.colormap = gdk_x11_display_get_window_colormap (display_x11);
   xattributes_mask |= CWColormap;
 
-  if (surface->surface_type == GDK_SURFACE_TEMP)
+  if (surface->surface_type == GDK_SURFACE_TEMP ||
+      surface->surface_type == GDK_SURFACE_POPUP)
     {
       xattributes.save_under = True;
       xattributes.override_redirect = True;
@@ -899,6 +908,12 @@ _gdk_x11_display_create_surface (GdkDisplay     *display,
 
   gdk_surface_freeze_toplevel_updates (surface);
 
+  if (parent)
+    {
+      GdkX11Surface *parent_impl = GDK_X11_SURFACE (parent);
+      parent_impl->popups = g_list_prepend (parent_impl->popups, surface);
+    }
+
   return surface;
 }
 
@@ -1231,8 +1246,8 @@ gdk_x11_surface_hide (GdkSurface *surface)
 
 static inline void
 x11_surface_move (GdkSurface *surface,
-                 gint       x,
-                 gint       y)
+                  gint        x,
+                  gint        y)
 {
   GdkX11Surface *impl = GDK_X11_SURFACE (surface);
 
@@ -1244,6 +1259,12 @@ x11_surface_move (GdkSurface *surface,
     {
       surface->x = x;
       surface->y = y;
+
+      if (surface->parent)
+        {
+          impl->offset_x = surface->x - surface->parent->x;
+          impl->offset_y = surface->y - surface->parent->y;
+        }
     }
 }
 
@@ -1283,10 +1304,10 @@ x11_surface_resize (GdkSurface *surface,
 
 static inline void
 x11_surface_move_resize (GdkSurface *surface,
-                        gint       x,
-                        gint       y,
-                        gint       width,
-                        gint       height)
+                         gint        x,
+                         gint        y,
+                         gint        width,
+                         gint        height)
 {
   GdkX11Surface *impl = GDK_X11_SURFACE (surface);
 
@@ -1314,6 +1335,12 @@ x11_surface_move_resize (GdkSurface *surface,
       surface->height = height;
 
       _gdk_x11_surface_update_size (GDK_X11_SURFACE (surface));
+
+      if (surface->parent)
+        {
+          impl->offset_x = surface->x - surface->parent->x;
+          impl->offset_y = surface->y - surface->parent->y;
+        }
     }
   else
     {
@@ -1324,11 +1351,11 @@ x11_surface_move_resize (GdkSurface *surface,
 
 static void
 gdk_x11_surface_move_resize (GdkSurface *surface,
-                            gboolean   with_move,
-                            gint       x,
-                            gint       y,
-                            gint       width,
-                            gint       height)
+                             gboolean    with_move,
+                             gint        x,
+                             gint        y,
+                             gint        width,
+                             gint        height)
 {
   if (with_move && (width < 0 && height < 0))
     x11_surface_move (surface, x, y);
@@ -1341,6 +1368,29 @@ gdk_x11_surface_move_resize (GdkSurface *surface,
     }
 }
 
+static void gdk_x11_surface_restack_toplevel (GdkSurface *surface,
+                                              GdkSurface *sibling,
+                                              gboolean    above);
+
+void
+gdk_x11_surface_update_popups (GdkSurface *parent)
+{
+  GdkX11Surface *impl = GDK_X11_SURFACE (parent);
+  GList *l;
+
+  for (l = impl->popups; l; l = l->next)
+    {
+      GdkX11Surface *popup_impl = l->data;
+      GdkSurface *popup = GDK_SURFACE (popup_impl);
+      int new_x = parent->x + popup_impl->offset_x;
+      int new_y = parent->y + popup_impl->offset_y;
+
+      if (new_x != popup->x || new_y != popup->y)
+        x11_surface_move (popup, new_x, new_y);
+      gdk_x11_surface_restack_toplevel (popup, parent, TRUE);
+    }
+}
+
 void
 _gdk_x11_surface_set_surface_scale (GdkSurface *surface,
                                  int scale)
@@ -1390,8 +1440,8 @@ gdk_x11_surface_raise (GdkSurface *surface)
 
 static void
 gdk_x11_surface_restack_toplevel (GdkSurface *surface,
-                                GdkSurface *sibling,
-                                gboolean   above)
+                                  GdkSurface *sibling,
+                                  gboolean    above)
 {
   XWindowChanges changes;
 
diff --git a/gdk/x11/gdksurface-x11.h b/gdk/x11/gdksurface-x11.h
index 6ffdbf24e6..c051d10d82 100644
--- a/gdk/x11/gdksurface-x11.h
+++ b/gdk/x11/gdksurface-x11.h
@@ -75,6 +75,11 @@ struct _GdkX11Surface
 #if defined (HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
   Damage damage;
 #endif
+
+  int offset_x;
+  int offset_y;
+
+  GList *popups;
 };
  
 struct _GdkX11SurfaceClass 


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