Commit dbe5058b authored by Benjamin Otte's avatar Benjamin Otte

cssnode: Add API to query the timestamp

... and pass it to the API that computes new styles.

A special timestamp of 0 means "please don't animate" and is used when
no frame clock is available for a node.
parent 5833858a
...@@ -226,6 +226,7 @@ gtk_css_style_needs_recreation (GtkCssStyle *style, ...@@ -226,6 +226,7 @@ gtk_css_style_needs_recreation (GtkCssStyle *style,
static GtkCssStyle * static GtkCssStyle *
gtk_css_node_real_update_style (GtkCssNode *cssnode, gtk_css_node_real_update_style (GtkCssNode *cssnode,
GtkCssChange pending_change, GtkCssChange pending_change,
gint64 timestamp,
GtkCssStyle *old_style) GtkCssStyle *old_style)
{ {
if (!gtk_css_style_needs_recreation (old_style, pending_change)) if (!gtk_css_style_needs_recreation (old_style, pending_change))
...@@ -285,6 +286,12 @@ gtk_css_node_real_get_style_provider (GtkCssNode *cssnode) ...@@ -285,6 +286,12 @@ gtk_css_node_real_get_style_provider (GtkCssNode *cssnode)
return NULL; return NULL;
} }
static GdkFrameClock *
gtk_css_node_real_get_frame_clock (GtkCssNode *cssnode)
{
return NULL;
}
static void static void
gtk_css_node_class_init (GtkCssNodeClass *klass) gtk_css_node_class_init (GtkCssNodeClass *klass)
{ {
...@@ -302,6 +309,7 @@ gtk_css_node_class_init (GtkCssNodeClass *klass) ...@@ -302,6 +309,7 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
klass->create_widget_path = gtk_css_node_real_create_widget_path; klass->create_widget_path = gtk_css_node_real_create_widget_path;
klass->get_widget_path = gtk_css_node_real_get_widget_path; klass->get_widget_path = gtk_css_node_real_get_widget_path;
klass->get_style_provider = gtk_css_node_real_get_style_provider; klass->get_style_provider = gtk_css_node_real_get_style_provider;
klass->get_frame_clock = gtk_css_node_real_get_frame_clock;
} }
static void static void
...@@ -314,6 +322,27 @@ gtk_css_node_init (GtkCssNode *cssnode) ...@@ -314,6 +322,27 @@ gtk_css_node_init (GtkCssNode *cssnode)
cssnode->visible = TRUE; cssnode->visible = TRUE;
} }
static GdkFrameClock *
gtk_css_node_get_frame_clock_or_null (GtkCssNode *cssnode)
{
while (cssnode->parent)
cssnode = cssnode->parent;
return GTK_CSS_NODE_GET_CLASS (cssnode)->get_frame_clock (cssnode);
}
static gint64
gtk_css_node_get_timestamp (GtkCssNode *cssnode)
{
GdkFrameClock *frameclock;
frameclock = gtk_css_node_get_frame_clock_or_null (cssnode);
if (frameclock == NULL)
return 0;
return gdk_frame_clock_get_frame_time (frameclock);
}
static void static void
gtk_css_node_parent_was_unset (GtkCssNode *node) gtk_css_node_parent_was_unset (GtkCssNode *node)
{ {
...@@ -440,6 +469,7 @@ gtk_css_node_reposition (GtkCssNode *node, ...@@ -440,6 +469,7 @@ gtk_css_node_reposition (GtkCssNode *node,
if (gtk_css_node_get_style_provider_or_null (node) == NULL) if (gtk_css_node_get_style_provider_or_null (node) == NULL)
gtk_css_node_invalidate_style_provider (node); gtk_css_node_invalidate_style_provider (node);
gtk_css_node_invalidate (node, GTK_CSS_CHANGE_TIMESTAMP | GTK_CSS_CHANGE_ANIMATIONS);
} }
if (parent) if (parent)
...@@ -560,22 +590,30 @@ gtk_css_node_propagate_pending_changes (GtkCssNode *cssnode, ...@@ -560,22 +590,30 @@ gtk_css_node_propagate_pending_changes (GtkCssNode *cssnode,
} }
} }
static gboolean
gtk_css_node_needs_new_style (GtkCssNode *cssnode)
{
return cssnode->style_is_invalid;
}
static void static void
gtk_css_node_ensure_style (GtkCssNode *cssnode) gtk_css_node_ensure_style (GtkCssNode *cssnode,
gint64 current_time)
{ {
GtkCssStyle *new_style; GtkCssStyle *new_style;
if (!cssnode->style_is_invalid) if (!gtk_css_node_needs_new_style (cssnode))
return; return;
if (cssnode->parent) if (cssnode->parent)
gtk_css_node_ensure_style (cssnode->parent); gtk_css_node_ensure_style (cssnode->parent, current_time);
if (cssnode->previous_sibling) if (cssnode->previous_sibling)
gtk_css_node_ensure_style (cssnode->previous_sibling); gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode, new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode,
cssnode->pending_changes, cssnode->pending_changes,
current_time,
cssnode->style); cssnode->style);
gtk_css_node_propagate_pending_changes (cssnode, new_style != NULL); gtk_css_node_propagate_pending_changes (cssnode, new_style != NULL);
...@@ -593,7 +631,12 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode) ...@@ -593,7 +631,12 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode)
GtkCssStyle * GtkCssStyle *
gtk_css_node_get_style (GtkCssNode *cssnode) gtk_css_node_get_style (GtkCssNode *cssnode)
{ {
gtk_css_node_ensure_style (cssnode); if (gtk_css_node_needs_new_style (cssnode))
{
gint64 timestamp = gtk_css_node_get_timestamp (cssnode);
gtk_css_node_ensure_style (cssnode, timestamp);
}
return cssnode->style; return cssnode->style;
} }
...@@ -755,6 +798,20 @@ gtk_css_node_invalidate_style_provider (GtkCssNode *cssnode) ...@@ -755,6 +798,20 @@ gtk_css_node_invalidate_style_provider (GtkCssNode *cssnode)
} }
} }
void
gtk_css_node_invalidate_frame_clock (GtkCssNode *cssnode,
gboolean just_timestamp)
{
/* frame clock is handled by the top level */
if (cssnode->parent)
return;
if (just_timestamp)
gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_TIMESTAMP);
else
gtk_css_node_invalidate (cssnode, GTK_CSS_CHANGE_TIMESTAMP | GTK_CSS_CHANGE_ANIMATIONS);
}
void void
gtk_css_node_invalidate (GtkCssNode *cssnode, gtk_css_node_invalidate (GtkCssNode *cssnode,
GtkCssChange change) GtkCssChange change)
......
...@@ -70,8 +70,11 @@ struct _GtkCssNodeClass ...@@ -70,8 +70,11 @@ struct _GtkCssNodeClass
const GtkWidgetPath * (* get_widget_path) (GtkCssNode *cssnode); const GtkWidgetPath * (* get_widget_path) (GtkCssNode *cssnode);
/* get style provider to use or NULL to use parent's */ /* get style provider to use or NULL to use parent's */
GtkStyleProviderPrivate *(* get_style_provider) (GtkCssNode *cssnode); GtkStyleProviderPrivate *(* get_style_provider) (GtkCssNode *cssnode);
/* get frame clock or NULL (only relevant for root node) */
GdkFrameClock * (* get_frame_clock) (GtkCssNode *cssnode);
GtkCssStyle * (* update_style) (GtkCssNode *cssnode, GtkCssStyle * (* update_style) (GtkCssNode *cssnode,
GtkCssChange pending_changes, GtkCssChange pending_changes,
gint64 timestamp,
GtkCssStyle *old_style); GtkCssStyle *old_style);
void (* invalidate) (GtkCssNode *node); void (* invalidate) (GtkCssNode *node);
void (* queue_validate) (GtkCssNode *node); void (* queue_validate) (GtkCssNode *node);
...@@ -140,6 +143,9 @@ GtkCssStyle * gtk_css_node_create_style (GtkCssNode * ...@@ -140,6 +143,9 @@ GtkCssStyle * gtk_css_node_create_style (GtkCssNode *
void gtk_css_node_invalidate_style_provider void gtk_css_node_invalidate_style_provider
(GtkCssNode *cssnode); (GtkCssNode *cssnode);
void gtk_css_node_invalidate_frame_clock
(GtkCssNode *cssnode,
gboolean just_timestamp);
void gtk_css_node_invalidate (GtkCssNode *cssnode, void gtk_css_node_invalidate (GtkCssNode *cssnode,
GtkCssChange change); GtkCssChange change);
void gtk_css_node_validate (GtkCssNode *cssnode, void gtk_css_node_validate (GtkCssNode *cssnode,
......
...@@ -57,7 +57,6 @@ _gtk_css_change_for_sibling (GtkCssChange match) ...@@ -57,7 +57,6 @@ _gtk_css_change_for_sibling (GtkCssChange match)
{ GTK_CSS_CHANGE_POSITION, GTK_CSS_CHANGE_SIBLING_POSITION }, { GTK_CSS_CHANGE_POSITION, GTK_CSS_CHANGE_SIBLING_POSITION },
{ GTK_CSS_CHANGE_STATE, GTK_CSS_CHANGE_SIBLING_STATE }, { GTK_CSS_CHANGE_STATE, GTK_CSS_CHANGE_SIBLING_STATE },
{ GTK_CSS_CHANGE_SOURCE, 0 }, { GTK_CSS_CHANGE_SOURCE, 0 },
{ GTK_CSS_CHANGE_ANIMATE, 0 },
{ GTK_CSS_CHANGE_PARENT_STYLE, 0 } { GTK_CSS_CHANGE_PARENT_STYLE, 0 }
}; };
...@@ -77,7 +76,6 @@ _gtk_css_change_for_child (GtkCssChange match) ...@@ -77,7 +76,6 @@ _gtk_css_change_for_child (GtkCssChange match)
{ GTK_CSS_CHANGE_SIBLING_POSITION, GTK_CSS_CHANGE_PARENT_SIBLING_POSITION }, { 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_SIBLING_STATE, GTK_CSS_CHANGE_PARENT_SIBLING_STATE },
{ GTK_CSS_CHANGE_SOURCE, 0 }, { GTK_CSS_CHANGE_SOURCE, 0 },
{ GTK_CSS_CHANGE_ANIMATE, 0 },
{ GTK_CSS_CHANGE_PARENT_STYLE, 0 } { GTK_CSS_CHANGE_PARENT_STYLE, 0 }
}; };
......
...@@ -51,8 +51,9 @@ typedef enum { /*< skip >*/ ...@@ -51,8 +51,9 @@ typedef enum { /*< skip >*/
GTK_CSS_CHANGE_PARENT_SIBLING_STATE = (1 << 15), GTK_CSS_CHANGE_PARENT_SIBLING_STATE = (1 << 15),
/* add more */ /* add more */
GTK_CSS_CHANGE_SOURCE = (1 << 16), GTK_CSS_CHANGE_SOURCE = (1 << 16),
GTK_CSS_CHANGE_ANIMATE = (1 << 17), GTK_CSS_CHANGE_PARENT_STYLE = (1 << 17),
GTK_CSS_CHANGE_PARENT_STYLE = (1 << 18), GTK_CSS_CHANGE_TIMESTAMP = (1 << 18),
GTK_CSS_CHANGE_ANIMATIONS = (1 << 19),
GTK_CSS_CHANGE_RESERVED_BIT = (1 << 31) /* Used internally in gtkcssselector.c */ GTK_CSS_CHANGE_RESERVED_BIT = (1 << 31) /* Used internally in gtkcssselector.c */
} GtkCssChange; } GtkCssChange;
......
...@@ -36,14 +36,28 @@ G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE) ...@@ -36,14 +36,28 @@ G_DEFINE_TYPE (GtkCssWidgetNode, gtk_css_widget_node, GTK_TYPE_CSS_NODE)
static GtkCssStyle * static GtkCssStyle *
gtk_css_widget_node_update_style (GtkCssNode *cssnode, gtk_css_widget_node_update_style (GtkCssNode *cssnode,
GtkCssChange pending_change, GtkCssChange pending_change,
gint64 timestamp,
GtkCssStyle *old_style) GtkCssStyle *old_style)
{ {
if (old_style == NULL) if (old_style == NULL)
return GTK_CSS_NODE_CLASS (gtk_css_widget_node_parent_class)->update_style (cssnode, pending_change, old_style); return GTK_CSS_NODE_CLASS (gtk_css_widget_node_parent_class)->update_style (cssnode, pending_change, timestamp, old_style);
return NULL; return NULL;
} }
static gboolean
gtk_css_widget_node_queue_callback (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer user_data)
{
GtkCssNode *node = user_data;
gtk_css_node_invalidate_frame_clock (node, TRUE);
_gtk_container_queue_restyle (GTK_CONTAINER (widget));
return G_SOURCE_CONTINUE;
}
static void static void
gtk_css_widget_node_queue_validate (GtkCssNode *node) gtk_css_widget_node_queue_validate (GtkCssNode *node)
{ {
...@@ -52,8 +66,8 @@ gtk_css_widget_node_queue_validate (GtkCssNode *node) ...@@ -52,8 +66,8 @@ gtk_css_widget_node_queue_validate (GtkCssNode *node)
G_GNUC_BEGIN_IGNORE_DEPRECATIONS G_GNUC_BEGIN_IGNORE_DEPRECATIONS
if (GTK_IS_RESIZE_CONTAINER (widget_node->widget)) if (GTK_IS_RESIZE_CONTAINER (widget_node->widget))
widget_node->validate_cb_id = gtk_widget_add_tick_callback (widget_node->widget, widget_node->validate_cb_id = gtk_widget_add_tick_callback (widget_node->widget,
(GtkTickCallback) _gtk_container_queue_restyle, gtk_css_widget_node_queue_callback,
NULL, node,
NULL); NULL);
G_GNUC_END_IGNORE_DEPRECATIONS G_GNUC_END_IGNORE_DEPRECATIONS
} }
...@@ -128,7 +142,7 @@ gtk_css_widget_node_validate (GtkCssNode *node, ...@@ -128,7 +142,7 @@ gtk_css_widget_node_validate (GtkCssNode *node,
new_static_style = validate_static_style (node, static_style, change); new_static_style = validate_static_style (node, static_style, change);
if (new_static_style != static_style) if (new_static_style != static_style || (change & GTK_CSS_CHANGE_ANIMATIONS))
{ {
GtkCssNode *parent = gtk_css_node_get_parent (node); GtkCssNode *parent = gtk_css_node_get_parent (node);
new_style = gtk_css_animated_style_new (new_static_style, new_style = gtk_css_animated_style_new (new_static_style,
...@@ -139,7 +153,7 @@ gtk_css_widget_node_validate (GtkCssNode *node, ...@@ -139,7 +153,7 @@ gtk_css_widget_node_validate (GtkCssNode *node,
g_object_unref (new_static_style); g_object_unref (new_static_style);
} }
else if (GTK_IS_CSS_ANIMATED_STYLE (style)) else if (GTK_IS_CSS_ANIMATED_STYLE (style) && (change & GTK_CSS_CHANGE_TIMESTAMP))
{ {
new_style = gtk_css_animated_style_new_advance (GTK_CSS_ANIMATED_STYLE (style), new_style = gtk_css_animated_style_new_advance (GTK_CSS_ANIMATED_STYLE (style),
static_style, static_style,
...@@ -264,6 +278,17 @@ gtk_css_widget_node_get_style_provider (GtkCssNode *node) ...@@ -264,6 +278,17 @@ gtk_css_widget_node_get_style_provider (GtkCssNode *node)
return gtk_style_context_get_style_provider (gtk_widget_get_style_context (widget_node->widget)); return gtk_style_context_get_style_provider (gtk_widget_get_style_context (widget_node->widget));
} }
static GdkFrameClock *
gtk_css_widget_node_get_frame_clock (GtkCssNode *node)
{
GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
if (widget_node->widget == NULL)
return NULL;
return gtk_widget_get_frame_clock (widget_node->widget);
}
static void static void
gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass) gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass)
{ {
...@@ -277,6 +302,7 @@ gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass) ...@@ -277,6 +302,7 @@ gtk_css_widget_node_class_init (GtkCssWidgetNodeClass *klass)
node_class->create_widget_path = gtk_css_widget_node_create_widget_path; node_class->create_widget_path = gtk_css_widget_node_create_widget_path;
node_class->get_widget_path = gtk_css_widget_node_get_widget_path; node_class->get_widget_path = gtk_css_widget_node_get_widget_path;
node_class->get_style_provider = gtk_css_widget_node_get_style_provider; node_class->get_style_provider = gtk_css_widget_node_get_style_provider;
node_class->get_frame_clock = gtk_css_widget_node_get_frame_clock;
} }
static void static void
......
...@@ -5446,6 +5446,8 @@ gtk_widget_connect_frame_clock (GtkWidget *widget, ...@@ -5446,6 +5446,8 @@ gtk_widget_connect_frame_clock (GtkWidget *widget,
gdk_frame_clock_begin_updating (frame_clock); gdk_frame_clock_begin_updating (frame_clock);
} }
gtk_css_node_invalidate_frame_clock (priv->cssnode, FALSE);
if (priv->context) if (priv->context)
gtk_style_context_set_frame_clock (priv->context, frame_clock); gtk_style_context_set_frame_clock (priv->context, frame_clock);
} }
...@@ -5459,6 +5461,8 @@ gtk_widget_disconnect_frame_clock (GtkWidget *widget, ...@@ -5459,6 +5461,8 @@ gtk_widget_disconnect_frame_clock (GtkWidget *widget,
if (GTK_IS_CONTAINER (widget)) if (GTK_IS_CONTAINER (widget))
_gtk_container_stop_idle_sizer (GTK_CONTAINER (widget)); _gtk_container_stop_idle_sizer (GTK_CONTAINER (widget));
gtk_css_node_invalidate_frame_clock (priv->cssnode, FALSE);
if (priv->clock_tick_id) if (priv->clock_tick_id)
{ {
g_signal_handler_disconnect (frame_clock, priv->clock_tick_id); g_signal_handler_disconnect (frame_clock, priv->clock_tick_id);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment