Change GdkFrameClock from an interface to a class

It's unlikely that anyone will want to have, say, a GtkWidget that
also acts as a GdkFrameClock, so an abstract base class is as
flexible as making GdkFrameClock an interface, but has advantages:

 - If we decide to never make implementing your own frame clock
   possible, we can remove the virtualization.
 - We can put functionality like history into the base class.
 - Avoids the oddity of a interface without a public interface
   VTable, which may cause problems for language bindings.
This commit is contained in:
Owen W. Taylor
2013-02-12 15:02:21 -05:00
parent be22b9fbb9
commit 5f2d1654a5
6 changed files with 156 additions and 103 deletions

View File

@ -105,6 +105,7 @@ gdk_private_headers = \
gdkdisplayprivate.h \ gdkdisplayprivate.h \
gdkdndprivate.h \ gdkdndprivate.h \
gdkframeclockidle.h \ gdkframeclockidle.h \
gdkframeclockprivate.h \
gdkscreenprivate.h \ gdkscreenprivate.h \
gdkinternals.h \ gdkinternals.h \
gdkintl.h \ gdkintl.h \

View File

@ -26,7 +26,7 @@
#include "config.h" #include "config.h"
#include "gdkframeclock.h" #include "gdkframeclockprivate.h"
/** /**
* SECTION:frameclock * SECTION:frameclock
@ -74,7 +74,7 @@
* time that doesn't have a lot to do with wall clock time. * time that doesn't have a lot to do with wall clock time.
*/ */
G_DEFINE_INTERFACE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT) G_DEFINE_ABSTRACT_TYPE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT)
enum { enum {
FRAME_REQUESTED, FRAME_REQUESTED,
@ -90,9 +90,28 @@ enum {
static guint signals[LAST_SIGNAL]; static guint signals[LAST_SIGNAL];
static void struct _GdkFrameClockPrivate
gdk_frame_clock_default_init (GdkFrameClockInterface *iface)
{ {
GdkFrameHistory *history;
};
static void
gdk_frame_clock_finalize (GObject *object)
{
GdkFrameClockPrivate *priv = GDK_FRAME_CLOCK (object)->priv;
g_object_unref (priv->history);
G_OBJECT_CLASS (gdk_frame_clock_parent_class)->finalize (object);
}
static void
gdk_frame_clock_class_init (GdkFrameClockClass *klass)
{
GObjectClass *gobject_class = (GObjectClass*) klass;
gobject_class->finalize = gdk_frame_clock_finalize;
/** /**
* GdkFrameClock::frame-requested: * GdkFrameClock::frame-requested:
* @clock: the frame clock emitting the signal * @clock: the frame clock emitting the signal
@ -221,6 +240,21 @@ gdk_frame_clock_default_init (GdkFrameClockInterface *iface)
NULL, NULL, NULL, NULL,
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
g_type_class_add_private (klass, sizeof (GdkFrameClockPrivate));
}
static void
gdk_frame_clock_init (GdkFrameClock *clock)
{
GdkFrameClockPrivate *priv;
clock->priv = G_TYPE_INSTANCE_GET_PRIVATE (clock,
GDK_TYPE_FRAME_CLOCK,
GdkFrameClockPrivate);
priv = clock->priv;
priv->history = gdk_frame_history_new ();
} }
/** /**
@ -247,7 +281,7 @@ gdk_frame_clock_get_frame_time (GdkFrameClock *clock)
{ {
g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), 0); g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), 0);
return GDK_FRAME_CLOCK_GET_IFACE (clock)->get_frame_time (clock); return GDK_FRAME_CLOCK_GET_CLASS (clock)->get_frame_time (clock);
} }
/** /**
@ -270,7 +304,7 @@ gdk_frame_clock_request_phase (GdkFrameClock *clock,
{ {
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock)); g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
GDK_FRAME_CLOCK_GET_IFACE (clock)->request_phase (clock, phase); GDK_FRAME_CLOCK_GET_CLASS (clock)->request_phase (clock, phase);
} }
@ -279,7 +313,7 @@ gdk_frame_clock_freeze (GdkFrameClock *clock)
{ {
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock)); g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
GDK_FRAME_CLOCK_GET_IFACE (clock)->freeze (clock); GDK_FRAME_CLOCK_GET_CLASS (clock)->freeze (clock);
} }
@ -288,7 +322,7 @@ gdk_frame_clock_thaw (GdkFrameClock *clock)
{ {
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock)); g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
GDK_FRAME_CLOCK_GET_IFACE (clock)->thaw (clock); GDK_FRAME_CLOCK_GET_CLASS (clock)->thaw (clock);
} }
/** /**
@ -303,9 +337,13 @@ gdk_frame_clock_thaw (GdkFrameClock *clock)
GdkFrameHistory * GdkFrameHistory *
gdk_frame_clock_get_history (GdkFrameClock *clock) gdk_frame_clock_get_history (GdkFrameClock *clock)
{ {
GdkFrameClockPrivate *priv;
g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), NULL); g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), NULL);
return GDK_FRAME_CLOCK_GET_IFACE (clock)->get_history (clock); priv = clock->priv;
return priv->history;
} }
/** /**
@ -324,7 +362,7 @@ gdk_frame_clock_get_requested (GdkFrameClock *clock)
{ {
g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), FALSE); g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), FALSE);
return GDK_FRAME_CLOCK_GET_IFACE (clock)->get_requested (clock); return GDK_FRAME_CLOCK_GET_CLASS (clock)->get_requested (clock);
} }
/** /**
@ -350,22 +388,6 @@ gdk_frame_clock_get_frame_time_val (GdkFrameClock *clock,
timeval->tv_usec = (time_ms % 1000) * 1000; timeval->tv_usec = (time_ms % 1000) * 1000;
} }
/**
* gdk_frame_clock_frame_requested:
* @clock: the clock
*
* Emits the frame-requested signal. Used in implementations of the
* #GdkFrameClock interface.
*/
void
gdk_frame_clock_frame_requested (GdkFrameClock *clock)
{
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
g_signal_emit (G_OBJECT (clock),
signals[FRAME_REQUESTED], 0);
}
GdkFrameTimings * GdkFrameTimings *
gdk_frame_clock_get_current_frame_timings (GdkFrameClock *clock) gdk_frame_clock_get_current_frame_timings (GdkFrameClock *clock)
{ {

View File

@ -35,13 +35,16 @@
G_BEGIN_DECLS G_BEGIN_DECLS
typedef struct _GdkFrameClock GdkFrameClock; #define GDK_TYPE_FRAME_CLOCK (gdk_frame_clock_get_type ())
typedef struct _GdkFrameClockInterface GdkFrameClockInterface; #define GDK_FRAME_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_FRAME_CLOCK, GdkFrameClock))
#define GDK_FRAME_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_FRAME_CLOCK, GdkFrameClockClass))
#define GDK_IS_FRAME_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_FRAME_CLOCK))
#define GDK_IS_FRAME_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_FRAME_CLOCK))
#define GDK_FRAME_CLOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_FRAME_CLOCK, GdkFrameClockClass))
#define GDK_TYPE_FRAME_CLOCK (gdk_frame_clock_get_type ()) typedef struct _GdkFrameClock GdkFrameClock;
#define GDK_FRAME_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_FRAME_CLOCK, GdkFrameClock)) typedef struct _GdkFrameClockPrivate GdkFrameClockPrivate;
#define GDK_IS_FRAME_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_FRAME_CLOCK)) typedef struct _GdkFrameClockClass GdkFrameClockClass;
#define GDK_FRAME_CLOCK_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GDK_TYPE_FRAME_CLOCK, GdkFrameClockInterface))
typedef enum { typedef enum {
GDK_FRAME_CLOCK_PHASE_NONE = 0, GDK_FRAME_CLOCK_PHASE_NONE = 0,
@ -54,32 +57,6 @@ typedef enum {
GDK_FRAME_CLOCK_PHASE_AFTER_PAINT = 1 << 6 GDK_FRAME_CLOCK_PHASE_AFTER_PAINT = 1 << 6
} GdkFrameClockPhase; } GdkFrameClockPhase;
struct _GdkFrameClockInterface
{
GTypeInterface base_iface;
guint64 (* get_frame_time) (GdkFrameClock *clock);
void (* request_phase) (GdkFrameClock *clock,
GdkFrameClockPhase phase);
GdkFrameClockPhase (* get_requested) (GdkFrameClock *clock);
void (* freeze) (GdkFrameClock *clock);
void (* thaw) (GdkFrameClock *clock);
GdkFrameHistory * (* get_history) (GdkFrameClock *clock);
/* signals */
/* void (* frame_requested) (GdkFrameClock *clock); */
/* void (* flush_events) (GdkFrameClock *clock); */
/* void (* before_paint) (GdkFrameClock *clock); */
/* void (* update) (GdkFrameClock *clock); */
/* void (* layout) (GdkFrameClock *clock); */
/* void (* paint) (GdkFrameClock *clock); */
/* void (* after_paint) (GdkFrameClock *clock); */
/* void (* resume_events) (GdkFrameClock *clock); */
};
GType gdk_frame_clock_get_type (void) G_GNUC_CONST; GType gdk_frame_clock_get_type (void) G_GNUC_CONST;
guint64 gdk_frame_clock_get_frame_time (GdkFrameClock *clock); guint64 gdk_frame_clock_get_frame_time (GdkFrameClock *clock);
@ -104,9 +81,6 @@ void gdk_frame_clock_get_refresh_info (GdkFrameClock *clock,
GdkFrameTimings *gdk_frame_clock_get_current_frame_timings (GdkFrameClock *clock); GdkFrameTimings *gdk_frame_clock_get_current_frame_timings (GdkFrameClock *clock);
/* Signal emitters (used in frame clock implementations) */
void gdk_frame_clock_frame_requested (GdkFrameClock *clock);
G_END_DECLS G_END_DECLS
#endif /* __GDK_FRAME_CLOCK_H__ */ #endif /* __GDK_FRAME_CLOCK_H__ */

View File

@ -27,6 +27,7 @@
#include "config.h" #include "config.h"
#include "gdkinternals.h" #include "gdkinternals.h"
#include "gdkframeclockprivate.h"
#include "gdkframeclockidle.h" #include "gdkframeclockidle.h"
#include "gdk.h" #include "gdk.h"
@ -34,7 +35,6 @@
struct _GdkFrameClockIdlePrivate struct _GdkFrameClockIdlePrivate
{ {
GdkFrameHistory *history;
GTimer *timer; GTimer *timer;
/* timer_base is used to avoid ever going backward */ /* timer_base is used to avoid ever going backward */
guint64 timer_base; guint64 timer_base;
@ -56,11 +56,8 @@ static gboolean gdk_frame_clock_flush_idle (void *data);
static gboolean gdk_frame_clock_paint_idle (void *data); static gboolean gdk_frame_clock_paint_idle (void *data);
static void gdk_frame_clock_idle_finalize (GObject *object); static void gdk_frame_clock_idle_finalize (GObject *object);
static void gdk_frame_clock_idle_interface_init (GdkFrameClockInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GdkFrameClockIdle, gdk_frame_clock_idle, G_TYPE_OBJECT, G_DEFINE_TYPE (GdkFrameClockIdle, gdk_frame_clock_idle, GDK_TYPE_FRAME_CLOCK)
G_IMPLEMENT_INTERFACE (GDK_TYPE_FRAME_CLOCK,
gdk_frame_clock_idle_interface_init))
static gint64 sleep_serial; static gint64 sleep_serial;
static gint64 sleep_source_prepare_time; static gint64 sleep_source_prepare_time;
@ -114,16 +111,6 @@ get_sleep_serial (void)
return sleep_serial; return sleep_serial;
} }
static void
gdk_frame_clock_idle_class_init (GdkFrameClockIdleClass *klass)
{
GObjectClass *gobject_class = (GObjectClass*) klass;
gobject_class->finalize = gdk_frame_clock_idle_finalize;
g_type_class_add_private (klass, sizeof (GdkFrameClockIdlePrivate));
}
static void static void
gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle) gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
{ {
@ -134,7 +121,6 @@ gdk_frame_clock_idle_init (GdkFrameClockIdle *frame_clock_idle)
GdkFrameClockIdlePrivate); GdkFrameClockIdlePrivate);
priv = frame_clock_idle->priv; priv = frame_clock_idle->priv;
priv->history = gdk_frame_history_new ();
priv->timer = g_timer_new (); priv->timer = g_timer_new ();
priv->freeze_count = 0; priv->freeze_count = 0;
} }
@ -235,7 +221,7 @@ maybe_start_idle (GdkFrameClockIdle *clock_idle)
g_object_ref (clock_idle), g_object_ref (clock_idle),
(GDestroyNotify) g_object_unref); (GDestroyNotify) g_object_unref);
gdk_frame_clock_frame_requested (GDK_FRAME_CLOCK (clock_idle)); g_signal_emit_by_name (clock_idle, "frame-requested");
} }
} }
} }
@ -288,6 +274,7 @@ gdk_frame_clock_paint_idle (void *data)
GdkFrameClock *clock = GDK_FRAME_CLOCK (data); GdkFrameClock *clock = GDK_FRAME_CLOCK (data);
GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock); GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
GdkFrameClockIdlePrivate *priv = clock_idle->priv; GdkFrameClockIdlePrivate *priv = clock_idle->priv;
GdkFrameHistory *history = gdk_frame_clock_get_history (clock);
gboolean skip_to_resume_events; gboolean skip_to_resume_events;
GdkFrameTimings *timings = NULL; GdkFrameTimings *timings = NULL;
gint64 frame_counter = 0; gint64 frame_counter = 0;
@ -301,8 +288,8 @@ gdk_frame_clock_paint_idle (void *data)
if (priv->phase > GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT) if (priv->phase > GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT)
{ {
frame_counter = gdk_frame_history_get_frame_counter (priv->history); frame_counter = gdk_frame_history_get_frame_counter (history);
timings = gdk_frame_history_get_timings (priv->history, frame_counter); timings = gdk_frame_history_get_timings (history, frame_counter);
} }
if (!skip_to_resume_events) if (!skip_to_resume_events)
@ -317,9 +304,9 @@ gdk_frame_clock_paint_idle (void *data)
{ {
priv->frame_time = compute_frame_time (clock_idle); priv->frame_time = compute_frame_time (clock_idle);
gdk_frame_history_begin_frame (priv->history); gdk_frame_history_begin_frame (history);
frame_counter = gdk_frame_history_get_frame_counter (priv->history); frame_counter = gdk_frame_history_get_frame_counter (history);
timings = gdk_frame_history_get_timings (priv->history, frame_counter); timings = gdk_frame_history_get_timings (history, frame_counter);
gdk_frame_timings_set_frame_time (timings, priv->frame_time); gdk_frame_timings_set_frame_time (timings, priv->frame_time);
@ -406,7 +393,7 @@ gdk_frame_clock_paint_idle (void *data)
if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0) if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
{ {
if (gdk_frame_timings_get_complete (timings)) if (gdk_frame_timings_get_complete (timings))
_gdk_frame_history_debug_print (priv->history, timings); _gdk_frame_history_debug_print (history, timings);
} }
#endif /* G_ENABLE_DEBUG */ #endif /* G_ENABLE_DEBUG */
@ -501,24 +488,21 @@ gdk_frame_clock_idle_thaw (GdkFrameClock *clock)
} }
} }
static GdkFrameHistory *
gdk_frame_clock_idle_get_history (GdkFrameClock *clock)
{
GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
GdkFrameClockIdlePrivate *priv = clock_idle->priv;
return priv->history;
}
static void static void
gdk_frame_clock_idle_interface_init (GdkFrameClockInterface *iface) gdk_frame_clock_idle_class_init (GdkFrameClockIdleClass *klass)
{ {
iface->get_frame_time = gdk_frame_clock_idle_get_frame_time; GObjectClass *gobject_class = (GObjectClass*) klass;
iface->request_phase = gdk_frame_clock_idle_request_phase; GdkFrameClockClass *frame_clock_class = (GdkFrameClockClass *)klass;
iface->get_requested = gdk_frame_clock_idle_get_requested;
iface->freeze = gdk_frame_clock_idle_freeze; gobject_class->finalize = gdk_frame_clock_idle_finalize;
iface->thaw = gdk_frame_clock_idle_thaw;
iface->get_history = gdk_frame_clock_idle_get_history; frame_clock_class->get_frame_time = gdk_frame_clock_idle_get_frame_time;
frame_clock_class->request_phase = gdk_frame_clock_idle_request_phase;
frame_clock_class->get_requested = gdk_frame_clock_idle_get_requested;
frame_clock_class->freeze = gdk_frame_clock_idle_freeze;
frame_clock_class->thaw = gdk_frame_clock_idle_thaw;
g_type_class_add_private (klass, sizeof (GdkFrameClockIdlePrivate));
} }
GdkFrameClock * GdkFrameClock *

View File

@ -29,7 +29,7 @@
#ifndef __GDK_FRAME_CLOCK_IDLE_H__ #ifndef __GDK_FRAME_CLOCK_IDLE_H__
#define __GDK_FRAME_CLOCK_IDLE_H__ #define __GDK_FRAME_CLOCK_IDLE_H__
#include <gdk/gdkframeclock.h> #include "gdkframeclockprivate.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -47,7 +47,7 @@ typedef struct _GdkFrameClockIdleClass GdkFrameClockIdleClass;
struct _GdkFrameClockIdle struct _GdkFrameClockIdle
{ {
GObject parent_instance; GdkFrameClock parent_instance;
/*< private >*/ /*< private >*/
GdkFrameClockIdlePrivate *priv; GdkFrameClockIdlePrivate *priv;
@ -55,7 +55,7 @@ struct _GdkFrameClockIdle
struct _GdkFrameClockIdleClass struct _GdkFrameClockIdleClass
{ {
GObjectClass parent_class; GdkFrameClockClass parent_class;
}; };
GType gdk_frame_clock_idle_get_type (void) G_GNUC_CONST; GType gdk_frame_clock_idle_get_type (void) G_GNUC_CONST;

View File

@ -0,0 +1,72 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2010. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
/* Uninstalled header, internal to GDK */
#ifndef __GDK_FRAME_CLOCK_PRIVATE_H__
#define __GDK_FRAME_CLOCK_PRIVATE_H__
#include <gdk/gdkframeclock.h>
G_BEGIN_DECLS
typedef struct _GdkFrameClockIdlePrivate GdkFrameClockIdlePrivate;
struct _GdkFrameClock
{
GObject parent_instance;
/*< private >*/
GdkFrameClockPrivate *priv;
};
struct _GdkFrameClockClass
{
GObjectClass parent_class;
guint64 (* get_frame_time) (GdkFrameClock *clock);
void (* request_phase) (GdkFrameClock *clock,
GdkFrameClockPhase phase);
GdkFrameClockPhase (* get_requested) (GdkFrameClock *clock);
void (* freeze) (GdkFrameClock *clock);
void (* thaw) (GdkFrameClock *clock);
/* signals */
/* void (* frame_requested) (GdkFrameClock *clock); */
/* void (* flush_events) (GdkFrameClock *clock); */
/* void (* before_paint) (GdkFrameClock *clock); */
/* void (* update) (GdkFrameClock *clock); */
/* void (* layout) (GdkFrameClock *clock); */
/* void (* paint) (GdkFrameClock *clock); */
/* void (* after_paint) (GdkFrameClock *clock); */
/* void (* resume_events) (GdkFrameClock *clock); */
};
G_END_DECLS
#endif /* __GDK_FRAME_CLOCK_PRIVATE_H__ */