#include <gobject/gvaluecollector.h>
#include "gtkstylecontextprivate.h"
+#include "gtkcontainerprivate.h"
+#include "gtkcsscolorvalueprivate.h"
+#include "gtkcsscornervalueprivate.h"
#include "gtkcssenginevalueprivate.h"
+#include "gtkcssnumbervalueprivate.h"
#include "gtkcssrgbavalueprivate.h"
+#include "gtkdebug.h"
#include "gtkstylepropertiesprivate.h"
#include "gtktypebuiltins.h"
#include "gtkthemingengineprivate.h"
#include "gtkwidget.h"
#include "gtkwindow.h"
#include "gtkprivate.h"
-#include "gtksymboliccolorprivate.h"
-#include "gtkcssnumbervalueprivate.h"
#include "gtkiconfactory.h"
#include "gtkwidgetpath.h"
#include "gtkwidgetprivate.h"
#include "gtkstylecascadeprivate.h"
#include "gtkstyleproviderprivate.h"
#include "gtksettings.h"
+#include "gtksettingsprivate.h"
+
+#include "deprecated/gtkgradientprivate.h"
+#include "deprecated/gtksymboliccolorprivate.h"
/**
* SECTION:gtkstylecontext
/* When these change we do a full restyling. Otherwise we try to figure out
* if we need to change things. */
-#define GTK_STYLE_CONTEXT_RADICAL_CHANGE (GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS)
+#define GTK_STYLE_CONTEXT_RADICAL_CHANGE (GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_SOURCE)
/* When these change we don't clear the cache. This takes more memory but makes
* things go faster. */
#define GTK_STYLE_CONTEXT_CACHED_CHANGE (GTK_CSS_CHANGE_STATE)
struct GtkStyleInfo
{
+ GtkStyleInfo *next;
GArray *style_classes;
GArray *regions;
GtkJunctionSides junction_sides;
{
GtkCssComputedValues *store;
GArray *property_cache;
+ guint ref_count;
};
struct _GtkStyleContextPrivate
GtkStyleContext *parent;
GSList *children;
- GtkWidget *widget;
+ GtkWidget *widget;
GtkWidgetPath *widget_path;
GHashTable *style_data;
- GSList *info_stack;
-
- GtkThemingEngine *theming_engine;
+ GtkStyleInfo *info;
- GtkTextDirection direction;
+ GdkFrameClock *frame_clock;
+ guint frame_clock_update_id;
GtkCssChange relevant_changes;
GtkCssChange pending_changes;
- guint invalidating_context : 1;
+ const GtkBitmask *invalidating_context;
+ guint animating : 1;
guint invalid : 1;
};
static void gtk_style_context_finalize (GObject *object);
+static void frame_clock_target_iface_init (GdkFrameClockTargetInterface *target);
+
static void gtk_style_context_impl_set_property (GObject *object,
guint prop_id,
const GValue *value,
guint prop_id,
GValue *value,
GParamSpec *pspec);
-static GtkSymbolicColor *
- gtk_style_context_color_lookup_func (gpointer contextp,
- const char *name);
+static StyleData *style_data_lookup (GtkStyleContext *context);
+
+static void gtk_style_context_disconnect_update (GtkStyleContext *context);
+static void gtk_style_context_connect_update (GtkStyleContext *context);
-G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
+G_DEFINE_TYPE_WITH_CODE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GDK_TYPE_FRAME_CLOCK_TARGET, frame_clock_target_iface_init))
static void
gtk_style_context_real_changed (GtkStyleContext *context)
g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
}
+static void
+gtk_style_context_set_clock (GdkFrameClockTarget *target,
+ GdkFrameClock *clock)
+{
+ GtkStyleContext *context = GTK_STYLE_CONTEXT (target);
+ GtkStyleContextPrivate *priv = context->priv;
+
+ gtk_style_context_disconnect_update (context);
+ priv->frame_clock = clock;
+ if (priv->animating)
+ gtk_style_context_connect_update (context);
+}
+
+static void
+frame_clock_target_iface_init (GdkFrameClockTargetInterface *iface)
+{
+ iface->set_clock = gtk_style_context_set_clock;
+}
+
+static StyleData *
+style_data_new (void)
+{
+ StyleData *data;
+
+ data = g_slice_new0 (StyleData);
+ data->ref_count = 1;
+
+ return data;
+}
+
+static void
+clear_property_cache (StyleData *data)
+{
+ guint i;
+
+ if (!data->property_cache)
+ return;
+
+ for (i = 0; i < data->property_cache->len; i++)
+ {
+ PropertyValue *node = &g_array_index (data->property_cache, PropertyValue, i);
+
+ g_param_spec_unref (node->pspec);
+ g_value_unset (&node->value);
+ }
+
+ g_array_free (data->property_cache, TRUE);
+ data->property_cache = NULL;
+}
+
+static StyleData *
+style_data_ref (StyleData *style_data)
+{
+ style_data->ref_count++;
+
+ return style_data;
+}
+
+static void
+style_data_unref (StyleData *data)
+{
+ data->ref_count--;
+
+ if (data->ref_count > 0)
+ return;
+
+ g_object_unref (data->store);
+ clear_property_cache (data);
+
+ g_slice_free (StyleData, data);
+}
+
+static gboolean
+style_data_is_animating (StyleData *style_data)
+{
+ return !_gtk_css_computed_values_is_static (style_data->store);
+}
+
static GtkStyleInfo *
style_info_new (void)
{
return info;
}
+static void
+style_info_set_data (GtkStyleInfo *info,
+ StyleData *data)
+{
+ if (info->data == data)
+ return;
+
+ if (data)
+ style_data_ref (data);
+
+ if (info->data)
+ style_data_unref (info->data);
+
+ info->data = data;
+}
+
static void
style_info_free (GtkStyleInfo *info)
{
+ style_info_set_data (info, NULL);
g_array_free (info->style_classes, TRUE);
g_array_free (info->regions, TRUE);
g_slice_free (GtkStyleInfo, info);
}
static GtkStyleInfo *
-style_info_copy (const GtkStyleInfo *info)
+style_info_pop (GtkStyleInfo *info)
+{
+ GtkStyleInfo *next = info->next;
+
+ style_info_free (info);
+
+ return next;
+}
+
+static GtkStyleInfo *
+style_info_copy (GtkStyleInfo *info)
{
GtkStyleInfo *copy;
info->regions->data,
info->regions->len);
+ copy->next = info;
copy->junction_sides = info->junction_sides;
copy->state_flags = info->state_flags;
- copy->data = info->data;
+ style_info_set_data (copy, info->data);
return copy;
}
return TRUE;
}
-static StyleData *
-style_data_new (void)
+static void
+gtk_style_context_cascade_changed (GtkStyleCascade *cascade,
+ GtkStyleContext *context)
{
- StyleData *data;
-
- data = g_slice_new0 (StyleData);
-
- return data;
+ _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_SOURCE);
}
static void
-clear_property_cache (StyleData *data)
+gtk_style_context_set_cascade (GtkStyleContext *context,
+ GtkStyleCascade *cascade)
{
- guint i;
+ GtkStyleContextPrivate *priv;
- if (!data->property_cache)
+ priv = context->priv;
+
+ if (priv->cascade == cascade)
return;
- for (i = 0; i < data->property_cache->len; i++)
+ if (cascade)
{
- PropertyValue *node = &g_array_index (data->property_cache, PropertyValue, i);
-
- g_param_spec_unref (node->pspec);
- g_value_unset (&node->value);
+ g_object_ref (cascade);
+ g_signal_connect (cascade,
+ "-gtk-private-changed",
+ G_CALLBACK (gtk_style_context_cascade_changed),
+ context);
}
- g_array_free (data->property_cache, TRUE);
- data->property_cache = NULL;
-}
+ if (priv->cascade)
+ {
+ g_signal_handlers_disconnect_by_func (priv->cascade,
+ gtk_style_context_cascade_changed,
+ context);
+ g_object_unref (priv->cascade);
+ }
-static void
-style_data_free (StyleData *data)
-{
- g_object_unref (data->store);
- clear_property_cache (data);
+ priv->cascade = cascade;
- g_slice_free (StyleData, data);
+ if (cascade)
+ gtk_style_context_cascade_changed (cascade, context);
}
static void
gtk_style_context_init (GtkStyleContext *style_context)
{
GtkStyleContextPrivate *priv;
- GtkStyleInfo *info;
priv = style_context->priv = G_TYPE_INSTANCE_GET_PRIVATE (style_context,
GTK_TYPE_STYLE_CONTEXT,
priv->style_data = g_hash_table_new_full (style_info_hash,
style_info_equal,
(GDestroyNotify) style_info_free,
- (GDestroyNotify) style_data_free);
- priv->theming_engine = g_object_ref ((gpointer) gtk_theming_engine_load (NULL));
-
- priv->direction = GTK_TEXT_DIR_LTR;
+ (GDestroyNotify) style_data_unref);
priv->screen = gdk_screen_get_default ();
- priv->cascade = _gtk_style_cascade_get_for_screen (priv->screen);
- g_object_ref (priv->cascade);
priv->relevant_changes = GTK_CSS_CHANGE_ANY;
/* Create default info store */
- info = style_info_new ();
- priv->info_stack = g_slist_prepend (priv->info_stack, info);
+ priv->info = style_info_new ();
+ priv->info->state_flags = GTK_STATE_FLAG_DIR_LTR;
+
+ gtk_style_context_set_cascade (style_context,
+ _gtk_style_cascade_get_for_screen (priv->screen));
+}
+
+static void
+gtk_style_context_update (GdkFrameClock *clock,
+ GtkStyleContext *context)
+{
+ _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANIMATE);
+
+ /* A little blech to request one more than we need */
+ gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
+}
+
+static gboolean
+gtk_style_context_is_animating (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv = context->priv;
+
+ return priv->animating;
+}
+
+static void
+gtk_style_context_disconnect_update (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv = context->priv;
+
+ if (priv->frame_clock && priv->frame_clock_update_id)
+ {
+ g_signal_handler_disconnect (priv->frame_clock,
+ priv->frame_clock_update_id);
+ priv->frame_clock_update_id = 0;
+ }
+}
+
+static void
+gtk_style_context_connect_update (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv = context->priv;
+
+ if (priv->frame_clock && priv->frame_clock_update_id == 0)
+ {
+ priv->frame_clock_update_id = g_signal_connect (priv->frame_clock,
+ "update",
+ G_CALLBACK (gtk_style_context_update),
+ context);
+ gdk_frame_clock_request_phase (priv->frame_clock, GDK_FRAME_CLOCK_PHASE_UPDATE);
+ }
+}
+
+static void
+gtk_style_context_stop_animating (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv = context->priv;
+
+ if (!gtk_style_context_is_animating (context))
+ return;
+
+ priv->animating = FALSE;
+
+ gtk_style_context_disconnect_update (context);
+ if (priv->widget)
+ {
+ gtk_widget_remove_frame_clock_target (priv->widget,
+ GDK_FRAME_CLOCK_TARGET (context));
+ }
+}
+
+static void
+gtk_style_context_start_animating (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv = context->priv;
+
+ if (gtk_style_context_is_animating (context))
+ return;
+
+ priv->animating = TRUE;
+
+ gtk_style_context_connect_update (context);
+ if (priv->widget)
+ {
+ gtk_widget_add_frame_clock_target (priv->widget,
+ GDK_FRAME_CLOCK_TARGET (context));
+ }
+}
+
+static gboolean
+gtk_style_context_should_animate (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ gboolean animate;
+
+ priv = context->priv;
+
+ if (priv->widget == NULL)
+ return FALSE;
+
+ if (!gtk_widget_get_mapped (priv->widget))
+ return FALSE;
+
+ data = style_data_lookup (context);
+ if (!style_data_is_animating (data))
+ return FALSE;
+
+ g_object_get (gtk_widget_get_settings (context->priv->widget),
+ "gtk-enable-animations", &animate,
+ NULL);
+
+ return animate;
+}
+
+void
+_gtk_style_context_update_animating (GtkStyleContext *context)
+{
+ if (gtk_style_context_should_animate (context))
+ gtk_style_context_start_animating (context);
+ else
+ gtk_style_context_stop_animating (context);
}
static void
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);
gtk_style_context_set_parent (style_context, NULL);
+ gtk_style_context_set_cascade (style_context, NULL);
+
if (priv->widget_path)
gtk_widget_path_free (priv->widget_path);
g_hash_table_destroy (priv->style_data);
- g_object_unref (priv->cascade);
-
- g_slist_free_full (priv->info_stack, (GDestroyNotify) style_info_free);
-
- if (priv->theming_engine)
- g_object_unref (priv->theming_engine);
+ while (priv->info)
+ priv->info = style_info_pop (priv->info);
G_OBJECT_CLASS (gtk_style_context_parent_class)->finalize (object);
}
g_value_get_object (value));
break;
case PROP_DIRECTION:
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
gtk_style_context_set_direction (style_context,
g_value_get_enum (value));
+ G_GNUC_END_IGNORE_DEPRECATIONS;
break;
case PROP_PARENT:
gtk_style_context_set_parent (style_context,
g_value_set_object (value, priv->screen);
break;
case PROP_DIRECTION:
- g_value_set_enum (value, priv->direction);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+ g_value_set_enum (value, gtk_style_context_get_direction (style_context));
+ G_GNUC_END_IGNORE_DEPRECATIONS;
break;
case PROP_PARENT:
g_value_set_object (value, priv->parent);
}
}
-static void
-build_properties (GtkStyleContext *context,
- StyleData *style_data,
- GtkWidgetPath *path,
- GtkStateFlags state)
-{
- GtkStyleContextPrivate *priv;
- GtkCssMatcher matcher;
- GtkCssLookup *lookup;
-
- priv = context->priv;
-
- _gtk_css_matcher_init (&matcher, path, state);
- lookup = _gtk_css_lookup_new ();
-
- _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
- &matcher,
- lookup);
-
- style_data->store = _gtk_css_computed_values_new ();
- _gtk_css_lookup_resolve (lookup, context, style_data->store);
- _gtk_css_lookup_free (lookup);
-}
-
static GtkWidgetPath *
-create_query_path (GtkStyleContext *context)
+create_query_path (GtkStyleContext *context,
+ GtkStyleInfo *info)
{
GtkStyleContextPrivate *priv;
GtkWidgetPath *path;
- GtkStyleInfo *info;
guint i, pos;
priv = context->priv;
- path = gtk_widget_path_copy (priv->widget ? gtk_widget_get_path (priv->widget) : priv->widget_path);
+ path = priv->widget ? _gtk_widget_create_path (priv->widget) : gtk_widget_path_copy (priv->widget_path);
pos = gtk_widget_path_length (path) - 1;
- info = priv->info_stack->data;
-
/* Set widget regions */
for (i = 0; i < info->regions->len; i++)
{
return path;
}
+static void
+build_properties (GtkStyleContext *context,
+ GtkCssComputedValues *values,
+ GtkStyleInfo *info,
+ const GtkBitmask *relevant_changes)
+{
+ GtkStyleContextPrivate *priv;
+ GtkCssMatcher matcher;
+ GtkWidgetPath *path;
+ GtkCssLookup *lookup;
+
+ priv = context->priv;
+
+ path = create_query_path (context, info);
+ lookup = _gtk_css_lookup_new (relevant_changes);
+
+ if (_gtk_css_matcher_init (&matcher, path, info->state_flags))
+ _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+ &matcher,
+ lookup);
+
+ _gtk_css_lookup_resolve (lookup,
+ GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+ values,
+ priv->parent ? style_data_lookup (priv->parent)->store : NULL);
+
+ _gtk_css_lookup_free (lookup);
+ gtk_widget_path_free (path);
+}
+
static StyleData *
style_data_lookup (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
+ StyleData *data;
priv = context->priv;
- info = priv->info_stack->data;
+ info = priv->info;
/* Current data in use is cached, just return it */
if (info->data)
g_assert (priv->widget != NULL || priv->widget_path != NULL);
- info->data = g_hash_table_lookup (priv->style_data, info);
-
- if (!info->data)
+ data = g_hash_table_lookup (priv->style_data, info);
+ if (data)
{
- GtkWidgetPath *path;
+ style_info_set_data (info, data);
+ return data;
+ }
- path = create_query_path (context);
+ data = style_data_new ();
+ data->store = _gtk_css_computed_values_new ();
+ style_info_set_data (info, data);
+ g_hash_table_insert (priv->style_data,
+ style_info_copy (info),
+ data);
- info->data = style_data_new ();
- g_hash_table_insert (priv->style_data,
- style_info_copy (info),
- info->data);
+ build_properties (context, data->store, info, NULL);
- build_properties (context, info->data, path, info->state_flags);
+ return data;
+}
- gtk_widget_path_free (path);
- }
+static StyleData *
+style_data_lookup_for_state (GtkStyleContext *context,
+ GtkStateFlags state)
+{
+ StyleData *data;
- if (priv->theming_engine)
- g_object_unref (priv->theming_engine);
+ if (context->priv->info->state_flags == state)
+ return style_data_lookup (context);
- priv->theming_engine = g_object_ref (
- _gtk_css_engine_value_get_engine (
- _gtk_css_computed_values_get_value (info->data->store, GTK_CSS_PROPERTY_ENGINE)));
+ gtk_style_context_save (context);
+ gtk_style_context_set_state (context, state);
+ data = style_data_lookup (context);
+ gtk_style_context_restore (context);
- return info->data;
+ return data;
}
static void
{
if (priv->parent)
gtk_style_context_set_invalid (priv->parent, TRUE);
- else if (priv->widget)
- gtk_widget_queue_resize (priv->widget);
+ else if (GTK_IS_RESIZE_CONTAINER (priv->widget))
+ _gtk_container_queue_restyle (GTK_CONTAINER (priv->widget));
}
}
static gboolean
gtk_style_context_is_saved (GtkStyleContext *context)
{
- return context->priv->info_stack->next != NULL;
+ return context->priv->info->next != NULL;
}
static void
GtkCssChange change)
{
GtkStyleContextPrivate *priv = context->priv;
- GtkStyleInfo *info = priv->info_stack->data;
+ GtkStyleInfo *info = priv->info;
if (gtk_style_context_is_saved (context))
{
- info->data = NULL;
+ style_info_set_data (info, NULL);
}
else
{
- _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_STATE);
+ _gtk_style_context_queue_invalidate (context, change);
/* XXX: We need to invalidate siblings here somehow */
}
}
context->priv->widget = widget;
+ _gtk_style_context_update_animating (context);
+
_gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_SELF);
}
* %GTK_STYLE_PROVIDER_PRIORITY_USER
*
* Adds a style provider to @context, to be used in style construction.
+ * Note that a style provider added by this function only affects
+ * the style of the widget to which @context belongs. If you want
+ * to affect the style of all widgets, use
+ * gtk_style_context_add_provider_for_screen().
*
* <note><para>If both priorities are the same, A #GtkStyleProvider
* added through this function takes precedence over another added
new_cascade = _gtk_style_cascade_new ();
_gtk_style_cascade_set_parent (new_cascade, priv->cascade);
- g_object_unref (priv->cascade);
- priv->cascade = new_cascade;
+ _gtk_style_cascade_add_provider (new_cascade, provider, priority);
+ gtk_style_context_set_cascade (context, new_cascade);
+ g_object_unref (new_cascade);
+ }
+ else
+ {
+ _gtk_style_cascade_add_provider (priv->cascade, provider, priority);
}
-
- _gtk_style_cascade_add_provider (priv->cascade, provider, priority);
-
- gtk_style_context_invalidate (context);
}
/**
* %GTK_STYLE_PROVIDER_PRIORITY_USER
*
* Adds a global style provider to @screen, which will be used
- * in style construction for all #GtkStyleContext<!-- -->s under
- * @screen.
+ * in style construction for all #GtkStyleContexts under @screen.
*
* GTK+ uses this to make styling information from #GtkSettings
* available.
g_return_if_fail (GDK_IS_SCREEN (screen));
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
+ g_return_if_fail (!GTK_IS_SETTINGS (provider) || _gtk_settings_get_screen (GTK_SETTINGS (provider)) == screen);
cascade = _gtk_style_cascade_get_for_screen (screen);
_gtk_style_cascade_add_provider (cascade, provider, priority);
g_return_if_fail (GDK_IS_SCREEN (screen));
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
+ g_return_if_fail (!GTK_IS_SETTINGS (provider));
cascade = _gtk_style_cascade_get_for_screen (screen);
_gtk_style_cascade_remove_provider (cascade, provider);
return;
}
- gtk_style_context_save (context);
- gtk_style_context_set_state (context, state);
- data = style_data_lookup (context);
+ data = style_data_lookup_for_state (context, state);
_gtk_style_property_query (prop, value, gtk_style_context_query_func, data->store);
- gtk_style_context_restore (context);
}
/**
gtk_style_context_set_state (GtkStyleContext *context,
GtkStateFlags flags)
{
- GtkStyleContextPrivate *priv;
- GtkStyleInfo *info;
-
+ GtkStateFlags old_flags;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
- priv = context->priv;
- info = priv->info_stack->data;
- info->state_flags = flags;
+ old_flags = context->priv->info->state_flags;
+ if (old_flags == flags)
+ return;
+
+ context->priv->info->state_flags = flags;
+
+ if (((old_flags ^ flags) & (GTK_STATE_FLAG_DIR_LTR | GTK_STATE_FLAG_DIR_RTL)) &&
+ !gtk_style_context_is_saved (context))
+ g_object_notify (G_OBJECT (context), "direction");
gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_STATE);
}
**/
GtkStateFlags
gtk_style_context_get_state (GtkStyleContext *context)
-{
- GtkStyleContextPrivate *priv;
- GtkStyleInfo *info;
-
+{
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
- priv = context->priv;
- info = priv->info_stack->data;
-
- return info->state_flags;
+ return context->priv->info->state_flags;
}
/**
gtk_style_context_save (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
- GtkStyleInfo *info;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
priv = context->priv;
- g_assert (priv->info_stack != NULL);
-
- info = style_info_copy (priv->info_stack->data);
- priv->info_stack = g_slist_prepend (priv->info_stack, info);
+ priv->info = style_info_copy (priv->info);
+ /* Need to unset animations here because we can not know what style
+ * class potential transitions came from once we save().
+ */
+ if (priv->info->data && style_data_is_animating (priv->info->data))
+ style_info_set_data (priv->info, NULL);
}
/**
gtk_style_context_restore (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
- GtkStyleInfo *info;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
priv = context->priv;
- if (priv->info_stack)
- {
- info = priv->info_stack->data;
- priv->info_stack = g_slist_remove (priv->info_stack, info);
- style_info_free (info);
- }
+ priv->info = style_info_pop (priv->info);
- if (!priv->info_stack)
+ if (!priv->info)
{
g_warning ("Unpaired gtk_style_context_restore() call");
/* Create default region */
- info = style_info_new ();
- priv->info_stack = g_slist_prepend (priv->info_stack, info);
+ priv->info = style_info_new ();
}
}
priv = context->priv;
class_quark = g_quark_from_string (class_name);
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
if (!style_class_find (info->style_classes, class_quark, &position))
{
priv = context->priv;
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
if (style_class_find (info->style_classes, class_quark, &position))
{
priv = context->priv;
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
if (style_class_find (info->style_classes, class_quark, NULL))
return TRUE;
priv = context->priv;
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
for (i = 0; i < info->style_classes->len; i++)
{
priv = context->priv;
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
for (i = 0; i < info->regions->len; i++)
{
priv = context->priv;
region_quark = g_quark_from_string (region_name);
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
if (!region_find (info->regions, region_quark, &position))
{
priv = context->priv;
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
if (region_find (info->regions, region_quark, &position))
{
priv = context->priv;
- g_assert (priv->info_stack != NULL);
- info = priv->info_stack->data;
+ info = priv->info;
if (region_find (info->regions, region_quark, &position))
{
return _gtk_css_computed_values_get_value (data->store, property_id);
}
-double
-_gtk_style_context_get_number (GtkStyleContext *context,
- guint property_id,
- double one_hundred_percent)
-{
- GtkCssValue *value;
-
- value = _gtk_style_context_peek_property (context, property_id);
- return _gtk_css_number_value_get (value, one_hundred_percent);
-}
-
const GValue *
_gtk_style_context_peek_style_property (GtkStyleContext *context,
GType widget_type,
priv = context->priv;
- gtk_style_context_save (context);
- gtk_style_context_set_state (context, state);
- data = style_data_lookup (context);
- gtk_style_context_restore (context);
+ data = style_data_lookup_for_state (context, state);
key.widget_type = widget_type;
key.state = state;
if (priv->widget || priv->widget_path)
{
+ GtkWidgetPath *widget_path = priv->widget ? _gtk_widget_create_path (priv->widget) : priv->widget_path;
+
if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
- priv->widget ? gtk_widget_get_path (priv->widget)
- : priv->widget_path,
+ widget_path,
state, pspec, &pcache->value))
{
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+
/* Resolve symbolic colors to GdkColor/GdkRGBA */
if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
{
else
g_value_init (&pcache->value, GDK_TYPE_COLOR);
- if (_gtk_style_context_resolve_color (context, color, &rgba))
+ if (_gtk_style_context_resolve_color (context, _gtk_symbolic_color_get_css_value (color), &rgba, NULL))
{
if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
g_value_set_boxed (&pcache->value, &rgba);
gtk_symbolic_color_unref (color);
}
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+
+ if (priv->widget)
+ gtk_widget_path_free (widget_path);
+
return &pcache->value;
}
+
+ if (priv->widget)
+ gtk_widget_path_free (widget_path);
}
/* not supplied by any provider, revert to default */
if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
{
- g_object_unref (priv->cascade);
- priv->cascade = _gtk_style_cascade_get_for_screen (screen);
- g_object_ref (priv->cascade);
+ gtk_style_context_set_cascade (context, _gtk_style_cascade_get_for_screen (screen));
}
else
{
priv->screen = screen;
g_object_notify (G_OBJECT (context), "screen");
-
- gtk_style_context_invalidate (context);
}
/**
* call this yourself.
*
* Since: 3.0
+ *
+ * Deprecated: 3.8: Use gtk_style_context_set_state() with
+ * #GTK_STATE_FLAG_DIR_LTR and #GTK_STATE_FLAG_DIR_RTL
+ * instead.
**/
void
gtk_style_context_set_direction (GtkStyleContext *context,
GtkTextDirection direction)
{
- GtkStyleContextPrivate *priv;
+ GtkStateFlags state;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
- priv = context->priv;
- priv->direction = direction;
+ state = gtk_style_context_get_state (context);
+ state &= ~(GTK_STATE_FLAG_DIR_LTR | GTK_STATE_FLAG_DIR_RTL);
+
+ switch (direction)
+ {
+ case GTK_TEXT_DIR_LTR:
+ state |= GTK_STATE_FLAG_DIR_LTR;
+ break;
+
+ case GTK_TEXT_DIR_RTL:
+ state |= GTK_STATE_FLAG_DIR_RTL;
+ break;
+
+ case GTK_TEXT_DIR_NONE:
+ default:
+ break;
+ }
- g_object_notify (G_OBJECT (context), "direction");
+ gtk_style_context_set_state (context, state);
}
/**
* Returns: the widget direction
*
* Since: 3.0
+ *
+ * Deprecated: 3.8: Use gtk_style_context_get_state() and
+ * check for #GTK_STATE_FLAG_DIR_LTR and
+ * #GTK_STATE_FLAG_DIR_RTL instead.
**/
GtkTextDirection
gtk_style_context_get_direction (GtkStyleContext *context)
{
- GtkStyleContextPrivate *priv;
+ GtkStateFlags state;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), GTK_TEXT_DIR_LTR);
- priv = context->priv;
- return priv->direction;
+ state = gtk_style_context_get_state (context);
+
+ if (state & GTK_STATE_FLAG_DIR_LTR)
+ return GTK_TEXT_DIR_LTR;
+ else if (state & GTK_STATE_FLAG_DIR_RTL)
+ return GTK_TEXT_DIR_RTL;
+ else
+ return GTK_TEXT_DIR_NONE;
}
/**
gtk_style_context_set_junction_sides (GtkStyleContext *context,
GtkJunctionSides sides)
{
- GtkStyleContextPrivate *priv;
- GtkStyleInfo *info;
-
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
- priv = context->priv;
- info = priv->info_stack->data;
- info->junction_sides = sides;
+ context->priv->info->junction_sides = sides;
}
/**
GtkJunctionSides
gtk_style_context_get_junction_sides (GtkStyleContext *context)
{
- GtkStyleContextPrivate *priv;
- GtkStyleInfo *info;
-
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
- priv = context->priv;
- info = priv->info_stack->data;
- return info->junction_sides;
-}
-
-static GtkSymbolicColor *
-gtk_style_context_color_lookup_func (gpointer contextp,
- const char *name)
-{
- GtkStyleContext *context = contextp;
-
- return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade), name);
-}
-
-GtkCssValue *
-_gtk_style_context_resolve_color_value (GtkStyleContext *context,
- GtkCssValue *current,
- GtkCssValue *color)
-{
- g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
- g_return_val_if_fail (current != NULL, FALSE);
- g_return_val_if_fail (color != NULL, FALSE);
-
- return _gtk_symbolic_color_resolve_full ((GtkSymbolicColor *) color,
- current,
- gtk_style_context_color_lookup_func,
- context);
+ return context->priv->info->junction_sides;
}
-
gboolean
-_gtk_style_context_resolve_color (GtkStyleContext *context,
- GtkSymbolicColor *color,
- GdkRGBA *result)
+_gtk_style_context_resolve_color (GtkStyleContext *context,
+ GtkCssValue *color,
+ GdkRGBA *result,
+ GtkCssDependencies *dependencies)
{
GtkCssValue *val;
g_return_val_if_fail (color != NULL, FALSE);
g_return_val_if_fail (result != NULL, FALSE);
- val = _gtk_symbolic_color_resolve_full (color,
- _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR),
- gtk_style_context_color_lookup_func,
- context);
+ val = _gtk_css_color_value_resolve (color,
+ GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade),
+ _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR),
+ GTK_CSS_DEPENDS_ON_COLOR,
+ dependencies);
if (val == NULL)
return FALSE;
const gchar *color_name,
GdkRGBA *color)
{
- GtkSymbolicColor *sym_color;
+ GtkCssValue *value;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
g_return_val_if_fail (color_name != NULL, FALSE);
g_return_val_if_fail (color != NULL, FALSE);
- sym_color = gtk_style_context_color_lookup_func (context, color_name);
- if (sym_color == NULL)
+ value = _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade), color_name);
+ if (value == NULL)
return FALSE;
- return _gtk_style_context_resolve_color (context, sym_color, color);
+ return _gtk_style_context_resolve_color (context, value, color, NULL);
}
/**
gtk_style_context_clear_cache (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
- GSList *list;
+ GtkStyleInfo *info;
priv = context->priv;
- for (list = priv->info_stack; list; list = list->next)
+ for (info = priv->info; info; info = info->next)
{
- GtkStyleInfo *info = list->data;
- info->data = NULL;
+ style_info_set_data (info, NULL);
}
g_hash_table_remove_all (priv->style_data);
}
static void
-gtk_style_context_do_invalidate (GtkStyleContext *context)
+gtk_style_context_update_cache (GtkStyleContext *context,
+ const GtkBitmask *parent_changes)
+{
+ GtkStyleContextPrivate *priv;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ if (_gtk_bitmask_is_empty (parent_changes))
+ return;
+
+ priv = context->priv;
+
+ g_hash_table_iter_init (&iter, priv->style_data);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GtkStyleInfo *info = key;
+ StyleData *data = value;
+ GtkBitmask *changes;
+
+ changes = _gtk_css_computed_values_compute_dependencies (data->store, parent_changes);
+
+ if (!_gtk_bitmask_is_empty (changes))
+ build_properties (context, data->store, info, changes);
+
+ _gtk_bitmask_free (changes);
+ }
+}
+
+static void
+gtk_style_context_do_invalidate (GtkStyleContext *context,
+ const GtkBitmask *changes)
{
GtkStyleContextPrivate *priv;
if (priv->invalidating_context)
return;
- priv->invalidating_context = TRUE;
+ priv->invalidating_context = changes;
g_signal_emit (context, signals[CHANGED], 0);
- priv->invalidating_context = FALSE;
+ priv->invalidating_context = NULL;
}
-void
-_gtk_style_context_validate (GtkStyleContext *context,
- GtkCssChange change)
+static GtkBitmask *
+gtk_style_context_update_animations (GtkStyleContext *context,
+ gint64 timestamp)
{
- GtkStyleContextPrivate *priv;
- GSList *list;
-
- g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+ GtkBitmask *differences;
+ StyleData *style_data;
+
+ style_data = style_data_lookup (context);
- priv = context->priv;
+ differences = _gtk_css_computed_values_advance (style_data->store,
+ timestamp);
- change |= priv->pending_changes;
+ if (_gtk_css_computed_values_is_static (style_data->store))
+ _gtk_style_context_update_animating (context);
- if (!priv->invalid && change == 0)
- return;
+ return differences;
+}
- priv->pending_changes = 0;
- gtk_style_context_set_invalid (context, FALSE);
+static gboolean
+gtk_style_context_needs_full_revalidate (GtkStyleContext *context,
+ GtkCssChange change)
+{
+ GtkStyleContextPrivate *priv = context->priv;
/* Try to avoid invalidating if we can */
if (change & GTK_STYLE_CONTEXT_RADICAL_CHANGE)
if (priv->relevant_changes == GTK_CSS_CHANGE_ANY)
{
GtkWidgetPath *path;
- GtkCssMatcher matcher;
+ GtkCssMatcher matcher, superset;
- path = create_query_path (context);
- _gtk_css_matcher_init (&matcher, path, ((GtkStyleInfo *) priv->info_stack->data)->state_flags);
+ path = create_query_path (context, priv->info);
+ if (_gtk_css_matcher_init (&matcher, path, priv->info->state_flags))
+ {
+ _gtk_css_matcher_superset_init (&superset, &matcher, GTK_STYLE_CONTEXT_RADICAL_CHANGE & ~GTK_CSS_CHANGE_SOURCE);
+ priv->relevant_changes = _gtk_style_provider_private_get_change (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+ &superset);
+ }
+ else
+ priv->relevant_changes = 0;
- priv->relevant_changes = _gtk_style_provider_private_get_change (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
- &matcher);
priv->relevant_changes &= ~GTK_STYLE_CONTEXT_RADICAL_CHANGE;
gtk_widget_path_unref (path);
}
if (priv->relevant_changes & change)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gboolean
+gtk_style_context_should_create_transitions (GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv;
+ gboolean animate;
+
+ priv = context->priv;
+
+ if (priv->widget == NULL)
+ return FALSE;
+
+ if (!gtk_widget_get_mapped (priv->widget))
+ return FALSE;
+
+ g_object_get (gtk_widget_get_settings (context->priv->widget),
+ "gtk-enable-animations", &animate,
+ NULL);
+
+ return animate;
+}
+
+void
+_gtk_style_context_validate (GtkStyleContext *context,
+ gint64 timestamp,
+ GtkCssChange change,
+ const GtkBitmask *parent_changes)
+{
+ GtkStyleContextPrivate *priv;
+ GtkStyleInfo *info;
+ StyleData *current;
+ GtkBitmask *changes;
+ GSList *list;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+
+ change |= priv->pending_changes;
+
+ /* If you run your application with
+ * GTK_DEBUG=no-css-cache
+ * every invalidation will purge the cache and completely query
+ * everything anew form the cache. This is slow (in particular
+ * when animating), but useful for figuring out bugs.
+ *
+ * We achieve that by pretending that everything that could have
+ * changed has and so we of course totally need to redo everything.
+ *
+ * Note that this also completely revalidates child widgets all
+ * the time.
+ */
+ if (G_UNLIKELY (gtk_get_debug_flags () & GTK_DEBUG_NO_CSS_CACHE))
+ change = GTK_CSS_CHANGE_ANY;
+
+ if (!priv->invalid && change == 0 && _gtk_bitmask_is_empty (parent_changes))
+ return;
+
+ priv->pending_changes = 0;
+ gtk_style_context_set_invalid (context, FALSE);
+
+ info = priv->info;
+ if (info->data)
+ current = style_data_ref (info->data);
+ else
+ current = NULL;
+
+ /* Try to avoid invalidating if we can */
+ if (current == NULL ||
+ gtk_style_context_needs_full_revalidate (context, change))
{
- GtkStyleInfo *info = priv->info_stack->data;
+ StyleData *data;
if ((priv->relevant_changes & change) & ~GTK_STYLE_CONTEXT_CACHED_CHANGE)
- gtk_style_context_clear_cache (context);
+ {
+ gtk_style_context_clear_cache (context);
+ }
+ else
+ {
+ gtk_style_context_update_cache (context, parent_changes);
+ style_info_set_data (info, NULL);
+ }
+
+ data = style_data_lookup (context);
+
+ _gtk_css_computed_values_create_animations (data->store,
+ priv->parent ? style_data_lookup (priv->parent)->store : NULL,
+ timestamp,
+ GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+ current && gtk_style_context_should_create_transitions (context) ? current->store : NULL);
+ if (_gtk_css_computed_values_is_static (data->store))
+ change &= ~GTK_CSS_CHANGE_ANIMATE;
+ else
+ change |= GTK_CSS_CHANGE_ANIMATE;
+ _gtk_style_context_update_animating (context);
+
+ if (current)
+ {
+ changes = _gtk_css_computed_values_get_difference (data->store, current->store);
+
+ /* In the case where we keep the cache, we want unanimated values */
+ _gtk_css_computed_values_cancel_animations (current->store);
+ }
+ else
+ {
+ changes = _gtk_bitmask_new ();
+ changes = _gtk_bitmask_invert_range (changes, 0, _gtk_css_style_property_get_n_properties ());
+ }
+ }
+ else
+ {
+ changes = _gtk_css_computed_values_compute_dependencies (current->store, parent_changes);
+
+ gtk_style_context_update_cache (context, parent_changes);
+ }
+
+ if (current)
+ style_data_unref (current);
+
+ if (change & GTK_CSS_CHANGE_ANIMATE &&
+ gtk_style_context_is_animating (context))
+ {
+ GtkBitmask *animation_changes;
- info->data = NULL;
- gtk_style_context_do_invalidate (context);
+ animation_changes = gtk_style_context_update_animations (context, timestamp);
+ changes = _gtk_bitmask_union (changes, animation_changes);
+ _gtk_bitmask_free (animation_changes);
}
+ if (!_gtk_bitmask_is_empty (changes) || (change & GTK_CSS_CHANGE_FORCE_INVALIDATE))
+ gtk_style_context_do_invalidate (context, changes);
+
change = _gtk_css_change_for_child (change);
for (list = priv->children; list; list = list->next)
{
- _gtk_style_context_validate (list->data, change);
+ _gtk_style_context_validate (list->data, timestamp, change, changes);
}
+
+ _gtk_bitmask_free (changes);
}
void
priv = context->priv;
- if (priv->widget == NULL && priv->widget_path == NULL)
- return;
-
- priv->pending_changes |= change;
- gtk_style_context_set_invalid (context, TRUE);
+ if (priv->widget != NULL)
+ {
+ priv->pending_changes |= change;
+ gtk_style_context_set_invalid (context, TRUE);
+ }
+ else if (priv->widget_path == NULL)
+ {
+ gtk_style_context_invalidate (context);
+ }
}
/**
void
gtk_style_context_invalidate (GtkStyleContext *context)
{
+ GtkBitmask *changes;
+
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
gtk_style_context_clear_cache (context);
- gtk_style_context_do_invalidate (context);
+
+ changes = _gtk_bitmask_new ();
+ changes = _gtk_bitmask_invert_range (changes,
+ 0,
+ _gtk_css_style_property_get_n_properties ());
+ gtk_style_context_do_invalidate (context, changes);
+ _gtk_bitmask_free (changes);
+}
+
+static gboolean
+corner_value_is_right_angle (GtkCssValue *value)
+{
+ return _gtk_css_corner_value_get_x (value, 100) <= 0.0 &&
+ _gtk_css_corner_value_get_y (value, 100) <= 0.0;
}
/**
gtk_style_context_set_background (GtkStyleContext *context,
GdkWindow *window)
{
- GtkStateFlags state;
- cairo_pattern_t *pattern;
- GdkRGBA *color;
+ const GdkRGBA *color;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (GDK_IS_WINDOW (window));
- state = gtk_style_context_get_state (context);
- gtk_style_context_get (context, state,
- "background-image", &pattern,
- NULL);
- if (pattern)
- {
- gdk_window_set_background_pattern (window, pattern);
- cairo_pattern_destroy (pattern);
- return;
- }
+ /* This is a sophisitcated optimization.
+ * If we know the GDK window's background will be opaque, we mark
+ * it as opaque. This is so GDK can do all the optimizations it does
+ * for opaque windows and be fast.
+ * This is mainly used when scrolling.
+ *
+ * We could indeed just set black instead of the color we have.
+ */
+ color = _gtk_css_rgba_value_get_rgba (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BACKGROUND_COLOR));
- gtk_style_context_get (context, state,
- "background-color", &color,
- NULL);
- if (color)
+ if (color->alpha >= 1.0 &&
+ corner_value_is_right_angle (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS)) &&
+ corner_value_is_right_angle (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS)) &&
+ corner_value_is_right_angle (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS)) &&
+ corner_value_is_right_angle (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS)))
{
gdk_window_set_background_rgba (window, color);
- gdk_rgba_free (color);
+ }
+ else
+ {
+ GdkRGBA transparent = { 0.0, 0.0, 0.0, 0.0 };
+ gdk_window_set_background_rgba (window, &transparent);
}
}
* freed.
*
* Since: 3.0
+ *
+ * Deprecated: 3.8: Use gtk_style_context_get() for "font" or
+ * subproperties instead.
**/
const PangoFontDescription *
gtk_style_context_get_font (GtkStyleContext *context,
{
GtkStyleContextPrivate *priv;
StyleData *data;
- PangoFontDescription *description;
+ PangoFontDescription *description, *previous;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
priv = context->priv;
g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
- gtk_style_context_save (context);
- gtk_style_context_set_state (context, state);
- data = style_data_lookup (context);
- gtk_style_context_restore (context);
+ data = style_data_lookup_for_state (context, state);
/* Yuck, fonts are created on-demand but we don't return a ref.
* Do bad things to achieve this requirement */
- description = g_object_get_data (G_OBJECT (data->store), "font-cache-for-get_font");
- if (description == NULL)
+ gtk_style_context_get (context, state, "font", &description, NULL);
+
+ previous = g_object_get_data (G_OBJECT (data->store), "font-cache-for-get_font");
+
+ if (previous)
+ {
+ pango_font_description_merge (previous, description, TRUE);
+ pango_font_description_free (description);
+ description = previous;
+ }
+ else
{
- gtk_style_context_get (context, state, "font", &description, NULL);
g_object_set_data_full (G_OBJECT (data->store),
"font-cache-for-get_font",
description,
(GDestroyNotify) pango_font_description_free);
}
+
return description;
}
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_check (priv->theming_engine, cr,
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_check (engine, cr,
x, y, width, height);
cairo_restore (cr);
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_option (priv->theming_engine, cr,
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_option (engine, cr,
x, y, width, height);
cairo_restore (cr);
gdouble y,
gdouble size)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (size <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
gtk_style_context_save (context);
gtk_style_context_add_class (context, GTK_STYLE_CLASS_ARROW);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_arrow (priv->theming_engine, cr,
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_arrow (engine, cr,
angle, x, y, size);
gtk_style_context_restore (context);
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_background (priv->theming_engine, cr, x, y, width, height);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_background (engine, cr, x, y, width, height);
cairo_restore (cr);
}
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_frame (priv->theming_engine, cr, x, y, width, height);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_frame (engine, cr, x, y, width, height);
cairo_restore (cr);
}
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_expander (priv->theming_engine, cr, x, y, width, height);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_expander (engine, cr, x, y, width, height);
cairo_restore (cr);
}
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_focus (priv->theming_engine, cr, x, y, width, height);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_focus (engine, cr, x, y, width, height);
cairo_restore (cr);
}
gdouble y,
PangoLayout *layout)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
PangoRectangle extents;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (PANGO_IS_LAYOUT (layout));
g_return_if_fail (cr != NULL);
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
pango_layout_get_extents (layout, &extents, NULL);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_layout (priv->theming_engine, cr, x, y, layout);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_layout (engine, cr, x, y, layout);
cairo_restore (cr);
}
gdouble x1,
gdouble y1)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_line (priv->theming_engine, cr, x0, y0, x1, y1);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_line (engine, cr, x0, y0, x1, y1);
cairo_restore (cr);
}
gdouble height,
GtkOrientation orientation)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_slider (priv->theming_engine, cr, x, y, width, height, orientation);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_slider (engine, cr, x, y, width, height, orientation);
cairo_restore (cr);
}
gdouble xy0_gap,
gdouble xy1_gap)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
else
g_return_if_fail (xy1_gap <= width);
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_frame_gap (priv->theming_engine, cr,
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_frame_gap (engine, cr,
x, y, width, height, gap_side,
xy0_gap, xy1_gap);
gdouble height,
GtkPositionType gap_side)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_extension (priv->theming_engine, cr, x, y, width, height, gap_side);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_extension (engine, cr, x, y, width, height, gap_side);
cairo_restore (cr);
}
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_handle (priv->theming_engine, cr, x, y, width, height);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_handle (engine, cr, x, y, width, height);
cairo_restore (cr);
}
gdouble width,
gdouble height)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
if (width <= 0 || height <= 0)
return;
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_activity (priv->theming_engine, cr, x, y, width, height);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_activity (engine, cr, x, y, width, height);
cairo_restore (cr);
}
const GtkIconSource *source,
GtkIconSize size)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
g_return_val_if_fail (source != NULL, NULL);
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- return engine_class->render_icon_pixbuf (priv->theming_engine, source, size);
+ _gtk_theming_engine_set_context (engine, context);
+ return engine_class->render_icon_pixbuf (engine, source, size);
}
/**
gdouble x,
gdouble y)
{
- GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
+ GtkThemingEngine *engine;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
- priv = context->priv;
- engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
+ engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
cairo_save (cr);
- _gtk_theming_engine_set_context (priv->theming_engine, context);
- engine_class->render_icon (priv->theming_engine, cr, pixbuf, x, y);
+ _gtk_theming_engine_set_context (engine, context);
+ engine_class->render_icon (engine, cr, pixbuf, x, y);
cairo_restore (cr);
}
draw_arrow);
}
+/**
+ * _gtk_style_context_get_changes:
+ * @context: the context to query
+ *
+ * Queries the context for the changes for the currently executing
+ * GtkStyleContext::invalidate signal. If no signal is currently
+ * emitted, this function returns %NULL.
+ *
+ * FIXME 4.0: Make this part of the signal.
+ *
+ * Returns: %NULL or the currently invalidating changes
+ **/
+const GtkBitmask *
+_gtk_style_context_get_changes (GtkStyleContext *context)
+{
+ g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
+
+ return context->priv->invalidating_context;
+}
+
static AtkAttributeSet *
add_attribute (AtkAttributeSet *attributes,
AtkTextAttribute attr,
return attributes;
}
+
+cairo_pattern_t *
+gtk_gradient_resolve_for_context (GtkGradient *gradient,
+ GtkStyleContext *context)
+{
+ GtkStyleContextPrivate *priv = context->priv;
+ GtkCssDependencies ignored = 0;
+
+ g_return_val_if_fail (gradient != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
+
+ return _gtk_gradient_resolve_full (gradient,
+ GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
+ style_data_lookup (context)->store,
+ priv->parent ? style_data_lookup (priv->parent)->store : NULL,
+ &ignored);
+}
+