forked from AuroraMiddleware/gtk
59b0fa8133
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.
2404 lines
60 KiB
C
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);
|
|
}
|