summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk/gtkcsstypes.c4
-rw-r--r--gtk/gtkcsstypesprivate.h5
-rw-r--r--gtk/gtkstylecontext.c83
3 files changed, 89 insertions, 3 deletions
diff --git a/gtk/gtkcsstypes.c b/gtk/gtkcsstypes.c
index f83880afab..b69b0fecca 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 8890a5cce9..b0db18d0b9 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 0ac8eb3a96..8375328f94 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);