[gtk/wip.win32.fixes: 20/20] GDK-WIN32 surface: WIP!




commit 9d2fa47d79749b30a2d12761f1e04d975fb356cb
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Wed Dec 23 17:05:06 2020 +0800

    GDK-WIN32 surface: WIP!

 gdk/win32/gdkevents-win32.c  |   4 +-
 gdk/win32/gdksurface-win32.c | 306 ++++++++++++++++++++++++++++++-------------
 gdk/win32/gdksurface-win32.h |  27 +++-
 3 files changed, 238 insertions(+), 99 deletions(-)
---
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index 87f8404d96..a8aee32bab 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -1712,8 +1712,8 @@ _gdk_win32_surface_fill_min_max_info (GdkSurface  *window,
           mmi->ptMaxSize.y = nearest_info.rcWork.bottom - nearest_info.rcWork.top;
         }
 
-      mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXVIRTUALSCREEN) + impl->margins_x * impl->surface_scale;
-      mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYVIRTUALSCREEN) + impl->margins_y * impl->surface_scale;
+      mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXVIRTUALSCREEN) + impl->shadow_x * impl->surface_scale;
+      mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYVIRTUALSCREEN) + impl->shadow_y * impl->surface_scale;
     }
 
   return TRUE;
diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c
index d2cae761aa..fd726e15bb 100644
--- a/gdk/win32/gdksurface-win32.c
+++ b/gdk/win32/gdksurface-win32.c
@@ -737,18 +737,25 @@ gdk_win32_surface_destroy_notify (GdkSurface *window)
 }
 
 static void
-get_outer_rect (GdkSurface *window,
+get_outer_rect (GdkSurface *surface,
                int        width,
                int        height,
                RECT      *rect)
 {
-  GdkWin32Surface *impl = GDK_WIN32_SURFACE (window);
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
+  RECT conf_rect;
+  
+  g_print ("%s\n", G_STRFUNC);
 
   rect->left = rect->top = 0;
   rect->right = width * impl->surface_scale;
   rect->bottom = height * impl->surface_scale;
+  impl->next_layout.configured_width = width;
+  impl->next_layout.configured_height = height;
+
+  impl->next_layout.surface_geometry_dirty = TRUE;
 
-  _gdk_win32_adjust_client_rect (window, rect);
+  _gdk_win32_adjust_client_rect (surface, rect);
 }
 
 static void
@@ -1178,6 +1185,8 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window,
  out:
   surface->inhibit_configure = FALSE;
 
+  surface->next_layout.surface_geometry_dirty = TRUE;
+  g_print ("%s\n", G_STRFUNC);
   gdk_surface_request_layout (window);
 }
 
@@ -1218,10 +1227,10 @@ gdk_win32_surface_layout_popup (GdkSurface     *surface,
   gdk_surface_layout_popup_helper (surface,
                                    width,
                                    height,
-                                   impl->margins.left,
-                                   impl->margins.right,
-                                   impl->margins.top,
-                                   impl->margins.bottom,
+                                   impl->shadow.left,
+                                   impl->shadow.right,
+                                   impl->shadow.top,
+                                   impl->shadow.bottom,
                                    monitor,
                                    &bounds,
                                    layout,
@@ -2281,10 +2290,10 @@ snap_up (GdkSurface *window)
   y = 0;
   height = maxysize;
 
-  x = x - impl->margins.left;
-  y = y - impl->margins.top;
-  width += impl->margins_x;
-  height += impl->margins_y;
+  x = x - impl->shadow.left;
+  y = y - impl->shadow.top;
+  width += impl->shadow_x;
+  height += impl->shadow_y;
 
   gdk_win32_surface_move_resize (window, x, y, width, height);
 }
@@ -2307,10 +2316,10 @@ snap_left (GdkSurface  *window,
 
   rect.width = rect.width / 2;
 
-  rect.x = rect.x - impl->margins.left;
-  rect.y = rect.y - impl->margins.top;
-  rect.width = rect.width + impl->margins_x;
-  rect.height = rect.height + impl->margins_y;
+  rect.x = rect.x - impl->shadow.left;
+  rect.y = rect.y - impl->shadow.top;
+  rect.width = rect.width + impl->shadow_x;
+  rect.height = rect.height + impl->shadow_y;
 
   gdk_win32_surface_move_resize (window,
                                  rect.x, rect.y,
@@ -2336,10 +2345,10 @@ snap_right (GdkSurface  *window,
   rect.width = rect.width / 2;
   rect.x += rect.width;
 
-  rect.x = rect.x - impl->margins.left;
-  rect.y = rect.y - impl->margins.top;
-  rect.width = rect.width + impl->margins_x;
-  rect.height = rect.height + impl->margins_y;
+  rect.x = rect.x - impl->shadow.left;
+  rect.y = rect.y - impl->shadow.top;
+  rect.width = rect.width + impl->shadow_x;
+  rect.height = rect.height + impl->shadow_y;
 
   gdk_win32_surface_move_resize (window,
                                  rect.x, rect.y,
@@ -3479,10 +3488,10 @@ setup_drag_move_resize_context (GdkSurface                   *window,
        */
       if (op == GDK_WIN32_DRAGOP_MOVE && !maximized)
         {
-          swx += impl->margins.left / impl->surface_scale;
-          swy += impl->margins.top / impl->surface_scale;
-          swwidth -= impl->margins_x;
-          swheight -= impl->margins_y;
+          swx += impl->shadow.left / impl->surface_scale;
+          swy += impl->shadow.top / impl->surface_scale;
+          swwidth -= impl->shadow_x;
+          swheight -= impl->shadow_y;
         }
 
       pointer_outside_of_window = root_x < swx || root_x > swx + swwidth ||
@@ -3532,23 +3541,23 @@ setup_drag_move_resize_context (GdkSurface                   *window,
           unmax_width = placement.rcNormalPosition.right - placement.rcNormalPosition.left;
           unmax_height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top;
 
-          shadow_unmax_width = unmax_width - impl->margins_x * impl->surface_scale;
-          shadow_unmax_height = unmax_height - impl->margins_y * impl->surface_scale;
+          shadow_unmax_width = unmax_width - impl->shadow_x * impl->surface_scale;
+          shadow_unmax_height = unmax_height - impl->shadow_y * impl->surface_scale;
 
           if (offsetx * impl->surface_scale < (shadow_unmax_width / 2) &&
               offsety * impl->surface_scale < (shadow_unmax_height / 2))
             {
-              placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * 
impl->surface_scale;
+              placement.rcNormalPosition.top = (root_y - offsety + impl->shadow.top - _gdk_offset_y) * 
impl->surface_scale;
               placement.rcNormalPosition.bottom = placement.rcNormalPosition.top + unmax_height;
 
               if (left_half)
                 {
-                  placement.rcNormalPosition.left = (root_x - offsetx + impl->margins.left - _gdk_offset_x) 
* impl->surface_scale;
+                  placement.rcNormalPosition.left = (root_x - offsetx + impl->shadow.left - _gdk_offset_x) * 
impl->surface_scale;
                   placement.rcNormalPosition.right = placement.rcNormalPosition.left + unmax_width;
                 }
               else
                 {
-                  placement.rcNormalPosition.right = (root_x + offsetx + impl->margins.right - 
_gdk_offset_x) * impl->surface_scale;
+                  placement.rcNormalPosition.right = (root_x + offsetx + impl->shadow.right - _gdk_offset_x) 
* impl->surface_scale;
                   placement.rcNormalPosition.left = placement.rcNormalPosition.right - unmax_width;
                 }
             }
@@ -3559,7 +3568,7 @@ setup_drag_move_resize_context (GdkSurface                   *window,
                                                 (_gdk_offset_x * impl->surface_scale);
 
               if (offsety * impl->surface_scale < shadow_unmax_height / 2)
-                placement.rcNormalPosition.top = (root_y - offsety + impl->margins.top - _gdk_offset_y) * 
impl->surface_scale;
+                placement.rcNormalPosition.top = (root_y - offsety + impl->shadow.top - _gdk_offset_y) * 
impl->surface_scale;
               else
                 placement.rcNormalPosition.top = (root_y * impl->surface_scale) -
                                                  (unmax_height / 2) -
@@ -3586,18 +3595,18 @@ setup_drag_move_resize_context (GdkSurface                   *window,
 
           if (op == GDK_WIN32_DRAGOP_MOVE)
             {
-              snew_pos.width -= impl->margins_x;
-              snew_pos.height -= impl->margins_y;
+              snew_pos.width -= impl->shadow_x;
+              snew_pos.height -= impl->shadow_y;
             }
 
           if (offsetx < snew_pos.width / 2 && offsety < snew_pos.height / 2)
             {
-              new_pos.y = root_y - offsety + impl->margins.top / impl->surface_scale;
+              new_pos.y = root_y - offsety + impl->shadow.top / impl->surface_scale;
 
               if (left_half)
-                new_pos.x = root_x - offsetx + impl->margins.left / impl->surface_scale;
+                new_pos.x = root_x - offsetx + impl->shadow.left / impl->surface_scale;
               else
-                new_pos.x = root_x + offsetx + impl->margins.left / impl->surface_scale - new_pos.width;
+                new_pos.x = root_x + offsetx + impl->shadow.left / impl->surface_scale - new_pos.width;
             }
           else
             {
@@ -3932,6 +3941,8 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
        rect.bottom != new_rect.bottom))
     {
       context->native_move_resize_pending = TRUE;
+      impl->next_layout.surface_geometry_dirty = TRUE;
+      g_print ("%s (resize)\n", G_STRFUNC);
       gdk_surface_request_layout (window);
     }
   else if (context->op == GDK_WIN32_DRAGOP_MOVE &&
@@ -3941,8 +3952,10 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window,
       SIZE window_size;
       POINT window_position;
 
+      impl->next_layout.surface_geometry_dirty = TRUE;
       context->native_move_resize_pending = FALSE;
 
+      g_print ("%s (move)\n", G_STRFUNC);
       gdk_surface_request_layout (window);
 
       gdk_win32_get_window_size_and_position_from_client_rect (window,
@@ -4361,21 +4374,27 @@ gdk_win32_surface_set_shadow_width (GdkSurface *window,
   if (GDK_SURFACE_DESTROYED (window))
     return;
 
+  if (impl->shadow.left == left &&
+      impl->shadow.right == right * impl->surface_scale &&
+      impl->shadow.top == top &&
+      impl->shadow.bottom == bottom * impl->surface_scale)
+    return;
+
   GDK_NOTE (MISC, g_print ("gdk_win32_surface_set_shadow_width: window %p, "
                            "left %d, top %d, right %d, bottom %d\n",
                            window, left, top, right, bottom));
 
-  impl->zero_margins = left == 0 && right == 0 && top == 0 && bottom == 0;
+  impl->zero_shadow = left == 0 && right == 0 && top == 0 && bottom == 0;
 
-  if (impl->zero_margins)
+  if (impl->zero_shadow)
     return;
 
-  impl->margins.left = left;
-  impl->margins.right = right * impl->surface_scale;
-  impl->margins.top = top;
-  impl->margins.bottom = bottom * impl->surface_scale;
-  impl->margins_x = left + right;
-  impl->margins_y = top + bottom;
+  impl->shadow.left = left;
+  impl->shadow.right = right * impl->surface_scale;
+  impl->shadow.top = top;
+  impl->shadow.bottom = bottom * impl->surface_scale;
+  impl->shadow_x = left + right;
+  impl->shadow_y = top + bottom;
 }
 
 
@@ -4448,6 +4467,145 @@ gdk_win32_surface_set_input_region (GdkSurface     *window,
    */
 }
 
+static gboolean
+compute_toplevel_size (GdkSurface *surface,
+                       gboolean    update_geometry,
+                       int        *width,
+                       int        *height)
+{
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
+  GdkDisplay *display = gdk_surface_get_display (surface);
+  GdkMonitor *monitor;
+  GdkToplevelSize size;
+  int bounds_width, bounds_height;
+  GdkGeometry geometry;
+  GdkSurfaceHints mask;
+  RECT rect;
+
+  monitor = gdk_display_get_monitor_at_surface (display, surface);
+  if (monitor)
+    {
+      GdkRectangle workarea;
+
+      gdk_win32_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);
+  g_print ("width height: %d %d\n", size.width, size.height);
+  g_warn_if_fail (size.width > 0);
+  g_warn_if_fail (size.height > 0);
+  *width = size.width;
+  *height = size.height;
+
+  if (update_geometry)
+    {
+      if (size.shadow.is_valid)
+        {
+          gdk_win32_surface_set_shadow_width (surface,
+                                              size.shadow.left,
+                                              size.shadow.right,
+                                              size.shadow.top,
+                                              size.shadow.bottom);
+        }
+
+      if (gdk_toplevel_layout_get_resizable (impl->toplevel_layout))
+        {
+          geometry.min_width = size.min_width;
+          geometry.min_height = size.min_height;
+          mask = GDK_HINT_MIN_SIZE;
+        }
+      else
+        {
+          geometry.max_width = geometry.min_width = *width;
+          geometry.max_height = geometry.min_height = *height;
+          mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
+        }
+
+      gdk_win32_surface_set_geometry_hints (surface, &geometry, mask);
+    }
+
+  gdk_surface_constrain_size (&geometry, mask, *width, *height, width, height);
+  gdk_win32_surface_resize (surface, *width, *height);
+
+  if ((impl->last_computed_width != size.width ||
+       impl->last_computed_height != size.height) &&
+      (impl->next_layout.configured_width != size.width ||
+       impl->next_layout.configured_height != size.height))
+    {
+      *width = size.width;
+      *height = size.height;
+      impl->last_computed_width = size.width;
+      impl->last_computed_height = size.height;
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+gdk_win32_surface_request_layout (GdkSurface *surface)
+{
+  RECT rect;
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
+
+  _gdk_win32_get_window_rect (surface, &rect);
+  impl = GDK_WIN32_SURFACE (surface);
+  impl->unscaled_width = rect.right - rect.left;
+  impl->unscaled_height = rect.bottom - rect.top;
+  impl->next_layout.configured_width = (impl->unscaled_width + impl->surface_scale - 1) / 
impl->surface_scale;
+  impl->next_layout.configured_height = (impl->unscaled_height + impl->surface_scale - 1) / 
impl->surface_scale;
+  surface->x = rect.left / impl->surface_scale;
+  surface->y = rect.top / impl->surface_scale;
+  impl->next_layout.surface_geometry_dirty = TRUE;
+  g_print ("request layout!\n");
+}
+
+static gboolean
+gdk_win32_surface_compute_size (GdkSurface *surface)
+{
+  GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface);
+
+  g_print ("compute size\n");
+
+  if (GDK_IS_TOPLEVEL (surface) && impl->next_layout.surface_geometry_dirty)
+    {
+      int width, height;
+
+      if (compute_toplevel_size (surface, TRUE, &width, &height))
+        gdk_win32_surface_resize (surface, width, height);
+
+      if (surface->resize_count == 0)
+        {
+          surface->width = impl->next_layout.configured_width;
+          surface->height = impl->next_layout.configured_height;
+          _gdk_surface_update_size (surface);
+        }
+
+      impl->next_layout.surface_geometry_dirty = FALSE;
+      impl->next_layout.configure_pending = FALSE;
+    }
+  else
+    {
+      surface->width = impl->next_layout.configured_width;
+      surface->height = impl->next_layout.configured_height;
+
+      _gdk_surface_update_size (surface);
+
+      impl->next_layout.surface_geometry_dirty = FALSE;
+    }
+
+  return surface->resize_count > 0;
+}
+
 static void
 gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
 {
@@ -4474,6 +4632,8 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass)
   impl_class->create_gl_context = _gdk_win32_surface_create_gl_context;
   impl_class->get_scale_factor = _gdk_win32_surface_get_scale_factor;
   impl_class->get_unscaled_size = _gdk_win32_surface_get_unscaled_size;
+  impl_class->request_layout = gdk_win32_surface_request_layout;
+  impl_class->compute_size = gdk_win32_surface_compute_size;
 }
 
 HGDIOBJ
@@ -4769,51 +4929,23 @@ gdk_win32_toplevel_present (GdkToplevel       *toplevel,
   GdkSurface *surface = GDK_SURFACE (toplevel);
   GdkDisplay *display = gdk_surface_get_display (surface);
   GdkMonitor *monitor;
-  GdkToplevelSize size;
-  int bounds_width, bounds_height;
   int width, height;
-  GdkGeometry geometry;
-  GdkSurfaceHints mask;
   gboolean maximize;
   gboolean fullscreen;
+  GdkWin32Surface *impl;
+  gboolean was_mapped;
 
-  monitor = gdk_display_get_monitor_at_surface (display, surface);
-  if (monitor)
-    {
-      GdkRectangle workarea;
+  if (surface->destroyed)
+    return;
 
-      gdk_win32_monitor_get_workarea (monitor, &workarea);
-      bounds_width = workarea.width;
-      bounds_height = workarea.height;
-    }
-  else
-    {
-      bounds_width = G_MAXINT;
-      bounds_height = G_MAXINT;
-    }
+  was_mapped = GDK_SURFACE_IS_MAPPED (surface);
+  impl = GDK_WIN32_SURFACE (surface);
 
-  gdk_toplevel_size_init (&size, bounds_width, bounds_height);
-  gdk_toplevel_notify_compute_size (toplevel, &size);
-  g_warn_if_fail (size.width > 0);
-  g_warn_if_fail (size.height > 0);
-  width = size.width;
-  height = size.height;
+  g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref);
+  impl->toplevel_layout = gdk_toplevel_layout_copy (layout);
 
-  if (gdk_toplevel_layout_get_resizable (layout))
-    {
-      geometry.min_width = size.min_width;
-      geometry.min_height = size.min_height;
-      mask = GDK_HINT_MIN_SIZE;
-    }
-  else
-    {
-      geometry.max_width = geometry.min_width = width;
-      geometry.max_height = geometry.min_height = height;
-      mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
-    }
-  gdk_win32_surface_set_geometry_hints (surface, &geometry, mask);
-  gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
-  gdk_win32_surface_resize (surface, width, height);
+  if (compute_toplevel_size (surface, FALSE, &width, &height))
+    gdk_win32_surface_resize (surface, width, height);
 
   if (gdk_toplevel_layout_get_maximized (layout, &maximize))
     {
@@ -4831,17 +4963,11 @@ gdk_win32_toplevel_present (GdkToplevel       *toplevel,
         gdk_win32_surface_unfullscreen (surface);
     }
 
-  gdk_win32_surface_show (surface, FALSE);
-  maybe_notify_mapped (surface);
+  g_print ("%s\n", G_STRFUNC);
+  gdk_surface_request_layout (surface);
 
-  if (size.shadow.is_valid)
-    {
-      gdk_win32_surface_set_shadow_width (surface,
-                                          size.shadow.left,
-                                          size.shadow.right,
-                                          size.shadow.top,
-                                          size.shadow.bottom);
-    }
+  gdk_win32_surface_show (surface, was_mapped);
+  maybe_notify_mapped (surface);
 }
 
 static gboolean
diff --git a/gdk/win32/gdksurface-win32.h b/gdk/win32/gdksurface-win32.h
index 8fa4b93cb2..f0c5890046 100644
--- a/gdk/win32/gdksurface-win32.h
+++ b/gdk/win32/gdksurface-win32.h
@@ -257,16 +257,16 @@ struct _GdkWin32Surface
   int initial_y;
 
   /* left/right/top/bottom width of the shadow/resize-grip around the window */
-  RECT margins;
+  RECT shadow;
 
-  /* left+right and top+bottom from @margins */
-  int margins_x;
-  int margins_y;
+  /* left+right and top+bottom from @shadow */
+  int shadow_x;
+  int shadow_y;
 
-  /* Set to TRUE when GTK tells us that margins are 0 everywhere.
-   * We don't actually set margins to 0, we just set this bit.
+  /* Set to TRUE when GTK tells us that shadow are 0 everywhere.
+   * We don't actually set shadow to 0, we just set this bit.
    */
-  guint zero_margins : 1;
+  guint zero_shadow : 1;
   guint inhibit_configure : 1;
 
   /* If TRUE, the @temp_styles is set to the styles that were temporarily
@@ -330,6 +330,19 @@ struct _GdkWin32Surface
   int unscaled_width;
   int unscaled_height;
 
+  /* Surface sizing */
+  int last_computed_width;
+  int last_computed_height;
+
+  GdkToplevelLayout *toplevel_layout;
+  
+  struct {
+    int configured_width;
+    int configured_height;
+    gboolean configure_pending;
+    gboolean surface_geometry_dirty;
+  } next_layout;
+
 #ifdef GDK_WIN32_ENABLE_EGL
   EGLSurface egl_surface;
   EGLSurface egl_dummy_surface;


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