[gtk: 31/88] gdk/x11: Flush layout changes to the frame clack dispatch




commit 65ad9d6d96710c60e23f858373d7fc17488d365e
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Dec 2 09:45:31 2020 +0100

    gdk/x11: Flush layout changes to the frame clack dispatch
    
    This follows the trail of the Wayland backend in that GdkSurface changes
    happen during the layout phase, and that a GDK_CONFIGURE no longer being
    used to communicate the size changes of a surface; this now also uses
    the layout signal on the GdkSurface.

 gdk/x11/gdkdisplay-x11.c |  28 ++++++--
 gdk/x11/gdksurface-x11.c | 168 +++++++++++++++++++++++++++++++++++++++--------
 gdk/x11/gdksurface-x11.h |  13 ++++
 3 files changed, 175 insertions(+), 34 deletions(-)
---
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 0df79d289b..692f85230c 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -901,11 +901,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
        xevent->xconfigure.event == xevent->xconfigure.window)
         {
           int x, y;
-          int c_w = (xevent->xconfigure.width + surface_impl->surface_scale - 1) / 
surface_impl->surface_scale;
-          int c_h = (xevent->xconfigure.height + surface_impl->surface_scale - 1) / 
surface_impl->surface_scale;
+          int configured_width;
+          int configured_height;
           int new_abs_x, new_abs_y;
 
-          event = gdk_configure_event_new (surface, c_w, c_h);
+          configured_width =
+            (xevent->xconfigure.width + surface_impl->surface_scale - 1) /
+            surface_impl->surface_scale;
+          configured_height =
+            (xevent->xconfigure.height + surface_impl->surface_scale - 1) /
+            surface_impl->surface_scale;
 
          if (!xevent->xconfigure.send_event &&
              !xevent->xconfigure.override_redirect &&
@@ -915,6 +920,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
              int ty = 0;
              Window child_window = 0;
 
+              if (surface_impl->pending_configure_events == 1)
+                {
+                  surface_impl->pending_configure_events = 0;
+                  gdk_surface_thaw_updates (surface);
+                }
+              else if (surface_impl->pending_configure_events > 1)
+                {
+                  surface_impl->pending_configure_events--;
+                }
+
               x = y = 0;
              gdk_x11_display_error_trap_push (display);
              if (XTranslateCoordinates (GDK_SURFACE_XDISPLAY (surface),
@@ -955,10 +970,11 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator,
             {
               surface_impl->unscaled_width = xevent->xconfigure.width;
               surface_impl->unscaled_height = xevent->xconfigure.height;
-              gdk_configure_event_get_size (event, &surface->width, &surface->height);
 
-              _gdk_surface_update_size (surface);
-              _gdk_x11_surface_update_size (surface_impl);
+              surface_impl->next_layout.configured_width = configured_width;
+              surface_impl->next_layout.configured_height = configured_height;
+              surface_impl->next_layout.surface_geometry_dirty = TRUE;
+              gdk_surface_request_layout (surface);
             }
 
           if (surface->resize_count >= 1)
diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c
index c4b14e11e3..a207c8964b 100644
--- a/gdk/x11/gdksurface-x11.c
+++ b/gdk/x11/gdksurface-x11.c
@@ -192,6 +192,112 @@ gdk_x11_surface_get_unscaled_size (GdkSurface *surface,
     *unscaled_height = impl->unscaled_height;
 }
 
+static void
+update_shadow_size (GdkSurface *surface,
+                    int         shadow_left,
+                    int         shadow_right,
+                    int         shadow_top,
+                    int         shadow_bottom)
+{
+  GdkX11Surface *impl = GDK_X11_SURFACE (surface);
+  Atom frame_extents;
+  gulong data[4];
+
+  if (impl->shadow_left == shadow_left &&
+      impl->shadow_right == shadow_right &&
+      impl->shadow_top == shadow_top &&
+      impl->shadow_bottom == shadow_bottom)
+    return;
+
+  impl->shadow_left = shadow_left;
+  impl->shadow_right = shadow_right;
+  impl->shadow_top = shadow_top;
+  impl->shadow_bottom = shadow_bottom;
+
+  data[0] = shadow_left * impl->surface_scale;
+  data[1] = shadow_right * impl->surface_scale;
+  data[2] = shadow_top * impl->surface_scale;
+  data[3] = shadow_bottom * impl->surface_scale;
+
+  frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (surface),
+                                                         "_GTK_FRAME_EXTENTS");
+  XChangeProperty (GDK_SURFACE_XDISPLAY (surface),
+                   GDK_SURFACE_XID (surface),
+                   frame_extents, XA_CARDINAL,
+                   32, PropModeReplace,
+                   (guchar *) &data, 4);
+}
+
+static void
+gdk_x11_surface_request_layout (GdkSurface *surface)
+{
+  GdkX11Surface *impl = GDK_X11_SURFACE (surface);
+
+  impl->next_layout.surface_geometry_dirty = TRUE;
+}
+
+static void
+gdk_x11_surface_compute_size (GdkSurface *surface)
+{
+  GdkX11Surface *impl = GDK_X11_SURFACE (surface);
+
+  if (GDK_IS_TOPLEVEL (surface))
+    {
+      if (impl->next_layout.surface_geometry_dirty)
+        {
+          GdkDisplay *display = gdk_surface_get_display (surface);
+          GdkMonitor *monitor;
+          GdkToplevelSize size;
+          int bounds_width, bounds_height;
+
+          monitor = gdk_display_get_monitor_at_surface (display, surface);
+          if (monitor)
+            {
+              GdkRectangle workarea;
+
+              gdk_x11_monitor_get_workarea (monitor, &workarea);
+              bounds_width = workarea.width;
+              bounds_height = workarea.height;
+            }
+          else
+            {
+              bounds_width = G_MAXINT;
+              bounds_height = G_MAXINT;
+            }
+
+          gdk_toplevel_size_init (&size, bounds_width, bounds_height);
+          gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
+
+          if (size.margin.is_valid)
+            {
+              update_shadow_size (surface,
+                                  size.margin.left,
+                                  size.margin.right,
+                                  size.margin.top,
+                                  size.margin.bottom);
+            }
+
+          surface->width = impl->next_layout.configured_width;
+          surface->height = impl->next_layout.configured_height;
+
+          _gdk_surface_update_size (surface);
+          _gdk_x11_surface_update_size (impl);
+
+          impl->next_layout.surface_geometry_dirty = FALSE;
+        }
+    }
+  else
+    {
+      surface->width = impl->next_layout.configured_width;
+      surface->height = impl->next_layout.configured_height;
+
+      _gdk_surface_update_size (surface);
+      _gdk_x11_surface_update_size (impl);
+
+      impl->next_layout.surface_geometry_dirty = FALSE;
+    }
+}
+
 gboolean
 gdk_x11_surface_supports_edge_constraints (GdkSurface *surface)
 {
@@ -1424,6 +1530,9 @@ x11_surface_move (GdkSurface *surface,
           surface->x = x;
           surface->y = y;
         }
+
+      impl->next_layout.surface_geometry_dirty = TRUE;
+      gdk_surface_request_layout (surface);
     }
 }
 
@@ -1450,10 +1559,10 @@ x11_surface_resize (GdkSurface *surface,
     {
       impl->unscaled_width = width * impl->surface_scale;
       impl->unscaled_height = height * impl->surface_scale;
-      surface->width = width;
-      surface->height = height;
-      _gdk_surface_update_size (surface);
-      _gdk_x11_surface_update_size (GDK_X11_SURFACE (surface));
+      impl->next_layout.configured_width = width;
+      impl->next_layout.configured_height = height;
+      impl->next_layout.surface_geometry_dirty = TRUE;
+      gdk_surface_request_layout (surface);
     }
   else
     {
@@ -1491,10 +1600,10 @@ x11_surface_move_resize (GdkSurface *surface,
 
       impl->unscaled_width = width * impl->surface_scale;
       impl->unscaled_height = height * impl->surface_scale;
-      surface->width = width;
-      surface->height = height;
-
-      _gdk_x11_surface_update_size (GDK_X11_SURFACE (surface));
+      impl->next_layout.configured_width = width;
+      impl->next_layout.configured_height = height;
+      impl->next_layout.surface_geometry_dirty = TRUE;
+      gdk_surface_request_layout (surface);
 
       if (surface->parent)
         {
@@ -2822,22 +2931,6 @@ gdk_x11_surface_set_shadow_width (GdkSurface *surface,
                                  int        top,
                                  int        bottom)
 {
-  GdkX11Surface *impl = GDK_X11_SURFACE (surface);
-  Atom frame_extents;
-  gulong data[4] = {
-    left * impl->surface_scale,
-    right * impl->surface_scale,
-    top * impl->surface_scale,
-    bottom * impl->surface_scale
-  };
-
-  frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (surface),
-                                                         "_GTK_FRAME_EXTENTS");
-  XChangeProperty (GDK_SURFACE_XDISPLAY (surface),
-                   GDK_SURFACE_XID (surface),
-                   frame_extents, XA_CARDINAL,
-                   32, PropModeReplace,
-                   (guchar *) &data, 4);
 }
 
 /**
@@ -4568,6 +4661,8 @@ gdk_x11_surface_class_init (GdkX11SurfaceClass *klass)
   impl_class->set_shadow_width = gdk_x11_surface_set_shadow_width;
   impl_class->create_gl_context = gdk_x11_surface_create_gl_context;
   impl_class->get_unscaled_size = gdk_x11_surface_get_unscaled_size;
+  impl_class->request_layout = gdk_x11_surface_request_layout;
+  impl_class->compute_size = gdk_x11_surface_compute_size;
 }
 
 #define LAST_PROP 1
@@ -4854,6 +4949,7 @@ gdk_x11_toplevel_present (GdkToplevel       *toplevel,
                           GdkToplevelLayout *layout)
 {
   GdkSurface *surface = GDK_SURFACE (toplevel);
+  GdkX11Surface *impl = GDK_X11_SURFACE (surface);
   GdkDisplay *display = gdk_surface_get_display (surface);
   GdkMonitor *monitor;
   GdkToplevelSize size;
@@ -4863,6 +4959,11 @@ gdk_x11_toplevel_present (GdkToplevel       *toplevel,
   GdkSurfaceHints mask;
   gboolean was_mapped;
 
+  if (surface->destroyed)
+    return;
+
+  was_mapped = GDK_SURFACE_IS_MAPPED (surface);
+
   gdk_x11_surface_unminimize (surface);
 
   monitor = gdk_display_get_monitor_at_surface (display, surface);
@@ -4903,6 +5004,19 @@ gdk_x11_toplevel_present (GdkToplevel       *toplevel,
   gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
   gdk_x11_surface_toplevel_resize (surface, width, height);
 
+  if (size.margin.is_valid)
+    {
+      update_shadow_size (surface,
+                          size.margin.left,
+                          size.margin.right,
+                          size.margin.top,
+                          size.margin.bottom);
+    }
+
+  impl->pending_configure_events++;
+  if (impl->pending_configure_events == 1)
+    gdk_surface_freeze_updates (surface);
+
   if (gdk_toplevel_layout_get_maximized (layout))
     gdk_x11_surface_maximize (surface);
   else
@@ -4921,10 +5035,8 @@ gdk_x11_toplevel_present (GdkToplevel       *toplevel,
   else
     gdk_x11_surface_unfullscreen (surface);
 
-  if (surface->destroyed)
-    return;
-
-  was_mapped = GDK_SURFACE_IS_MAPPED (surface);
+  impl->next_layout.surface_geometry_dirty = TRUE;
+  gdk_surface_request_layout (surface);
 
   if (!was_mapped)
     gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0);
diff --git a/gdk/x11/gdksurface-x11.h b/gdk/x11/gdksurface-x11.h
index eb23474afd..f6ccfa2f21 100644
--- a/gdk/x11/gdksurface-x11.h
+++ b/gdk/x11/gdksurface-x11.h
@@ -59,6 +59,11 @@ struct _GdkX11Surface
 
   int surface_scale;
 
+  int shadow_left;
+  int shadow_right;
+  int shadow_top;
+  int shadow_bottom;
+
   /* Width and height not divided by surface_scale - this matters in the
    * corner-case where the window manager assigns us a size that isn't
    * a multiple of surface_scale - for example for a maximized window
@@ -67,6 +72,14 @@ struct _GdkX11Surface
   int unscaled_width;
   int unscaled_height;
 
+  int pending_configure_events;
+
+  struct {
+    int configured_width;
+    int configured_height;
+    gboolean surface_geometry_dirty;
+  } next_layout;
+
   cairo_surface_t *cairo_surface;
 
   int abs_x;


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