gtk2/gtk/gtkstylecontext.c
Carlos Garnacho 59b0fa8133 Remove GtkOrientation parameter from gtk_render_handle().
The case for paned can be guessed out from the height and width,
for handlebox the orientation parameter doesn't make much sense,
and this way it could also be used for resize grips.
2010-12-04 15:38:21 +01:00

2404 lines
60 KiB
C

/* GTK - The GIMP Toolkit
* Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gdk/gdk.h>
#include <stdlib.h>
#include <gobject/gvaluecollector.h>
#include "gtkstylecontext.h"
#include "gtktypebuiltins.h"
#include "gtkthemingengine.h"
#include "gtkintl.h"
#include "gtkwidget.h"
#include "gtkwindow.h"
#include "gtkprivate.h"
#include "gtkanimationdescription.h"
#include "gtktimeline.h"
typedef struct GtkStyleContextPrivate GtkStyleContextPrivate;
typedef struct GtkStyleProviderData GtkStyleProviderData;
typedef struct GtkStyleInfo GtkStyleInfo;
typedef struct GtkRegion GtkRegion;
typedef struct PropertyValue PropertyValue;
typedef struct AnimationInfo AnimationInfo;
typedef struct StyleData StyleData;
struct GtkRegion
{
GQuark class_quark;
GtkRegionFlags flags;
};
struct GtkStyleProviderData
{
GtkStyleProvider *provider;
guint priority;
};
struct PropertyValue
{
GType widget_type;
GParamSpec *pspec;
GValue value;
};
struct GtkStyleInfo
{
GArray *style_classes;
GArray *regions;
GtkJunctionSides junction_sides;
};
struct StyleData
{
GtkStyleSet *store;
GSList *icon_factories;
GArray *property_cache;
};
struct AnimationInfo
{
GtkTimeline *timeline;
gpointer region_id;
GdkWindow *window;
GtkStateType state;
gboolean target_value;
cairo_region_t *invalidation_region;
GArray *rectangles;
};
struct GtkStyleContextPrivate
{
GdkScreen *screen;
GList *providers;
GList *providers_last;
GtkWidgetPath *widget_path;
GHashTable *style_data;
GSList *info_stack;
StyleData *current_data;
GtkStateFlags state_flags;
GSList *animation_regions;
GSList *animations;
guint animations_invalidated : 1;
guint invalidating_context : 1;
GtkThemingEngine *theming_engine;
GtkTextDirection direction;
};
enum {
PROP_0,
PROP_SCREEN,
PROP_DIRECTION
};
enum {
CHANGED,
LAST_SIGNAL
};
guint signals[LAST_SIGNAL] = { 0 };
static GQuark provider_list_quark = 0;
static void gtk_style_context_finalize (GObject *object);
static void gtk_style_context_impl_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void gtk_style_context_impl_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
static void
gtk_style_context_class_init (GtkStyleContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gtk_style_context_finalize;
object_class->set_property = gtk_style_context_impl_set_property;
object_class->get_property = gtk_style_context_impl_get_property;
signals[CHANGED] =
g_signal_new (I_("changed"),
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkStyleContextClass, changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_object_class_install_property (object_class,
PROP_SCREEN,
g_param_spec_object ("screen",
P_("Screen"),
P_("The associated GdkScreen"),
GDK_TYPE_SCREEN,
GTK_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_DIRECTION,
g_param_spec_enum ("direction",
P_("Direction"),
P_("Text direction"),
GTK_TYPE_TEXT_DIRECTION,
GTK_TEXT_DIR_LTR,
GTK_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
}
static GtkStyleInfo *
style_info_new (void)
{
GtkStyleInfo *info;
info = g_slice_new0 (GtkStyleInfo);
info->style_classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
info->regions = g_array_new (FALSE, FALSE, sizeof (GtkRegion));
return info;
}
static void
style_info_free (GtkStyleInfo *info)
{
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)
{
GtkStyleInfo *copy;
copy = style_info_new ();
g_array_insert_vals (copy->style_classes, 0,
info->style_classes->data,
info->style_classes->len);
g_array_insert_vals (copy->regions, 0,
info->regions->data,
info->regions->len);
copy->junction_sides = info->junction_sides;
return copy;
}
static guint
style_info_hash (gconstpointer elem)
{
const GtkStyleInfo *info;
guint i, hash = 0;
info = elem;
for (i = 0; i < info->style_classes->len; i++)
{
hash += g_array_index (info->style_classes, GQuark, i);
hash <<= 5;
}
for (i = 0; i < info->regions->len; i++)
{
GtkRegion *region;
region = &g_array_index (info->regions, GtkRegion, i);
hash += region->class_quark;
hash += region->flags;
hash <<= 5;
}
return hash;
}
static gboolean
style_info_equal (gconstpointer elem1,
gconstpointer elem2)
{
const GtkStyleInfo *info1, *info2;
info1 = elem1;
info2 = elem2;
if (info1->junction_sides != info2->junction_sides)
return FALSE;
if (info1->style_classes->len != info2->style_classes->len)
return FALSE;
if (memcmp (info1->style_classes->data,
info2->style_classes->data,
info1->style_classes->len * sizeof (GQuark)) != 0)
return FALSE;
if (info1->regions->len != info2->regions->len)
return FALSE;
if (memcmp (info1->regions->data,
info2->regions->data,
info1->regions->len * sizeof (GtkRegion)) != 0)
return FALSE;
return TRUE;
}
static StyleData *
style_data_new (void)
{
StyleData *data;
data = g_slice_new0 (StyleData);
data->store = gtk_style_set_new ();
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 void
style_data_free (StyleData *data)
{
g_object_unref (data->store);
clear_property_cache (data);
g_slist_foreach (data->icon_factories, (GFunc) g_object_unref, NULL);
g_slist_free (data->icon_factories);
g_slice_free (StyleData, data);
}
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,
GtkStyleContextPrivate);
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_RTL;
/* Create default info store */
info = style_info_new ();
priv->info_stack = g_slist_prepend (priv->info_stack, info);
}
static GtkStyleProviderData *
style_provider_data_new (GtkStyleProvider *provider,
guint priority)
{
GtkStyleProviderData *data;
data = g_slice_new (GtkStyleProviderData);
data->provider = g_object_ref (provider);
data->priority = priority;
return data;
}
static void
style_provider_data_free (GtkStyleProviderData *data)
{
g_object_unref (data->provider);
g_slice_free (GtkStyleProviderData, data);
}
static void
animation_info_free (AnimationInfo *info)
{
g_object_unref (info->timeline);
g_object_unref (info->window);
if (info->invalidation_region)
cairo_region_destroy (info->invalidation_region);
g_array_free (info->rectangles, TRUE);
g_slice_free (AnimationInfo, info);
}
static void
timeline_frame_cb (GtkTimeline *timeline,
gdouble progress,
gpointer user_data)
{
AnimationInfo *info;
info = user_data;
if (info->invalidation_region &&
!cairo_region_is_empty (info->invalidation_region))
gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
else
gdk_window_invalidate_rect (info->window, NULL, TRUE);
}
static void
timeline_finished_cb (GtkTimeline *timeline,
gpointer user_data)
{
GtkStyleContextPrivate *priv;
GtkStyleContext *context;
AnimationInfo *info;
GSList *l;
context = user_data;
priv = context->priv;
for (l = priv->animations; l; l = l->next)
{
info = l->data;
if (info->timeline == timeline)
{
priv->animations = g_slist_delete_link (priv->animations, l);
/* Invalidate one last time the area, so the final content is painted */
if (info->invalidation_region &&
!cairo_region_is_empty (info->invalidation_region))
gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
else
gdk_window_invalidate_rect (info->window, NULL, TRUE);
animation_info_free (info);
break;
}
}
}
static AnimationInfo *
animation_info_new (GtkStyleContext *context,
gdouble duration,
GtkTimelineProgressType progress_type,
GtkStateType state,
gboolean target_value,
GdkWindow *window)
{
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->window = g_object_ref (window);
info->state = state;
info->target_value = target_value;
gtk_timeline_set_progress_type (info->timeline, progress_type);
if (!target_value)
{
gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
gtk_timeline_rewind (info->timeline);
}
g_signal_connect (info->timeline, "frame",
G_CALLBACK (timeline_frame_cb), info);
g_signal_connect (info->timeline, "finished",
G_CALLBACK (timeline_finished_cb), context);
gtk_timeline_start (info->timeline);
return info;
}
static AnimationInfo *
animation_info_lookup (GtkStyleContext *context,
gpointer region_id,
GtkStateType state)
{
GtkStyleContextPrivate *priv;
GSList *l;
priv = context->priv;
for (l = priv->animations; l; l = l->next)
{
AnimationInfo *info;
info = l->data;
if (info->state == state &&
info->region_id == region_id)
return info;
}
return NULL;
}
static void
gtk_style_context_finalize (GObject *object)
{
GtkStyleContextPrivate *priv;
GtkStyleContext *style_context;
GSList *l;
style_context = GTK_STYLE_CONTEXT (object);
priv = style_context->priv;
if (priv->widget_path)
gtk_widget_path_free (priv->widget_path);
g_hash_table_destroy (priv->style_data);
g_list_foreach (priv->providers, (GFunc) style_provider_data_free, NULL);
g_list_free (priv->providers);
g_slist_foreach (priv->info_stack, (GFunc) style_info_free, NULL);
g_slist_free (priv->info_stack);
g_slist_free (priv->animation_regions);
for (l = priv->animations; l; l = l->next)
animation_info_free ((AnimationInfo *) l->data);
g_slist_free (priv->animations);
if (priv->theming_engine)
g_object_unref (priv->theming_engine);
G_OBJECT_CLASS (gtk_style_context_parent_class)->finalize (object);
}
static void
gtk_style_context_impl_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkStyleContextPrivate *priv;
GtkStyleContext *style_context;
style_context = GTK_STYLE_CONTEXT (object);
priv = style_context->priv;
switch (prop_id)
{
case PROP_SCREEN:
gtk_style_context_set_screen (style_context,
g_value_get_object (value));
break;
case PROP_DIRECTION:
gtk_style_context_set_direction (style_context,
g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_style_context_impl_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkStyleContextPrivate *priv;
GtkStyleContext *style_context;
style_context = GTK_STYLE_CONTEXT (object);
priv = style_context->priv;
switch (prop_id)
{
case PROP_SCREEN:
g_value_set_object (value, priv->screen);
break;
case PROP_DIRECTION:
g_value_set_enum (value, priv->direction);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
GList *
find_next_candidate (GList *local,
GList *global)
{
if (local && global)
{
GtkStyleProviderData *local_data, *global_data;
local_data = local->data;
global_data = global->data;
if (local_data->priority >= global_data->priority)
return local;
else
return global;
}
else if (local)
return local;
else if (global)
return global;
return NULL;
}
static void
build_properties (GtkStyleContext *context,
StyleData *style_data,
GtkWidgetPath *path)
{
GtkStyleContextPrivate *priv;
GList *elem, *list, *global_list = NULL;
priv = context->priv;
list = priv->providers;
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)
{
GtkStyleProviderData *data;
GtkStyleSet *provider_style;
data = elem->data;
if (elem == list)
list = list->next;
else
global_list = global_list->next;
provider_style = gtk_style_provider_get_style (data->provider, path);
if (provider_style)
{
gtk_style_set_merge (style_data->store, provider_style, TRUE);
g_object_unref (provider_style);
}
}
}
static void
build_icon_factories (GtkStyleContext *context,
StyleData *style_data,
GtkWidgetPath *path)
{
GtkStyleContextPrivate *priv;
GList *elem, *list, *global_list = NULL;
priv = context->priv;
list = priv->providers_last;
if (priv->screen)
{
global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
global_list = g_list_last (global_list);
}
while ((elem = find_next_candidate (list, global_list)) != NULL)
{
GtkIconFactory *factory;
GtkStyleProviderData *data;
data = elem->data;
if (elem == list)
list = list->prev;
else
global_list = global_list->prev;
factory = gtk_style_provider_get_icon_factory (data->provider, path);
if (factory)
style_data->icon_factories = g_slist_prepend (style_data->icon_factories, factory);
}
}
GtkWidgetPath *
create_query_path (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
GtkWidgetPath *path;
GtkStyleInfo *info;
guint i, pos;
priv = context->priv;
path = 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++)
{
GtkRegion *region;
region = &g_array_index (info->regions, GtkRegion, i);
gtk_widget_path_iter_add_region (path, pos,
g_quark_to_string (region->class_quark),
region->flags);
}
/* Set widget classes */
for (i = 0; i < info->style_classes->len; i++)
{
GQuark quark;
quark = g_array_index (info->style_classes, GQuark, i);
gtk_widget_path_iter_add_class (path, pos,
g_quark_to_string (quark));
}
return path;
}
StyleData *
style_data_lookup (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
StyleData *data;
priv = context->priv;
/* Current data in use is cached, just return it */
if (priv->current_data)
return priv->current_data;
g_assert (priv->widget_path != NULL);
data = g_hash_table_lookup (priv->style_data, priv->info_stack->data);
if (!data)
{
GtkWidgetPath *path;
data = style_data_new ();
path = create_query_path (context);
build_properties (context, data, path);
build_icon_factories (context, data, path);
g_hash_table_insert (priv->style_data,
style_info_copy (priv->info_stack->data),
data);
gtk_widget_path_free (path);
}
priv->current_data = data;
if (priv->theming_engine)
g_object_unref (priv->theming_engine);
gtk_style_set_get (data->store, 0,
"engine", &priv->theming_engine,
NULL);
return data;
}
static void
style_provider_add (GList **list,
GtkStyleProvider *provider,
guint priority)
{
GtkStyleProviderData *new_data;
gboolean added = FALSE;
GList *l = *list;
new_data = style_provider_data_new (provider, priority);
while (l)
{
GtkStyleProviderData *data;
data = l->data;
/* Provider was already attached to the style
* context, remove in order to add the new data
*/
if (data->provider == provider)
{
GList *link;
link = l;
l = l->next;
/* Remove and free link */
*list = g_list_remove_link (*list, link);
style_provider_data_free (link->data);
g_list_free_1 (link);
continue;
}
if (!added &&
data->priority > priority)
{
*list = g_list_insert_before (*list, l, new_data);
added = TRUE;
}
l = l->next;
}
if (!added)
*list = g_list_append (*list, new_data);
}
static gboolean
style_provider_remove (GList **list,
GtkStyleProvider *provider)
{
GList *l = *list;
while (l)
{
GtkStyleProviderData *data;
data = l->data;
if (data->provider == provider)
{
*list = g_list_remove_link (*list, l);
style_provider_data_free (l->data);
g_list_free_1 (l);
return TRUE;
}
l = l->next;
}
return FALSE;
}
void
gtk_style_context_add_provider (GtkStyleContext *context,
GtkStyleProvider *provider,
guint priority)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
priv = context->priv;
style_provider_add (&priv->providers, provider, priority);
priv->providers_last = g_list_last (priv->providers);
gtk_style_context_invalidate (context);
}
void
gtk_style_context_remove_provider (GtkStyleContext *context,
GtkStyleProvider *provider)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
priv = context->priv;
if (style_provider_remove (&priv->providers, provider))
{
priv->providers_last = g_list_last (priv->providers);
gtk_style_context_invalidate (context);
}
}
void
gtk_style_context_reset_widgets (GdkScreen *screen)
{
GList *list, *toplevels;
toplevels = gtk_window_list_toplevels ();
g_list_foreach (toplevels, (GFunc) g_object_ref, NULL);
for (list = toplevels; list; list = list->next)
{
if (gtk_widget_get_screen (list->data) == screen)
gtk_widget_reset_style (list->data);
g_object_unref (list->data);
}
g_list_free (toplevels);
}
void
gtk_style_context_add_provider_for_screen (GdkScreen *screen,
GtkStyleProvider *provider,
guint priority)
{
GList *providers, *list;
g_return_if_fail (GDK_IS_SCREEN (screen));
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
if (G_UNLIKELY (!provider_list_quark))
provider_list_quark = g_quark_from_static_string ("gtk-provider-list-quark");
list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
style_provider_add (&list, provider, priority);
if (list != providers)
g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
gtk_style_context_reset_widgets (screen);
}
void
gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
GtkStyleProvider *provider)
{
GList *providers, *list;
g_return_if_fail (GDK_IS_SCREEN (screen));
g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
if (G_UNLIKELY (!provider_list_quark))
return;
list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
if (style_provider_remove (&list, provider))
{
if (list != providers)
g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
gtk_style_context_reset_widgets (screen);
}
}
void
gtk_style_context_get_property (GtkStyleContext *context,
const gchar *property,
GtkStateFlags state,
GValue *value)
{
GtkStyleContextPrivate *priv;
StyleData *data;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (property != NULL);
g_return_if_fail (value != NULL);
priv = context->priv;
g_return_if_fail (priv->widget_path != NULL);
data = style_data_lookup (context);
gtk_style_set_get_property (data->store, property, state, value);
}
void
gtk_style_context_get_valist (GtkStyleContext *context,
GtkStateFlags state,
va_list args)
{
GtkStyleContextPrivate *priv;
StyleData *data;
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);
gtk_style_set_get_valist (data->store, state, args);
}
void
gtk_style_context_get (GtkStyleContext *context,
GtkStateFlags state,
...)
{
GtkStyleContextPrivate *priv;
StyleData *data;
va_list args;
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);
va_start (args, state);
gtk_style_set_get_valist (data->store, state, args);
va_end (args);
}
void
gtk_style_context_set_state (GtkStyleContext *context,
GtkStateFlags flags)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
priv = context->priv;
priv->state_flags = flags;
}
GtkStateFlags
gtk_style_context_get_state (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
priv = context->priv;
return priv->state_flags;
}
static gboolean
context_has_animatable_region (GtkStyleContext *context,
gpointer region_id)
{
GtkStyleContextPrivate *priv;
GSList *r;
/* NULL region_id means everything
* rendered through the style context
*/
if (!region_id)
return TRUE;
priv = context->priv;
for (r = priv->animation_regions; r; r = r->next)
{
if (r->data == region_id)
return TRUE;
}
return FALSE;
}
gboolean
gtk_style_context_is_state_set (GtkStyleContext *context,
GtkStateType state,
gdouble *progress)
{
GtkStyleContextPrivate *priv;
gboolean state_set;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
priv = context->priv;
switch (state)
{
case GTK_STATE_NORMAL:
state_set = (priv->state_flags == 0);
break;
case GTK_STATE_ACTIVE:
state_set = (priv->state_flags & GTK_STATE_FLAG_ACTIVE);
break;
case GTK_STATE_PRELIGHT:
state_set = (priv->state_flags & GTK_STATE_FLAG_PRELIGHT);
break;
case GTK_STATE_SELECTED:
state_set = (priv->state_flags & GTK_STATE_FLAG_SELECTED);
break;
case GTK_STATE_INSENSITIVE:
state_set = (priv->state_flags & GTK_STATE_FLAG_INSENSITIVE);
break;
case GTK_STATE_INCONSISTENT:
state_set = (priv->state_flags & GTK_STATE_FLAG_INCONSISTENT);
break;
case GTK_STATE_FOCUSED:
state_set = (priv->state_flags & GTK_STATE_FLAG_FOCUSED);
break;
default:
g_assert_not_reached ();
}
if (progress)
{
AnimationInfo *info;
GSList *l;
*progress = (state_set) ? 1 : 0;
for (l = priv->animations; l; l = l->next)
{
info = l->data;
if (info->state == state &&
context_has_animatable_region (context, info->region_id))
{
*progress = gtk_timeline_get_progress (info->timeline);
break;
}
}
}
return state_set;
}
void
gtk_style_context_set_path (GtkStyleContext *context,
GtkWidgetPath *path)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (path != NULL);
priv = context->priv;
if (priv->widget_path)
{
gtk_widget_path_free (priv->widget_path);
priv->widget_path = NULL;
}
if (path)
priv->widget_path = gtk_widget_path_copy (path);
gtk_style_context_invalidate (context);
}
G_CONST_RETURN GtkWidgetPath *
gtk_style_context_get_path (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
priv = context->priv;
return priv->widget_path;
}
void
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);
}
void
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);
}
if (!priv->info_stack)
{
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->current_data = NULL;
}
static gboolean
style_class_find (GArray *array,
GQuark class_quark,
guint *position)
{
gint min, max, mid;
gboolean found = FALSE;
guint pos;
if (position)
*position = 0;
if (!array || array->len == 0)
return FALSE;
min = 0;
max = array->len - 1;
do
{
GQuark item;
mid = (min + max) / 2;
item = g_array_index (array, GQuark, mid);
if (class_quark == item)
{
found = TRUE;
pos = mid;
}
else if (class_quark > item)
min = pos = mid + 1;
else
{
max = mid - 1;
pos = mid;
}
}
while (!found && min <= max);
if (position)
*position = pos;
return found;
}
static gboolean
region_find (GArray *array,
GQuark class_quark,
guint *position)
{
gint min, max, mid;
gboolean found = FALSE;
guint pos;
if (position)
*position = 0;
if (!array || array->len == 0)
return FALSE;
min = 0;
max = array->len - 1;
do
{
GtkRegion *region;
mid = (min + max) / 2;
region = &g_array_index (array, GtkRegion, mid);
if (region->class_quark == class_quark)
{
found = TRUE;
pos = mid;
}
else if (region->class_quark > class_quark)
min = pos = mid + 1;
else
{
max = mid - 1;
pos = mid;
}
}
while (!found && min <= max);
if (position)
*position = pos;
return found;
}
void
gtk_style_context_set_class (GtkStyleContext *context,
const gchar *class_name)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GQuark class_quark;
guint position;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (class_name != NULL);
priv = context->priv;
class_quark = g_quark_from_string (class_name);
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
if (!style_class_find (info->style_classes, class_quark, &position))
{
g_array_insert_val (info->style_classes, position, class_quark);
/* Unset current data, as it likely changed due to the class change */
priv->current_data = NULL;
}
}
void
gtk_style_context_unset_class (GtkStyleContext *context,
const gchar *class_name)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GQuark class_quark;
guint position;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (class_name != NULL);
class_quark = g_quark_try_string (class_name);
if (!class_quark)
return;
priv = context->priv;
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
if (style_class_find (info->style_classes, class_quark, &position))
{
g_array_remove_index (info->style_classes, position);
/* Unset current data, as it likely changed due to the class change */
priv->current_data = NULL;
}
}
gboolean
gtk_style_context_has_class (GtkStyleContext *context,
const gchar *class_name)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GQuark class_quark;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
g_return_val_if_fail (class_name != NULL, FALSE);
class_quark = g_quark_try_string (class_name);
if (!class_quark)
return FALSE;
priv = context->priv;
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
if (style_class_find (info->style_classes, class_quark, NULL))
return TRUE;
return FALSE;
}
GList *
gtk_style_context_list_classes (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GList *classes = NULL;
guint i;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
priv = context->priv;
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
for (i = 0; i < info->style_classes->len; i++)
{
GQuark quark;
quark = g_array_index (info->style_classes, GQuark, i);
classes = g_list_prepend (classes, (gchar *) g_quark_to_string (quark));
}
return classes;
}
GList *
gtk_style_context_list_regions (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GList *classes = NULL;
guint i;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
priv = context->priv;
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
for (i = 0; i < info->regions->len; i++)
{
GtkRegion *region;
const gchar *class_name;
region = &g_array_index (info->regions, GtkRegion, i);
class_name = g_quark_to_string (region->class_quark);
classes = g_list_prepend (classes, (gchar *) class_name);
}
return classes;
}
void
gtk_style_context_set_region (GtkStyleContext *context,
const gchar *class_name,
GtkRegionFlags flags)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GQuark class_quark;
guint position;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (class_name != NULL);
priv = context->priv;
class_quark = g_quark_from_string (class_name);
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
if (!region_find (info->regions, class_quark, &position))
{
GtkRegion region;
region.class_quark = class_quark;
region.flags = flags;
g_array_insert_val (info->regions, position, region);
/* Unset current data, as it likely changed due to the region change */
priv->current_data = NULL;
}
}
void
gtk_style_context_unset_region (GtkStyleContext *context,
const gchar *class_name)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GQuark class_quark;
guint position;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (class_name != NULL);
class_quark = g_quark_try_string (class_name);
if (!class_quark)
return;
priv = context->priv;
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
if (region_find (info->regions, class_quark, &position))
{
g_array_remove_index (info->regions, position);
/* Unset current data, as it likely changed due to the region change */
priv->current_data = NULL;
}
}
gboolean
gtk_style_context_has_region (GtkStyleContext *context,
const gchar *class_name,
GtkRegionFlags *flags_return)
{
GtkStyleContextPrivate *priv;
GtkStyleInfo *info;
GQuark class_quark;
guint position;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
g_return_val_if_fail (class_name != NULL, FALSE);
if (flags_return)
*flags_return = 0;
class_quark = g_quark_try_string (class_name);
if (!class_quark)
return FALSE;
priv = context->priv;
g_assert (priv->info_stack != NULL);
info = priv->info_stack->data;
if (region_find (info->regions, class_quark, &position))
{
if (flags_return)
{
GtkRegion *region;
region = &g_array_index (info->regions, GtkRegion, position);
*flags_return = region->flags;
}
return TRUE;
}
return FALSE;
}
static gint
style_property_values_cmp (gconstpointer bsearch_node1,
gconstpointer bsearch_node2)
{
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
return val1->widget_type < val2->widget_type ? -1 : 1;
}
const GValue *
_gtk_style_context_peek_style_property (GtkStyleContext *context,
GType widget_type,
GParamSpec *pspec)
{
GtkStyleContextPrivate *priv;
PropertyValue *pcache, key = { 0 };
StyleData *data;
GList *list;
guint i;
priv = context->priv;
data = style_data_lookup (context);
key.widget_type = widget_type;
key.pspec = pspec;
/* need value cache array */
if (!data->property_cache)
data->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
else
{
pcache = bsearch (&key,
data->property_cache->data, data->property_cache->len,
sizeof (PropertyValue), style_property_values_cmp);
if (pcache)
return &pcache->value;
}
i = 0;
while (i < data->property_cache->len &&
style_property_values_cmp (&key, &g_array_index (data->property_cache, PropertyValue, i)) >= 0)
i++;
g_array_insert_val (data->property_cache, i, key);
pcache = &g_array_index (data->property_cache, PropertyValue, i);
/* cache miss, initialize value type, then set contents */
g_param_spec_ref (pcache->pspec);
g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
if (priv->widget_path)
{
for (list = priv->providers_last; list; list = list->prev)
{
GtkStyleProviderData *data;
data = list->data;
if (gtk_style_provider_get_style_property (data->provider, priv->widget_path,
pspec->name, &pcache->value))
return &pcache->value;
}
}
/* not supplied by any provider, revert to default */
g_param_value_set_default (pspec, &pcache->value);
return &pcache->value;
}
void
gtk_style_context_get_style_property (GtkStyleContext *context,
const gchar *property_name,
GValue *value)
{
GtkStyleContextPrivate *priv;
GtkWidgetClass *widget_class;
GParamSpec *pspec;
const GValue *peek_value;
GType widget_type;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (property_name != NULL);
g_return_if_fail (value != NULL);
priv = context->priv;
if (!priv->widget_path)
return;
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, property_name);
g_type_class_unref (widget_class);
if (!pspec)
{
g_warning ("%s: widget class `%s' has no style property named `%s'",
G_STRLOC,
g_type_name (widget_type),
property_name);
return;
}
peek_value = _gtk_style_context_peek_style_property (context,
widget_type,
pspec);
if (G_VALUE_TYPE (value) == G_VALUE_TYPE (peek_value))
g_value_copy (peek_value, value);
else if (g_value_type_transformable (G_VALUE_TYPE (peek_value), G_VALUE_TYPE (value)))
g_value_transform (peek_value, value);
else
g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
pspec->name,
G_VALUE_TYPE_NAME (peek_value),
G_VALUE_TYPE_NAME (value));
}
void
gtk_style_context_get_style_valist (GtkStyleContext *context,
va_list args)
{
GtkStyleContextPrivate *priv;
const gchar *prop_name;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
prop_name = va_arg (args, const gchar *);
priv = context->priv;
if (!priv->widget_path)
return;
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);
if (!pspec)
{
g_warning ("%s: widget class `%s' has no style property named `%s'",
G_STRLOC,
g_type_name (widget_type),
prop_name);
continue;
}
peek_value = _gtk_style_context_peek_style_property (context,
widget_type,
pspec);
G_VALUE_LCOPY (peek_value, args, 0, &error);
if (error)
{
g_warning ("can't retrieve style property `%s' of type `%s': %s",
pspec->name,
G_VALUE_TYPE_NAME (peek_value),
error);
g_free (error);
}
prop_name = va_arg (args, const gchar *);
}
}
void
gtk_style_context_get_style (GtkStyleContext *context,
...)
{
va_list args;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
va_start (args, context);
gtk_style_context_get_style_valist (context, args);
va_end (args);
}
GtkIconSet *
gtk_style_context_lookup_icon_set (GtkStyleContext *context,
const gchar *stock_id)
{
GtkStyleContextPrivate *priv;
StyleData *data;
GSList *list;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
g_return_val_if_fail (stock_id != NULL, NULL);
priv = context->priv;
g_return_val_if_fail (priv->widget_path != NULL, NULL);
data = style_data_lookup (context);
for (list = data->icon_factories; list; list = list->next)
{
GtkIconFactory *factory;
GtkIconSet *icon_set;
factory = list->data;
icon_set = gtk_icon_factory_lookup (factory, stock_id);
if (icon_set)
return icon_set;
}
return gtk_icon_factory_lookup_default (stock_id);
}
void
gtk_style_context_set_screen (GtkStyleContext *context,
GdkScreen *screen)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
priv = context->priv;
priv->screen = screen;
g_object_notify (G_OBJECT (context), "screen");
gtk_style_context_invalidate (context);
}
GdkScreen *
gtk_style_context_get_screen (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
priv = context->priv;
return priv->screen;
}
void
gtk_style_context_set_direction (GtkStyleContext *context,
GtkTextDirection direction)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
priv = context->priv;
priv->direction = direction;
g_object_notify (G_OBJECT (context), "direction");
}
GtkTextDirection
gtk_style_context_get_direction (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), GTK_TEXT_DIR_LTR);
priv = context->priv;
return priv->direction;
}
void
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;
}
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;
}
gboolean
gtk_style_context_lookup_color (GtkStyleContext *context,
const gchar *color_name,
GdkColor *color)
{
GtkStyleContextPrivate *priv;
GtkSymbolicColor *sym_color;
StyleData *data;
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);
priv = context->priv;
g_return_val_if_fail (priv->widget_path != NULL, FALSE);
data = style_data_lookup (context);
sym_color = gtk_style_set_lookup_color (data->store, color_name);
if (!sym_color)
return FALSE;
return gtk_symbolic_color_resolve (sym_color, data->store, color);
}
void
gtk_style_context_notify_state_change (GtkStyleContext *context,
GdkWindow *window,
gpointer region_id,
GtkStateType state,
gboolean state_value)
{
GtkStyleContextPrivate *priv;
GtkAnimationDescription *desc;
AnimationInfo *info;
GtkStateFlags flags;
StyleData *data;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (state < GTK_STATE_LAST);
priv = context->priv;
g_return_if_fail (priv->widget_path != NULL);
state_value = (state_value == TRUE);
switch (state)
{
case GTK_STATE_ACTIVE:
flags = GTK_STATE_FLAG_ACTIVE;
break;
case GTK_STATE_PRELIGHT:
flags = GTK_STATE_FLAG_PRELIGHT;
break;
case GTK_STATE_SELECTED:
flags = GTK_STATE_FLAG_SELECTED;
break;
case GTK_STATE_INSENSITIVE:
flags = GTK_STATE_FLAG_INSENSITIVE;
break;
case GTK_STATE_INCONSISTENT:
flags = GTK_STATE_FLAG_INCONSISTENT;
break;
case GTK_STATE_FOCUSED:
flags = GTK_STATE_FLAG_FOCUSED;
break;
case GTK_STATE_NORMAL:
default:
flags = 0;
break;
}
/* Find out if there is any animation description for the given
* state, it will fallback to the normal state as well if necessary.
*/
data = style_data_lookup (context);
gtk_style_set_get (data->store, flags,
"transition", &desc,
NULL);
if (!desc)
return;
if (gtk_animation_description_get_duration (desc) == 0)
{
gtk_animation_description_unref (desc);
return;
}
info = animation_info_lookup (context, region_id, state);
if (info)
{
/* Reverse the animation if target values are the opposite */
if (info->target_value != state_value)
{
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);
info->target_value = state_value;
}
}
else
{
info = animation_info_new (context,
gtk_animation_description_get_duration (desc),
gtk_animation_description_get_progress_type (desc),
state, state_value, window);
priv->animations = g_slist_prepend (priv->animations, info);
priv->animations_invalidated = TRUE;
}
gtk_animation_description_unref (desc);
}
void
gtk_style_context_push_animatable_region (GtkStyleContext *context,
gpointer region_id)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
g_return_if_fail (region_id != NULL);
priv = context->priv;
priv->animation_regions = g_slist_prepend (priv->animation_regions, region_id);
}
void
gtk_style_context_pop_animatable_region (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
priv = context->priv;
priv->animation_regions = g_slist_delete_link (priv->animation_regions,
priv->animation_regions);
}
void
_gtk_style_context_invalidate_animation_areas (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
GSList *l;
priv = context->priv;
for (l = priv->animations; l; l = l->next)
{
AnimationInfo *info;
info = l->data;
/* A NULL invalidation region means it has to be recreated on
* the next expose event, this happens usually after a widget
* allocation change, so the next expose after it will update
* the invalidation region.
*/
if (info->invalidation_region)
{
cairo_region_destroy (info->invalidation_region);
info->invalidation_region = NULL;
}
}
priv->animations_invalidated = TRUE;
}
void
_gtk_style_context_coalesce_animation_areas (GtkStyleContext *context,
gint rel_x,
gint rel_y)
{
GtkStyleContextPrivate *priv;
GSList *l;
priv = context->priv;
if (!priv->animations_invalidated)
return;
for (l = priv->animations; l; l = l->next)
{
AnimationInfo *info;
guint i;
info = l->data;
if (info->invalidation_region)
continue;
/* FIXME: If this happens there's not much
* point in keeping the animation running.
*/
if (info->rectangles->len == 0)
continue;
info->invalidation_region = cairo_region_create ();
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;
cairo_region_union_rectangle (info->invalidation_region, rect);
}
g_array_remove_range (info->rectangles, 0, info->rectangles->len);
}
priv->animations_invalidated = FALSE;
}
static void
store_animation_region (GtkStyleContext *context,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GSList *l;
priv = context->priv;
if (!priv->animations_invalidated)
return;
for (l = priv->animations; l; l = l->next)
{
AnimationInfo *info;
info = l->data;
/* The animation doesn't need updatring
* the invalidation area, bail out.
*/
if (info->invalidation_region)
continue;
if (context_has_animatable_region (context, info->region_id))
{
cairo_rectangle_int_t rect;
rect.x = (gint) x;
rect.y = (gint) y;
rect.width = (gint) width;
rect.height = (gint) height;
g_array_append_val (info->rectangles, rect);
}
}
}
void
gtk_style_context_invalidate (GtkStyleContext *context)
{
GtkStyleContextPrivate *priv;
g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
priv = context->priv;
/* Avoid reentrancy */
if (priv->invalidating_context)
return;
priv->invalidating_context = TRUE;
g_hash_table_remove_all (priv->style_data);
priv->current_data = NULL;
g_signal_emit (context, signals[CHANGED], 0);
priv->invalidating_context = FALSE;
}
/* Paint methods */
void
gtk_render_check (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_option (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_arrow (GtkStyleContext *context,
cairo_t *cr,
gdouble angle,
gdouble x,
gdouble y,
gdouble size)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_background (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_frame (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_expander (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_focus (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_layout (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
PangoLayout *layout)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_layout (priv->theming_engine, cr, x, y, layout);
}
void
gtk_render_line (GtkStyleContext *context,
cairo_t *cr,
gdouble x0,
gdouble y0,
gdouble x1,
gdouble y1)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
_gtk_theming_engine_set_context (priv->theming_engine, context);
engine_class->render_line (priv->theming_engine, cr, x0, y0, x1, y1);
}
void
gtk_render_slider (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
GtkOrientation orientation)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_frame_gap (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
GtkPositionType gap_side,
gdouble xy0_gap,
gdouble xy1_gap)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_extension (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height,
GtkPositionType gap_side)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}
void
gtk_render_handle (GtkStyleContext *context,
cairo_t *cr,
gdouble x,
gdouble y,
gdouble width,
gdouble height)
{
GtkStyleContextPrivate *priv;
GtkThemingEngineClass *engine_class;
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);
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);
}