* for example.
*
* A frame clock is idle until someone requests a frame with
- * gdk_frame_clock_request_frame(). At that time, the frame clock
+ * gdk_frame_clock_request_phase(). At that time, the frame clock
* emits its GdkFrameClock:frame-requested signal if no frame was
* already pending.
*
}
/**
- * gdk_frame_clock_request_frame:
+ * gdk_frame_clock_request_phase:
* @clock: the clock
*
* Asks the frame clock to paint a frame. The frame
* Since: 3.0
*/
void
-gdk_frame_clock_request_frame (GdkFrameClock *clock)
+gdk_frame_clock_request_phase (GdkFrameClock *clock,
+ GdkFrameClockPhase phase)
{
g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
- GDK_FRAME_CLOCK_GET_IFACE (clock)->request_frame (clock);
+ GDK_FRAME_CLOCK_GET_IFACE (clock)->request_phase (clock, phase);
}
+
/**
- * gdk_frame_clock_get_frame_requested:
+ * gdk_frame_clock_get_requested:
* @clock: the clock
*
* Gets whether a frame paint has been requested but has not been
* Since: 3.0
* Return value: TRUE if a frame paint is pending
*/
-gboolean
-gdk_frame_clock_get_frame_requested (GdkFrameClock *clock)
+GdkFrameClockPhase
+gdk_frame_clock_get_requested (GdkFrameClock *clock)
{
g_return_val_if_fail (GDK_IS_FRAME_CLOCK (clock), FALSE);
- return GDK_FRAME_CLOCK_GET_IFACE (clock)->get_frame_requested (clock);
+ return GDK_FRAME_CLOCK_GET_IFACE (clock)->get_requested (clock);
}
/**
g_signal_emit (G_OBJECT (clock),
signals[FRAME_REQUESTED], 0);
}
-
-/**
- * gdk_frame_clock_paint:
- * @clock: the clock
- *
- * Emits the before-paint, paint, and after-paint signals. Used in
- * implementations of the #GdkFrameClock interface.
- */
-void
-gdk_frame_clock_paint (GdkFrameClock *clock)
-{
- g_return_if_fail (GDK_IS_FRAME_CLOCK (clock));
-
- g_signal_emit (G_OBJECT (clock),
- signals[BEFORE_PAINT], 0);
-
- g_signal_emit (G_OBJECT (clock),
- signals[LAYOUT], 0);
-
- g_signal_emit (G_OBJECT (clock),
- signals[PAINT], 0);
-
- g_signal_emit (G_OBJECT (clock),
- signals[AFTER_PAINT], 0);
-}
typedef struct _GdkFrameClock GdkFrameClock;
typedef struct _GdkFrameClockInterface GdkFrameClockInterface;
+typedef enum {
+ GDK_FRAME_CLOCK_PHASE_NONE = 0,
+ GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT = 1 << 0,
+ GDK_FRAME_CLOCK_PHASE_LAYOUT = 1 << 1,
+ GDK_FRAME_CLOCK_PHASE_PAINT = 1 << 2,
+ GDK_FRAME_CLOCK_PHASE_AFTER_PAINT = 1 << 3
+} GdkFrameClockPhase;
+
struct _GdkFrameClockInterface
{
GTypeInterface base_iface;
guint64 (* get_frame_time) (GdkFrameClock *clock);
- void (* request_frame) (GdkFrameClock *clock);
- gboolean (* get_frame_requested) (GdkFrameClock *clock);
+
+ void (* request_phase) (GdkFrameClock *clock,
+ GdkFrameClockPhase phase);
+ GdkFrameClockPhase (* get_requested) (GdkFrameClock *clock);
/* signals */
/* void (* frame_requested) (GdkFrameClock *clock); */
/* void (* before_paint) (GdkFrameClock *clock); */
- /* void (* layout) 1(GdkFrameClock *clock); */
+ /* void (* layout) (GdkFrameClock *clock); */
/* void (* paint) (GdkFrameClock *clock); */
/* void (* after_paint) (GdkFrameClock *clock); */
};
GType gdk_frame_clock_get_type (void) G_GNUC_CONST;
guint64 gdk_frame_clock_get_frame_time (GdkFrameClock *clock);
-void gdk_frame_clock_request_frame (GdkFrameClock *clock);
-gboolean gdk_frame_clock_get_frame_requested (GdkFrameClock *clock);
+
+void gdk_frame_clock_request_phase (GdkFrameClock *clock,
+ GdkFrameClockPhase phase);
+GdkFrameClockPhase gdk_frame_clock_get_requested (GdkFrameClock *clock);
/* Convenience API */
void gdk_frame_clock_get_frame_time_val (GdkFrameClock *clock,
/* Signal emitters (used in frame clock implementations) */
void gdk_frame_clock_frame_requested (GdkFrameClock *clock);
-void gdk_frame_clock_paint (GdkFrameClock *clock);
G_END_DECLS
guint idle_id;
- unsigned int in_paint : 1;
+ GdkFrameClockPhase requested;
+ GdkFrameClockPhase phase;
};
+static gboolean gdk_frame_clock_paint_idle (void *data);
+
static void gdk_frame_clock_idle_finalize (GObject *object);
static void gdk_frame_clock_idle_interface_init (GdkFrameClockInterface *iface);
guint64 computed_frame_time;
/* can't change frame time during a paint */
- if (priv->in_paint)
+ if (priv->phase != GDK_FRAME_CLOCK_PHASE_NONE)
return priv->frame_time;
/* Outside a paint, pick something close to "now" */
return priv->frame_time;
}
+static void
+maybe_start_idle (GdkFrameClockIdle *clock_idle)
+{
+ GdkFrameClockIdlePrivate *priv = clock_idle->priv;
+
+ if (priv->idle_id == 0 && priv->requested != 0)
+ {
+ priv->idle_id = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
+ gdk_frame_clock_paint_idle,
+ g_object_ref (clock_idle),
+ (GDestroyNotify) g_object_unref);
+
+ gdk_frame_clock_frame_requested (GDK_FRAME_CLOCK (clock_idle));
+ }
+}
+
static gboolean
gdk_frame_clock_paint_idle (void *data)
{
priv->idle_id = 0;
- priv->in_paint = TRUE;
priv->frame_time = compute_frame_time (clock_idle);
- gdk_frame_clock_paint (clock);
-
- priv->in_paint = FALSE;
+ priv->phase = GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT;
+ priv->requested &= ~GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT;
+ g_signal_emit_by_name (G_OBJECT (clock), "before-paint");
+ priv->phase = GDK_FRAME_CLOCK_PHASE_LAYOUT;
+ priv->requested &= ~GDK_FRAME_CLOCK_PHASE_LAYOUT;
+ g_signal_emit_by_name (G_OBJECT (clock), "layout");
+ priv->phase = GDK_FRAME_CLOCK_PHASE_PAINT;
+ priv->requested &= ~GDK_FRAME_CLOCK_PHASE_PAINT;
+ g_signal_emit_by_name (G_OBJECT (clock), "paint");
+ priv->phase = GDK_FRAME_CLOCK_PHASE_AFTER_PAINT;
+ priv->requested &= ~GDK_FRAME_CLOCK_PHASE_AFTER_PAINT;
+ g_signal_emit_by_name (G_OBJECT (clock), "after-paint");
+ priv->phase = GDK_FRAME_CLOCK_PHASE_NONE;
+
+ maybe_start_idle (clock_idle);
return FALSE;
}
static void
-gdk_frame_clock_idle_request_frame (GdkFrameClock *clock)
+gdk_frame_clock_idle_request_phase (GdkFrameClock *clock,
+ GdkFrameClockPhase phase)
{
- GdkFrameClockIdlePrivate *priv = GDK_FRAME_CLOCK_IDLE (clock)->priv;
-
- if (priv->idle_id == 0)
- {
- priv->idle_id = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
- gdk_frame_clock_paint_idle,
- g_object_ref (clock),
- (GDestroyNotify) g_object_unref);
+ GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock);
+ GdkFrameClockIdlePrivate *priv = clock_idle->priv;
- gdk_frame_clock_frame_requested (clock);
- }
+ priv->requested |= phase;
+ maybe_start_idle (clock_idle);
}
-static gboolean
-gdk_frame_clock_idle_get_frame_requested (GdkFrameClock *clock)
+static GdkFrameClockPhase
+gdk_frame_clock_idle_get_requested (GdkFrameClock *clock)
{
GdkFrameClockIdlePrivate *priv = GDK_FRAME_CLOCK_IDLE (clock)->priv;
- return priv->idle_id != 0;
+ return priv->requested;
}
static void
gdk_frame_clock_idle_interface_init (GdkFrameClockInterface *iface)
{
iface->get_frame_time = gdk_frame_clock_idle_get_frame_time;
- iface->request_frame = gdk_frame_clock_idle_request_frame;
- iface->get_frame_requested = gdk_frame_clock_idle_get_frame_requested;
+ iface->request_phase = gdk_frame_clock_idle_request_phase;
+ iface->get_requested = gdk_frame_clock_idle_get_requested;
+}
+
+GdkFrameClock *
+_gdk_frame_clock_idle_new (void)
+{
+ GdkFrameClockIdle *clock;
+
+ clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
+
+ return GDK_FRAME_CLOCK (clock);
}
gdk_window_is_toplevel_frozen (window)))
return;
- gdk_frame_clock_request_frame (gdk_window_get_frame_clock (window));
+ gdk_frame_clock_request_phase (gdk_window_get_frame_clock (window),
+ GDK_FRAME_CLOCK_PHASE_PAINT);
}
void
}
else
{
- gdk_frame_clock_request_frame (clock);
+ gdk_frame_clock_request_phase (clock,
+ GDK_FRAME_CLOCK_PHASE_LAYOUT);
}
}
container->priv->resize_clock = clock;
container->priv->resize_handler = g_signal_connect (clock, "layout",
G_CALLBACK (gtk_container_idle_sizer), container);
- gdk_frame_clock_request_frame (clock);
+ gdk_frame_clock_request_phase (clock,
+ GDK_FRAME_CLOCK_PHASE_LAYOUT);
}
static void
* then update the animation by calling
* gdk_frame_clock_get_frame_time() again during each repaint.
*
- * gdk_frame_clock_request_frame() will result in a new frame on the
+ * gdk_frame_clock_request_phase() will result in a new frame on the
* clock, but won't necessarily repaint any widgets. To repaint a
* widget, you have to use gtk_widget_queue_draw() which invalidates
* the widget (thus scheduling it to receive a draw on the next