From c4545cc5d47364b66b7ecd7bb482210fb8c8655a Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Wed, 3 Oct 2012 19:38:40 -0400 Subject: [PATCH] GdkFrameClock: Make the phase explicit when requesting the frame Instead of having gdk_frame_clock_request_frame() have gdk_frame_clock_request_phase() where we can say what phase we need. This allows us to know if we get a frame-request during layout whether it's just a request for drawing from the layout, or whether another layout phase is needed. https://bugzilla.gnome.org/show_bug.cgi?id=685460 --- gdk/gdkframeclock.c | 43 ++++++----------------- gdk/gdkframeclock.h | 23 ++++++++---- gdk/gdkframeclockidle.c | 77 ++++++++++++++++++++++++++++++----------- gdk/gdkwindow.c | 3 +- gtk/gtkcontainer.c | 6 ++-- gtk/gtkwidget.c | 2 +- 6 files changed, 90 insertions(+), 64 deletions(-) diff --git a/gdk/gdkframeclock.c b/gdk/gdkframeclock.c index ca5484080d..9fcf642c36 100644 --- a/gdk/gdkframeclock.c +++ b/gdk/gdkframeclock.c @@ -47,7 +47,7 @@ * 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. * @@ -203,7 +203,7 @@ gdk_frame_clock_get_frame_time (GdkFrameClock *clock) } /** - * gdk_frame_clock_request_frame: + * gdk_frame_clock_request_phase: * @clock: the clock * * Asks the frame clock to paint a frame. The frame @@ -217,15 +217,17 @@ gdk_frame_clock_get_frame_time (GdkFrameClock *clock) * 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 @@ -235,12 +237,12 @@ gdk_frame_clock_request_frame (GdkFrameClock *clock) * 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); } /** @@ -281,28 +283,3 @@ gdk_frame_clock_frame_requested (GdkFrameClock *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); -} diff --git a/gdk/gdkframeclock.h b/gdk/gdkframeclock.h index 043a890514..fe0ea58b60 100644 --- a/gdk/gdkframeclock.h +++ b/gdk/gdkframeclock.h @@ -43,18 +43,28 @@ G_BEGIN_DECLS 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); */ }; @@ -62,8 +72,10 @@ struct _GdkFrameClockInterface 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, @@ -71,7 +83,6 @@ 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 diff --git a/gdk/gdkframeclockidle.c b/gdk/gdkframeclockidle.c index ff20632e70..bdcb16a08a 100644 --- a/gdk/gdkframeclockidle.c +++ b/gdk/gdkframeclockidle.c @@ -38,9 +38,12 @@ struct _GdkFrameClockIdlePrivate 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); @@ -113,7 +116,7 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock) 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" */ @@ -130,6 +133,22 @@ gdk_frame_clock_idle_get_frame_time (GdkFrameClock *clock) 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) { @@ -139,44 +158,60 @@ 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->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; - priv->in_paint = FALSE; + 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; + GdkFrameClockIdle *clock_idle = GDK_FRAME_CLOCK_IDLE (clock); + GdkFrameClockIdlePrivate *priv = clock_idle->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); - - 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); } diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index f82ad162b4..e3b5026c83 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -3947,7 +3947,8 @@ gdk_window_schedule_update (GdkWindow *window) 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 diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c index 938887ea14..e73ef2a700 100644 --- a/gtk/gtkcontainer.c +++ b/gtk/gtkcontainer.c @@ -1686,7 +1686,8 @@ gtk_container_idle_sizer (GdkFrameClock *clock, } else { - gdk_frame_clock_request_frame (clock); + gdk_frame_clock_request_phase (clock, + GDK_FRAME_CLOCK_PHASE_LAYOUT); } } @@ -1705,7 +1706,8 @@ gtk_container_start_idle_sizer (GtkContainer *container) 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 diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index e1cf124f68..63fbcae40b 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -4793,7 +4793,7 @@ gtk_widget_queue_resize_no_redraw (GtkWidget *widget) * 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