[gtk+/wip/cssvalue: 149/165] stylecontext: Add an animating framework



commit f636df2ebb323b79425c1a376ca9c967f30ed70a
Author: Benjamin Otte <otte redhat com>
Date:   Tue Apr 10 15:37:35 2012 +0200

    stylecontext: Add an animating framework
    
    The design principles were:
    
    - synchronized
    If multiple style contexts are animating, they should all do an
    animation step at the same time.
    
    - degrades well
    Even when there's thousands of style contexts all animating at the same
    time, the animation steps don't starve the CPU. This is achieved by
    making sure the timeout is really fast. It just sets a bunch of flags.
    
    - no hidden bottlenecks
    Turning animatability on or off on a style context is O(1).
    
    So far it is unused.

 gtk/gtkcsstypes.c        |    4 ++-
 gtk/gtkcsstypesprivate.h |    5 ++-
 gtk/gtkstylecontext.c    |   83 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 89 insertions(+), 3 deletions(-)
---
diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c
index f83880a..b69b0fe 100644
--- a/gtk/gtkcsstypes.c
+++ b/gtk/gtkcsstypes.c
@@ -56,7 +56,8 @@ _gtk_css_change_for_sibling (GtkCssChange match)
     { GTK_CSS_CHANGE_NAME, GTK_CSS_CHANGE_SIBLING_NAME },
     { GTK_CSS_CHANGE_POSITION, GTK_CSS_CHANGE_SIBLING_POSITION },
     { GTK_CSS_CHANGE_STATE, GTK_CSS_CHANGE_SIBLING_STATE },
-    { GTK_CSS_CHANGE_SOURCE, 0 }
+    { GTK_CSS_CHANGE_SOURCE, 0 },
+    { GTK_CSS_CHANGE_ANIMATE, 0 }
   };
 
   return gtk_css_change_translate (match, table, G_N_ELEMENTS (table)); 
@@ -75,6 +76,7 @@ _gtk_css_change_for_child (GtkCssChange match)
     { GTK_CSS_CHANGE_SIBLING_POSITION, GTK_CSS_CHANGE_PARENT_SIBLING_POSITION },
     { GTK_CSS_CHANGE_SIBLING_STATE, GTK_CSS_CHANGE_PARENT_SIBLING_STATE },
     { GTK_CSS_CHANGE_SOURCE, 0 },
+    { GTK_CSS_CHANGE_ANIMATE, 0 }
   };
 
   return gtk_css_change_translate (match, table, G_N_ELEMENTS (table)); 
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
index 8890a5c..b0db18d 100644
--- a/gtk/gtkcsstypesprivate.h
+++ b/gtk/gtkcsstypesprivate.h
@@ -43,10 +43,11 @@ typedef enum { /*< skip >*/
   GTK_CSS_CHANGE_PARENT_SIBLING_POSITION  = (1 << 14),
   GTK_CSS_CHANGE_PARENT_SIBLING_STATE     = (1 << 15),
   /* add more */
-  GTK_CSS_CHANGE_SOURCE                   = (1 << 16)
+  GTK_CSS_CHANGE_SOURCE                   = (1 << 16),
+  GTK_CSS_CHANGE_ANIMATE                  = (1 << 17)
 } GtkCssChange;
 
-#define GTK_CSS_CHANGE_ANY ((1 << 17) - 1)
+#define GTK_CSS_CHANGE_ANY ((1 << 18) - 1)
 #define GTK_CSS_CHANGE_ANY_SELF (GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_POSITION | GTK_CSS_CHANGE_STATE)
 #define GTK_CSS_CHANGE_ANY_SIBLING (GTK_CSS_CHANGE_SIBLING_CLASS | GTK_CSS_CHANGE_SIBLING_NAME | \
                                     GTK_CSS_CHANGE_SIBLING_POSITION | GTK_CSS_CHANGE_SIBLING_STATE)
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 0ac8eb3..8375328 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -350,6 +350,9 @@ struct _GtkStyleContextPrivate
 
   GtkStyleCascade *cascade;
 
+  GtkStyleContext *animation_list_prev;
+  GtkStyleContext *animation_list_next;
+
   GtkStyleContext *parent;
   GSList *children;
   GtkWidget *widget;            
@@ -379,6 +382,8 @@ enum {
 };
 
 static guint signals[LAST_SIGNAL] = { 0 };
+static GtkStyleContext *_running_animations = NULL;
+guint _running_animations_timer_id = 0;
 
 static void gtk_style_context_finalize (GObject *object);
 
@@ -675,6 +680,82 @@ gtk_style_context_init (GtkStyleContext *style_context)
                                  _gtk_style_cascade_get_for_screen (priv->screen));
 }
 
+static gboolean
+gtk_style_context_do_animations (gpointer unused)
+{
+  GtkStyleContext *context;
+
+  for (context = _running_animations;
+       context != NULL;
+       context = context->priv->animation_list_next)
+    {
+      _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANIMATE);
+    }
+
+  return TRUE;
+}
+
+static gboolean
+gtk_style_context_is_animating (GtkStyleContext *context)
+{
+  GtkStyleContextPrivate *priv = context->priv;
+
+  return priv->animation_list_prev != NULL
+      || _running_animations == context;
+}
+
+static void
+gtk_style_context_stop_animating (GtkStyleContext *context)
+{
+  GtkStyleContextPrivate *priv = context->priv;
+
+  if (!gtk_style_context_is_animating (context))
+    return;
+
+  if (priv->animation_list_prev == NULL)
+    {
+      _running_animations = priv->animation_list_next;
+
+      if (_running_animations == NULL)
+        {
+          /* we were the last animation */
+          g_source_remove (_running_animations_timer_id);
+          _running_animations_timer_id = 0;
+        }
+    }
+  else
+    priv->animation_list_prev->priv->animation_list_next = priv->animation_list_next;
+
+  if (priv->animation_list_next)
+    priv->animation_list_next->priv->animation_list_prev = priv->animation_list_prev;
+
+  priv->animation_list_next = NULL;
+  priv->animation_list_prev = NULL;
+}
+
+static void G_GNUC_UNUSED
+gtk_style_context_start_animating (GtkStyleContext *context)
+{
+  GtkStyleContextPrivate *priv = context->priv;
+
+  if (gtk_style_context_is_animating (context))
+    return;
+
+  if (_running_animations == NULL)
+    {
+      _running_animations_timer_id = gdk_threads_add_timeout (25,
+                                                              gtk_style_context_do_animations,
+                                                              NULL);
+      _running_animations = context;
+    }
+  else
+    {
+      priv->animation_list_next = _running_animations;
+      _running_animations->priv->animation_list_prev = context;
+      _running_animations = context;
+    }
+}
+
 static void
 gtk_style_context_finalize (GObject *object)
 {
@@ -684,6 +765,8 @@ gtk_style_context_finalize (GObject *object)
   style_context = GTK_STYLE_CONTEXT (object);
   priv = style_context->priv;
 
+  gtk_style_context_stop_animating (style_context);
+
   /* children hold a reference to us */
   g_assert (priv->children == NULL);
 



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