#include <stdlib.h>
#include <gobject/gvaluecollector.h>
-#include "gtkstylecontext.h"
+#include "gtkstylecontextprivate.h"
#include "gtktypebuiltins.h"
#include "gtkthemingengine.h"
#include "gtkintl.h"
#include "gtksymboliccolor.h"
#include "gtkanimationdescription.h"
#include "gtktimeline.h"
+#include "gtkiconfactory.h"
+#include "gtkwidgetprivate.h"
/**
* SECTION:gtkstylecontext
* If you are using custom styling on an applications, you probably want then
* to make your style information prevail to the theme's, so you must use
* a #GtkStyleProvider with the %GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
- * priority, keep in mind that the user settings in $HOME/.gtk-3.0.css will
+ * priority, keep in mind that the user settings in
+ * <filename><replaceable>XDG_CONFIG_HOME</replaceable>/gtk-3.0/gtk.css</filename> will
* still take precedence over your changes, as it uses the
* %GTK_STYLE_PROVIDER_PRIORITY_USER priority.
* </para>
* </refsect2>
*/
-typedef struct GtkStyleContextPrivate GtkStyleContextPrivate;
typedef struct GtkStyleProviderData GtkStyleProviderData;
typedef struct GtkStyleInfo GtkStyleInfo;
typedef struct GtkRegion GtkRegion;
{
GType widget_type;
GParamSpec *pspec;
+ GtkStateFlags state;
GValue value;
};
GtkTimeline *timeline;
gpointer region_id;
+
+ /* Region stack (until region_id) at the time of
+ * rendering, this is used for nested cancellation.
+ */
+ GSList *parent_regions;
+
GdkWindow *window;
GtkStateType state;
gboolean target_value;
GArray *rectangles;
};
-struct GtkStyleContextPrivate
+struct _GtkStyleContextPrivate
{
GdkScreen *screen;
LAST_SIGNAL
};
-guint signals[LAST_SIGNAL] = { 0 };
+static guint signals[LAST_SIGNAL] = { 0 };
static GQuark provider_list_quark = 0;
+static GdkRGBA fallback_color = { 1.0, 0.75, 0.75, 1.0 };
+static GtkBorder fallback_border = { 0 };
static void gtk_style_context_finalize (GObject *object);
(GDestroyNotify) style_data_free);
priv->theming_engine = g_object_ref ((gpointer) gtk_theming_engine_load (NULL));
- priv->direction = GTK_TEXT_DIR_RTL;
+ priv->direction = GTK_TEXT_DIR_LTR;
priv->screen = gdk_screen_get_default ();
cairo_region_destroy (info->invalidation_region);
g_array_free (info->rectangles, TRUE);
+ g_slist_free (info->parent_regions);
g_slice_free (AnimationInfo, info);
}
info = g_slice_new0 (AnimationInfo);
info->rectangles = g_array_new (FALSE, FALSE, sizeof (cairo_rectangle_int_t));
- info->timeline = gtk_timeline_new (duration);
+ info->timeline = _gtk_timeline_new (duration);
info->window = g_object_ref (window);
info->state = state;
info->target_value = target_value;
info->region_id = region_id;
- gtk_timeline_set_progress_type (info->timeline, progress_type);
- gtk_timeline_set_loop (info->timeline, loop);
+ _gtk_timeline_set_progress_type (info->timeline, progress_type);
+ _gtk_timeline_set_loop (info->timeline, loop);
if (!loop && !target_value)
{
- gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
- gtk_timeline_rewind (info->timeline);
+ _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
+ _gtk_timeline_rewind (info->timeline);
}
g_signal_connect (info->timeline, "frame",
g_signal_connect (info->timeline, "finished",
G_CALLBACK (timeline_finished_cb), context);
- gtk_timeline_start (info->timeline);
+ _gtk_timeline_start (info->timeline);
return info;
}
const GValue *value,
GParamSpec *pspec)
{
- GtkStyleContextPrivate *priv;
GtkStyleContext *style_context;
style_context = GTK_STYLE_CONTEXT (object);
- priv = style_context->priv;
switch (prop_id)
{
GValue *value,
GParamSpec *pspec)
{
- GtkStyleContextPrivate *priv;
GtkStyleContext *style_context;
+ GtkStyleContextPrivate *priv;
style_context = GTK_STYLE_CONTEXT (object);
priv = style_context->priv;
}
static GList *
-find_next_candidate (GList *local,
- GList *global)
+find_next_candidate (GList *local,
+ GList *global,
+ gboolean ascending)
{
if (local && global)
{
global_data = global->data;
if (local_data->priority < global_data->priority)
- return local;
+ return (ascending) ? local : global;
else
- return global;
+ return (ascending) ? global : local;
}
else if (local)
return local;
if (priv->screen)
global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
- while ((elem = find_next_candidate (list, global_list)) != NULL)
+ while ((elem = find_next_candidate (list, global_list, TRUE)) != NULL)
{
GtkStyleProviderData *data;
GtkStyleProperties *provider_style;
global_list = g_list_last (global_list);
}
- while ((elem = find_next_candidate (list, global_list)) != NULL)
+ while ((elem = find_next_candidate (list, global_list, FALSE)) != NULL)
{
GtkIconFactory *factory;
GtkStyleProviderData *data;
}
}
-GtkWidgetPath *
+static GtkWidgetPath *
create_query_path (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
gtk_style_properties_get (data->store, 0,
"engine", &priv->theming_engine,
NULL);
+
+ if (!priv->theming_engine)
+ priv->theming_engine = g_object_ref (gtk_theming_engine_load (NULL));
+
return data;
}
*
* Adds a style provider to @context, to be used in style construction.
*
+ * <note><para>If both priorities are the same, A #GtkStyleProvider
+ * added through this function takes precedence over another added
+ * through gtk_style_context_add_provider_for_screen().</para></note>
+ *
* Since: 3.0
**/
void
{
GList *list, *toplevels;
+ _gtk_icon_set_invalidate_caches ();
+
toplevels = gtk_window_list_toplevels ();
g_list_foreach (toplevels, (GFunc) g_object_ref, NULL);
* GTK+ uses this to make styling information from #GtkSettings
* available.
*
+ * <note><para>If both priorities are the same, A #GtkStyleProvider
+ * added through gtk_style_context_add_provider() takes precedence
+ * over another added through this function.</para></note>
+ *
* Since: 3.0
**/
void
gpointer region_id)
{
GtkStyleContextPrivate *priv;
- GSList *r;
/* NULL region_id means everything
* rendered through the style context
return TRUE;
priv = context->priv;
-
- for (r = priv->animation_regions; r; r = r->next)
- {
- if (r->data == region_id)
- return TRUE;
- }
-
- return FALSE;
+ return g_slist_find (priv->animation_regions, region_id) != NULL;
}
/**
context_has_animatable_region (context, info->region_id))
{
if (progress)
- *progress = gtk_timeline_get_progress (info->timeline);
+ *progress = _gtk_timeline_get_progress (info->timeline);
return TRUE;
}
return classes;
}
+gboolean
+_gtk_style_context_check_region_name (const gchar *str)
+{
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ if (!g_ascii_islower (str[0]))
+ return FALSE;
+
+ while (*str)
+ {
+ if (*str != '-' &&
+ !g_ascii_islower (*str))
+ return FALSE;
+
+ str++;
+ }
+
+ return TRUE;
+}
+
/**
* gtk_style_context_add_region:
* @context: a #GtkStyleContext
*
* would apply to even and odd rows, respectively.
*
+ * <note><para>Region names must only contain lowercase letters
+ * and '-', starting always with a lowercase letter.</para></note>
+ *
* Since: 3.0
**/
void
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (region_name != NULL);
+ g_return_if_fail (_gtk_style_context_check_region_name (region_name));
priv = context->priv;
region_quark = g_quark_from_string (region_name);
const PropertyValue *val1 = bsearch_node1;
const PropertyValue *val2 = bsearch_node2;
- if (val1->widget_type == val2->widget_type)
- return val1->pspec < val2->pspec ? -1 : val1->pspec == val2->pspec ? 0 : 1;
- else
+ if (val1->widget_type != val2->widget_type)
return val1->widget_type < val2->widget_type ? -1 : 1;
+
+ if (val1->pspec != val2->pspec)
+ return val1->pspec < val2->pspec ? -1 : 1;
+
+ if (val1->state != val2->state)
+ return val1->state < val2->state ? -1 : 1;
+
+ return 0;
}
const GValue *
_gtk_style_context_peek_style_property (GtkStyleContext *context,
GType widget_type,
+ GtkStateFlags state,
GParamSpec *pspec)
{
GtkStyleContextPrivate *priv;
data = style_data_lookup (context);
key.widget_type = widget_type;
+ key.state = state;
key.pspec = pspec;
/* need value cache array */
list = priv->providers_last;
global = global_list;
- while ((elem = find_next_candidate (list, global)) != NULL)
+ while ((elem = find_next_candidate (list, global, FALSE)) != NULL)
{
GtkStyleProviderData *provider_data;
global = global->prev;
if (gtk_style_provider_get_style_property (provider_data->provider,
- priv->widget_path, pspec,
- &pcache->value))
+ priv->widget_path, state,
+ pspec, &pcache->value))
{
/* Resolve symbolic colors to GdkColor/GdkRGBA */
if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
GtkSymbolicColor *color;
GdkRGBA rgba;
- color = g_value_get_boxed (&pcache->value);
+ color = g_value_dup_boxed (&pcache->value);
+
+ g_value_unset (&pcache->value);
+
+ if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
+ g_value_init (&pcache->value, GDK_TYPE_RGBA);
+ else
+ g_value_init (&pcache->value, GDK_TYPE_COLOR);
if (gtk_symbolic_color_resolve (color, data->store, &rgba))
{
- g_value_unset (&pcache->value);
-
if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
- {
- g_value_init (&pcache->value, GDK_TYPE_RGBA);
- g_value_set_boxed (&pcache->value, &rgba);
- }
+ g_value_set_boxed (&pcache->value, &rgba);
else
{
GdkColor rgb;
rgb.green = rgba.green * 65535. + 0.5;
rgb.blue = rgba.blue * 65535. + 0.5;
- g_value_init (&pcache->value, GDK_TYPE_COLOR);
g_value_set_boxed (&pcache->value, &rgb);
}
}
else
g_param_value_set_default (pspec, &pcache->value);
+
+ gtk_symbolic_color_unref (color);
}
return &pcache->value;
* gtk_style_context_get_style_property:
* @context: a #GtkStyleContext
* @property_name: the name of the widget style property
- * @value: (out) (transfer full): Return location for the property value
+ * @value: Return location for the property value
*
* Gets the value for a widget style property.
*
{
GtkStyleContextPrivate *priv;
GtkWidgetClass *widget_class;
+ GtkStateFlags state;
GParamSpec *pspec;
const GValue *peek_value;
GType widget_type;
if (!priv->widget_path)
return;
- widget_type = gtk_widget_path_get_widget_type (priv->widget_path);
+ widget_type = gtk_widget_path_get_object_type (priv->widget_path);
+
+ if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
+ {
+ g_warning ("%s: can't get style properties for non-widget class `%s'",
+ G_STRLOC,
+ g_type_name (widget_type));
+ return;
+ }
widget_class = g_type_class_ref (widget_type);
pspec = gtk_widget_class_find_style_property (widget_class, property_name);
return;
}
- peek_value = _gtk_style_context_peek_style_property (context,
- widget_type,
- pspec);
+ state = gtk_style_context_get_state (context);
+ peek_value = _gtk_style_context_peek_style_property (context, widget_type,
+ state, pspec);
if (G_VALUE_TYPE (value) == G_VALUE_TYPE (peek_value))
g_value_copy (peek_value, value);
{
GtkStyleContextPrivate *priv;
const gchar *prop_name;
+ GtkStateFlags state;
+ GType widget_type;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
if (!priv->widget_path)
return;
+ widget_type = gtk_widget_path_get_object_type (priv->widget_path);
+
+ if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
+ {
+ g_warning ("%s: can't get style properties for non-widget class `%s'",
+ G_STRLOC,
+ g_type_name (widget_type));
+ return;
+ }
+
+ state = gtk_style_context_get_state (context);
+
while (prop_name)
{
GtkWidgetClass *widget_class;
GParamSpec *pspec;
const GValue *peek_value;
- GType widget_type;
gchar *error;
- widget_type = gtk_widget_path_get_widget_type (priv->widget_path);
-
widget_class = g_type_class_ref (widget_type);
pspec = gtk_widget_class_find_style_property (widget_class, prop_name);
g_type_class_unref (widget_class);
continue;
}
- peek_value = _gtk_style_context_peek_style_property (context,
- widget_type,
- pspec);
+ peek_value = _gtk_style_context_peek_style_property (context, widget_type,
+ state, pspec);
G_VALUE_LCOPY (peek_value, args, 0, &error);
*
* Returns the #GdkScreen to which @context is attached.
*
- * Returns: a #GdkScreen, or %NULL.
+ * Returns: (transfer none): a #GdkScreen.
**/
GdkScreen *
gtk_style_context_get_screen (GtkStyleContext *context)
if (!desc)
return;
- if (gtk_animation_description_get_duration (desc) == 0)
+ if (_gtk_animation_description_get_duration (desc) == 0)
{
- gtk_animation_description_unref (desc);
+ _gtk_animation_description_unref (desc);
return;
}
info->target_value != state_value)
{
/* Target values are the opposite */
- if (!gtk_timeline_get_loop (info->timeline))
+ if (!_gtk_timeline_get_loop (info->timeline))
{
/* Reverse the animation */
- if (gtk_timeline_get_direction (info->timeline) == GTK_TIMELINE_DIRECTION_FORWARD)
- gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
+ if (_gtk_timeline_get_direction (info->timeline) == GTK_TIMELINE_DIRECTION_FORWARD)
+ _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
else
- gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_FORWARD);
+ _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_FORWARD);
info->target_value = state_value;
}
else
{
/* Take it out of its looping state */
- gtk_timeline_set_loop (info->timeline, FALSE);
+ _gtk_timeline_set_loop (info->timeline, FALSE);
}
}
else if (!info &&
- (!gtk_animation_description_get_loop (desc) ||
+ (!_gtk_animation_description_get_loop (desc) ||
state_value))
{
info = animation_info_new (context, region_id,
- gtk_animation_description_get_duration (desc),
- gtk_animation_description_get_progress_type (desc),
- gtk_animation_description_get_loop (desc),
+ _gtk_animation_description_get_duration (desc),
+ _gtk_animation_description_get_progress_type (desc),
+ _gtk_animation_description_get_loop (desc),
state, state_value, window);
priv->animations = g_slist_prepend (priv->animations, info);
priv->animations_invalidated = TRUE;
}
- gtk_animation_description_unref (desc);
+ _gtk_animation_description_unref (desc);
+}
+
+/**
+ * gtk_style_context_cancel_animations:
+ * @context: a #GtkStyleContext
+ * @region_id: (allow-none): animatable region to stop, or %NULL.
+ * See gtk_style_context_push_animatable_region()
+ *
+ * Stops all running animations for @region_id and all animatable
+ * regions underneath.
+ *
+ * A %NULL @region_id will stop all ongoing animations in @context,
+ * when dealing with a #GtkStyleContext obtained through
+ * gtk_widget_get_style_context(), this is normally done for you
+ * in all circumstances you would expect all widget to be stopped,
+ * so this should be only used in complex widgets with different
+ * animatable regions.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_cancel_animations (GtkStyleContext *context,
+ gpointer region_id)
+{
+ GtkStyleContextPrivate *priv;
+ AnimationInfo *info;
+ GSList *l;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+ l = priv->animations;
+
+ while (l)
+ {
+ info = l->data;
+ l = l->next;
+
+ if (!region_id ||
+ info->region_id == region_id ||
+ g_slist_find (info->parent_regions, region_id))
+ {
+ priv->animations = g_slist_remove (priv->animations, info);
+ animation_info_free (info);
+ }
+ }
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+ GdkWindow *child)
+{
+ GtkWidget *child_widget, *parent_widget;
+ GdkWindow *window;
+
+ gdk_window_get_user_data (child, (gpointer *) &child_widget);
+ gdk_window_get_user_data (parent, (gpointer *) &parent_widget);
+
+ if (child_widget != parent_widget &&
+ !gtk_widget_is_ancestor (child_widget, parent_widget))
+ return FALSE;
+
+ window = child;
+
+ while (window)
+ {
+ if (window == parent)
+ return TRUE;
+
+ window = gdk_window_get_parent (window);
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_style_context_scroll_animations:
+ * @context: a #GtkStyleContext
+ * @window: a #GdkWindow used previously in
+ * gtk_style_context_notify_state_change()
+ * @dx: Amount to scroll in the X axis
+ * @dy: Amount to scroll in the Y axis
+ *
+ * This function is analogous to gdk_window_scroll(), and
+ * should be called together with it so the invalidation
+ * areas for any ongoing animation are scrolled together
+ * with it.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_scroll_animations (GtkStyleContext *context,
+ GdkWindow *window,
+ gint dx,
+ gint dy)
+{
+ GtkStyleContextPrivate *priv;
+ AnimationInfo *info;
+ GSList *l;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ priv = context->priv;
+ l = priv->animations;
+
+ while (l)
+ {
+ info = l->data;
+ l = l->next;
+
+ if (info->invalidation_region &&
+ (window == info->window ||
+ is_parent_of (window, info->window)))
+ cairo_region_translate (info->invalidation_region, dx, dy);
+ }
}
/**
void
_gtk_style_context_coalesce_animation_areas (GtkStyleContext *context,
- gint rel_x,
- gint rel_y)
+ GtkWidget *widget)
{
GtkStyleContextPrivate *priv;
GSList *l;
while (l)
{
AnimationInfo *info;
+ gint rel_x, rel_y;
GSList *cur;
guint i;
if (info->invalidation_region)
continue;
- /* There's not much point in keeping the animation running */
if (info->rectangles->len == 0)
- {
- priv->animations = g_slist_remove (priv->animations, info);
- animation_info_free (info);
- continue;
- }
+ continue;
info->invalidation_region = cairo_region_create ();
+ _gtk_widget_get_translation_to_window (widget, info->window, &rel_x, &rel_y);
for (i = 0; i < info->rectangles->len; i++)
{
cairo_rectangle_int_t *rect;
rect = &g_array_index (info->rectangles, cairo_rectangle_int_t, i);
- rect->x += rel_x;
- rect->y += rel_y;
+
+ /* These are widget relative coordinates,
+ * so have them inverted to be window relative
+ */
+ rect->x -= rel_x;
+ rect->y -= rel_y;
cairo_region_union_rectangle (info->invalidation_region, rect);
}
rect.height = (gint) height;
g_array_append_val (info->rectangles, rect);
+
+ if (!info->parent_regions)
+ {
+ GSList *parent_regions;
+
+ parent_regions = g_slist_find (priv->animation_regions, info->region_id);
+ info->parent_regions = g_slist_copy (parent_regions);
+ }
}
}
}
}
}
+/**
+ * gtk_style_context_get_color:
+ * @context: a #GtkStyleContext
+ * @state: state to retrieve the color for
+ * @color: (out): return value for the foreground color
+ *
+ * Gets the foreground color for a given state.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_get_color (GtkStyleContext *context,
+ GtkStateFlags state,
+ GdkRGBA *color)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ const GValue *value;
+ GdkRGBA *c;
+
+ g_return_if_fail (color != NULL);
+ *color = fallback_color;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+ g_return_if_fail (priv->widget_path != NULL);
+
+ data = style_data_lookup (context);
+ value = _gtk_style_properties_peek_property (data->store,
+ "color", state);
+
+ if (value)
+ {
+ c = g_value_get_boxed (value);
+ *color = *c;
+ }
+}
+
+/**
+ * gtk_style_context_get_background_color:
+ * @context: a #GtkStyleContext
+ * @state: state to retrieve the color for
+ * @color: (out): return value for the background color
+ *
+ * Gets the background color for a given state.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_get_background_color (GtkStyleContext *context,
+ GtkStateFlags state,
+ GdkRGBA *color)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ const GValue *value;
+ GdkRGBA *c;
+
+ g_return_if_fail (color != NULL);
+ *color = fallback_color;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+ g_return_if_fail (priv->widget_path != NULL);
+
+ data = style_data_lookup (context);
+ value = _gtk_style_properties_peek_property (data->store,
+ "background-color", state);
+
+ if (value)
+ {
+ c = g_value_get_boxed (value);
+ *color = *c;
+ }
+}
+
+/**
+ * gtk_style_context_get_border_color:
+ * @context: a #GtkStyleContext
+ * @state: state to retrieve the color for
+ * @color: (out): return value for the border color
+ *
+ * Gets the border color for a given state.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_get_border_color (GtkStyleContext *context,
+ GtkStateFlags state,
+ GdkRGBA *color)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ const GValue *value;
+ GdkRGBA *c;
+
+ g_return_if_fail (color != NULL);
+ *color = fallback_color;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+ g_return_if_fail (priv->widget_path != NULL);
+
+ data = style_data_lookup (context);
+ value = _gtk_style_properties_peek_property (data->store,
+ "border-color", state);
+
+ if (value)
+ {
+ c = g_value_get_boxed (value);
+ *color = *c;
+ }
+}
+
+/**
+ * gtk_style_context_get_border:
+ * @context: a #GtkStyleContext
+ * @state: state to retrieve the border for
+ * @border: (out): return value for the border settings
+ *
+ * Gets the border for a given state as a #GtkBorder.
+ * See %GTK_STYLE_PROPERTY_BORDER_WIDTH.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_get_border (GtkStyleContext *context,
+ GtkStateFlags state,
+ GtkBorder *border)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ const GValue *value;
+ GtkBorder *b;
+
+ g_return_if_fail (border != NULL);
+ *border = fallback_border;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+ g_return_if_fail (priv->widget_path != NULL);
+
+ data = style_data_lookup (context);
+ value = _gtk_style_properties_peek_property (data->store,
+ "border-width", state);
+
+ if (value)
+ {
+ b = g_value_get_boxed (value);
+ *border = *b;
+ }
+}
+
+/**
+ * gtk_style_context_get_padding:
+ * @context: a #GtkStyleContext
+ * @state: state to retrieve the padding for
+ * @padding: (out): return value for the padding settings
+ *
+ * Gets the padding for a given state as a #GtkBorder.
+ * See %GTK_STYLE_PROPERTY_PADDING.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_get_padding (GtkStyleContext *context,
+ GtkStateFlags state,
+ GtkBorder *padding)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ const GValue *value;
+ GtkBorder *b;
+
+ g_return_if_fail (padding != NULL);
+ *padding = fallback_border;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+ g_return_if_fail (priv->widget_path != NULL);
+
+ data = style_data_lookup (context);
+ value = _gtk_style_properties_peek_property (data->store,
+ "padding", state);
+
+ if (value)
+ {
+ b = g_value_get_boxed (value);
+ *padding = *b;
+ }
+}
+
+/**
+ * gtk_style_context_get_margin:
+ * @context: a #GtkStyleContext
+ * @state: state to retrieve the border for
+ * @margin: (out): return value for the margin settings
+ *
+ * Gets the margin for a given state as a #GtkBorder.
+ * See %GTK_STYLE_PROPERTY_MARGIN.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_style_context_get_margin (GtkStyleContext *context,
+ GtkStateFlags state,
+ GtkBorder *margin)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ const GValue *value;
+ GtkBorder *b;
+
+ g_return_if_fail (margin != NULL);
+ *margin = fallback_border;
+
+ g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
+
+ priv = context->priv;
+ g_return_if_fail (priv->widget_path != NULL);
+
+ data = style_data_lookup (context);
+ value = _gtk_style_properties_peek_property (data->store,
+ "margin", state);
+
+ if (value)
+ {
+ b = g_value_get_boxed (value);
+ *margin = *b;
+ }
+}
+
+/**
+ * gtk_style_context_get_font:
+ * @context: a #GtkStyleContext
+ * @state: state to retrieve the font for
+ *
+ * Returns the font description for a given state. The returned
+ * object is const and will remain valid until the
+ * #GtkStyleContext::changed signal happens.
+ *
+ * Returns: (transfer none): the #PangoFontDescription for the given
+ * state. This object is owned by GTK+ and should not be
+ * freed.
+ *
+ * Since: 3.0
+ **/
+const PangoFontDescription *
+gtk_style_context_get_font (GtkStyleContext *context,
+ GtkStateFlags state)
+{
+ GtkStyleContextPrivate *priv;
+ StyleData *data;
+ const GValue *value;
+
+ g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
+
+ priv = context->priv;
+ g_return_val_if_fail (priv->widget_path != NULL, NULL);
+
+ data = style_data_lookup (context);
+ value = _gtk_style_properties_peek_property (data->store, "font", state);
+
+ if (value)
+ return g_value_get_boxed (value);
+
+ return NULL;
+}
+
+static void
+get_cursor_color (GtkStyleContext *context,
+ gboolean primary,
+ GdkRGBA *color)
+{
+ GdkColor *style_color;
+
+ gtk_style_context_get_style (context,
+ primary ? "cursor-color" : "secondary-cursor-color",
+ &style_color,
+ NULL);
+
+ if (style_color)
+ {
+ color->red = style_color->red / 65535;
+ color->green = style_color->green / 65535;
+ color->blue = style_color->blue / 65535;
+ color->alpha = 1;
+
+ gdk_color_free (style_color);
+ }
+ else
+ {
+ gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, color);
+
+ if (!primary)
+ {
+ GdkRGBA bg;
+
+ gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
+
+ color->red = (color->red + bg.red) * 0.5;
+ color->green = (color->green + bg.green) * 0.5;
+ color->blue = (color->blue + bg.blue) * 0.5;
+ }
+ }
+}
+
+void
+_gtk_style_context_get_cursor_color (GtkStyleContext *context,
+ GdkRGBA *primary_color,
+ GdkRGBA *secondary_color)
+{
+ if (primary_color)
+ get_cursor_color (context, TRUE, primary_color);
+
+ if (secondary_color)
+ get_cursor_color (context, FALSE, secondary_color);
+}
+
/* Paint methods */
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_check (priv->theming_engine, cr,
x, y, width, height);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_option (priv->theming_engine, cr,
x, y, width, height);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (size > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, size, size);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_arrow (priv->theming_engine, cr,
angle, x, y, size);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_background (priv->theming_engine, cr, x, y, width, height);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_frame (priv->theming_engine, cr, x, y, width, height);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_expander (priv->theming_engine, cr, x, y, width, height);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_focus (priv->theming_engine, cr, x, y, width, height);
+
+ cairo_restore (cr);
}
/**
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);
+ cairo_save (cr);
+
pango_layout_get_extents (layout, &extents, NULL);
store_animation_region (context,
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_layout (priv->theming_engine, cr, x, y, layout);
+
+ cairo_restore (cr);
}
/**
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_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);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_slider (priv->theming_engine, cr, x, y, width, height, orientation);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
+ g_return_if_fail (xy0_gap <= xy1_gap);
+ g_return_if_fail (xy0_gap >= 0);
+
+ if (gap_side == GTK_POS_LEFT ||
+ gap_side == GTK_POS_RIGHT)
+ g_return_if_fail (xy1_gap <= height);
+ else
+ g_return_if_fail (xy1_gap <= width);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_frame_gap (priv->theming_engine, cr,
x, y, width, height, gap_side,
xy0_gap, xy1_gap);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_extension (priv->theming_engine, cr, x, y, width, height, gap_side);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_handle (priv->theming_engine, cr, x, y, width, height);
+
+ cairo_restore (cr);
}
/**
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (cr != NULL);
+ g_return_if_fail (width > 0);
+ g_return_if_fail (height > 0);
priv = context->priv;
engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
+ cairo_save (cr);
+
store_animation_region (context, x, y, width, height);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_activity (priv->theming_engine, cr, x, y, width, height);
+
+ cairo_restore (cr);
}
/**
GtkThemingEngineClass *engine_class;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
- g_return_val_if_fail (size == -1 || size <= GTK_ICON_SIZE_DIALOG, 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;