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




commit d570d6e35c239aa939a95e3428f3e961fdd04b14
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 |  4 ++++
 gdk/macos/gdkmacossurface.c         | 23 +++++++++++++++++++++++
 gdk/macos/gdkmacostoplevelsurface.c | 23 ++++++++++++++++++++---
 4 files changed, 53 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 b3e0b2006b..3cfcf1076a 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -60,6 +60,8 @@ struct _GdkMacosSurface
   int shadow_bottom;
   int shadow_left;
 
+  cairo_rectangle_int_t next_frame;
+
   gint64 pending_frame_counter;
 
   guint did_initial_present : 1;
@@ -123,6 +125,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 85a921ebf8..6966db7894 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -708,6 +708,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]