diff --git a/gtk/gtkcssnode.c b/gtk/gtkcssnode.c index 8559a59b9e..a8dcaa0d2e 100644 --- a/gtk/gtkcssnode.c +++ b/gtk/gtkcssnode.c @@ -637,6 +637,12 @@ gtk_css_node_init (GtkCssNode *cssnode) cssnode->visible = TRUE; } +GtkCssNode * +gtk_css_node_new (void) +{ + return g_object_new (GTK_TYPE_CSS_NODE, NULL); +} + static GdkFrameClock * gtk_css_node_get_frame_clock_or_null (GtkCssNode *cssnode) { diff --git a/gtk/gtkcssnodeprivate.h b/gtk/gtkcssnodeprivate.h index 7792647f77..2f9587ed17 100644 --- a/gtk/gtkcssnodeprivate.h +++ b/gtk/gtkcssnodeprivate.h @@ -93,6 +93,8 @@ struct _GtkCssNodeClass GType gtk_css_node_get_type (void) G_GNUC_CONST; +GtkCssNode * gtk_css_node_new (void); + void gtk_css_node_set_parent (GtkCssNode *cssnode, GtkCssNode *parent); void gtk_css_node_insert_after (GtkCssNode *parent, diff --git a/gtk/gtkswitch.c b/gtk/gtkswitch.c index 103382db56..8aecb882c0 100644 --- a/gtk/gtkswitch.c +++ b/gtk/gtkswitch.c @@ -42,15 +42,18 @@ #include "gtkswitch.h" #include "deprecated/gtkactivatable.h" +#include "deprecated/gtktoggleaction.h" #include "gtkintl.h" #include "gtkprivate.h" -#include "deprecated/gtktoggleaction.h" #include "gtkwidget.h" #include "gtkmarshalers.h" #include "gtkapplicationprivate.h" #include "gtkactionable.h" #include "a11y/gtkswitchaccessible.h" #include "gtkactionhelper.h" +#include "gtkcssnodeprivate.h" +#include "gtkcssstylepropertyprivate.h" +#include "gtkstylecontextprivate.h" #include "gtkwidgetprivate.h" #include "gtkcssshadowsvalueprivate.h" #include "gtkstylecontextprivate.h" @@ -69,6 +72,8 @@ struct _GtkSwitchPrivate GtkGesture *pan_gesture; GtkGesture *multipress_gesture; + GtkCssNode *slider_node; + double handle_pos; gint64 start_time; gint64 end_time; @@ -257,9 +262,7 @@ gtk_switch_pan_gesture_pan (GtkGesturePan *gesture, context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); - gtk_style_context_save (context); - gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); + gtk_style_context_save_to_node (context, priv->slider_node); gtk_style_context_get_padding (context, state, &padding); gtk_style_context_restore (context); @@ -351,6 +354,8 @@ gtk_switch_get_preferred_width (GtkWidget *widget, gint *minimum, gint *natural) { + GtkSwitch *self; + GtkSwitchPrivate *priv; GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; @@ -358,13 +363,12 @@ gtk_switch_get_preferred_width (GtkWidget *widget, PangoLayout *layout; PangoRectangle logical_rect; + self = GTK_SWITCH (widget); + priv = self->priv; context = gtk_widget_get_style_context (widget); state = gtk_style_context_get_state (context); - gtk_style_context_save (context); - - gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); + gtk_style_context_save_to_node (context, priv->slider_node); gtk_style_context_get_padding (context, state, &padding); width = padding.left + padding.right; @@ -403,6 +407,8 @@ gtk_switch_get_preferred_height (GtkWidget *widget, gint *minimum, gint *natural) { + GtkSwitch *self; + GtkSwitchPrivate *priv; GtkStyleContext *context; GtkStateFlags state; GtkBorder padding; @@ -411,13 +417,13 @@ gtk_switch_get_preferred_height (GtkWidget *widget, PangoRectangle logical_rect; gchar *str; + self = GTK_SWITCH (widget); + priv = self->priv; context = gtk_widget_get_style_context (widget); state = gtk_style_context_get_state (context); - gtk_style_context_save (context); + gtk_style_context_save_to_node (context, priv->slider_node); - gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); gtk_style_context_get_padding (context, state, &padding); height = padding.top + padding.bottom; @@ -565,9 +571,7 @@ gtk_switch_paint_handle (GtkWidget *widget, { GtkStyleContext *context = gtk_widget_get_style_context (widget); - gtk_style_context_save (context); - gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); + gtk_style_context_save_to_node (context, GTK_SWITCH (widget)->priv->slider_node); gtk_render_slider (context, cr, box->x, box->y, @@ -594,10 +598,7 @@ gtk_switch_draw (GtkWidget *widget, context = gtk_widget_get_style_context (widget); state = gtk_widget_get_state_flags (widget); - gtk_style_context_save (context); - - gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TROUGH); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_SLIDER); + gtk_style_context_save_to_node (context, priv->slider_node); gtk_style_context_get_padding (context, state, &padding); @@ -870,6 +871,29 @@ state_set (GtkSwitch *sw, gboolean state) return TRUE; } +static void +node_style_changed_cb (GtkCssNode *node, + GtkCssStyle *old_style, + GtkCssStyle *new_style, + GtkWidget *widget) +{ + GtkBitmask *changes; + static GtkBitmask *affects_size = NULL; + + if (G_UNLIKELY (affects_size == NULL)) + affects_size = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP); + + changes = _gtk_bitmask_new (); + changes = gtk_css_style_add_difference (changes, old_style, new_style); + + if (_gtk_bitmask_intersects (changes, affects_size)) + gtk_widget_queue_resize (widget); + else + gtk_widget_queue_draw (widget); + + _gtk_bitmask_free (changes); +} + static void gtk_switch_class_init (GtkSwitchClass *klass) { @@ -1032,6 +1056,7 @@ gtk_switch_init (GtkSwitch *self) GtkSwitchPrivate *priv; GtkStyleContext *context; GtkGesture *gesture; + GtkCssNode *widget_node; priv = self->priv = gtk_switch_get_instance_private (self); @@ -1039,6 +1064,15 @@ gtk_switch_init (GtkSwitch *self) gtk_widget_set_has_window (GTK_WIDGET (self), FALSE); gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE); + widget_node = gtk_widget_get_css_node (GTK_WIDGET (self)); + priv->slider_node = gtk_css_node_new (); + gtk_css_node_set_widget_type (priv->slider_node, GTK_TYPE_SWITCH); + gtk_css_node_add_class (priv->slider_node, g_quark_from_string (GTK_STYLE_CLASS_SLIDER)); + gtk_css_node_set_parent (priv->slider_node, widget_node); + gtk_css_node_set_state (priv->slider_node, gtk_css_node_get_state (widget_node)); + g_signal_connect_object (priv->slider_node, "style-changed", G_CALLBACK (node_style_changed_cb), self, 0); + g_object_unref (priv->slider_node); + gesture = gtk_gesture_multi_press_new (GTK_WIDGET (self)); gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture), FALSE); gtk_gesture_single_set_exclusive (GTK_GESTURE_SINGLE (gesture), TRUE);