[gtk/wip/chergert/macos-iosurface: 4/4] macos: delay window resize until compute-size




commit d3b032320e3fca7a605bcc5f685cdc1f62024a77
Author: Christian Hergert <christian hergert me>
Date:   Fri Feb 11 22:10:40 2022 -0800

    macos: delay window resize until compute-size
    
    In GTK 4, we have the ability to perform sizing changes from compute-size
    during the layout phase. Since the macOS backend already tracks window
    resizes manually, we can avoid doing the setFrame: immediately and instead
    do it within the frame clock.
    
    Doing so gives us vastly better resize experience as we're more likely to
    get the size change and updated contents in the same frame.

 gdk/macos/GdkMacosWindow.c          | 15 ++++++---------
 gdk/macos/gdkmacossurface-private.h |  5 +++++
 gdk/macos/gdkmacossurface.c         | 23 +++++++++++++++++++++++
 gdk/macos/gdkmacostoplevelsurface.c | 23 ++++++++++++++++++++---
 4 files changed, 54 insertions(+), 12 deletions(-)
---
diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c
index 8cecb4a534..fda0087a75 100644
--- a/gdk/macos/GdkMacosWindow.c
+++ b/gdk/macos/GdkMacosWindow.c
@@ -560,15 +560,12 @@ typedef NSString *CALayerContentsGravity;
       new_frame.size.height = min_size.height;
     }
 
-  /* We could also apply aspect ratio:
-     new_frame.size.height = new_frame.size.width / [self aspectRatio].width * [self aspectRatio].height;
-  */
-
-  [self setFrame:new_frame display:NO];
-
-  /* Let the resizing be handled by GTK. */
-  if (g_main_context_pending (NULL))
-    g_main_context_iteration (NULL, FALSE);
+  /* We don't want to change the window size until we get to our
+   * next layout operation so that things are more likely to stay
+   * synchronized with contents vs frame.
+   */
+  _gdk_macos_surface_set_next_frame ([self gdkSurface], new_frame);
+  gdk_surface_request_layout (GDK_SURFACE ([self gdkSurface]));
 
   inTrackManualResize = NO;
 
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
index cfc5f82db3..637cc2ebfb 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -60,10 +60,13 @@ struct _GdkMacosSurface
   int shadow_bottom;
   int shadow_left;
 
+  cairo_rectangle_int_t next_frame;
+
   gint64 pending_frame_counter;
 
   guint did_initial_present : 1;
   guint geometry_dirty : 1;
+  guint next_frame_set : 1;
 };
 
 struct _GdkMacosSurfaceClass
@@ -121,6 +124,8 @@ void               _gdk_macos_surface_move_resize             (GdkMacosSurface
                                                                int                   height);
 gboolean           _gdk_macos_surface_is_tracking             (GdkMacosSurface      *self,
                                                                NSTrackingArea       *area);
+void               _gdk_macos_surface_set_next_frame          (GdkMacosSurface      *self,
+                                                               NSRect                next_frame);
 void               _gdk_macos_surface_monitor_changed         (GdkMacosSurface      *self);
 GdkMonitor        *_gdk_macos_surface_get_best_monitor        (GdkMacosSurface      *self);
 void               _gdk_macos_surface_reposition_children     (GdkMacosSurface      *self);
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index be669783d5..caebed5c56 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -696,6 +696,29 @@ _gdk_macos_surface_resize (GdkMacosSurface *self,
   _gdk_macos_surface_move_resize (self, -1, -1, width, height);
 }
 
+void
+_gdk_macos_surface_set_next_frame (GdkMacosSurface *self,
+                                   NSRect           next_frame)
+{
+  GdkDisplay *display;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  display = gdk_surface_get_display (GDK_SURFACE (self));
+
+  _gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display),
+                                          next_frame.origin.x,
+                                          next_frame.origin.y + next_frame.size.height,
+                                          &self->next_frame.x, &self->next_frame.y);
+  self->next_frame.width = next_frame.size.width;
+  self->next_frame.height = next_frame.size.height;
+
+  self->next_frame_set = TRUE;
+  self->geometry_dirty = TRUE;
+
+  gdk_surface_request_layout (GDK_SURFACE (self));
+}
+
 void
 _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self)
 {
diff --git a/gdk/macos/gdkmacostoplevelsurface.c b/gdk/macos/gdkmacostoplevelsurface.c
index 17b1cec708..cf09fff73c 100644
--- a/gdk/macos/gdkmacostoplevelsurface.c
+++ b/gdk/macos/gdkmacostoplevelsurface.c
@@ -419,8 +419,16 @@ _gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
   g_warn_if_fail (size.width > 0);
   g_warn_if_fail (size.height > 0);
 
-  width = surface->width;
-  height = surface->height;
+  if (GDK_MACOS_SURFACE (self)->next_frame_set)
+    {
+      width = GDK_MACOS_SURFACE (self)->next_frame.width;
+      height = GDK_MACOS_SURFACE (self)->next_frame.height;
+    }
+  else
+    {
+      width = surface->width;
+      height = surface->height;
+    }
 
   if (self->layout != NULL &&
       gdk_toplevel_layout_get_resizable (self->layout))
@@ -446,7 +454,16 @@ _gdk_macos_toplevel_surface_compute_size (GdkSurface *surface)
   gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
 
   _gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
-  _gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
+
+  if (GDK_MACOS_SURFACE (self)->next_frame_set)
+    _gdk_macos_surface_move_resize (GDK_MACOS_SURFACE (self),
+                                    GDK_MACOS_SURFACE (self)->next_frame.x,
+                                    GDK_MACOS_SURFACE (self)->next_frame.y,
+                                    width, height);
+  else
+    _gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
+
+  GDK_MACOS_SURFACE (self)->next_frame_set = FALSE;
 
   return FALSE;
 }


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