[gtk/wip/chergert/quartz4u] macos: start on display link based frame clock
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/quartz4u] macos: start on display link based frame clock
- Date: Tue, 5 May 2020 01:02:41 +0000 (UTC)
commit 676bac31bc195268ea56deab6fd3b8deb2acf60f
Author: Christian Hergert <chergert redhat com>
Date: Mon May 4 18:00:57 2020 -0700
macos: start on display link based frame clock
gdk/macos/GdkMacosWindow.c | 1 -
gdk/macos/gdkdisplaylinksource.c | 253 ++++++++++++++++++++++++++++++++++++
gdk/macos/gdkdisplaylinksource.h | 48 +++++++
gdk/macos/gdkmacosdisplay-private.h | 4 +
gdk/macos/gdkmacosdisplay.c | 115 ++++++++++++----
gdk/macos/gdkmacossurface-private.h | 6 +-
gdk/macos/gdkmacossurface.c | 108 +++++++++------
gdk/macos/meson.build | 2 +
8 files changed, 475 insertions(+), 62 deletions(-)
---
diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c
index 678990993d..6b3c0ecf0e 100644
--- a/gdk/macos/GdkMacosWindow.c
+++ b/gdk/macos/GdkMacosWindow.c
@@ -247,7 +247,6 @@
event = gdk_configure_event_new (surface,
content_rect.size.width,
content_rect.size.height);
-
_gdk_event_queue_append (display, event);
[self checkSendEnterNotify];
diff --git a/gdk/macos/gdkdisplaylinksource.c b/gdk/macos/gdkdisplaylinksource.c
new file mode 100644
index 0000000000..2961042724
--- /dev/null
+++ b/gdk/macos/gdkdisplaylinksource.c
@@ -0,0 +1,253 @@
+/* gdkdisplaylinksource.c
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian Hergert <christian hergert me>
+ */
+
+#include "config.h"
+
+#include <AppKit/AppKit.h>
+#include <mach/mach_time.h>
+
+#include "gdkdisplaylinksource.h"
+
+#include "gdkmacoseventsource-private.h"
+
+static gint64 host_to_frame_clock_time (gint64 host_time);
+
+static gboolean
+gdk_display_link_source_prepare (GSource *source,
+ gint *timeout_)
+{
+ GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+ gint64 now;
+
+ now = g_source_get_time (source);
+
+ if (now < impl->presentation_time)
+ *timeout_ = (impl->presentation_time - now) / 1000L;
+ else
+ *timeout_ = -1;
+
+ return impl->needs_dispatch;
+}
+
+static gboolean
+gdk_display_link_source_check (GSource *source)
+{
+ GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+ return impl->needs_dispatch;
+}
+
+static gboolean
+gdk_display_link_source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+ gboolean ret = G_SOURCE_CONTINUE;
+
+ impl->needs_dispatch = FALSE;
+
+ if (callback != NULL)
+ ret = callback (user_data);
+
+ return ret;
+}
+
+static void
+gdk_display_link_source_finalize (GSource *source)
+{
+ GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
+
+ CVDisplayLinkStop (impl->display_link);
+ CVDisplayLinkRelease (impl->display_link);
+}
+
+static GSourceFuncs gdk_display_link_source_funcs = {
+ gdk_display_link_source_prepare,
+ gdk_display_link_source_check,
+ gdk_display_link_source_dispatch,
+ gdk_display_link_source_finalize
+};
+
+void
+gdk_display_link_source_pause (GdkDisplayLinkSource *source)
+{
+ CVDisplayLinkStop (source->display_link);
+}
+
+void
+gdk_display_link_source_unpause (GdkDisplayLinkSource *source)
+{
+ CVDisplayLinkStart (source->display_link);
+}
+
+static CVReturn
+gdk_display_link_source_frame_cb (CVDisplayLinkRef display_link,
+ const CVTimeStamp *inNow,
+ const CVTimeStamp *inOutputTime,
+ CVOptionFlags flagsIn,
+ CVOptionFlags *flagsOut,
+ void *user_data)
+{
+ GdkDisplayLinkSource *impl = user_data;
+ gint64 presentation_time;
+ gboolean needs_wakeup;
+
+ needs_wakeup = !g_atomic_int_get (&impl->needs_dispatch);
+
+ presentation_time = host_to_frame_clock_time (inOutputTime->hostTime);
+
+ impl->presentation_time = presentation_time;
+ impl->needs_dispatch = TRUE;
+
+ if (needs_wakeup)
+ {
+ NSEvent *event;
+
+ /* Post a message so we'll break out of the message loop.
+ *
+ * We don't use g_main_context_wakeup() here because that
+ * would result in sending a message to the pipe(2) fd in
+ * the select thread which would then send this message as
+ * well. Lots of extra work.
+ */
+ event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
+ location: NSZeroPoint
+ modifierFlags: 0
+ timestamp: 0
+ windowNumber: 0
+ context: nil
+ subtype: GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP
+ data1: 0
+ data2: 0];
+
+ [NSApp postEvent:event atStart:YES];
+ }
+
+ return kCVReturnSuccess;
+}
+
+/**
+ * gdk_display_link_source_new:
+ *
+ * Creates a new #GSource that will activate the dispatch function upon
+ * notification from a CVDisplayLink that a new frame should be drawn.
+ *
+ * Effort is made to keep the transition from the high-priority
+ * CVDisplayLink thread into this GSource lightweight. However, this is
+ * somewhat non-ideal since the best case would be to do the drawing
+ * from the high-priority thread.
+ *
+ * Returns: (transfer full): A newly created #GSource.
+ */
+GSource *
+gdk_display_link_source_new (void)
+{
+ GdkDisplayLinkSource *impl;
+ GSource *source;
+ CVReturn ret;
+ double period;
+
+ source = g_source_new (&gdk_display_link_source_funcs, sizeof *impl);
+ impl = (GdkDisplayLinkSource *)source;
+
+ /*
+ * Create our link based on currently connected displays.
+ * If there are multiple displays, this will be something that tries
+ * to work for all of them. In the future, we may want to explore multiple
+ * links based on the connected displays.
+ */
+ ret = CVDisplayLinkCreateWithActiveCGDisplays (&impl->display_link);
+ if (ret != kCVReturnSuccess)
+ {
+ g_warning ("Failed to initialize CVDisplayLink!");
+ return source;
+ }
+
+ /*
+ * Determine our nominal period between frames.
+ */
+ period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
+ if (period == 0.0)
+ period = 1.0 / 60.0;
+ impl->refresh_interval = period * 1000000L;
+
+ /*
+ * Wire up our callback to be executed within the high-priority thread.
+ */
+ CVDisplayLinkSetOutputCallback (impl->display_link,
+ gdk_display_link_source_frame_cb,
+ source);
+
+ g_source_set_name (source, "[gdk] quartz frame clock");
+
+ return source;
+}
+
+static gint64
+host_to_frame_clock_time (gint64 host_time)
+{
+ static mach_timebase_info_data_t timebase_info;
+
+ /*
+ * NOTE:
+ *
+ * This code is taken from GLib to match g_get_monotonic_time().
+ */
+ if (G_UNLIKELY (timebase_info.denom == 0))
+ {
+ /* This is a fraction that we must use to scale
+ * mach_absolute_time() by in order to reach nanoseconds.
+ *
+ * We've only ever observed this to be 1/1, but maybe it could be
+ * 1000/1 if mach time is microseconds already, or 1/1000 if
+ * picoseconds. Try to deal nicely with that.
+ */
+ mach_timebase_info (&timebase_info);
+
+ /* We actually want microseconds... */
+ if (timebase_info.numer % 1000 == 0)
+ timebase_info.numer /= 1000;
+ else
+ timebase_info.denom *= 1000;
+
+ /* We want to make the numer 1 to avoid having to multiply... */
+ if (timebase_info.denom % timebase_info.numer == 0)
+ {
+ timebase_info.denom /= timebase_info.numer;
+ timebase_info.numer = 1;
+ }
+ else
+ {
+ /* We could just multiply by timebase_info.numer below, but why
+ * bother for a case that may never actually exist...
+ *
+ * Plus -- performing the multiplication would risk integer
+ * overflow. If we ever actually end up in this situation, we
+ * should more carefully evaluate the correct course of action.
+ */
+ mach_timebase_info (&timebase_info); /* Get a fresh copy for a better message */
+ g_error ("Got weird mach timebase info of %d/%d. Please file a bug against GLib.",
+ timebase_info.numer, timebase_info.denom);
+ }
+ }
+
+ return host_time / timebase_info.denom;
+}
diff --git a/gdk/macos/gdkdisplaylinksource.h b/gdk/macos/gdkdisplaylinksource.h
new file mode 100644
index 0000000000..7493b0c0d4
--- /dev/null
+++ b/gdk/macos/gdkdisplaylinksource.h
@@ -0,0 +1,48 @@
+/* gdkdisplaylinksource.h
+ *
+ * Copyright (C) 2015 Christian Hergert <christian hergert me>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Christian Hergert <christian hergert me>
+ */
+
+#ifndef GDK_DISPLAY_LINK_SOURCE_H
+#define GDK_DISPLAY_LINK_SOURCE_H
+
+#include <glib.h>
+
+#include <QuartzCore/QuartzCore.h>
+
+G_BEGIN_DECLS
+
+typedef struct
+{
+ GSource source;
+
+ CVDisplayLinkRef display_link;
+ gint64 refresh_interval;
+
+ volatile gint64 presentation_time;
+ volatile guint needs_dispatch;
+} GdkDisplayLinkSource;
+
+GSource *gdk_display_link_source_new (void);
+void gdk_display_link_source_pause (GdkDisplayLinkSource *source);
+void gdk_display_link_source_unpause (GdkDisplayLinkSource *source);
+
+G_END_DECLS
+
+#endif /* GDK_DISPLAY_LINK_SOURCE_H */
diff --git a/gdk/macos/gdkmacosdisplay-private.h b/gdk/macos/gdkmacosdisplay-private.h
index d7b737fd5d..7184c920d1 100644
--- a/gdk/macos/gdkmacosdisplay-private.h
+++ b/gdk/macos/gdkmacosdisplay-private.h
@@ -57,6 +57,10 @@ GdkMacosSurface *_gdk_macos_display_get_surface_at_display_coords (GdkMacosDisp
void _gdk_macos_display_stacking_changed (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);
G_END_DECLS
diff --git a/gdk/macos/gdkmacosdisplay.c b/gdk/macos/gdkmacosdisplay.c
index 587b3b5268..bfc00190e7 100644
--- a/gdk/macos/gdkmacosdisplay.c
+++ b/gdk/macos/gdkmacosdisplay.c
@@ -23,10 +23,11 @@
#import "GdkMacosWindow.h"
+#include "gdkdisplayprivate.h"
#include "gdkeventsprivate.h"
+#include "gdkdisplaylinksource.h"
#include "gdkmacoscairocontext-private.h"
-#include "gdkdisplayprivate.h"
#include "gdkmacoseventsource-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacoskeymap-private.h"
@@ -71,18 +72,22 @@
struct _GdkMacosDisplay
{
- GdkDisplay parent_instance;
+ GdkDisplay parent_instance;
+
+ char *name;
+ GdkMacosKeymap *keymap;
- char *name;
- GdkMacosKeymap *keymap;
+ GPtrArray *monitors;
- GPtrArray *monitors;
- GQueue surfaces;
+ GQueue surfaces;
- int width;
- int height;
- int min_x;
- int min_y;
+ GSource *frame_source;
+ GQueue awaiting_frames;
+
+ int width;
+ int height;
+ int min_x;
+ int min_y;
};
struct _GdkMacosDisplayClass
@@ -233,6 +238,52 @@ 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_display_remove_frame_callback (self, surface);
+ _gdk_macos_surface_thaw (surface,
+ source->presentation_time,
+ source->refresh_interval);
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+gdk_macos_display_load_display_link (GdkMacosDisplay *self)
+{
+ self->frame_source = gdk_display_link_source_new ();
+ g_source_set_callback (self->frame_source,
+ gdk_macos_display_frame_cb,
+ self,
+ NULL);
+ g_source_attach (self->frame_source, NULL);
+}
+
static const gchar *
gdk_macos_display_get_name (GdkDisplay *display)
{
@@ -318,17 +369,11 @@ void
_gdk_macos_display_surface_removed (GdkMacosDisplay *self,
GdkMacosSurface *surface)
{
- GList *stacking;
-
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
g_return_if_fail (GDK_IS_MACOS_SURFACE (surface));
- stacking = _gdk_macos_surface_get_stacking (surface);
-
- g_queue_unlink (&self->surfaces, stacking);
-
- stacking->prev = NULL;
- stacking->next = NULL;
+ g_queue_unlink (&self->surfaces, &surface->stacking);
+ g_queue_unlink (&self->awaiting_frames, &surface->frame_link);
}
void
@@ -357,8 +402,8 @@ _gdk_macos_display_stacking_changed (GdkMacosDisplay *self)
continue;
surface = [(GdkMacosWindow *)nswindow getGdkSurface];
- link = _gdk_macos_surface_get_stacking (surface);
+ link = &surface->stacking;
link->prev = NULL;
link->next = NULL;
@@ -389,9 +434,7 @@ gdk_macos_display_create_surface (GdkDisplay *display,
if (surface != NULL)
{
- GList *stacking = _gdk_macos_surface_get_stacking (surface);
-
- g_queue_push_head_link (&self->surfaces, stacking);
+ g_queue_push_head_link (&self->surfaces, &surface->stacking);
_gdk_macos_display_stacking_changed (self);
}
@@ -413,6 +456,7 @@ gdk_macos_display_finalize (GObject *object)
{
GdkMacosDisplay *self = (GdkMacosDisplay *)object;
+ g_clear_pointer (&self->frame_source, g_source_unref);
g_clear_pointer (&self->monitors, g_ptr_array_unref);
g_clear_pointer (&self->name, g_free);
@@ -475,6 +519,7 @@ _gdk_macos_display_open (const gchar *display_name)
gdk_macos_display_load_seat (self);
gdk_macos_display_load_monitors (self);
+ gdk_macos_display_load_display_link (self);
if (event_source == NULL)
{
@@ -630,3 +675,29 @@ _gdk_macos_display_get_surface_at_display_coords (GdkMacosDisplay *self,
return NULL;
}
+
+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));
+
+ g_queue_push_tail_link (&self->awaiting_frames, &surface->frame_link);
+
+ 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));
+
+ g_queue_unlink (&self->awaiting_frames, &surface->frame_link);
+
+ if (self->awaiting_frames.length == 0)
+ gdk_display_link_source_pause ((GdkDisplayLinkSource *)self->frame_source);
+}
diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h
index 6ea572b9da..6a2f08183d 100644
--- a/gdk/macos/gdkmacossurface-private.h
+++ b/gdk/macos/gdkmacossurface-private.h
@@ -38,6 +38,8 @@ G_BEGIN_DECLS
struct _GdkMacosSurface
{
GdkSurface parent_instance;
+ GList stacking;
+ GList frame_link;
};
struct _GdkMacosSurfaceClass
@@ -54,7 +56,6 @@ GdkMacosSurface *_gdk_macos_surface_new (GdkMacosDisplay
int height);
NSWindow *_gdk_macos_surface_get_native (GdkMacosSurface *self);
CGDirectDisplayID _gdk_macos_surface_get_screen_id (GdkMacosSurface *self);
-GList *_gdk_macos_surface_get_stacking (GdkMacosSurface *self);
const char *_gdk_macos_surface_get_title (GdkMacosSurface *self);
void _gdk_macos_surface_set_title (GdkMacosSurface *self,
const gchar *title);
@@ -80,6 +81,9 @@ void _gdk_macos_surface_damage_cairo (GdkMacosSurface
cairo_region_t *painted);
void _gdk_macos_surface_set_is_key (GdkMacosSurface *self,
gboolean is_key);
+void _gdk_macos_surface_thaw (GdkMacosSurface *self,
+ gint64
predicted_presentation_time,
+ gint64 refresh_interval);
G_END_DECLS
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index d789e55934..3e367c2d5f 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -40,8 +40,6 @@
typedef struct
{
- GList stacking;
-
GdkMacosWindow *window;
char *title;
@@ -53,6 +51,8 @@ typedef struct
int scale;
+ gint64 pending_frame_counter;
+
guint modal_hint : 1;
guint is_key : 1;
} GdkMacosSurfacePrivate;
@@ -67,16 +67,6 @@ enum {
static GParamSpec *properties [LAST_PROP];
-GList *
-_gdk_macos_surface_get_stacking (GdkMacosSurface *self)
-{
- GdkMacosSurfacePrivate *priv = gdk_macos_surface_get_instance_private (self);
-
- g_return_val_if_fail (GDK_IS_MACOS_SURFACE (self), NULL);
-
- return &priv->stacking;
-}
-
static gboolean
window_is_fullscreen (GdkMacosSurface *self)
{
@@ -118,6 +108,8 @@ gdk_macos_surface_hide (GdkSurface *surface)
gdk_seat_ungrab (seat);
[priv->window hide];
+
+ _gdk_surface_clear_update_area (surface);
}
static gint
@@ -191,13 +183,6 @@ gdk_macos_surface_begin_move_drag (GdkSurface *surface,
[priv->window beginManualMove];
}
-static void
-gdk_macos_surface_predict_presentation_time (GdkMacosSurface *self)
-{
- g_assert (GDK_IS_MACOS_SURFACE (self));
-
-}
-
static void
gdk_macos_surface_begin_frame (GdkMacosSurface *self)
{
@@ -208,8 +193,22 @@ gdk_macos_surface_begin_frame (GdkMacosSurface *self)
static void
gdk_macos_surface_end_frame (GdkMacosSurface *self)
{
+ GdkMacosSurfacePrivate *priv = gdk_macos_surface_get_instance_private (self);
+ GdkFrameTimings *timings;
+ GdkFrameClock *frame_clock;
+ GdkDisplay *display;
+
g_assert (GDK_IS_MACOS_SURFACE (self));
+ display = gdk_surface_get_display (GDK_SURFACE (self));
+ frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
+
+ if ((timings = gdk_frame_clock_get_current_timings (frame_clock)))
+ priv->pending_frame_counter = timings->frame_counter;
+
+ _gdk_macos_display_add_frame_callback (GDK_MACOS_DISPLAY (display), self);
+
+ gdk_surface_freeze_updates (GDK_SURFACE (self));
}
static void
@@ -224,7 +223,6 @@ gdk_macos_surface_before_paint (GdkMacosSurface *self,
if (surface->update_freeze_count > 0)
return;
- gdk_macos_surface_predict_presentation_time (self);
gdk_macos_surface_begin_frame (self);
}
@@ -337,8 +335,8 @@ gdk_macos_surface_destroy (GdkSurface *surface,
_gdk_macos_display_surface_removed (GDK_MACOS_DISPLAY (surface->display), self);
- g_assert (priv->stacking.prev == NULL);
- g_assert (priv->stacking.next == NULL);
+ g_assert (self->stacking.prev == NULL);
+ g_assert (self->stacking.next == NULL);
GDK_END_MACOS_ALLOC_POOL;
}
@@ -353,18 +351,19 @@ gdk_macos_surface_constructed (GObject *object)
G_OBJECT_CLASS (gdk_macos_surface_parent_class)->constructed (object);
- frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
-
- g_signal_connect_object (frame_clock,
- "before-paint",
- G_CALLBACK (gdk_macos_surface_before_paint),
- self,
- G_CONNECT_SWAPPED);
- g_signal_connect_object (frame_clock,
- "after-paint",
- G_CALLBACK (gdk_macos_surface_after_paint),
- self,
- G_CONNECT_SWAPPED);
+ if ((frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self))))
+ {
+ g_signal_connect_object (frame_clock,
+ "before-paint",
+ G_CALLBACK (gdk_macos_surface_before_paint),
+ self,
+ G_CONNECT_SWAPPED);
+ g_signal_connect_object (frame_clock,
+ "after-paint",
+ G_CALLBACK (gdk_macos_surface_after_paint),
+ self,
+ G_CONNECT_SWAPPED);
+ }
}
static void
@@ -441,9 +440,8 @@ gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass)
static void
gdk_macos_surface_init (GdkMacosSurface *self)
{
- GdkMacosSurfacePrivate *priv = gdk_macos_surface_get_instance_private (self);
-
- priv->stacking.data = self;
+ self->stacking.data = self;
+ self->frame_link.data = self;
}
GdkMacosSurface *
@@ -727,6 +725,40 @@ _gdk_macos_surface_set_is_key (GdkMacosSurface *self,
gdk_synthesize_surface_state (GDK_SURFACE (self), GDK_SURFACE_STATE_FOCUSED, 0);
event = gdk_focus_event_new (GDK_SURFACE (self), keyboard, NULL, is_key);
- _gdk_event_queue_append (display, event);
+ _gdk_event_queue_append (GDK_DISPLAY (display), event);
+ }
+}
+
+void
+_gdk_macos_surface_thaw (GdkMacosSurface *self,
+ gint64 presentation_time,
+ gint64 refresh_interval)
+{
+ GdkMacosSurfacePrivate *priv = gdk_macos_surface_get_instance_private (self);
+ GdkFrameTimings *timings;
+ GdkFrameClock *frame_clock;
+
+ g_return_if_fail (GDK_IS_MACOS_SURFACE (self));
+
+ gdk_surface_thaw_updates (GDK_SURFACE (self));
+
+ frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self));
+
+ if (priv->pending_frame_counter)
+ {
+ timings = gdk_frame_clock_get_timings (frame_clock, priv->pending_frame_counter);
+
+ if (timings != NULL)
+ timings->presentation_time = presentation_time - refresh_interval;
+
+ priv->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;
}
}
diff --git a/gdk/macos/meson.build b/gdk/macos/meson.build
index 03fae86055..0ee0e11e1f 100644
--- a/gdk/macos/meson.build
+++ b/gdk/macos/meson.build
@@ -1,4 +1,5 @@
gdk_macos_sources = files([
+ 'gdkdisplaylinksource.c',
'GdkMacosWindow.c',
'gdkmacoscairocontext.c',
'gdkmacoscursor.c',
@@ -32,6 +33,7 @@ install_headers(gdk_macos_public_headers, 'gdkmacos.h', subdir: 'gtk-4.0/gdk/mac
gdk_macos_frameworks = [
'AppKit',
'Carbon',
+ 'CoreVideo',
'CoreServices',
]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]