[gtk+/wip/frame-synchronization: 4/33] GdkPaintClock: Make the phase explicit when requesting the frame



commit 8e9a30c4c133cc76765af3cd3bbf9cff56ab6f52
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Wed Oct 3 19:38:40 2012 -0400

    GdkPaintClock: Make the phase explicit when requesting the frame
    
    Instead of having gdk_paint_clock_request_frame() have
    gdk_paint_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/gdkpaintclock.c     |   43 ++++++-------------------
 gdk/gdkpaintclock.h     |   23 ++++++++++---
 gdk/gdkpaintclockidle.c |   79 ++++++++++++++++++++++++++++++++++-------------
 gdk/gdkwindow.c         |    3 +-
 gtk/gtkcontainer.c      |    6 ++-
 gtk/gtkwidget.c         |    2 +-
 6 files changed, 91 insertions(+), 65 deletions(-)
---
diff --git a/gdk/gdkpaintclock.c b/gdk/gdkpaintclock.c
index c27839a..5de34d6 100644
--- a/gdk/gdkpaintclock.c
+++ b/gdk/gdkpaintclock.c
@@ -47,7 +47,7 @@
  * for example.
  *
  * A paint clock is idle until someone requests a frame with
- * gdk_paint_clock_request_frame(). At that time, the paint clock
+ * gdk_paint_clock_request_phase(). At that time, the paint clock
  * emits its GdkPaintClock:frame-requested signal if no frame was
  * already pending.
  *
@@ -203,7 +203,7 @@ gdk_paint_clock_get_frame_time (GdkPaintClock *clock)
 }
 
 /**
- * gdk_paint_clock_request_frame:
+ * gdk_paint_clock_request_phase:
  * @clock: the clock
  *
  * Asks the frame clock to paint a frame. The frame
@@ -217,15 +217,17 @@ gdk_paint_clock_get_frame_time (GdkPaintClock *clock)
  * Since: 3.0
  */
 void
-gdk_paint_clock_request_frame (GdkPaintClock *clock)
+gdk_paint_clock_request_phase (GdkPaintClock      *clock,
+                               GdkPaintClockPhase  phase)
 {
   g_return_if_fail (GDK_IS_PAINT_CLOCK (clock));
 
-  GDK_PAINT_CLOCK_GET_IFACE (clock)->request_frame (clock);
+  GDK_PAINT_CLOCK_GET_IFACE (clock)->request_phase (clock, phase);
 }
 
+
 /**
- * gdk_paint_clock_get_frame_requested:
+ * gdk_paint_clock_get_requested:
  * @clock: the clock
  *
  * Gets whether a frame paint has been requested but has not been
@@ -235,12 +237,12 @@ gdk_paint_clock_request_frame (GdkPaintClock *clock)
  * Since: 3.0
  * Return value: TRUE if a frame paint is pending
  */
-gboolean
-gdk_paint_clock_get_frame_requested (GdkPaintClock *clock)
+GdkPaintClockPhase
+gdk_paint_clock_get_requested (GdkPaintClock *clock)
 {
   g_return_val_if_fail (GDK_IS_PAINT_CLOCK (clock), FALSE);
 
-  return GDK_PAINT_CLOCK_GET_IFACE (clock)->get_frame_requested (clock);
+  return GDK_PAINT_CLOCK_GET_IFACE (clock)->get_requested (clock);
 }
 
 /**
@@ -281,28 +283,3 @@ gdk_paint_clock_frame_requested (GdkPaintClock *clock)
   g_signal_emit (G_OBJECT (clock),
                  signals[FRAME_REQUESTED], 0);
 }
-
-/**
- * gdk_paint_clock_paint:
- * @clock: the clock
- *
- * Emits the before-paint, paint, and after-paint signals. Used in
- * implementations of the #GdkPaintClock interface.
- */
-void
-gdk_paint_clock_paint (GdkPaintClock *clock)
-{
-  g_return_if_fail (GDK_IS_PAINT_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/gdkpaintclock.h b/gdk/gdkpaintclock.h
index 40d92da..0bafc1e 100644
--- a/gdk/gdkpaintclock.h
+++ b/gdk/gdkpaintclock.h
@@ -43,18 +43,28 @@ G_BEGIN_DECLS
 typedef struct _GdkPaintClock          GdkPaintClock;
 typedef struct _GdkPaintClockInterface GdkPaintClockInterface;
 
+typedef enum {
+  GDK_PAINT_CLOCK_PHASE_NONE         = 0,
+  GDK_PAINT_CLOCK_PHASE_BEFORE_PAINT = 1 << 0,
+  GDK_PAINT_CLOCK_PHASE_LAYOUT       = 1 << 1,
+  GDK_PAINT_CLOCK_PHASE_PAINT        = 1 << 2,
+  GDK_PAINT_CLOCK_PHASE_AFTER_PAINT  = 1 << 3
+} GdkPaintClockPhase;
+
 struct _GdkPaintClockInterface
 {
   GTypeInterface		   base_iface;
 
   guint64  (* get_frame_time)      (GdkPaintClock *clock);
-  void     (* request_frame)       (GdkPaintClock *clock);
-  gboolean (* get_frame_requested) (GdkPaintClock *clock);
+
+  void               (* request_phase) (GdkPaintClock      *clock,
+                                        GdkPaintClockPhase  phase);
+  GdkPaintClockPhase (* get_requested) (GdkPaintClock      *clock);
 
   /* signals */
   /* void (* frame_requested)    (GdkPaintClock *clock); */
   /* void (* before_paint)       (GdkPaintClock *clock); */
-  /* void (* layout)             1(GdkPaintClock *clock); */
+  /* void (* layout)             (GdkPaintClock *clock); */
   /* void (* paint)              (GdkPaintClock *clock); */
   /* void (* after_paint)        (GdkPaintClock *clock); */
 };
@@ -62,8 +72,10 @@ struct _GdkPaintClockInterface
 GType    gdk_paint_clock_get_type             (void) G_GNUC_CONST;
 
 guint64  gdk_paint_clock_get_frame_time      (GdkPaintClock *clock);
-void     gdk_paint_clock_request_frame       (GdkPaintClock *clock);
-gboolean gdk_paint_clock_get_frame_requested (GdkPaintClock *clock);
+
+void               gdk_paint_clock_request_phase (GdkPaintClock      *clock,
+                                                  GdkPaintClockPhase  phase);
+GdkPaintClockPhase gdk_paint_clock_get_requested (GdkPaintClock      *clock);
 
 /* Convenience API */
 void  gdk_paint_clock_get_frame_time_val (GdkPaintClock  *clock,
@@ -71,7 +83,6 @@ void  gdk_paint_clock_get_frame_time_val (GdkPaintClock  *clock,
 
 /* Signal emitters (used in paint clock implementations) */
 void     gdk_paint_clock_frame_requested     (GdkPaintClock *clock);
-void     gdk_paint_clock_paint               (GdkPaintClock *clock);
 
 G_END_DECLS
 
diff --git a/gdk/gdkpaintclockidle.c b/gdk/gdkpaintclockidle.c
index c967af54..adbdbe7 100644
--- a/gdk/gdkpaintclockidle.c
+++ b/gdk/gdkpaintclockidle.c
@@ -38,9 +38,12 @@ struct _GdkPaintClockIdlePrivate
 
   guint idle_id;
 
-  unsigned int in_paint : 1;
+  GdkPaintClockPhase requested;
+  GdkPaintClockPhase phase;
 };
 
+static gboolean gdk_paint_clock_paint_idle (void *data);
+
 static void gdk_paint_clock_idle_finalize             (GObject                *object);
 static void gdk_paint_clock_idle_interface_init       (GdkPaintClockInterface *iface);
 
@@ -113,7 +116,7 @@ gdk_paint_clock_idle_get_frame_time (GdkPaintClock *clock)
   guint64 computed_frame_time;
 
   /* can't change frame time during a paint */
-  if (priv->in_paint)
+  if (priv->phase != GDK_PAINT_CLOCK_PHASE_NONE)
     return priv->frame_time;
 
   /* Outside a paint, pick something close to "now" */
@@ -130,6 +133,22 @@ gdk_paint_clock_idle_get_frame_time (GdkPaintClock *clock)
   return priv->frame_time;
 }
 
+static void
+maybe_start_idle (GdkPaintClockIdle *clock_idle)
+{
+  GdkPaintClockIdlePrivate *priv = clock_idle->priv;
+
+  if (priv->idle_id == 0 && priv->requested != 0)
+    {
+      priv->idle_id = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
+                                                 gdk_paint_clock_paint_idle,
+                                                 g_object_ref (clock_idle),
+                                                 (GDestroyNotify) g_object_unref);
+
+      gdk_paint_clock_frame_requested (GDK_PAINT_CLOCK (clock_idle));
+    }
+}
+
 static gboolean
 gdk_paint_clock_paint_idle (void *data)
 {
@@ -139,44 +158,60 @@ gdk_paint_clock_paint_idle (void *data)
 
   priv->idle_id = 0;
 
-  priv->in_paint = TRUE;
   priv->frame_time = compute_frame_time (clock_idle);
 
-  gdk_paint_clock_paint (clock);
-
-  priv->in_paint = FALSE;
+  priv->phase = GDK_PAINT_CLOCK_PHASE_BEFORE_PAINT;
+  priv->requested &= ~GDK_PAINT_CLOCK_PHASE_BEFORE_PAINT;
+  g_signal_emit_by_name (G_OBJECT (clock), "before-paint");
+  priv->phase = GDK_PAINT_CLOCK_PHASE_LAYOUT;
+  priv->requested &= ~GDK_PAINT_CLOCK_PHASE_LAYOUT;
+  g_signal_emit_by_name (G_OBJECT (clock), "layout");
+  priv->phase = GDK_PAINT_CLOCK_PHASE_PAINT;
+  priv->requested &= ~GDK_PAINT_CLOCK_PHASE_PAINT;
+  g_signal_emit_by_name (G_OBJECT (clock), "paint");
+  priv->phase = GDK_PAINT_CLOCK_PHASE_AFTER_PAINT;
+  priv->requested &= ~GDK_PAINT_CLOCK_PHASE_AFTER_PAINT;
+  g_signal_emit_by_name (G_OBJECT (clock), "after-paint");
+  priv->phase = GDK_PAINT_CLOCK_PHASE_NONE;
+
+  maybe_start_idle (clock_idle);
 
   return FALSE;
 }
 
 static void
-gdk_paint_clock_idle_request_frame (GdkPaintClock *clock)
+gdk_paint_clock_idle_request_phase (GdkPaintClock      *clock,
+                                    GdkPaintClockPhase  phase)
 {
-  GdkPaintClockIdlePrivate *priv = GDK_PAINT_CLOCK_IDLE (clock)->priv;
-
-  if (priv->idle_id == 0)
-    {
-      priv->idle_id = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
-                                                 gdk_paint_clock_paint_idle,
-                                                 g_object_ref (clock),
-                                                 (GDestroyNotify) g_object_unref);
+  GdkPaintClockIdle *clock_idle = GDK_PAINT_CLOCK_IDLE (clock);
+  GdkPaintClockIdlePrivate *priv = clock_idle->priv;
 
-      gdk_paint_clock_frame_requested (clock);
-    }
+  priv->requested |= phase;
+  maybe_start_idle (clock_idle);
 }
 
-static gboolean
-gdk_paint_clock_idle_get_frame_requested (GdkPaintClock *clock)
+static GdkPaintClockPhase
+gdk_paint_clock_idle_get_requested (GdkPaintClock *clock)
 {
   GdkPaintClockIdlePrivate *priv = GDK_PAINT_CLOCK_IDLE (clock)->priv;
 
-  return priv->idle_id != 0;
+  return priv->requested;
 }
 
 static void
 gdk_paint_clock_idle_interface_init (GdkPaintClockInterface *iface)
 {
   iface->get_frame_time = gdk_paint_clock_idle_get_frame_time;
-  iface->request_frame = gdk_paint_clock_idle_request_frame;
-  iface->get_frame_requested = gdk_paint_clock_idle_get_frame_requested;
+  iface->request_phase = gdk_paint_clock_idle_request_phase;
+  iface->get_requested = gdk_paint_clock_idle_get_requested;
+}
+
+GdkPaintClock *
+_gdk_paint_clock_idle_new (void)
+{
+  GdkPaintClockIdle *clock;
+
+  clock = g_object_new (GDK_TYPE_PAINT_CLOCK_IDLE, NULL);
+
+  return GDK_PAINT_CLOCK (clock);
 }
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index e35d31b..5d65c08 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -3879,7 +3879,8 @@ gdk_window_schedule_update (GdkWindow *window)
        gdk_window_is_toplevel_frozen (window)))
     return;
 
-  gdk_paint_clock_request_frame (gdk_window_get_paint_clock (window));
+  gdk_paint_clock_request_phase (gdk_window_get_paint_clock (window),
+                                 GDK_PAINT_CLOCK_PHASE_PAINT);
 }
 
 void
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 7ecb7c9..345fe3b 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -1685,7 +1685,8 @@ gtk_container_idle_sizer (GdkPaintClock *clock,
     }
   else
     {
-      gdk_paint_clock_request_frame (clock);
+      gdk_paint_clock_request_phase (clock,
+                                     GDK_PAINT_CLOCK_PHASE_LAYOUT);
     }
 }
 
@@ -1704,7 +1705,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_paint_clock_request_frame (clock);
+  gdk_paint_clock_request_phase (clock,
+                                 GDK_PAINT_CLOCK_PHASE_LAYOUT);
 }
 
 static void
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 0ae4baa..1562877 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -4691,7 +4691,7 @@ gtk_widget_queue_resize_no_redraw (GtkWidget *widget)
  * then update the animation by calling
  * gdk_paint_clock_get_frame_time() again during each repaint.
  *
- * gdk_paint_clock_request_frame() will result in a new frame on the
+ * gdk_paint_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



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