[gtk/wip/chergert/for-4-6: 14/56] macos: support mix-rate monitors




commit 856728ea1074457a426c3cc9224800551849360e
Author: Christian Hergert <christian hergert me>
Date:   Sun Feb 27 23:31:28 2022 -0800

    macos: support mix-rate monitors
    
    Previously, a single CVDisplayLink was used to drive updates for all
    surfaces across all monitors. It used a 'best guess' rate which would
    allow for updates across monitors of mixed rates. This is undesirable for
    situations where you might have a 144hz monitor as it does not allow for
    reaching up to that frame rate.
    
    Instead, we want to use a per-monitor CVDisplayLink which will fire at the
    rate of the monitor down to the level of updates we require. This commit
    does just that.
    
    When a surface crosses onto a new monitor, that monitor is used to drive
    the GdkFrameClock.
    
    Fixes #4732

 gdk/macos/gdkmacosdisplay-private.h |  15 ----
 gdk/macos/gdkmacosdisplay.c         | 105 -------------------------
 gdk/macos/gdkmacosmonitor-private.h |  14 ++--
 gdk/macos/gdkmacosmonitor.c         | 139 +++++++++++++++++++++++++++++++--
 gdk/macos/gdkmacossurface-private.h |   7 +-
 gdk/macos/gdkmacossurface.c         | 151 ++++++++++++++++++++++--------------
 6 files changed, 242 insertions(+), 189 deletions(-)
---
diff --git a/gdk/macos/gdkmacosdisplay-private.h b/gdk/macos/gdkmacosdisplay-private.h
index b9f33fe20e..ef17618d61 100644
--- a/gdk/macos/gdkmacosdisplay-private.h
+++ b/gdk/macos/gdkmacosdisplay-private.h
@@ -68,16 +68,6 @@ struct _GdkMacosDisplay
    */
   GQueue sorted_surfaces;
 
-  /* Our CVDisplayLink based GSource which we use to freeze/thaw the
-   * GdkFrameClock for the surface.
-   */
-  GSource *frame_source;
-
-  /* A queue of surfaces which we know are awaiting frames to be drawn. This
-   * uses the GdkMacosSurface.frame link.
-   */
-  GQueue awaiting_frames;
-
   /* The surface that is receiving keyboard events */
   GdkMacosSurface *keyboard_surface;
 
@@ -138,10 +128,6 @@ GdkMacosSurface *_gdk_macos_display_get_surface_at_display_coords  (GdkMacosDisp
 void             _gdk_macos_display_reload_monitors                (GdkMacosDisplay *self);
 void             _gdk_macos_display_surface_removed                (GdkMacosDisplay *self,
                                                                     GdkMacosSurface *surface);
-void             _gdk_macos_display_add_frame_callback             (GdkMacosDisplay *self,
-                                                                    GdkMacosSurface *surface);
-void             _gdk_macos_display_remove_frame_callback          (GdkMacosDisplay *self,
-                                                                    GdkMacosSurface *surface);
 NSWindow        *_gdk_macos_display_find_native_under_pointer      (GdkMacosDisplay *self,
                                                                     int             *x,
                                                                     int             *y);
@@ -157,7 +143,6 @@ void             _gdk_macos_display_surface_resigned_key           (GdkMacosDisp
                                                                     GdkMacosSurface *surface);
 void             _gdk_macos_display_surface_became_key             (GdkMacosDisplay *self,
                                                                     GdkMacosSurface *surface);
-int              _gdk_macos_display_get_nominal_refresh_rate       (GdkMacosDisplay *self);
 void             _gdk_macos_display_clear_sorting                  (GdkMacosDisplay *self);
 const GList     *_gdk_macos_display_get_surfaces                   (GdkMacosDisplay *self);
 void             _gdk_macos_display_send_button_event              (GdkMacosDisplay *self,
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index 5501a16318..cb0331419d 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -231,56 +231,6 @@ gdk_macos_display_load_seat (GdkMacosDisplay *self)
   g_object_unref (seat);
 }
 
-static gboolean
-gdk_macos_display_frame_cb (gpointer data)
-{
-  GdkMacosDisplay *self = data;
-  GdkDisplayLinkSource *source;
-  gint64 presentation_time;
-  gint64 now;
-  GList *iter;
-
-  g_assert (GDK_IS_MACOS_DISPLAY (self));
-
-  source = (GdkDisplayLinkSource *)self->frame_source;
-
-  presentation_time = source->presentation_time;
-  now = g_source_get_time ((GSource *)source);
-
-  iter = self->awaiting_frames.head;
-
-  while (iter != NULL)
-    {
-      GdkMacosSurface *surface = iter->data;
-
-      g_assert (GDK_IS_MACOS_SURFACE (surface));
-
-      iter = iter->next;
-
-      _gdk_macos_surface_publish_timings (surface,
-                                          source->presentation_time,
-                                          source->refresh_interval);
-
-      _gdk_macos_display_remove_frame_callback (self, surface);
-
-      if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
-        gdk_surface_thaw_updates (GDK_SURFACE (surface));
-    }
-
-  return G_SOURCE_CONTINUE;
-}
-
-static void
-gdk_macos_display_load_display_link (GdkMacosDisplay *self)
-{
-  self->frame_source = gdk_display_link_source_new (CGMainDisplayID ());
-  g_source_set_callback (self->frame_source,
-                         gdk_macos_display_frame_cb,
-                         self,
-                         NULL);
-  g_source_attach (self->frame_source, NULL);
-}
-
 static const char *
 gdk_macos_display_get_name (GdkDisplay *display)
 {
@@ -384,7 +334,6 @@ _gdk_macos_display_surface_added (GdkMacosDisplay *self,
   g_assert (GDK_IS_MACOS_SURFACE (surface));
   g_assert (!queue_contains (&self->sorted_surfaces, &surface->sorted));
   g_assert (!queue_contains (&self->main_surfaces, &surface->main));
-  g_assert (!queue_contains (&self->awaiting_frames, &surface->frame));
   g_assert (surface->sorted.data == surface);
   g_assert (surface->main.data == surface);
   g_assert (surface->frame.data == surface);
@@ -411,9 +360,6 @@ _gdk_macos_display_surface_removed (GdkMacosDisplay *self,
   if (queue_contains (&self->main_surfaces, &surface->main))
     _gdk_macos_display_surface_resigned_main (self, surface);
 
-  if (queue_contains (&self->awaiting_frames, &surface->frame))
-    g_queue_unlink (&self->awaiting_frames, &surface->frame);
-
   g_return_if_fail (self->keyboard_surface != surface);
 }
 
@@ -649,7 +595,6 @@ gdk_macos_display_finalize (GObject *object)
   g_clear_pointer (&self->active_drags, g_hash_table_unref);
   g_clear_pointer (&self->active_drops, g_hash_table_unref);
   g_clear_object (&GDK_DISPLAY (self)->clipboard);
-  g_clear_pointer (&self->frame_source, g_source_unref);
   g_clear_object (&self->monitors);
   g_clear_pointer (&self->name, g_free);
 
@@ -724,9 +669,6 @@ _gdk_macos_display_open (const char *display_name)
 
   gdk_macos_display_load_seat (self);
   gdk_macos_display_load_clipboard (self);
-
-  /* Load CVDisplayLink before monitors to access refresh rates */
-  gdk_macos_display_load_display_link (self);
   _gdk_macos_display_reload_monitors (self);
 
   /* Initialize feedback from display server */
@@ -972,42 +914,6 @@ _gdk_macos_display_get_surface_at_display_coords (GdkMacosDisplay *self,
   return _gdk_macos_display_get_surface_at_coords (self, x_gdk, y_gdk, surface_x, surface_y);
 }
 
-void
-_gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
-                                       GdkMacosSurface *surface)
-{
-  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
-  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
-
-  if (!queue_contains (&self->awaiting_frames, &surface->frame))
-    {
-      /* Processing frames is always head to tail, so push to the
-       * head so that we don't possibly re-enter this right after
-       * adding to the queue.
-       */
-      g_queue_push_head_link (&self->awaiting_frames, &surface->frame);
-
-      if (self->awaiting_frames.length == 1)
-        gdk_display_link_source_unpause ((GdkDisplayLinkSource *)self->frame_source);
-    }
-}
-
-void
-_gdk_macos_display_remove_frame_callback (GdkMacosDisplay *self,
-                                          GdkMacosSurface *surface)
-{
-  g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
-  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
-
-  if (queue_contains (&self->awaiting_frames, &surface->frame))
-    {
-      g_queue_unlink (&self->awaiting_frames, &surface->frame);
-
-      if (self->awaiting_frames.length == 0)
-        gdk_display_link_source_pause ((GdkDisplayLinkSource *)self->frame_source);
-    }
-}
-
 NSWindow *
 _gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
                                               int             *x,
@@ -1027,17 +933,6 @@ _gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
   return NULL;
 }
 
-int
-_gdk_macos_display_get_nominal_refresh_rate (GdkMacosDisplay *self)
-{
-  g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), 60 * 1000);
-
-  if (self->frame_source == NULL)
-    return 60 * 1000;
-
-  return ((GdkDisplayLinkSource *)self->frame_source)->refresh_rate;
-}
-
 void
 _gdk_macos_display_clear_sorting (GdkMacosDisplay *self)
 {
diff --git a/gdk/macos/gdkmacosmonitor-private.h b/gdk/macos/gdkmacosmonitor-private.h
index e15f17352d..fee511d057 100644
--- a/gdk/macos/gdkmacosmonitor-private.h
+++ b/gdk/macos/gdkmacosmonitor-private.h
@@ -29,11 +29,15 @@
 
 G_BEGIN_DECLS
 
-GdkMacosMonitor   *_gdk_macos_monitor_new             (GdkMacosDisplay   *display,
-                                                       CGDirectDisplayID  screen_id);
-CGDirectDisplayID  _gdk_macos_monitor_get_screen_id   (GdkMacosMonitor   *self);
-gboolean           _gdk_macos_monitor_reconfigure     (GdkMacosMonitor   *self);
-CGColorSpaceRef    _gdk_macos_monitor_copy_colorspace (GdkMacosMonitor   *self);
+GdkMacosMonitor   *_gdk_macos_monitor_new                   (GdkMacosDisplay   *display,
+                                                             CGDirectDisplayID  screen_id);
+CGDirectDisplayID  _gdk_macos_monitor_get_screen_id         (GdkMacosMonitor   *self);
+gboolean           _gdk_macos_monitor_reconfigure           (GdkMacosMonitor   *self);
+CGColorSpaceRef    _gdk_macos_monitor_copy_colorspace       (GdkMacosMonitor   *self);
+void               _gdk_macos_monitor_add_frame_callback    (GdkMacosMonitor   *self,
+                                                             GdkMacosSurface   *surface);
+void               _gdk_macos_monitor_remove_frame_callback (GdkMacosMonitor   *self,
+                                                             GdkMacosSurface   *surface);
 
 G_END_DECLS
 
diff --git a/gdk/macos/gdkmacosmonitor.c b/gdk/macos/gdkmacosmonitor.c
index 6df1da0edc..3773ec5355 100644
--- a/gdk/macos/gdkmacosmonitor.c
+++ b/gdk/macos/gdkmacosmonitor.c
@@ -22,16 +22,21 @@
 #include <gdk/gdk.h>
 #include <math.h>
 
+#include "gdkdisplaylinksource.h"
 #include "gdkmacosdisplay-private.h"
 #include "gdkmacosmonitor-private.h"
+#include "gdkmacossurface-private.h"
 #include "gdkmacosutils-private.h"
 
 struct _GdkMacosMonitor
 {
-  GdkMonitor        parent_instance;
-  CGDirectDisplayID screen_id;
-  NSRect            workarea;
-  guint             has_opengl : 1;
+  GdkMonitor            parent_instance;
+  CGDirectDisplayID     screen_id;
+  GdkDisplayLinkSource *display_link;
+  NSRect                workarea;
+  GQueue                awaiting_frames;
+  guint                 has_opengl : 1;
+  guint                 in_frame : 1;
 };
 
 struct _GdkMacosMonitorClass
@@ -75,9 +80,26 @@ gdk_macos_monitor_get_workarea (GdkMonitor   *monitor,
   geometry->height = self->workarea.size.height;
 }
 
+static void
+gdk_macos_monitor_dispose (GObject *object)
+{
+  GdkMacosMonitor *self = (GdkMacosMonitor *)object;
+
+  if (self->display_link)
+    {
+      g_source_destroy ((GSource *)self->display_link);
+      g_clear_pointer ((GSource **)&self->display_link, g_source_unref);
+    }
+
+  G_OBJECT_CLASS (gdk_macos_monitor_parent_class)->dispose (object);
+}
+
 static void
 gdk_macos_monitor_class_init (GdkMacosMonitorClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gdk_macos_monitor_dispose;
 }
 
 static void
@@ -188,6 +210,68 @@ find_screen (CGDirectDisplayID screen_id)
   return screen;
 }
 
+static gboolean
+gdk_macos_monitor_display_link_cb (GdkMacosMonitor *self)
+{
+  gint64 presentation_time;
+  gint64 refresh_interval;
+  gint64 now;
+  GList *iter;
+
+  g_assert (GDK_IS_MACOS_MONITOR (self));
+  g_assert (!self->display_link->paused);
+
+  self->in_frame = TRUE;
+
+  presentation_time = self->display_link->presentation_time;
+  refresh_interval = self->display_link->refresh_interval;
+  now = g_source_get_time ((GSource *)self->display_link);
+
+  iter = self->awaiting_frames.head;
+
+  while (iter != NULL)
+    {
+      GdkMacosSurface *surface = iter->data;
+
+      g_assert (GDK_IS_MACOS_SURFACE (surface));
+
+      iter = iter->next;
+
+      g_queue_unlink (&self->awaiting_frames, &surface->frame);
+      _gdk_macos_surface_frame_presented (surface, presentation_time, refresh_interval);
+    }
+
+  if (self->awaiting_frames.length == 0 && !self->display_link->paused)
+    gdk_display_link_source_pause (self->display_link);
+
+  self->in_frame = FALSE;
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+_gdk_macos_monitor_reset_display_link (GdkMacosMonitor  *self,
+                                       CGDisplayModeRef  mode)
+{
+  GSource *source;
+
+  g_assert (GDK_IS_MACOS_MONITOR (self));
+
+  if (self->display_link)
+    {
+      g_source_destroy ((GSource *)self->display_link);
+      g_clear_pointer ((GSource **)&self->display_link, g_source_unref);
+    }
+
+  source = gdk_display_link_source_new (self->screen_id, mode);
+  self->display_link = (GdkDisplayLinkSource *)source;
+  g_source_set_callback (source,
+                         (GSourceFunc) gdk_macos_monitor_display_link_cb,
+                         self,
+                         NULL);
+  g_source_attach (source, NULL);
+}
+
 gboolean
 _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
 {
@@ -241,7 +325,7 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
    * setting (which is also used by the frame clock).
    */
   if (!(refresh_rate = CGDisplayModeGetRefreshRate (mode)))
-    refresh_rate = _gdk_macos_display_get_nominal_refresh_rate (display);
+    refresh_rate = 60 * 1000;
 
   gdk_monitor_set_connector (GDK_MONITOR (self), connector);
   gdk_monitor_set_model (GDK_MONITOR (self), name);
@@ -261,6 +345,9 @@ _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
    */
   self->has_opengl = !!has_opengl;
 
+  /* Create a new display link to receive feedback about when to render */
+  _gdk_macos_monitor_reset_display_link (self, mode);
+
   CGDisplayModeRelease (mode);
   g_free (name);
   g_free (connector);
@@ -302,3 +389,45 @@ _gdk_macos_monitor_copy_colorspace (GdkMacosMonitor *self)
 
   return CGDisplayCopyColorSpace (self->screen_id);
 }
+
+void
+_gdk_macos_monitor_add_frame_callback (GdkMacosMonitor *self,
+                                       GdkMacosSurface *surface)
+{
+  g_return_if_fail (GDK_IS_MACOS_MONITOR (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+  g_return_if_fail (surface->frame.data == (gpointer)surface);
+  g_return_if_fail (surface->frame.prev == NULL);
+  g_return_if_fail (surface->frame.next == NULL);
+  g_return_if_fail (self->awaiting_frames.head != &surface->frame);
+  g_return_if_fail (self->awaiting_frames.tail != &surface->frame);
+
+  /* Processing frames is always head to tail, so push to the
+   * head so that we don't possibly re-enter this right after
+   * adding to the queue.
+   */
+  if (!queue_contains (&self->awaiting_frames, &surface->frame))
+    {
+      g_queue_push_head_link (&self->awaiting_frames, &surface->frame);
+
+      if (!self->in_frame && self->awaiting_frames.length == 1)
+        gdk_display_link_source_unpause (self->display_link);
+    }
+}
+
+void
+_gdk_macos_monitor_remove_frame_callback (GdkMacosMonitor *self,
+                                          GdkMacosSurface *surface)
+{
+  g_return_if_fail (GDK_IS_MACOS_MONITOR (self));
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
+  g_return_if_fail (surface->frame.data == (gpointer)surface);
+
+  if (queue_contains (&self->awaiting_frames, &surface->frame))
+    {
+      g_queue_unlink (&self->awaiting_frames, &surface->frame);
+
+      if (!self->in_frame && self->awaiting_frames.length == 0)
+        gdk_display_link_source_pause (self->display_link);
+    }
+}
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
index 5ac4201a42..15a7442c17 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -75,6 +75,8 @@ struct _GdkMacosSurface
   guint geometry_dirty : 1;
   guint next_frame_set : 1;
   guint show_on_next_swap : 1;
+  guint in_frame : 1;
+  guint awaiting_frame : 1;
 };
 
 struct _GdkMacosSurfaceClass
@@ -116,10 +118,11 @@ void               _gdk_macos_surface_resize                  (GdkMacosSurface
                                                                int                   width,
                                                                int                   height);
 void               _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface      *self);
-void               _gdk_macos_surface_show                    (GdkMacosSurface      *self);
-void               _gdk_macos_surface_publish_timings         (GdkMacosSurface      *self,
+void               _gdk_macos_surface_request_frame           (GdkMacosSurface      *self);
+void               _gdk_macos_surface_frame_presented         (GdkMacosSurface      *self,
                                                                gint64                
predicted_presentation_time,
                                                                gint64                refresh_interval);
+void               _gdk_macos_surface_show                    (GdkMacosSurface      *self);
 void               _gdk_macos_surface_synthesize_null_key     (GdkMacosSurface      *self);
 void               _gdk_macos_surface_move                    (GdkMacosSurface      *self,
                                                                int                   x,
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index cf9d7067f8..ac2353dd03 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -63,6 +63,73 @@ window_is_fullscreen (GdkMacosSurface *self)
   return ([self->window styleMask] & NSWindowStyleMaskFullScreen) != 0;
 }
 
+void
+_gdk_macos_surface_request_frame (GdkMacosSurface *self)
+{
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  if (self->awaiting_frame)
+    return;
+
+  self->awaiting_frame = TRUE;
+  _gdk_macos_monitor_add_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
+  gdk_surface_freeze_updates (GDK_SURFACE (self));
+}
+
+static void
+_gdk_macos_surface_cancel_frame (GdkMacosSurface *self)
+{
+  g_assert (GDK_IS_MACOS_SURFACE (self));
+
+  if (!self->awaiting_frame)
+    return;
+
+  self->awaiting_frame = FALSE;
+  _gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
+  gdk_surface_thaw_updates (GDK_SURFACE (self));
+}
+
+void
+_gdk_macos_surface_frame_presented (GdkMacosSurface *self,
+                                    gint64           presentation_time,
+                                    gint64           refresh_interval)
+{
+  GdkFrameTimings *timings;
+  GdkFrameClock *frame_clock;
+
+  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+  self->awaiting_frame = FALSE;
+
+  if (GDK_SURFACE_DESTROYED (self))
+    return;
+
+  frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
+
+  if (self->pending_frame_counter)
+    {
+      timings = gdk_frame_clock_get_timings (frame_clock, self->pending_frame_counter);
+
+      if (timings != NULL)
+        {
+          timings->presentation_time = presentation_time - refresh_interval;
+          timings->complete = TRUE;
+        }
+
+      self->pending_frame_counter = 0;
+    }
+
+  timings = gdk_frame_clock_get_current_timings (frame_clock);
+
+  if (timings != NULL)
+    {
+      timings->refresh_interval = refresh_interval;
+      timings->predicted_presentation_time = presentation_time;
+    }
+
+  if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
+    gdk_surface_thaw_updates (GDK_SURFACE (self));
+}
 
 void
 _gdk_macos_surface_reposition_children (GdkMacosSurface *self)
@@ -131,8 +198,6 @@ gdk_macos_surface_hide (GdkSurface *surface)
 
   self->show_on_next_swap = FALSE;
 
-  _gdk_macos_display_remove_frame_callback (GDK_MACOS_DISPLAY (surface->display), self);
-
   was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
   was_key = [self->window isKeyWindow];
 
@@ -157,8 +222,12 @@ gdk_macos_surface_hide (GdkSurface *surface)
         }
     }
 
-  if (was_mapped)
-    gdk_surface_freeze_updates (GDK_SURFACE (self));
+  if (self->awaiting_frame)
+    {
+      self->awaiting_frame = FALSE;
+      _gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
+      gdk_surface_freeze_updates (surface);
+    }
 }
 
 static int
@@ -202,6 +271,7 @@ gdk_macos_surface_begin_frame (GdkMacosSurface *self)
 {
   g_assert (GDK_IS_MACOS_SURFACE (self));
 
+  self->in_frame = TRUE;
 }
 
 static void
@@ -222,11 +292,9 @@ gdk_macos_surface_end_frame (GdkMacosSurface *self)
   if ((timings = gdk_frame_clock_get_current_timings (frame_clock)))
     self->pending_frame_counter = timings->frame_counter;
 
-  if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
-    {
-      _gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
-      gdk_surface_freeze_updates (GDK_SURFACE (self));
-    }
+  self->in_frame = FALSE;
+
+  _gdk_macos_surface_request_frame (self);
 }
 
 static void
@@ -400,7 +468,16 @@ gdk_macos_surface_destroy (GdkSurface *surface,
   GdkMacosWindow *window = g_steal_pointer (&self->window);
   GdkFrameClock *frame_clock;
 
-  g_clear_object (&self->best_monitor);
+  if (self->best_monitor)
+    {
+      if (self->awaiting_frame)
+        {
+          _gdk_macos_monitor_remove_frame_callback (GDK_MACOS_MONITOR (self->best_monitor), self);
+          self->awaiting_frame = FALSE;
+        }
+
+      g_clear_object (&self->best_monitor);
+    }
 
   if ((frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
     {
@@ -787,41 +864,6 @@ _gdk_macos_surface_configure (GdkMacosSurface *self)
   _gdk_macos_surface_reposition_children (self);
 }
 
-void
-_gdk_macos_surface_publish_timings (GdkMacosSurface *self,
-                                    gint64           presentation_time,
-                                    gint64           refresh_interval)
-{
-  GdkFrameTimings *timings;
-  GdkFrameClock *frame_clock;
-
-  g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
-
-  if (!(frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
-    return;
-
-  if (self->pending_frame_counter)
-    {
-      timings = gdk_frame_clock_get_timings (frame_clock, self->pending_frame_counter);
-
-      if (timings != NULL)
-        {
-          timings->presentation_time = presentation_time - refresh_interval;
-          timings->complete = TRUE;
-        }
-
-      self->pending_frame_counter = 0;
-    }
-
-  timings = gdk_frame_clock_get_current_timings (frame_clock);
-
-  if (timings != NULL)
-    {
-      timings->refresh_interval = refresh_interval;
-      timings->predicted_presentation_time = presentation_time;
-    }
-}
-
 void
 _gdk_macos_surface_show (GdkMacosSurface *self)
 {
@@ -832,22 +874,15 @@ _gdk_macos_surface_show (GdkMacosSurface *self)
   if (GDK_SURFACE_DESTROYED (self))
     return;
 
-  was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
-
-  if (!was_mapped)
-    gdk_surface_set_is_mapped (GDK_SURFACE (self), TRUE);
-
   _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display));
-
   self->show_on_next_swap = TRUE;
 
+  was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
+
   if (!was_mapped)
     {
-      if (gdk_surface_get_mapped (GDK_SURFACE (self)))
-        {
-          _gdk_macos_surface_configure (self);
-          gdk_surface_thaw_updates (GDK_SURFACE (self));
-        }
+      gdk_surface_set_is_mapped (GDK_SURFACE (self), TRUE);
+      gdk_surface_thaw_updates (GDK_SURFACE (self));
     }
 }
 
@@ -994,6 +1029,8 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
 
   g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
 
+  _gdk_macos_surface_cancel_frame (self);
+
   rect.x = self->root_x;
   rect.y = self->root_y;
   rect.width = GDK_SURFACE (self)->width;
@@ -1056,8 +1093,8 @@ _gdk_macos_surface_monitor_changed (GdkMacosSurface *self)
     }
 
   _gdk_macos_surface_configure (self);
-
   gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
+  _gdk_macos_surface_request_frame (self);
 }
 
 GdkMonitor *


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