#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 "gtkgradientprivate.h"
#include "gtkstylepropertiesprivate.h"
#include "gtktypebuiltins.h"
#include "gtkthemingengineprivate.h"
#include "gtkwidget.h"
#include "gtkwindow.h"
#include "gtkprivate.h"
-#include "gtksymboliccolorprivate.h"
#include "gtkiconfactory.h"
#include "gtkwidgetpath.h"
#include "gtkwidgetprivate.h"
#include "gtksettings.h"
#include "gtksettingsprivate.h"
+#include "deprecated/gtkgradientprivate.h"
+#include "deprecated/gtksymboliccolorprivate.h"
+
/**
* SECTION:gtkstylecontext
* @Short_description: Rendering UI elements
GHashTable *style_data;
GtkStyleInfo *info;
- GtkTextDirection direction;
-
GtkCssChange relevant_changes;
GtkCssChange pending_changes;
- guint invalidating_context : 1;
+ const GtkBitmask *invalidating_context;
guint invalid : 1;
};
(GDestroyNotify) style_info_free,
(GDestroyNotify) style_data_unref);
- priv->direction = GTK_TEXT_DIR_LTR;
-
priv->screen = gdk_screen_get_default ();
priv->relevant_changes = GTK_CSS_CHANGE_ANY;
/* Create default info store */
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));
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);
gtk_style_context_set_state (GtkStyleContext *context,
GtkStateFlags flags)
{
+ GtkStateFlags old_flags;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+ 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);
}
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,
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, NULL))
+ 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);
* 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);
- g_object_notify (G_OBJECT (context), "direction");
+ 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;
+ }
+
+ 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;
}
/**
gboolean
_gtk_style_context_resolve_color (GtkStyleContext *context,
- GtkSymbolicColor *color,
+ GtkCssValue *color,
GdkRGBA *result,
GtkCssDependencies *dependencies)
{
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_PROVIDER_PRIVATE (context->priv->cascade),
- _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR),
- GTK_CSS_DEPENDS_ON_COLOR,
- dependencies);
+ 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_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade), 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, NULL);
+ return _gtk_style_context_resolve_color (context, value, color, NULL);
}
/**
StyleData *data = value;
GtkBitmask *changes;
- changes = _gtk_bitmask_copy (parent_changes);
- changes = _gtk_bitmask_intersect (changes, data->store->depends_on_parent);
- if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
- changes = _gtk_bitmask_union (changes, data->store->depends_on_color);
- if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
- changes = _gtk_bitmask_union (changes, data->store->depends_on_font_size);
+ changes = _gtk_css_computed_values_compute_dependencies (data->store, parent_changes);
if (!_gtk_bitmask_is_empty (changes))
build_properties (context, data->store, info, changes);
}
static void
-gtk_style_context_do_invalidate (GtkStyleContext *context)
+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;
}
static GtkBitmask *
}
else
{
- changes = _gtk_bitmask_copy (parent_changes);
- changes = _gtk_bitmask_intersect (changes, current->store->depends_on_parent);
- if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
- changes = _gtk_bitmask_union (changes, current->store->depends_on_color);
- if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
- changes = _gtk_bitmask_union (changes, current->store->depends_on_font_size);
+ changes = _gtk_css_computed_values_compute_dependencies (current->store, parent_changes);
gtk_style_context_update_cache (context, parent_changes);
}
_gtk_bitmask_free (animation_changes);
}
- if (!_gtk_bitmask_is_empty (changes))
- gtk_style_context_do_invalidate (context);
+ 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)
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;
- 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);
+ /* 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);
/* 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;
}
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,