1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
24 #include <gobject/gvaluecollector.h>
26 #include "gtkstylecontextprivate.h"
27 #include "gtkstylepropertiesprivate.h"
28 #include "gtktypebuiltins.h"
29 #include "gtkthemingengine.h"
31 #include "gtkwidget.h"
32 #include "gtkwindow.h"
33 #include "gtkprivate.h"
34 #include "gtksymboliccolor.h"
35 #include "gtkanimationdescription.h"
36 #include "gtktimeline.h"
37 #include "gtkiconfactory.h"
38 #include "gtkwidgetprivate.h"
41 * SECTION:gtkstylecontext
42 * @Short_description: Rendering UI elements
43 * @Title: GtkStyleContext
45 * #GtkStyleContext is an object that stores styling information affecting
46 * a widget defined by #GtkWidgetPath.
48 * In order to construct the final style information, #GtkStyleContext
49 * queries information from all attached #GtkStyleProviders. Style providers
50 * can be either attached explicitly to the context through
51 * gtk_style_context_add_provider(), or to the screen through
52 * gtk_style_context_add_provider_for_screen(). The resulting style is a
53 * combination of all providers' information in priority order.
55 * For GTK+ widgets, any #GtkStyleContext returned by
56 * gtk_widget_get_style_context() will already have a #GtkWidgetPath, a
57 * #GdkScreen and RTL/LTR information set. The style context will be also
58 * updated automatically if any of these settings change on the widget.
60 * If you are using the theming layer standalone, you will need to set a
61 * widget path and a screen yourself to the created style context through
62 * gtk_style_context_set_path() and gtk_style_context_set_screen(), as well
63 * as updating the context yourself using gtk_style_context_invalidate()
64 * whenever any of the conditions change, such as a change in the
65 * #GtkSettings:gtk-theme-name setting or a hierarchy change in the rendered
68 * <refsect2 id="gtkstylecontext-animations">
69 * <title>Transition animations</title>
71 * #GtkStyleContext has built-in support for state change transitions.
72 * Note that these animations respect the #GtkSettings:gtk-enable-animations
76 * For simple widgets where state changes affect the whole widget area,
77 * calling gtk_style_context_notify_state_change() with a %NULL region
78 * is sufficient to trigger the transition animation. And GTK+ already
79 * does that when gtk_widget_set_state() or gtk_widget_set_state_flags()
83 * If a widget needs to declare several animatable regions (i.e. not
84 * affecting the whole widget area), its #GtkWidget::draw signal handler
85 * needs to wrap the render operations for the different regions with
86 * calls to gtk_style_context_push_animatable_region() and
87 * gtk_style_context_pop_animatable_region(). These functions take an
88 * identifier for the region which must be unique within the style context.
89 * For simple widgets with a fixed set of animatable regions, using an
90 * enumeration works well:
93 * <title>Using an enumeration to identify animatable regions</title>
104 * spin_button_draw (GtkWidget *widget,
107 * GtkStyleContext *context;
109 * context = gtk_widget_get_style_context (widget);
111 * gtk_style_context_push_animatable_region (context,
112 * GUINT_TO_POINTER (REGION_ENTRY));
114 * gtk_render_background (cr, 0, 0, 100, 30);
115 * gtk_render_frame (cr, 0, 0, 100, 30);
117 * gtk_style_context_pop_animatable_region (context);
124 * For complex widgets with an arbitrary number of animatable regions, it
125 * is up to the implementation to come up with a way to uniquely identify
126 * each animatable region. Using pointers to internal structs is one way
130 * <title>Using struct pointers to identify animatable regions</title>
133 * notebook_draw_tab (GtkWidget *widget,
134 * NotebookPage *page,
137 * gtk_style_context_push_animatable_region (context, page);
138 * gtk_render_extension (cr, page->x, page->y, page->width, page->height);
139 * gtk_style_context_pop_animatable_region (context);
144 * The widget also needs to notify the style context about a state change
145 * for a given animatable region so the animation is triggered.
148 * <title>Triggering a state change animation on a region</title>
151 * notebook_motion_notify (GtkWidget *widget,
152 * GdkEventMotion *event)
154 * GtkStyleContext *context;
155 * NotebookPage *page;
157 * context = gtk_widget_get_style_context (widget);
158 * page = find_page_under_pointer (widget, event);
159 * gtk_style_context_notify_state_change (context,
160 * gtk_widget_get_window (widget),
162 * GTK_STATE_PRELIGHT,
169 * gtk_style_context_notify_state_change() accepts %NULL region IDs as a
170 * special value, in this case, the whole widget area will be updated
174 * <refsect2 id="gtkstylecontext-classes">
175 * <title>Style classes and regions</title>
177 * Widgets can add style classes to their context, which can be used
178 * to associate different styles by class (see <xref linkend="gtkcssprovider-selectors"/>). Theme engines can also use style classes to vary their
179 * rendering. GTK+ has a number of predefined style classes:
184 * <entry>Style class</entry>
185 * <entry>Macro</entry>
186 * <entry>Used by</entry>
191 * <entry>button</entry>
192 * <entry>GTK_STYLE_CLASS_BUTTON</entry>
193 * <entry>#GtkButton, #GtkToggleButton, #GtkRadioButton, #GtkCheckButton</entry>
196 * <entry>default</entry>
197 * <entry>GTK_STYLE_CLASS_DEFAULT</entry>
198 * <entry>#GtkButton</entry>
201 * <entry>check</entry>
202 * <entry>GTK_STYLE_CLASS_CHECK</entry>
203 * <entry>#GtkCheckButton, #GtkCheckMenuItem, #GtkCellRendererToggle</entry>
206 * <entry>radio</entry>
207 * <entry>GTK_STYLE_CLASS_RADIO</entry>
208 * <entry>#GtkRadioButton, #GtkRadioMenuItem, #GtkCellRendererToggle</entry>
211 * <entry>arrow</entry>
212 * <entry>GTK_STYLE_CLASS_ARROW</entry>
213 * <entry>#GtkArrow</entry>
216 * <entry>calendar</entry>
217 * <entry>GTK_STYLE_CLASS_CALENDAR</entry>
218 * <entry>#GtkCalendar</entry>
221 * <entry>entry</entry>
222 * <entry>GTK_STYLE_CLASS_ENTRY</entry>
223 * <entry>#GtkEntry</entry>
226 * <entry>cell</entry>
227 * <entry>GTK_STYLE_CLASS_CELL</entry>
228 * <entry>#GtkCellRendererToggle</entry>
231 * <entry>menu</entry>
232 * <entry>GTK_STYLE_CLASS_MENU</entry>
233 * <entry>#GtkMenu, #GtkMenuItem, #GtkCheckMenuItem, #GtkRadioMenuItem</entry>
236 * <entry>expander</entry>
237 * <entry>GTK_STYLE_CLASS_EXPANDER</entry>
238 * <entry>#GtkExpander</entry>
241 * <entry>tooltip</entry>
242 * <entry>GTK_STYLE_CLASS_TOOLTIP</entry>
243 * <entry>#GtkTooltip</entry>
246 * <entry>frame</entry>
247 * <entry>GTK_STYLE_CLASS_FRAME</entry>
248 * <entry>#GtkFrame</entry>
251 * <entry>scrolled-window</entry>
253 * <entry>#GtkScrolledWindow</entry>
256 * <entry>viewport</entry>
258 * <entry>#GtkViewport</entry>
261 * <entry>trough</entry>
262 * <entry>GTK_STYLE_CLASS_TROUGH</entry>
263 * <entry>#GtkScrollbar, #GtkProgressBar, #GtkScale</entry>
266 * <entry>progressbar</entry>
267 * <entry>GTK_STYLE_CLASS_PROGRESSBAR</entry>
268 * <entry>#GtkProgressBar, #GtkCellRendererProgress</entry>
271 * <entry>slider</entry>
272 * <entry>GTK_STYLE_CLASS_SLIDER</entry>
273 * <entry>#GtkScrollbar, #GtkScale</entry>
276 * <entry>menuitem</entry>
277 * <entry>GTK_STYLE_CLASS_MENUITEM</entry>
278 * <entry>#GtkMenuItem</entry>
281 * <entry>popup</entry>
283 * <entry>#GtkMenu</entry>
286 * <entry>accelerator</entry>
287 * <entry>GTK_STYLE_CLASS_ACCELERATOR</entry>
288 * <entry>#GtkAccelLabel</entry>
291 * <entry>menubar</entry>
292 * <entry>GTK_STYLE_CLASS_MENUBAR</entry>
293 * <entry>#GtkMenuBar</entry>
296 * <entry>toolbar</entry>
297 * <entry>GTK_STYLE_CLASS_TOOLBAR</entry>
298 * <entry>#GtkToolbar</entry>
301 * <entry>dock</entry>
302 * <entry>GTK_STYLE_CLASS_DOCK</entry>
303 * <entry>#GtkHandleBox</entry>
306 * <entry>notebook</entry>
308 * <entry>#GtkNotebook</entry>
311 * <entry>background</entry>
312 * <entry>GTK_STYLE_CLASS_BACKGROUND</entry>
313 * <entry>#GtkWindow</entry>
316 * <entry>rubberband</entry>
317 * <entry>GTK_STYLE_CLASS_RUBBERBAND</entry>
321 * <entry>header</entry>
322 * <entry>GTK_STYLE_CLASS_HEADER</entry>
326 * <entry>grip</entry>
327 * <entry>GTK_STYLE_CLASS_GRIP</entry>
328 * <entry>#GtkWindow</entry>
331 * <entry>spinner</entry>
332 * <entry>GTK_STYLE_CLASS_SPINNER</entry>
333 * <entry>#GtkSpinner</entry>
340 * Widgets can also add regions with flags to their context.
341 * The regions used by GTK+ widgets are:
346 * <entry>Region</entry>
347 * <entry>Flags</entry>
348 * <entry>Macro</entry>
349 * <entry>Used by</entry>
355 * <entry>even, odd</entry>
356 * <entry>GTK_STYLE_REGION_ROW</entry>
357 * <entry>#GtkTreeView</entry>
360 * <entry>column</entry>
361 * <entry>first, last, sorted</entry>
362 * <entry>GTK_STYLE_REGION_COLUMN</entry>
363 * <entry>#GtkTreeView</entry>
366 * <entry>column-header</entry>
368 * <entry>GTK_STYLE_REGION_COLUMN_HEADER</entry>
373 * <entry>even, odd, first, last</entry>
374 * <entry>GTK_STYLE_REGION_TAB</entry>
375 * <entry>#GtkNotebook</entry>
382 * <refsect2 id="gtkstylecontext-custom-styling">
383 * <title>Custom styling in UI libraries and applications</title>
385 * If you are developing a library with custom #GtkWidget<!-- -->s that
386 * render differently than standard components, you may need to add a
387 * #GtkStyleProvider yourself with the %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK
388 * priority, either a #GtkCssProvider or a custom object implementing the
389 * #GtkStyleProvider interface. This way theming engines may still attempt
390 * to style your UI elements in a different way if needed so.
393 * If you are using custom styling on an applications, you probably want then
394 * to make your style information prevail to the theme's, so you must use
395 * a #GtkStyleProvider with the %GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
396 * priority, keep in mind that the user settings in
397 * <filename><replaceable>XDG_CONFIG_HOME</replaceable>/gtk-3.0/gtk.css</filename> will
398 * still take precedence over your changes, as it uses the
399 * %GTK_STYLE_PROVIDER_PRIORITY_USER priority.
402 * If a custom theming engine is needed, you probably want to implement a
403 * #GtkStyleProvider yourself so it points to your #GtkThemingEngine
404 * implementation, as #GtkCssProvider uses gtk_theming_engine_load()
405 * which loads the theming engine module from the standard paths.
410 typedef struct GtkStyleProviderData GtkStyleProviderData;
411 typedef struct GtkStyleInfo GtkStyleInfo;
412 typedef struct GtkRegion GtkRegion;
413 typedef struct PropertyValue PropertyValue;
414 typedef struct AnimationInfo AnimationInfo;
415 typedef struct StyleData StyleData;
420 GtkRegionFlags flags;
423 struct GtkStyleProviderData
425 GtkStyleProvider *provider;
439 GArray *style_classes;
441 GtkJunctionSides junction_sides;
442 GtkStateFlags state_flags;
447 GtkStyleProperties *store;
448 GSList *icon_factories;
449 GArray *property_cache;
454 GtkTimeline *timeline;
458 /* Region stack (until region_id) at the time of
459 * rendering, this is used for nested cancellation.
461 GSList *parent_regions;
465 gboolean target_value;
467 cairo_region_t *invalidation_region;
471 struct _GtkStyleContextPrivate
476 GList *providers_last;
478 GtkWidgetPath *widget_path;
479 GHashTable *style_data;
481 StyleData *current_data;
483 GSList *animation_regions;
486 GtkThemingEngine *theming_engine;
488 GtkTextDirection direction;
490 guint animations_invalidated : 1;
491 guint invalidating_context : 1;
505 static guint signals[LAST_SIGNAL] = { 0 };
507 static GQuark provider_list_quark = 0;
508 static GdkRGBA fallback_color = { 1.0, 0.75, 0.75, 1.0 };
509 static GtkBorder fallback_border = { 0 };
511 static void gtk_style_context_finalize (GObject *object);
513 static void gtk_style_context_impl_set_property (GObject *object,
517 static void gtk_style_context_impl_get_property (GObject *object,
523 G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
526 gtk_style_context_class_init (GtkStyleContextClass *klass)
528 GObjectClass *object_class = G_OBJECT_CLASS (klass);
530 object_class->finalize = gtk_style_context_finalize;
531 object_class->set_property = gtk_style_context_impl_set_property;
532 object_class->get_property = gtk_style_context_impl_get_property;
535 g_signal_new (I_("changed"),
536 G_TYPE_FROM_CLASS (object_class),
538 G_STRUCT_OFFSET (GtkStyleContextClass, changed),
540 g_cclosure_marshal_VOID__VOID,
543 g_object_class_install_property (object_class,
545 g_param_spec_object ("screen",
547 P_("The associated GdkScreen"),
549 GTK_PARAM_READWRITE));
550 g_object_class_install_property (object_class,
552 g_param_spec_enum ("direction",
554 P_("Text direction"),
555 GTK_TYPE_TEXT_DIRECTION,
557 GTK_PARAM_READWRITE));
559 g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
562 static GtkStyleInfo *
563 style_info_new (void)
567 info = g_slice_new0 (GtkStyleInfo);
568 info->style_classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
569 info->regions = g_array_new (FALSE, FALSE, sizeof (GtkRegion));
575 style_info_free (GtkStyleInfo *info)
577 g_array_free (info->style_classes, TRUE);
578 g_array_free (info->regions, TRUE);
579 g_slice_free (GtkStyleInfo, info);
582 static GtkStyleInfo *
583 style_info_copy (const GtkStyleInfo *info)
587 copy = style_info_new ();
588 g_array_insert_vals (copy->style_classes, 0,
589 info->style_classes->data,
590 info->style_classes->len);
592 g_array_insert_vals (copy->regions, 0,
596 copy->junction_sides = info->junction_sides;
597 copy->state_flags = info->state_flags;
603 style_info_hash (gconstpointer elem)
605 const GtkStyleInfo *info;
610 for (i = 0; i < info->style_classes->len; i++)
612 hash += g_array_index (info->style_classes, GQuark, i);
616 for (i = 0; i < info->regions->len; i++)
620 region = &g_array_index (info->regions, GtkRegion, i);
621 hash += region->class_quark;
622 hash += region->flags;
630 style_info_equal (gconstpointer elem1,
633 const GtkStyleInfo *info1, *info2;
638 if (info1->junction_sides != info2->junction_sides)
641 if (info1->style_classes->len != info2->style_classes->len)
644 if (memcmp (info1->style_classes->data,
645 info2->style_classes->data,
646 info1->style_classes->len * sizeof (GQuark)) != 0)
649 if (info1->regions->len != info2->regions->len)
652 if (memcmp (info1->regions->data,
653 info2->regions->data,
654 info1->regions->len * sizeof (GtkRegion)) != 0)
661 style_data_new (void)
665 data = g_slice_new0 (StyleData);
666 data->store = gtk_style_properties_new ();
672 clear_property_cache (StyleData *data)
676 if (!data->property_cache)
679 for (i = 0; i < data->property_cache->len; i++)
681 PropertyValue *node = &g_array_index (data->property_cache, PropertyValue, i);
683 g_param_spec_unref (node->pspec);
684 g_value_unset (&node->value);
687 g_array_free (data->property_cache, TRUE);
688 data->property_cache = NULL;
692 style_data_free (StyleData *data)
694 g_object_unref (data->store);
695 clear_property_cache (data);
697 g_slist_foreach (data->icon_factories, (GFunc) g_object_unref, NULL);
698 g_slist_free (data->icon_factories);
700 g_slice_free (StyleData, data);
704 gtk_style_context_init (GtkStyleContext *style_context)
706 GtkStyleContextPrivate *priv;
709 priv = style_context->priv = G_TYPE_INSTANCE_GET_PRIVATE (style_context,
710 GTK_TYPE_STYLE_CONTEXT,
711 GtkStyleContextPrivate);
713 priv->style_data = g_hash_table_new_full (style_info_hash,
715 (GDestroyNotify) style_info_free,
716 (GDestroyNotify) style_data_free);
717 priv->theming_engine = g_object_ref ((gpointer) gtk_theming_engine_load (NULL));
719 priv->direction = GTK_TEXT_DIR_LTR;
721 priv->screen = gdk_screen_get_default ();
723 /* Create default info store */
724 info = style_info_new ();
725 priv->info_stack = g_slist_prepend (priv->info_stack, info);
728 static GtkStyleProviderData *
729 style_provider_data_new (GtkStyleProvider *provider,
732 GtkStyleProviderData *data;
734 data = g_slice_new (GtkStyleProviderData);
735 data->provider = g_object_ref (provider);
736 data->priority = priority;
742 style_provider_data_free (GtkStyleProviderData *data)
744 g_object_unref (data->provider);
745 g_slice_free (GtkStyleProviderData, data);
749 animation_info_free (AnimationInfo *info)
751 g_object_unref (info->timeline);
752 g_object_unref (info->window);
754 if (info->invalidation_region)
755 cairo_region_destroy (info->invalidation_region);
757 g_array_free (info->rectangles, TRUE);
758 g_slist_free (info->parent_regions);
759 g_slice_free (AnimationInfo, info);
762 static AnimationInfo *
763 animation_info_lookup_by_timeline (GtkStyleContext *context,
764 GtkTimeline *timeline)
766 GtkStyleContextPrivate *priv;
770 priv = context->priv;
772 for (l = priv->animations; l; l = l->next)
776 if (info->timeline == timeline)
784 timeline_frame_cb (GtkTimeline *timeline,
788 GtkStyleContextPrivate *priv;
789 GtkStyleContext *context;
793 priv = context->priv;
794 info = animation_info_lookup_by_timeline (context, timeline);
796 g_assert (info != NULL);
798 /* Cancel transition if window is gone */
799 if (gdk_window_is_destroyed (info->window) ||
800 !gdk_window_is_visible (info->window))
802 priv->animations = g_slist_remove (priv->animations, info);
803 animation_info_free (info);
807 if (info->invalidation_region &&
808 !cairo_region_is_empty (info->invalidation_region))
809 gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
811 gdk_window_invalidate_rect (info->window, NULL, TRUE);
815 timeline_finished_cb (GtkTimeline *timeline,
818 GtkStyleContextPrivate *priv;
819 GtkStyleContext *context;
823 priv = context->priv;
824 info = animation_info_lookup_by_timeline (context, timeline);
826 g_assert (info != NULL);
828 priv->animations = g_slist_remove (priv->animations, info);
830 /* Invalidate one last time the area, so the final content is painted */
831 if (info->invalidation_region &&
832 !cairo_region_is_empty (info->invalidation_region))
833 gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
835 gdk_window_invalidate_rect (info->window, NULL, TRUE);
837 animation_info_free (info);
840 static AnimationInfo *
841 animation_info_new (GtkStyleContext *context,
844 GtkTimelineProgressType progress_type,
847 gboolean target_value,
852 info = g_slice_new0 (AnimationInfo);
854 info->rectangles = g_array_new (FALSE, FALSE, sizeof (cairo_rectangle_int_t));
855 info->timeline = _gtk_timeline_new (duration);
856 info->window = g_object_ref (window);
858 info->target_value = target_value;
859 info->region_id = region_id;
861 _gtk_timeline_set_progress_type (info->timeline, progress_type);
862 _gtk_timeline_set_loop (info->timeline, loop);
864 if (!loop && !target_value)
866 _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
867 _gtk_timeline_rewind (info->timeline);
870 g_signal_connect (info->timeline, "frame",
871 G_CALLBACK (timeline_frame_cb), context);
872 g_signal_connect (info->timeline, "finished",
873 G_CALLBACK (timeline_finished_cb), context);
875 _gtk_timeline_start (info->timeline);
880 static AnimationInfo *
881 animation_info_lookup (GtkStyleContext *context,
885 GtkStyleContextPrivate *priv;
888 priv = context->priv;
890 for (l = priv->animations; l; l = l->next)
896 if (info->state == state &&
897 info->region_id == region_id)
905 gtk_style_context_finalize (GObject *object)
907 GtkStyleContextPrivate *priv;
908 GtkStyleContext *style_context;
911 style_context = GTK_STYLE_CONTEXT (object);
912 priv = style_context->priv;
914 if (priv->widget_path)
915 gtk_widget_path_free (priv->widget_path);
917 g_hash_table_destroy (priv->style_data);
919 g_list_foreach (priv->providers, (GFunc) style_provider_data_free, NULL);
920 g_list_free (priv->providers);
922 g_slist_foreach (priv->info_stack, (GFunc) style_info_free, NULL);
923 g_slist_free (priv->info_stack);
925 g_slist_free (priv->animation_regions);
927 for (l = priv->animations; l; l = l->next)
928 animation_info_free ((AnimationInfo *) l->data);
930 g_slist_free (priv->animations);
932 if (priv->theming_engine)
933 g_object_unref (priv->theming_engine);
935 G_OBJECT_CLASS (gtk_style_context_parent_class)->finalize (object);
939 gtk_style_context_impl_set_property (GObject *object,
944 GtkStyleContext *style_context;
946 style_context = GTK_STYLE_CONTEXT (object);
951 gtk_style_context_set_screen (style_context,
952 g_value_get_object (value));
955 gtk_style_context_set_direction (style_context,
956 g_value_get_enum (value));
959 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
965 gtk_style_context_impl_get_property (GObject *object,
970 GtkStyleContext *style_context;
971 GtkStyleContextPrivate *priv;
973 style_context = GTK_STYLE_CONTEXT (object);
974 priv = style_context->priv;
979 g_value_set_object (value, priv->screen);
982 g_value_set_enum (value, priv->direction);
985 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
991 find_next_candidate (GList *local,
997 GtkStyleProviderData *local_data, *global_data;
999 local_data = local->data;
1000 global_data = global->data;
1002 if (local_data->priority < global_data->priority)
1003 return (ascending) ? local : global;
1005 return (ascending) ? global : local;
1016 build_properties (GtkStyleContext *context,
1017 StyleData *style_data,
1018 GtkWidgetPath *path)
1020 GtkStyleContextPrivate *priv;
1021 GList *elem, *list, *global_list = NULL;
1023 priv = context->priv;
1024 list = priv->providers;
1027 global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
1029 while ((elem = find_next_candidate (list, global_list, TRUE)) != NULL)
1031 GtkStyleProviderData *data;
1032 GtkStyleProperties *provider_style;
1039 global_list = global_list->next;
1041 provider_style = gtk_style_provider_get_style (data->provider, path);
1045 gtk_style_properties_merge (style_data->store, provider_style, TRUE);
1046 g_object_unref (provider_style);
1052 build_icon_factories (GtkStyleContext *context,
1053 StyleData *style_data,
1054 GtkWidgetPath *path)
1056 GtkStyleContextPrivate *priv;
1057 GList *elem, *list, *global_list = NULL;
1059 priv = context->priv;
1060 list = priv->providers_last;
1064 global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
1065 global_list = g_list_last (global_list);
1068 while ((elem = find_next_candidate (list, global_list, FALSE)) != NULL)
1070 GtkIconFactory *factory;
1071 GtkStyleProviderData *data;
1078 global_list = global_list->prev;
1080 factory = gtk_style_provider_get_icon_factory (data->provider, path);
1083 style_data->icon_factories = g_slist_prepend (style_data->icon_factories, factory);
1087 static GtkWidgetPath *
1088 create_query_path (GtkStyleContext *context)
1090 GtkStyleContextPrivate *priv;
1091 GtkWidgetPath *path;
1095 priv = context->priv;
1096 path = gtk_widget_path_copy (priv->widget_path);
1097 pos = gtk_widget_path_length (path) - 1;
1099 info = priv->info_stack->data;
1101 /* Set widget regions */
1102 for (i = 0; i < info->regions->len; i++)
1106 region = &g_array_index (info->regions, GtkRegion, i);
1107 gtk_widget_path_iter_add_region (path, pos,
1108 g_quark_to_string (region->class_quark),
1112 /* Set widget classes */
1113 for (i = 0; i < info->style_classes->len; i++)
1117 quark = g_array_index (info->style_classes, GQuark, i);
1118 gtk_widget_path_iter_add_class (path, pos,
1119 g_quark_to_string (quark));
1126 style_data_lookup (GtkStyleContext *context)
1128 GtkStyleContextPrivate *priv;
1131 priv = context->priv;
1133 /* Current data in use is cached, just return it */
1134 if (priv->current_data)
1135 return priv->current_data;
1137 g_assert (priv->widget_path != NULL);
1139 data = g_hash_table_lookup (priv->style_data, priv->info_stack->data);
1143 GtkWidgetPath *path;
1145 data = style_data_new ();
1146 path = create_query_path (context);
1148 build_properties (context, data, path);
1149 build_icon_factories (context, data, path);
1151 g_hash_table_insert (priv->style_data,
1152 style_info_copy (priv->info_stack->data),
1155 gtk_widget_path_free (path);
1158 priv->current_data = data;
1160 if (priv->theming_engine)
1161 g_object_unref (priv->theming_engine);
1163 gtk_style_properties_get (data->store, 0,
1164 "engine", &priv->theming_engine,
1167 if (!priv->theming_engine)
1168 priv->theming_engine = g_object_ref (gtk_theming_engine_load (NULL));
1174 style_provider_add (GList **list,
1175 GtkStyleProvider *provider,
1178 GtkStyleProviderData *new_data;
1179 gboolean added = FALSE;
1182 new_data = style_provider_data_new (provider, priority);
1186 GtkStyleProviderData *data;
1190 /* Provider was already attached to the style
1191 * context, remove in order to add the new data
1193 if (data->provider == provider)
1200 /* Remove and free link */
1201 *list = g_list_remove_link (*list, link);
1202 style_provider_data_free (link->data);
1203 g_list_free_1 (link);
1209 data->priority > priority)
1211 *list = g_list_insert_before (*list, l, new_data);
1219 *list = g_list_append (*list, new_data);
1223 style_provider_remove (GList **list,
1224 GtkStyleProvider *provider)
1230 GtkStyleProviderData *data;
1234 if (data->provider == provider)
1236 *list = g_list_remove_link (*list, l);
1237 style_provider_data_free (l->data);
1250 * gtk_style_context_new:
1252 * Creates a standalone #GtkStyleContext, this style context
1253 * won't be attached to any widget, so you may want
1254 * to call gtk_style_context_set_path() yourself.
1257 * This function is only useful when using the theming layer
1258 * separated from GTK+, if you are using #GtkStyleContext to
1259 * theme #GtkWidget<!-- -->s, use gtk_widget_get_style_context()
1260 * in order to get a style context ready to theme the widget.
1263 * Returns: A newly created #GtkStyleContext.
1266 gtk_style_context_new (void)
1268 return g_object_new (GTK_TYPE_STYLE_CONTEXT, NULL);
1272 * gtk_style_context_add_provider:
1273 * @context: a #GtkStyleContext
1274 * @provider: a #GtkStyleProvider
1275 * @priority: the priority of the style provider. The lower
1276 * it is, the earlier it will be used in the style
1277 * construction. Typically this will be in the range
1278 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1279 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1281 * Adds a style provider to @context, to be used in style construction.
1283 * <note><para>If both priorities are the same, A #GtkStyleProvider
1284 * added through this function takes precedence over another added
1285 * through gtk_style_context_add_provider_for_screen().</para></note>
1290 gtk_style_context_add_provider (GtkStyleContext *context,
1291 GtkStyleProvider *provider,
1294 GtkStyleContextPrivate *priv;
1296 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1297 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1299 priv = context->priv;
1300 style_provider_add (&priv->providers, provider, priority);
1301 priv->providers_last = g_list_last (priv->providers);
1303 gtk_style_context_invalidate (context);
1307 * gtk_style_context_remove_provider:
1308 * @context: a #GtkStyleContext
1309 * @provider: a #GtkStyleProvider
1311 * Removes @provider from the style providers list in @context.
1316 gtk_style_context_remove_provider (GtkStyleContext *context,
1317 GtkStyleProvider *provider)
1319 GtkStyleContextPrivate *priv;
1321 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1322 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1324 priv = context->priv;
1326 if (style_provider_remove (&priv->providers, provider))
1328 priv->providers_last = g_list_last (priv->providers);
1330 gtk_style_context_invalidate (context);
1335 * gtk_style_context_reset_widgets:
1336 * @screen: a #GdkScreen
1338 * This function recomputes the styles for all widgets under a particular
1339 * #GdkScreen. This is useful when some global parameter has changed that
1340 * affects the appearance of all widgets, because when a widget gets a new
1341 * style, it will both redraw and recompute any cached information about
1342 * its appearance. As an example, it is used when the color scheme changes
1343 * in the related #GtkSettings object.
1348 gtk_style_context_reset_widgets (GdkScreen *screen)
1350 GList *list, *toplevels;
1352 _gtk_icon_set_invalidate_caches ();
1354 toplevels = gtk_window_list_toplevels ();
1355 g_list_foreach (toplevels, (GFunc) g_object_ref, NULL);
1357 for (list = toplevels; list; list = list->next)
1359 if (gtk_widget_get_screen (list->data) == screen)
1360 gtk_widget_reset_style (list->data);
1362 g_object_unref (list->data);
1365 g_list_free (toplevels);
1369 * gtk_style_context_add_provider_for_screen:
1370 * @screen: a #GdkScreen
1371 * @provider: a #GtkStyleProvider
1372 * @priority: the priority of the style provider. The lower
1373 * it is, the earlier it will be used in the style
1374 * construction. Typically this will be in the range
1375 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1376 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1378 * Adds a global style provider to @screen, which will be used
1379 * in style construction for all #GtkStyleContext<!-- -->s under
1382 * GTK+ uses this to make styling information from #GtkSettings
1385 * <note><para>If both priorities are the same, A #GtkStyleProvider
1386 * added through gtk_style_context_add_provider() takes precedence
1387 * over another added through this function.</para></note>
1392 gtk_style_context_add_provider_for_screen (GdkScreen *screen,
1393 GtkStyleProvider *provider,
1396 GList *providers, *list;
1398 g_return_if_fail (GDK_IS_SCREEN (screen));
1399 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1401 if (G_UNLIKELY (!provider_list_quark))
1402 provider_list_quark = g_quark_from_static_string ("gtk-provider-list-quark");
1404 list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
1405 style_provider_add (&list, provider, priority);
1407 if (list != providers)
1408 g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
1410 gtk_style_context_reset_widgets (screen);
1414 * gtk_style_context_remove_provider_for_screen:
1415 * @screen: a #GdkScreen
1416 * @provider: a #GtkStyleProvider
1418 * Removes @provider from the global style providers list in @screen.
1423 gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
1424 GtkStyleProvider *provider)
1426 GList *providers, *list;
1428 g_return_if_fail (GDK_IS_SCREEN (screen));
1429 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1431 if (G_UNLIKELY (!provider_list_quark))
1434 list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
1436 if (style_provider_remove (&list, provider))
1438 if (list != providers)
1439 g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
1441 gtk_style_context_reset_widgets (screen);
1446 * gtk_style_context_get_property:
1447 * @context: a #GtkStyleContext
1448 * @property: style property name
1449 * @state: state to retrieve the property value for
1450 * @value: (out) (transfer full): return location for the style property value
1452 * Gets a style property from @context for the given state.
1454 * When @value is no longer needed, g_value_unset() must be called
1455 * to free any allocated memory.
1460 gtk_style_context_get_property (GtkStyleContext *context,
1461 const gchar *property,
1462 GtkStateFlags state,
1465 GtkStyleContextPrivate *priv;
1468 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1469 g_return_if_fail (property != NULL);
1470 g_return_if_fail (value != NULL);
1472 priv = context->priv;
1474 g_return_if_fail (priv->widget_path != NULL);
1476 data = style_data_lookup (context);
1477 gtk_style_properties_get_property (data->store, property, state, value);
1481 * gtk_style_context_get_valist:
1482 * @context: a #GtkStyleContext
1483 * @state: state to retrieve the property values for
1484 * @args: va_list of property name/return location pairs, followed by %NULL
1486 * Retrieves several style property values from @context for a given state.
1491 gtk_style_context_get_valist (GtkStyleContext *context,
1492 GtkStateFlags state,
1495 GtkStyleContextPrivate *priv;
1498 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1500 priv = context->priv;
1501 g_return_if_fail (priv->widget_path != NULL);
1503 data = style_data_lookup (context);
1504 gtk_style_properties_get_valist (data->store, state, args);
1508 * gtk_style_context_get:
1509 * @context: a #GtkStyleContext
1510 * @state: state to retrieve the property values for
1511 * @...: property name /return value pairs, followed by %NULL
1513 * Retrieves several style property values from @context for a
1519 gtk_style_context_get (GtkStyleContext *context,
1520 GtkStateFlags state,
1523 GtkStyleContextPrivate *priv;
1527 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1529 priv = context->priv;
1530 g_return_if_fail (priv->widget_path != NULL);
1532 data = style_data_lookup (context);
1534 va_start (args, state);
1535 gtk_style_properties_get_valist (data->store, state, args);
1540 * gtk_style_context_set_state:
1541 * @context: a #GtkStyleContext
1542 * @flags: state to represent
1544 * Sets the state to be used when rendering with any
1545 * of the gtk_render_*() functions.
1550 gtk_style_context_set_state (GtkStyleContext *context,
1551 GtkStateFlags flags)
1553 GtkStyleContextPrivate *priv;
1556 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1558 priv = context->priv;
1559 info = priv->info_stack->data;
1560 info->state_flags = flags;
1564 * gtk_style_context_get_state:
1565 * @context: a #GtkStyleContext
1567 * Returns the state used when rendering.
1569 * Returns: the state flags
1574 gtk_style_context_get_state (GtkStyleContext *context)
1576 GtkStyleContextPrivate *priv;
1579 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
1581 priv = context->priv;
1582 info = priv->info_stack->data;
1584 return info->state_flags;
1588 context_has_animatable_region (GtkStyleContext *context,
1591 GtkStyleContextPrivate *priv;
1593 /* NULL region_id means everything
1594 * rendered through the style context
1599 priv = context->priv;
1600 return g_slist_find (priv->animation_regions, region_id) != NULL;
1604 * gtk_style_context_state_is_running:
1605 * @context: a #GtkStyleContext
1606 * @state: a widget state
1607 * @progress: (out): return location for the transition progress
1609 * Returns %TRUE if there is a transition animation running for the
1610 * current region (see gtk_style_context_push_animatable_region()).
1612 * If @progress is not %NULL, the animation progress will be returned
1613 * there, 0.0 means the state is closest to being unset, while 1.0 means
1614 * it's closest to being set. This means transition animation will
1615 * run from 0 to 1 when @state is being set and from 1 to 0 when
1618 * Returns: %TRUE if there is a running transition animation for @state.
1623 gtk_style_context_state_is_running (GtkStyleContext *context,
1627 GtkStyleContextPrivate *priv;
1628 AnimationInfo *info;
1631 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1633 priv = context->priv;
1635 for (l = priv->animations; l; l = l->next)
1639 if (info->state == state &&
1640 context_has_animatable_region (context, info->region_id))
1643 *progress = _gtk_timeline_get_progress (info->timeline);
1653 * gtk_style_context_set_path:
1654 * @context: a #GtkStyleContext
1655 * @path: a #GtkWidgetPath
1657 * Sets the #GtkWidgetPath used for style matching. As a
1658 * consequence, the style will be regenerated to match
1659 * the new given path.
1661 * If you are using a #GtkStyleContext returned from
1662 * gtk_widget_get_style_context(), you do not need to call
1668 gtk_style_context_set_path (GtkStyleContext *context,
1669 GtkWidgetPath *path)
1671 GtkStyleContextPrivate *priv;
1673 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1674 g_return_if_fail (path != NULL);
1676 priv = context->priv;
1678 if (priv->widget_path)
1680 gtk_widget_path_free (priv->widget_path);
1681 priv->widget_path = NULL;
1685 priv->widget_path = gtk_widget_path_copy (path);
1687 gtk_style_context_invalidate (context);
1691 * gtk_style_context_get_path:
1692 * @context: a #GtkStyleContext
1694 * Returns the widget path used for style matching.
1696 * Returns: (transfer none): A #GtkWidgetPath
1700 G_CONST_RETURN GtkWidgetPath *
1701 gtk_style_context_get_path (GtkStyleContext *context)
1703 GtkStyleContextPrivate *priv;
1705 priv = context->priv;
1706 return priv->widget_path;
1710 * gtk_style_context_save:
1711 * @context: a #GtkStyleContext
1713 * Saves the @context state, so all modifications done through
1714 * gtk_style_context_add_class(), gtk_style_context_remove_class(),
1715 * gtk_style_context_add_region(), gtk_style_context_remove_region()
1716 * or gtk_style_context_set_junction_sides() can be reverted in one
1717 * go through gtk_style_context_restore().
1722 gtk_style_context_save (GtkStyleContext *context)
1724 GtkStyleContextPrivate *priv;
1727 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1729 priv = context->priv;
1731 g_assert (priv->info_stack != NULL);
1733 info = style_info_copy (priv->info_stack->data);
1734 priv->info_stack = g_slist_prepend (priv->info_stack, info);
1738 * gtk_style_context_restore:
1739 * @context: a #GtkStyleContext
1741 * Restores @context state to a previous stage.
1742 * See gtk_style_context_save().
1747 gtk_style_context_restore (GtkStyleContext *context)
1749 GtkStyleContextPrivate *priv;
1752 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1754 priv = context->priv;
1756 if (priv->info_stack)
1758 info = priv->info_stack->data;
1759 priv->info_stack = g_slist_remove (priv->info_stack, info);
1760 style_info_free (info);
1763 if (!priv->info_stack)
1765 g_warning ("Unpaired gtk_style_context_restore() call");
1767 /* Create default region */
1768 info = style_info_new ();
1769 priv->info_stack = g_slist_prepend (priv->info_stack, info);
1772 priv->current_data = NULL;
1776 style_class_find (GArray *array,
1781 gboolean found = FALSE;
1787 if (!array || array->len == 0)
1791 max = array->len - 1;
1797 mid = (min + max) / 2;
1798 item = g_array_index (array, GQuark, mid);
1800 if (class_quark == item)
1805 else if (class_quark > item)
1806 min = pos = mid + 1;
1813 while (!found && min <= max);
1822 region_find (GArray *array,
1827 gboolean found = FALSE;
1833 if (!array || array->len == 0)
1837 max = array->len - 1;
1843 mid = (min + max) / 2;
1844 region = &g_array_index (array, GtkRegion, mid);
1846 if (region->class_quark == class_quark)
1851 else if (region->class_quark > class_quark)
1852 min = pos = mid + 1;
1859 while (!found && min <= max);
1868 * gtk_style_context_add_class:
1869 * @context: a #GtkStyleContext
1870 * @class_name: class name to use in styling
1872 * Adds a style class to @context, so posterior calls to
1873 * gtk_style_context_get() or any of the gtk_render_*()
1874 * functions will make use of this new class for styling.
1876 * In the CSS file format, a #GtkEntry defining an "entry"
1877 * class, would be matched by:
1880 * GtkEntry.entry { ... }
1883 * While any widget defining an "entry" class would be
1892 gtk_style_context_add_class (GtkStyleContext *context,
1893 const gchar *class_name)
1895 GtkStyleContextPrivate *priv;
1900 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1901 g_return_if_fail (class_name != NULL);
1903 priv = context->priv;
1904 class_quark = g_quark_from_string (class_name);
1906 g_assert (priv->info_stack != NULL);
1907 info = priv->info_stack->data;
1909 if (!style_class_find (info->style_classes, class_quark, &position))
1911 g_array_insert_val (info->style_classes, position, class_quark);
1913 /* Unset current data, as it likely changed due to the class change */
1914 priv->current_data = NULL;
1919 * gtk_style_context_remove_class:
1920 * @context: a #GtkStyleContext
1921 * @class_name: class name to remove
1923 * Removes @class_name from @context.
1928 gtk_style_context_remove_class (GtkStyleContext *context,
1929 const gchar *class_name)
1931 GtkStyleContextPrivate *priv;
1936 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1937 g_return_if_fail (class_name != NULL);
1939 class_quark = g_quark_try_string (class_name);
1944 priv = context->priv;
1946 g_assert (priv->info_stack != NULL);
1947 info = priv->info_stack->data;
1949 if (style_class_find (info->style_classes, class_quark, &position))
1951 g_array_remove_index (info->style_classes, position);
1953 /* Unset current data, as it likely changed due to the class change */
1954 priv->current_data = NULL;
1959 * gtk_style_context_has_class:
1960 * @context: a #GtkStyleContext
1961 * @class_name: a class name
1963 * Returns %TRUE if @context currently has defined the
1966 * Returns: %TRUE if @context has @class_name defined
1971 gtk_style_context_has_class (GtkStyleContext *context,
1972 const gchar *class_name)
1974 GtkStyleContextPrivate *priv;
1978 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1979 g_return_val_if_fail (class_name != NULL, FALSE);
1981 class_quark = g_quark_try_string (class_name);
1986 priv = context->priv;
1988 g_assert (priv->info_stack != NULL);
1989 info = priv->info_stack->data;
1991 if (style_class_find (info->style_classes, class_quark, NULL))
1998 * gtk_style_context_list_classes:
1999 * @context: a #GtkStyleContext
2001 * Returns the list of classes currently defined in @context.
2003 * Returns: (transfer container) (element-type utf8): a #GList of
2004 * strings with the currently defined classes. The contents
2005 * of the list are owned by GTK+, but you must free the list
2006 * itself with g_list_free() when you are done with it.
2011 gtk_style_context_list_classes (GtkStyleContext *context)
2013 GtkStyleContextPrivate *priv;
2015 GList *classes = NULL;
2018 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2020 priv = context->priv;
2022 g_assert (priv->info_stack != NULL);
2023 info = priv->info_stack->data;
2025 for (i = 0; i < info->style_classes->len; i++)
2029 quark = g_array_index (info->style_classes, GQuark, i);
2030 classes = g_list_prepend (classes, (gchar *) g_quark_to_string (quark));
2037 * gtk_style_context_list_regions:
2038 * @context: a #GtkStyleContext
2040 * Returns the list of regions currently defined in @context.
2042 * Returns: (transfer container) (element-type utf8): a #GList of
2043 * strings with the currently defined regions. The contents
2044 * of the list are owned by GTK+, but you must free the list
2045 * itself with g_list_free() when you are done with it.
2050 gtk_style_context_list_regions (GtkStyleContext *context)
2052 GtkStyleContextPrivate *priv;
2054 GList *classes = NULL;
2057 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2059 priv = context->priv;
2061 g_assert (priv->info_stack != NULL);
2062 info = priv->info_stack->data;
2064 for (i = 0; i < info->regions->len; i++)
2067 const gchar *class_name;
2069 region = &g_array_index (info->regions, GtkRegion, i);
2071 class_name = g_quark_to_string (region->class_quark);
2072 classes = g_list_prepend (classes, (gchar *) class_name);
2079 _gtk_style_context_check_region_name (const gchar *str)
2081 g_return_val_if_fail (str != NULL, FALSE);
2083 if (!g_ascii_islower (str[0]))
2089 !g_ascii_islower (*str))
2099 * gtk_style_context_add_region:
2100 * @context: a #GtkStyleContext
2101 * @region_name: region name to use in styling
2102 * @flags: flags that apply to the region
2104 * Adds a region to @context, so posterior calls to
2105 * gtk_style_context_get() or any of the gtk_render_*()
2106 * functions will make use of this new region for styling.
2108 * In the CSS file format, a #GtkTreeView defining a "row"
2109 * region, would be matched by:
2112 * GtkTreeView row { ... }
2115 * Pseudo-classes are used for matching @flags, so the two
2118 * GtkTreeView row:nth-child (even) { ... }
2119 * GtkTreeView row:nth-child (odd) { ... }
2122 * would apply to even and odd rows, respectively.
2124 * <note><para>Region names must only contain lowercase letters
2125 * and '-', starting always with a lowercase letter.</para></note>
2130 gtk_style_context_add_region (GtkStyleContext *context,
2131 const gchar *region_name,
2132 GtkRegionFlags flags)
2134 GtkStyleContextPrivate *priv;
2136 GQuark region_quark;
2139 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2140 g_return_if_fail (region_name != NULL);
2141 g_return_if_fail (_gtk_style_context_check_region_name (region_name));
2143 priv = context->priv;
2144 region_quark = g_quark_from_string (region_name);
2146 g_assert (priv->info_stack != NULL);
2147 info = priv->info_stack->data;
2149 if (!region_find (info->regions, region_quark, &position))
2153 region.class_quark = region_quark;
2154 region.flags = flags;
2156 g_array_insert_val (info->regions, position, region);
2158 /* Unset current data, as it likely changed due to the region change */
2159 priv->current_data = NULL;
2164 * gtk_style_context_remove_region:
2165 * @context: a #GtkStyleContext
2166 * @region_name: region name to unset
2168 * Removes a region from @context.
2173 gtk_style_context_remove_region (GtkStyleContext *context,
2174 const gchar *region_name)
2176 GtkStyleContextPrivate *priv;
2178 GQuark region_quark;
2181 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2182 g_return_if_fail (region_name != NULL);
2184 region_quark = g_quark_try_string (region_name);
2189 priv = context->priv;
2191 g_assert (priv->info_stack != NULL);
2192 info = priv->info_stack->data;
2194 if (region_find (info->regions, region_quark, &position))
2196 g_array_remove_index (info->regions, position);
2198 /* Unset current data, as it likely changed due to the region change */
2199 priv->current_data = NULL;
2204 * gtk_style_context_has_region:
2205 * @context: a #GtkStyleContext
2206 * @region_name: a region name
2207 * @flags_return: (out) (allow-none): return location for region flags
2209 * Returns %TRUE if @context has the region defined.
2210 * If @flags_return is not %NULL, it is set to the flags
2211 * affecting the region.
2213 * Returns: %TRUE if region is defined
2218 gtk_style_context_has_region (GtkStyleContext *context,
2219 const gchar *region_name,
2220 GtkRegionFlags *flags_return)
2222 GtkStyleContextPrivate *priv;
2224 GQuark region_quark;
2227 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2228 g_return_val_if_fail (region_name != NULL, FALSE);
2233 region_quark = g_quark_try_string (region_name);
2238 priv = context->priv;
2240 g_assert (priv->info_stack != NULL);
2241 info = priv->info_stack->data;
2243 if (region_find (info->regions, region_quark, &position))
2249 region = &g_array_index (info->regions, GtkRegion, position);
2250 *flags_return = region->flags;
2259 style_property_values_cmp (gconstpointer bsearch_node1,
2260 gconstpointer bsearch_node2)
2262 const PropertyValue *val1 = bsearch_node1;
2263 const PropertyValue *val2 = bsearch_node2;
2265 if (val1->widget_type != val2->widget_type)
2266 return val1->widget_type < val2->widget_type ? -1 : 1;
2268 if (val1->pspec != val2->pspec)
2269 return val1->pspec < val2->pspec ? -1 : 1;
2271 if (val1->state != val2->state)
2272 return val1->state < val2->state ? -1 : 1;
2278 _gtk_style_context_peek_style_property (GtkStyleContext *context,
2280 GtkStateFlags state,
2283 GtkStyleContextPrivate *priv;
2284 PropertyValue *pcache, key = { 0 };
2285 GList *global_list = NULL;
2289 priv = context->priv;
2290 data = style_data_lookup (context);
2292 key.widget_type = widget_type;
2296 /* need value cache array */
2297 if (!data->property_cache)
2298 data->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
2301 pcache = bsearch (&key,
2302 data->property_cache->data, data->property_cache->len,
2303 sizeof (PropertyValue), style_property_values_cmp);
2305 return &pcache->value;
2309 while (i < data->property_cache->len &&
2310 style_property_values_cmp (&key, &g_array_index (data->property_cache, PropertyValue, i)) >= 0)
2313 g_array_insert_val (data->property_cache, i, key);
2314 pcache = &g_array_index (data->property_cache, PropertyValue, i);
2316 /* cache miss, initialize value type, then set contents */
2317 g_param_spec_ref (pcache->pspec);
2318 g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
2322 global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
2323 global_list = g_list_last (global_list);
2326 if (priv->widget_path)
2328 GList *list, *global, *elem;
2330 list = priv->providers_last;
2331 global = global_list;
2333 while ((elem = find_next_candidate (list, global, FALSE)) != NULL)
2335 GtkStyleProviderData *provider_data;
2337 provider_data = elem->data;
2342 global = global->prev;
2344 if (gtk_style_provider_get_style_property (provider_data->provider,
2345 priv->widget_path, state,
2346 pspec, &pcache->value))
2348 /* Resolve symbolic colors to GdkColor/GdkRGBA */
2349 if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
2351 GtkSymbolicColor *color;
2354 color = g_value_dup_boxed (&pcache->value);
2356 g_value_unset (&pcache->value);
2358 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2359 g_value_init (&pcache->value, GDK_TYPE_RGBA);
2361 g_value_init (&pcache->value, GDK_TYPE_COLOR);
2363 if (gtk_symbolic_color_resolve (color, data->store, &rgba))
2365 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2366 g_value_set_boxed (&pcache->value, &rgba);
2371 rgb.red = rgba.red * 65535. + 0.5;
2372 rgb.green = rgba.green * 65535. + 0.5;
2373 rgb.blue = rgba.blue * 65535. + 0.5;
2375 g_value_set_boxed (&pcache->value, &rgb);
2379 g_param_value_set_default (pspec, &pcache->value);
2381 gtk_symbolic_color_unref (color);
2384 return &pcache->value;
2389 /* not supplied by any provider, revert to default */
2390 g_param_value_set_default (pspec, &pcache->value);
2392 return &pcache->value;
2396 * gtk_style_context_get_style_property:
2397 * @context: a #GtkStyleContext
2398 * @property_name: the name of the widget style property
2399 * @value: Return location for the property value
2401 * Gets the value for a widget style property.
2403 * When @value is no longer needed, g_value_unset() must be called
2404 * to free any allocated memory.
2407 gtk_style_context_get_style_property (GtkStyleContext *context,
2408 const gchar *property_name,
2411 GtkStyleContextPrivate *priv;
2412 GtkWidgetClass *widget_class;
2413 GtkStateFlags state;
2415 const GValue *peek_value;
2418 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2419 g_return_if_fail (property_name != NULL);
2420 g_return_if_fail (value != NULL);
2422 priv = context->priv;
2424 if (!priv->widget_path)
2427 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2429 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2431 g_warning ("%s: can't get style properties for non-widget class `%s'",
2433 g_type_name (widget_type));
2437 widget_class = g_type_class_ref (widget_type);
2438 pspec = gtk_widget_class_find_style_property (widget_class, property_name);
2439 g_type_class_unref (widget_class);
2443 g_warning ("%s: widget class `%s' has no style property named `%s'",
2445 g_type_name (widget_type),
2450 state = gtk_style_context_get_state (context);
2451 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2454 if (G_VALUE_TYPE (value) == G_VALUE_TYPE (peek_value))
2455 g_value_copy (peek_value, value);
2456 else if (g_value_type_transformable (G_VALUE_TYPE (peek_value), G_VALUE_TYPE (value)))
2457 g_value_transform (peek_value, value);
2459 g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
2461 G_VALUE_TYPE_NAME (peek_value),
2462 G_VALUE_TYPE_NAME (value));
2466 * gtk_style_context_get_style_valist:
2467 * @context: a #GtkStyleContext
2468 * @args: va_list of property name/return location pairs, followed by %NULL
2470 * Retrieves several widget style properties from @context according to the
2476 gtk_style_context_get_style_valist (GtkStyleContext *context,
2479 GtkStyleContextPrivate *priv;
2480 const gchar *prop_name;
2481 GtkStateFlags state;
2484 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2486 prop_name = va_arg (args, const gchar *);
2487 priv = context->priv;
2489 if (!priv->widget_path)
2492 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2494 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2496 g_warning ("%s: can't get style properties for non-widget class `%s'",
2498 g_type_name (widget_type));
2502 state = gtk_style_context_get_state (context);
2506 GtkWidgetClass *widget_class;
2508 const GValue *peek_value;
2511 widget_class = g_type_class_ref (widget_type);
2512 pspec = gtk_widget_class_find_style_property (widget_class, prop_name);
2513 g_type_class_unref (widget_class);
2517 g_warning ("%s: widget class `%s' has no style property named `%s'",
2519 g_type_name (widget_type),
2524 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2527 G_VALUE_LCOPY (peek_value, args, 0, &error);
2531 g_warning ("can't retrieve style property `%s' of type `%s': %s",
2533 G_VALUE_TYPE_NAME (peek_value),
2538 prop_name = va_arg (args, const gchar *);
2543 * gtk_style_context_get_style:
2544 * @context: a #GtkStyleContext
2545 * @...: property name /return value pairs, followed by %NULL
2547 * Retrieves several widget style properties from @context according to the
2553 gtk_style_context_get_style (GtkStyleContext *context,
2558 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2560 va_start (args, context);
2561 gtk_style_context_get_style_valist (context, args);
2567 * gtk_style_context_lookup_icon_set:
2568 * @context: a #GtkStyleContext
2569 * @stock_id: an icon name
2571 * Looks up @stock_id in the icon factories associated to @context and
2572 * the default icon factory, returning an icon set if found, otherwise
2575 * Returns: (transfer none): The looked up %GtkIconSet, or %NULL
2578 gtk_style_context_lookup_icon_set (GtkStyleContext *context,
2579 const gchar *stock_id)
2581 GtkStyleContextPrivate *priv;
2585 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2586 g_return_val_if_fail (stock_id != NULL, NULL);
2588 priv = context->priv;
2589 g_return_val_if_fail (priv->widget_path != NULL, NULL);
2591 data = style_data_lookup (context);
2593 for (list = data->icon_factories; list; list = list->next)
2595 GtkIconFactory *factory;
2596 GtkIconSet *icon_set;
2598 factory = list->data;
2599 icon_set = gtk_icon_factory_lookup (factory, stock_id);
2605 return gtk_icon_factory_lookup_default (stock_id);
2609 * gtk_style_context_set_screen:
2610 * @context: a #GtkStyleContext
2611 * @screen: a #GdkScreen
2613 * Attaches @context to the given screen.
2615 * The screen is used to add style information from 'global' style
2616 * providers, such as the screens #GtkSettings instance.
2618 * If you are using a #GtkStyleContext returned from
2619 * gtk_widget_get_style_context(), you do not need to
2620 * call this yourself.
2625 gtk_style_context_set_screen (GtkStyleContext *context,
2628 GtkStyleContextPrivate *priv;
2630 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2631 g_return_if_fail (GDK_IS_SCREEN (screen));
2633 priv = context->priv;
2634 if (priv->screen == screen)
2637 priv->screen = screen;
2639 g_object_notify (G_OBJECT (context), "screen");
2641 gtk_style_context_invalidate (context);
2645 * gtk_style_context_get_screen:
2646 * @context: a #GtkStyleContext
2648 * Returns the #GdkScreen to which @context is attached.
2650 * Returns: (transfer none): a #GdkScreen.
2653 gtk_style_context_get_screen (GtkStyleContext *context)
2655 GtkStyleContextPrivate *priv;
2657 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2659 priv = context->priv;
2660 return priv->screen;
2664 * gtk_style_context_set_direction:
2665 * @context: a #GtkStyleContext
2666 * @direction: the new direction.
2668 * Sets the reading direction for rendering purposes.
2670 * If you are using a #GtkStyleContext returned from
2671 * gtk_widget_get_style_context(), you do not need to
2672 * call this yourself.
2677 gtk_style_context_set_direction (GtkStyleContext *context,
2678 GtkTextDirection direction)
2680 GtkStyleContextPrivate *priv;
2682 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2684 priv = context->priv;
2685 priv->direction = direction;
2687 g_object_notify (G_OBJECT (context), "direction");
2691 * gtk_style_context_get_direction:
2692 * @context: a #GtkStyleContext
2694 * Returns the widget direction used for rendering.
2696 * Returns: the widget direction
2701 gtk_style_context_get_direction (GtkStyleContext *context)
2703 GtkStyleContextPrivate *priv;
2705 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), GTK_TEXT_DIR_LTR);
2707 priv = context->priv;
2708 return priv->direction;
2712 * gtk_style_context_set_junction_sides:
2713 * @context: a #GtkStyleContext
2714 * @sides: sides where rendered elements are visually connected to
2717 * Sets the sides where rendered elements (mostly through
2718 * gtk_render_frame()) will visually connect with other visual elements.
2720 * This is merely a hint that may or may not be honored
2721 * by theming engines.
2723 * Container widgets are expected to set junction hints as appropriate
2724 * for their children, so it should not normally be necessary to call
2725 * this function manually.
2730 gtk_style_context_set_junction_sides (GtkStyleContext *context,
2731 GtkJunctionSides sides)
2733 GtkStyleContextPrivate *priv;
2736 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2738 priv = context->priv;
2739 info = priv->info_stack->data;
2740 info->junction_sides = sides;
2744 * gtk_style_context_get_junction_sides:
2745 * @context: a #GtkStyleContext
2747 * Returns the sides where rendered elements connect visually with others.
2749 * Returns: the junction sides
2754 gtk_style_context_get_junction_sides (GtkStyleContext *context)
2756 GtkStyleContextPrivate *priv;
2759 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
2761 priv = context->priv;
2762 info = priv->info_stack->data;
2763 return info->junction_sides;
2767 * gtk_style_context_lookup_color:
2768 * @context: a #GtkStyleContext
2769 * @color_name: color name to lookup
2770 * @color: (out): Return location for the looked up color
2772 * Looks up and resolves a color name in the @context color map.
2774 * Returns: %TRUE if @color_name was found and resolved, %FALSE otherwise
2777 gtk_style_context_lookup_color (GtkStyleContext *context,
2778 const gchar *color_name,
2781 GtkStyleContextPrivate *priv;
2782 GtkSymbolicColor *sym_color;
2785 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2786 g_return_val_if_fail (color_name != NULL, FALSE);
2787 g_return_val_if_fail (color != NULL, FALSE);
2789 priv = context->priv;
2790 g_return_val_if_fail (priv->widget_path != NULL, FALSE);
2792 data = style_data_lookup (context);
2793 sym_color = gtk_style_properties_lookup_color (data->store, color_name);
2798 return gtk_symbolic_color_resolve (sym_color, data->store, color);
2802 * gtk_style_context_notify_state_change:
2803 * @context: a #GtkStyleContext
2804 * @window: a #GdkWindow
2805 * @region_id: (allow-none): animatable region to notify on, or %NULL.
2806 * See gtk_style_context_push_animatable_region()
2807 * @state: state to trigger transition for
2808 * @state_value: %TRUE if @state is the state we are changing to,
2809 * %FALSE if we are changing away from it
2811 * Notifies a state change on @context, so if the current style makes use
2812 * of transition animations, one will be started so all rendered elements
2813 * under @region_id are animated for state @state being set to value
2816 * The @window parameter is used in order to invalidate the rendered area
2817 * as the animation runs, so make sure it is the same window that is being
2818 * rendered on by the gtk_render_*() functions.
2820 * If @region_id is %NULL, all rendered elements using @context will be
2821 * affected by this state transition.
2823 * As a practical example, a #GtkButton notifying a state transition on
2824 * the prelight state:
2826 * gtk_style_context_notify_state_change (context,
2827 * gtk_widget_get_window (widget),
2829 * GTK_STATE_PRELIGHT,
2830 * button->in_button);
2833 * Can be handled in the CSS file like this:
2836 * background-color: #f00
2840 * background-color: #fff;
2841 * transition: 200ms linear
2845 * This combination will animate the button background from red to white
2846 * if a pointer enters the button, and back to red if the pointer leaves
2849 * Note that @state is used when finding the transition parameters, which
2850 * is why the style places the transition under the :hover pseudo-class.
2855 gtk_style_context_notify_state_change (GtkStyleContext *context,
2859 gboolean state_value)
2861 GtkStyleContextPrivate *priv;
2862 GtkAnimationDescription *desc;
2863 AnimationInfo *info;
2864 GtkStateFlags flags;
2867 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2868 g_return_if_fail (GDK_IS_WINDOW (window));
2869 g_return_if_fail (state > GTK_STATE_NORMAL && state <= GTK_STATE_FOCUSED);
2871 priv = context->priv;
2872 g_return_if_fail (priv->widget_path != NULL);
2874 state_value = (state_value == TRUE);
2878 case GTK_STATE_ACTIVE:
2879 flags = GTK_STATE_FLAG_ACTIVE;
2881 case GTK_STATE_PRELIGHT:
2882 flags = GTK_STATE_FLAG_PRELIGHT;
2884 case GTK_STATE_SELECTED:
2885 flags = GTK_STATE_FLAG_SELECTED;
2887 case GTK_STATE_INSENSITIVE:
2888 flags = GTK_STATE_FLAG_INSENSITIVE;
2890 case GTK_STATE_INCONSISTENT:
2891 flags = GTK_STATE_FLAG_INCONSISTENT;
2893 case GTK_STATE_FOCUSED:
2894 flags = GTK_STATE_FLAG_FOCUSED;
2896 case GTK_STATE_NORMAL:
2902 /* Find out if there is any animation description for the given
2903 * state, it will fallback to the normal state as well if necessary.
2905 data = style_data_lookup (context);
2906 gtk_style_properties_get (data->store, flags,
2907 "transition", &desc,
2913 if (_gtk_animation_description_get_duration (desc) == 0)
2915 _gtk_animation_description_unref (desc);
2919 info = animation_info_lookup (context, region_id, state);
2922 info->target_value != state_value)
2924 /* Target values are the opposite */
2925 if (!_gtk_timeline_get_loop (info->timeline))
2927 /* Reverse the animation */
2928 if (_gtk_timeline_get_direction (info->timeline) == GTK_TIMELINE_DIRECTION_FORWARD)
2929 _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
2931 _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_FORWARD);
2933 info->target_value = state_value;
2937 /* Take it out of its looping state */
2938 _gtk_timeline_set_loop (info->timeline, FALSE);
2942 (!_gtk_animation_description_get_loop (desc) ||
2945 info = animation_info_new (context, region_id,
2946 _gtk_animation_description_get_duration (desc),
2947 _gtk_animation_description_get_progress_type (desc),
2948 _gtk_animation_description_get_loop (desc),
2949 state, state_value, window);
2951 priv->animations = g_slist_prepend (priv->animations, info);
2952 priv->animations_invalidated = TRUE;
2955 _gtk_animation_description_unref (desc);
2959 * gtk_style_context_cancel_animations:
2960 * @context: a #GtkStyleContext
2961 * @region_id: (allow-none): animatable region to stop, or %NULL.
2962 * See gtk_style_context_push_animatable_region()
2964 * Stops all running animations for @region_id and all animatable
2965 * regions underneath.
2967 * A %NULL @region_id will stop all ongoing animations in @context,
2968 * when dealing with a #GtkStyleContext obtained through
2969 * gtk_widget_get_style_context(), this is normally done for you
2970 * in all circumstances you would expect all widget to be stopped,
2971 * so this should be only used in complex widgets with different
2972 * animatable regions.
2977 gtk_style_context_cancel_animations (GtkStyleContext *context,
2980 GtkStyleContextPrivate *priv;
2981 AnimationInfo *info;
2984 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2986 priv = context->priv;
2987 l = priv->animations;
2995 info->region_id == region_id ||
2996 g_slist_find (info->parent_regions, region_id))
2998 priv->animations = g_slist_remove (priv->animations, info);
2999 animation_info_free (info);
3005 is_parent_of (GdkWindow *parent,
3008 GtkWidget *child_widget, *parent_widget;
3011 gdk_window_get_user_data (child, (gpointer *) &child_widget);
3012 gdk_window_get_user_data (parent, (gpointer *) &parent_widget);
3014 if (child_widget != parent_widget &&
3015 !gtk_widget_is_ancestor (child_widget, parent_widget))
3022 if (window == parent)
3025 window = gdk_window_get_parent (window);
3032 * gtk_style_context_scroll_animations:
3033 * @context: a #GtkStyleContext
3034 * @window: a #GdkWindow used previously in
3035 * gtk_style_context_notify_state_change()
3036 * @dx: Amount to scroll in the X axis
3037 * @dy: Amount to scroll in the Y axis
3039 * This function is analogous to gdk_window_scroll(), and
3040 * should be called together with it so the invalidation
3041 * areas for any ongoing animation are scrolled together
3047 gtk_style_context_scroll_animations (GtkStyleContext *context,
3052 GtkStyleContextPrivate *priv;
3053 AnimationInfo *info;
3056 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3057 g_return_if_fail (GDK_IS_WINDOW (window));
3059 priv = context->priv;
3060 l = priv->animations;
3067 if (info->invalidation_region &&
3068 (window == info->window ||
3069 is_parent_of (window, info->window)))
3070 cairo_region_translate (info->invalidation_region, dx, dy);
3075 * gtk_style_context_push_animatable_region:
3076 * @context: a #GtkStyleContext
3077 * @region_id: unique identifier for the animatable region
3079 * Pushes an animatable region, so all further gtk_render_*() calls between
3080 * this call and the following gtk_style_context_pop_animatable_region()
3081 * will potentially show transition animations for this region if
3082 * gtk_style_context_notify_state_change() is called for a given state,
3083 * and the current theme/style defines transition animations for state
3086 * The @region_id used must be unique in @context so the theming engine
3087 * can uniquely identify rendered elements subject to a state transition.
3092 gtk_style_context_push_animatable_region (GtkStyleContext *context,
3095 GtkStyleContextPrivate *priv;
3097 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3098 g_return_if_fail (region_id != NULL);
3100 priv = context->priv;
3101 priv->animation_regions = g_slist_prepend (priv->animation_regions, region_id);
3105 * gtk_style_context_pop_animatable_region:
3106 * @context: a #GtkStyleContext
3108 * Pops an animatable region from @context.
3109 * See gtk_style_context_push_animatable_region().
3114 gtk_style_context_pop_animatable_region (GtkStyleContext *context)
3116 GtkStyleContextPrivate *priv;
3118 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3120 priv = context->priv;
3121 priv->animation_regions = g_slist_delete_link (priv->animation_regions,
3122 priv->animation_regions);
3126 _gtk_style_context_invalidate_animation_areas (GtkStyleContext *context)
3128 GtkStyleContextPrivate *priv;
3131 priv = context->priv;
3133 for (l = priv->animations; l; l = l->next)
3135 AnimationInfo *info;
3139 /* A NULL invalidation region means it has to be recreated on
3140 * the next expose event, this happens usually after a widget
3141 * allocation change, so the next expose after it will update
3142 * the invalidation region.
3144 if (info->invalidation_region)
3146 cairo_region_destroy (info->invalidation_region);
3147 info->invalidation_region = NULL;
3151 priv->animations_invalidated = TRUE;
3155 _gtk_style_context_coalesce_animation_areas (GtkStyleContext *context,
3158 GtkStyleContextPrivate *priv;
3161 priv = context->priv;
3163 if (!priv->animations_invalidated)
3166 l = priv->animations;
3170 AnimationInfo *info;
3179 if (info->invalidation_region)
3182 if (info->rectangles->len == 0)
3185 info->invalidation_region = cairo_region_create ();
3186 _gtk_widget_get_translation_to_window (widget, info->window, &rel_x, &rel_y);
3188 for (i = 0; i < info->rectangles->len; i++)
3190 cairo_rectangle_int_t *rect;
3192 rect = &g_array_index (info->rectangles, cairo_rectangle_int_t, i);
3194 /* These are widget relative coordinates,
3195 * so have them inverted to be window relative
3200 cairo_region_union_rectangle (info->invalidation_region, rect);
3203 g_array_remove_range (info->rectangles, 0, info->rectangles->len);
3206 priv->animations_invalidated = FALSE;
3210 store_animation_region (GtkStyleContext *context,
3216 GtkStyleContextPrivate *priv;
3219 priv = context->priv;
3221 if (!priv->animations_invalidated)
3224 for (l = priv->animations; l; l = l->next)
3226 AnimationInfo *info;
3230 /* The animation doesn't need updating
3231 * the invalidation area, bail out.
3233 if (info->invalidation_region)
3236 if (context_has_animatable_region (context, info->region_id))
3238 cairo_rectangle_int_t rect;
3242 rect.width = (gint) width;
3243 rect.height = (gint) height;
3245 g_array_append_val (info->rectangles, rect);
3247 if (!info->parent_regions)
3249 GSList *parent_regions;
3251 parent_regions = g_slist_find (priv->animation_regions, info->region_id);
3252 info->parent_regions = g_slist_copy (parent_regions);
3259 * gtk_style_context_invalidate:
3260 * @context: a #GtkStyleContext.
3262 * Invalidates @context style information, so it will be reconstructed
3265 * If you're using a #GtkStyleContext returned from
3266 * gtk_widget_get_style_context(), you do not need to
3267 * call this yourself.
3272 gtk_style_context_invalidate (GtkStyleContext *context)
3274 GtkStyleContextPrivate *priv;
3276 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3278 priv = context->priv;
3280 /* Avoid reentrancy */
3281 if (priv->invalidating_context)
3284 priv->invalidating_context = TRUE;
3286 g_hash_table_remove_all (priv->style_data);
3287 priv->current_data = NULL;
3289 g_signal_emit (context, signals[CHANGED], 0);
3291 priv->invalidating_context = FALSE;
3295 * gtk_style_context_set_background:
3296 * @context: a #GtkStyleContext
3297 * @window: a #GdkWindow
3299 * Sets the background of @window to the background pattern or
3300 * color specified in @context for its current state.
3305 gtk_style_context_set_background (GtkStyleContext *context,
3308 GtkStateFlags state;
3309 cairo_pattern_t *pattern;
3312 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3313 g_return_if_fail (GDK_IS_WINDOW (window));
3315 state = gtk_style_context_get_state (context);
3316 gtk_style_context_get (context, state,
3317 "background-image", &pattern,
3321 gdk_window_set_background_pattern (window, pattern);
3322 cairo_pattern_destroy (pattern);
3326 gtk_style_context_get (context, state,
3327 "background-color", &color,
3331 gdk_window_set_background_rgba (window, color);
3332 gdk_rgba_free (color);
3337 * gtk_style_context_get_color:
3338 * @context: a #GtkStyleContext
3339 * @state: state to retrieve the color for
3340 * @color: (out): return value for the foreground color
3342 * Gets the foreground color for a given state.
3347 gtk_style_context_get_color (GtkStyleContext *context,
3348 GtkStateFlags state,
3351 GtkStyleContextPrivate *priv;
3353 const GValue *value;
3356 g_return_if_fail (color != NULL);
3357 *color = fallback_color;
3359 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3361 priv = context->priv;
3362 g_return_if_fail (priv->widget_path != NULL);
3364 data = style_data_lookup (context);
3365 value = _gtk_style_properties_peek_property (data->store,
3370 c = g_value_get_boxed (value);
3376 * gtk_style_context_get_background_color:
3377 * @context: a #GtkStyleContext
3378 * @state: state to retrieve the color for
3379 * @color: (out): return value for the background color
3381 * Gets the background color for a given state.
3386 gtk_style_context_get_background_color (GtkStyleContext *context,
3387 GtkStateFlags state,
3390 GtkStyleContextPrivate *priv;
3392 const GValue *value;
3395 g_return_if_fail (color != NULL);
3396 *color = fallback_color;
3398 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3400 priv = context->priv;
3401 g_return_if_fail (priv->widget_path != NULL);
3403 data = style_data_lookup (context);
3404 value = _gtk_style_properties_peek_property (data->store,
3405 "background-color", state);
3409 c = g_value_get_boxed (value);
3415 * gtk_style_context_get_border_color:
3416 * @context: a #GtkStyleContext
3417 * @state: state to retrieve the color for
3418 * @color: (out): return value for the border color
3420 * Gets the border color for a given state.
3425 gtk_style_context_get_border_color (GtkStyleContext *context,
3426 GtkStateFlags state,
3429 GtkStyleContextPrivate *priv;
3431 const GValue *value;
3434 g_return_if_fail (color != NULL);
3435 *color = fallback_color;
3437 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3439 priv = context->priv;
3440 g_return_if_fail (priv->widget_path != NULL);
3442 data = style_data_lookup (context);
3443 value = _gtk_style_properties_peek_property (data->store,
3444 "border-color", state);
3448 c = g_value_get_boxed (value);
3454 * gtk_style_context_get_border:
3455 * @context: a #GtkStyleContext
3456 * @state: state to retrieve the border for
3457 * @border: (out): return value for the border settings
3459 * Gets the border for a given state as a #GtkBorder.
3460 * See %GTK_STYLE_PROPERTY_BORDER_WIDTH.
3465 gtk_style_context_get_border (GtkStyleContext *context,
3466 GtkStateFlags state,
3469 GtkStyleContextPrivate *priv;
3471 const GValue *value;
3474 g_return_if_fail (border != NULL);
3475 *border = fallback_border;
3477 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3479 priv = context->priv;
3480 g_return_if_fail (priv->widget_path != NULL);
3482 data = style_data_lookup (context);
3483 value = _gtk_style_properties_peek_property (data->store,
3484 "border-width", state);
3488 b = g_value_get_boxed (value);
3494 * gtk_style_context_get_padding:
3495 * @context: a #GtkStyleContext
3496 * @state: state to retrieve the padding for
3497 * @padding: (out): return value for the padding settings
3499 * Gets the padding for a given state as a #GtkBorder.
3500 * See %GTK_STYLE_PROPERTY_PADDING.
3505 gtk_style_context_get_padding (GtkStyleContext *context,
3506 GtkStateFlags state,
3509 GtkStyleContextPrivate *priv;
3511 const GValue *value;
3514 g_return_if_fail (padding != NULL);
3515 *padding = fallback_border;
3517 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3519 priv = context->priv;
3520 g_return_if_fail (priv->widget_path != NULL);
3522 data = style_data_lookup (context);
3523 value = _gtk_style_properties_peek_property (data->store,
3528 b = g_value_get_boxed (value);
3534 * gtk_style_context_get_margin:
3535 * @context: a #GtkStyleContext
3536 * @state: state to retrieve the border for
3537 * @margin: (out): return value for the margin settings
3539 * Gets the margin for a given state as a #GtkBorder.
3540 * See %GTK_STYLE_PROPERTY_MARGIN.
3545 gtk_style_context_get_margin (GtkStyleContext *context,
3546 GtkStateFlags state,
3549 GtkStyleContextPrivate *priv;
3551 const GValue *value;
3554 g_return_if_fail (margin != NULL);
3555 *margin = fallback_border;
3557 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3559 priv = context->priv;
3560 g_return_if_fail (priv->widget_path != NULL);
3562 data = style_data_lookup (context);
3563 value = _gtk_style_properties_peek_property (data->store,
3568 b = g_value_get_boxed (value);
3574 * gtk_style_context_get_font:
3575 * @context: a #GtkStyleContext
3576 * @state: state to retrieve the font for
3578 * Returns the font description for a given state. The returned
3579 * object is const and will remain valid until the
3580 * #GtkStyleContext::changed signal happens.
3582 * Returns: (transfer none): the #PangoFontDescription for the given
3583 * state. This object is owned by GTK+ and should not be
3588 const PangoFontDescription *
3589 gtk_style_context_get_font (GtkStyleContext *context,
3590 GtkStateFlags state)
3592 GtkStyleContextPrivate *priv;
3594 const GValue *value;
3596 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
3598 priv = context->priv;
3599 g_return_val_if_fail (priv->widget_path != NULL, NULL);
3601 data = style_data_lookup (context);
3602 value = _gtk_style_properties_peek_property (data->store, "font", state);
3605 return g_value_get_boxed (value);
3611 get_cursor_color (GtkStyleContext *context,
3615 GdkColor *style_color;
3617 gtk_style_context_get_style (context,
3618 primary ? "cursor-color" : "secondary-cursor-color",
3624 color->red = style_color->red / 65535.0;
3625 color->green = style_color->green / 65535.0;
3626 color->blue = style_color->blue / 65535.0;
3629 gdk_color_free (style_color);
3633 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, color);
3639 gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
3641 color->red = (color->red + bg.red) * 0.5;
3642 color->green = (color->green + bg.green) * 0.5;
3643 color->blue = (color->blue + bg.blue) * 0.5;
3649 _gtk_style_context_get_cursor_color (GtkStyleContext *context,
3650 GdkRGBA *primary_color,
3651 GdkRGBA *secondary_color)
3654 get_cursor_color (context, TRUE, primary_color);
3656 if (secondary_color)
3657 get_cursor_color (context, FALSE, secondary_color);
3664 * @context: a #GtkStyleContext
3666 * @x: X origin of the rectangle
3667 * @y: Y origin of the rectangle
3668 * @width: rectangle width
3669 * @height: rectangle height
3671 * Renders a checkmark (as in a #GtkCheckButton).
3673 * The %GTK_STATE_FLAG_ACTIVE state determines whether the check is
3674 * on or off, and %GTK_STATE_FLAG_INCONSISTENT determines whether it
3675 * should be marked as undefined.
3678 * <title>Typical checkmark rendering</title>
3679 * <inlinegraphic fileref="checks.png" format="PNG"/>
3685 gtk_render_check (GtkStyleContext *context,
3692 GtkStyleContextPrivate *priv;
3693 GtkThemingEngineClass *engine_class;
3695 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3696 g_return_if_fail (cr != NULL);
3698 if (width <= 0 || height <= 0)
3701 priv = context->priv;
3702 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3706 store_animation_region (context, x, y, width, height);
3708 _gtk_theming_engine_set_context (priv->theming_engine, context);
3709 engine_class->render_check (priv->theming_engine, cr,
3710 x, y, width, height);
3716 * gtk_render_option:
3717 * @context: a #GtkStyleContext
3719 * @x: X origin of the rectangle
3720 * @y: Y origin of the rectangle
3721 * @width: rectangle width
3722 * @height: rectangle height
3724 * Renders an option mark (as in a #GtkRadioButton), the %GTK_STATE_FLAG_ACTIVE
3725 * state will determine whether the option is on or off, and
3726 * %GTK_STATE_FLAG_INCONSISTENT whether it should be marked as undefined.
3729 * <title>Typical option mark rendering</title>
3730 * <inlinegraphic fileref="options.png" format="PNG"/>
3736 gtk_render_option (GtkStyleContext *context,
3743 GtkStyleContextPrivate *priv;
3744 GtkThemingEngineClass *engine_class;
3746 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3747 g_return_if_fail (cr != NULL);
3749 if (width <= 0 || height <= 0)
3752 priv = context->priv;
3753 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3757 store_animation_region (context, x, y, width, height);
3759 _gtk_theming_engine_set_context (priv->theming_engine, context);
3760 engine_class->render_option (priv->theming_engine, cr,
3761 x, y, width, height);
3768 * @context: a #GtkStyleContext
3770 * @angle: arrow angle from 0 to 2 * %G_PI, being 0 the arrow pointing to the north
3771 * @x: Center X for the render area
3772 * @y: Center Y for the render area
3773 * @size: square side for render area
3775 * Renders an arrow pointing to @angle.
3778 * <title>Typical arrow rendering at 0, 1&solidus;2 π, π and 3&solidus;2 π</title>
3779 * <inlinegraphic fileref="arrows.png" format="PNG"/>
3785 gtk_render_arrow (GtkStyleContext *context,
3792 GtkStyleContextPrivate *priv;
3793 GtkThemingEngineClass *engine_class;
3795 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3796 g_return_if_fail (cr != NULL);
3801 priv = context->priv;
3802 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3806 store_animation_region (context, x, y, size, size);
3808 _gtk_theming_engine_set_context (priv->theming_engine, context);
3809 engine_class->render_arrow (priv->theming_engine, cr,
3816 * gtk_render_background:
3817 * @context: a #GtkStyleContext
3819 * @x: X origin of the rectangle
3820 * @y: Y origin of the rectangle
3821 * @width: rectangle width
3822 * @height: rectangle height
3824 * Renders the background of an element.
3827 * <title>Typical background rendering, showing the effect of
3828 * <parameter>background-image</parameter>,
3829 * <parameter>border-width</parameter> and
3830 * <parameter>border-radius</parameter></title>
3831 * <inlinegraphic fileref="background.png" format="PNG"/>
3837 gtk_render_background (GtkStyleContext *context,
3844 GtkStyleContextPrivate *priv;
3845 GtkThemingEngineClass *engine_class;
3847 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3848 g_return_if_fail (cr != NULL);
3850 if (width <= 0 || height <= 0)
3853 priv = context->priv;
3854 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3858 store_animation_region (context, x, y, width, height);
3860 _gtk_theming_engine_set_context (priv->theming_engine, context);
3861 engine_class->render_background (priv->theming_engine, cr, x, y, width, height);
3868 * @context: a #GtkStyleContext
3870 * @x: X origin of the rectangle
3871 * @y: Y origin of the rectangle
3872 * @width: rectangle width
3873 * @height: rectangle height
3875 * Renders a frame around the rectangle defined by @x, @y, @width, @height.
3878 * <title>Examples of frame rendering, showing the effect of
3879 * <parameter>border-image</parameter>,
3880 * <parameter>border-color</parameter>,
3881 * <parameter>border-width</parameter>,
3882 * <parameter>border-radius</parameter> and
3884 * <inlinegraphic fileref="frames.png" format="PNG"/>
3890 gtk_render_frame (GtkStyleContext *context,
3897 GtkStyleContextPrivate *priv;
3898 GtkThemingEngineClass *engine_class;
3900 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3901 g_return_if_fail (cr != NULL);
3903 if (width <= 0 || height <= 0)
3906 priv = context->priv;
3907 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3911 store_animation_region (context, x, y, width, height);
3913 _gtk_theming_engine_set_context (priv->theming_engine, context);
3914 engine_class->render_frame (priv->theming_engine, cr, x, y, width, height);
3920 * gtk_render_expander:
3921 * @context: a #GtkStyleContext
3923 * @x: X origin of the rectangle
3924 * @y: Y origin of the rectangle
3925 * @width: rectangle width
3926 * @height: rectangle height
3928 * Renders an expander (as used in #GtkTreeView and #GtkExpander) in the area
3929 * defined by @x, @y, @width, @height. The state %GTK_STATE_FLAG_ACTIVE
3930 * determines whether the expander is collapsed or expanded.
3933 * <title>Typical expander rendering</title>
3934 * <inlinegraphic fileref="expanders.png" format="PNG"/>
3940 gtk_render_expander (GtkStyleContext *context,
3947 GtkStyleContextPrivate *priv;
3948 GtkThemingEngineClass *engine_class;
3950 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3951 g_return_if_fail (cr != NULL);
3953 if (width <= 0 || height <= 0)
3956 priv = context->priv;
3957 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3961 store_animation_region (context, x, y, width, height);
3963 _gtk_theming_engine_set_context (priv->theming_engine, context);
3964 engine_class->render_expander (priv->theming_engine, cr, x, y, width, height);
3971 * @context: a #GtkStyleContext
3973 * @x: X origin of the rectangle
3974 * @y: Y origin of the rectangle
3975 * @width: rectangle width
3976 * @height: rectangle height
3978 * Renders a focus indicator on the rectangle determined by @x, @y, @width, @height.
3980 * <title>Typical focus rendering</title>
3981 * <inlinegraphic fileref="focus.png" format="PNG"/>
3987 gtk_render_focus (GtkStyleContext *context,
3994 GtkStyleContextPrivate *priv;
3995 GtkThemingEngineClass *engine_class;
3997 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3998 g_return_if_fail (cr != NULL);
4000 if (width <= 0 || height <= 0)
4003 priv = context->priv;
4004 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4008 store_animation_region (context, x, y, width, height);
4010 _gtk_theming_engine_set_context (priv->theming_engine, context);
4011 engine_class->render_focus (priv->theming_engine, cr, x, y, width, height);
4017 * gtk_render_layout:
4018 * @context: a #GtkStyleContext
4022 * @layout: the #PangoLayout to render
4024 * Renders @layout on the coordinates @x, @y
4029 gtk_render_layout (GtkStyleContext *context,
4033 PangoLayout *layout)
4035 GtkStyleContextPrivate *priv;
4036 GtkThemingEngineClass *engine_class;
4037 PangoRectangle extents;
4039 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4040 g_return_if_fail (PANGO_IS_LAYOUT (layout));
4041 g_return_if_fail (cr != NULL);
4043 priv = context->priv;
4044 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4048 pango_layout_get_extents (layout, &extents, NULL);
4050 store_animation_region (context,
4056 _gtk_theming_engine_set_context (priv->theming_engine, context);
4057 engine_class->render_layout (priv->theming_engine, cr, x, y, layout);
4064 * @context: a #GtkStyleContext
4066 * @x0: X coordinate for the origin of the line
4067 * @y0: Y coordinate for the origin of the line
4068 * @x1: X coordinate for the end of the line
4069 * @y1: Y coordinate for the end of the line
4071 * Renders a line from (x0, y0) to (x1, y1).
4076 gtk_render_line (GtkStyleContext *context,
4083 GtkStyleContextPrivate *priv;
4084 GtkThemingEngineClass *engine_class;
4086 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4087 g_return_if_fail (cr != NULL);
4089 priv = context->priv;
4090 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4094 _gtk_theming_engine_set_context (priv->theming_engine, context);
4095 engine_class->render_line (priv->theming_engine, cr, x0, y0, x1, y1);
4101 * gtk_render_slider:
4102 * @context: a #GtkStyleContext
4104 * @x: X origin of the rectangle
4105 * @y: Y origin of the rectangle
4106 * @width: rectangle width
4107 * @height: rectangle height
4108 * @orientation: orientation of the slider
4110 * Renders a slider (as in #GtkScale) in the rectangle defined by @x, @y,
4111 * @width, @height. @orientation defines whether the slider is vertical
4115 * <title>Typical slider rendering</title>
4116 * <inlinegraphic fileref="sliders.png" format="PNG"/>
4122 gtk_render_slider (GtkStyleContext *context,
4128 GtkOrientation orientation)
4130 GtkStyleContextPrivate *priv;
4131 GtkThemingEngineClass *engine_class;
4133 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4134 g_return_if_fail (cr != NULL);
4136 if (width <= 0 || height <= 0)
4139 priv = context->priv;
4140 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4144 store_animation_region (context, x, y, width, height);
4146 _gtk_theming_engine_set_context (priv->theming_engine, context);
4147 engine_class->render_slider (priv->theming_engine, cr, x, y, width, height, orientation);
4153 * gtk_render_frame_gap:
4154 * @context: a #GtkStyleContext
4156 * @x: X origin of the rectangle
4157 * @y: Y origin of the rectangle
4158 * @width: rectangle width
4159 * @height: rectangle height
4160 * @gap_side: side where the gap is
4161 * @xy0_gap: initial coordinate (X or Y depending on @gap_side) for the gap
4162 * @xy1_gap: end coordinate (X or Y depending on @gap_side) for the gap
4164 * Renders a frame around the rectangle defined by (@x, @y, @width, @height),
4165 * leaving a gap on one side. @xy0_gap and @xy1_gap will mean X coordinates
4166 * for %GTK_POS_TOP and %GTK_POS_BOTTOM gap sides, and Y coordinates for
4167 * %GTK_POS_LEFT and %GTK_POS_RIGHT.
4170 * <title>Typical rendering of a frame with a gap</title>
4171 * <inlinegraphic fileref="frame-gap.png" format="PNG"/>
4177 gtk_render_frame_gap (GtkStyleContext *context,
4183 GtkPositionType gap_side,
4187 GtkStyleContextPrivate *priv;
4188 GtkThemingEngineClass *engine_class;
4190 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4191 g_return_if_fail (cr != NULL);
4192 g_return_if_fail (xy0_gap <= xy1_gap);
4193 g_return_if_fail (xy0_gap >= 0);
4195 if (width <= 0 || height <= 0)
4198 if (gap_side == GTK_POS_LEFT ||
4199 gap_side == GTK_POS_RIGHT)
4200 g_return_if_fail (xy1_gap <= height);
4202 g_return_if_fail (xy1_gap <= width);
4204 priv = context->priv;
4205 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4209 store_animation_region (context, x, y, width, height);
4211 _gtk_theming_engine_set_context (priv->theming_engine, context);
4212 engine_class->render_frame_gap (priv->theming_engine, cr,
4213 x, y, width, height, gap_side,
4220 * gtk_render_extension:
4221 * @context: a #GtkStyleContext
4223 * @x: X origin of the rectangle
4224 * @y: Y origin of the rectangle
4225 * @width: rectangle width
4226 * @height: rectangle height
4227 * @gap_side: side where the gap is
4229 * Renders a extension (as in a #GtkNotebook tab) in the rectangle
4230 * defined by @x, @y, @width, @height. The side where the extension
4231 * connects to is defined by @gap_side.
4234 * <title>Typical extension rendering</title>
4235 * <inlinegraphic fileref="extensions.png" format="PNG"/>
4241 gtk_render_extension (GtkStyleContext *context,
4247 GtkPositionType gap_side)
4249 GtkStyleContextPrivate *priv;
4250 GtkThemingEngineClass *engine_class;
4252 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4253 g_return_if_fail (cr != NULL);
4255 if (width <= 0 || height <= 0)
4258 priv = context->priv;
4259 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4263 store_animation_region (context, x, y, width, height);
4265 _gtk_theming_engine_set_context (priv->theming_engine, context);
4266 engine_class->render_extension (priv->theming_engine, cr, x, y, width, height, gap_side);
4272 * gtk_render_handle:
4273 * @context: a #GtkStyleContext
4275 * @x: X origin of the rectangle
4276 * @y: Y origin of the rectangle
4277 * @width: rectangle width
4278 * @height: rectangle height
4280 * Renders a handle (as in #GtkHandleBox, #GtkPaned and
4281 * #GtkWindow<!-- -->'s resize grip), in the rectangle
4282 * determined by @x, @y, @width, @height.
4285 * <title>Handles rendered for the paned and grip classes</title>
4286 * <inlinegraphic fileref="handles.png" format="PNG"/>
4292 gtk_render_handle (GtkStyleContext *context,
4299 GtkStyleContextPrivate *priv;
4300 GtkThemingEngineClass *engine_class;
4302 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4303 g_return_if_fail (cr != NULL);
4305 if (width <= 0 || height <= 0)
4308 priv = context->priv;
4309 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4313 store_animation_region (context, x, y, width, height);
4315 _gtk_theming_engine_set_context (priv->theming_engine, context);
4316 engine_class->render_handle (priv->theming_engine, cr, x, y, width, height);
4322 * gtk_render_activity:
4323 * @context: a #GtkStyleContext
4325 * @x: X origin of the rectangle
4326 * @y: Y origin of the rectangle
4327 * @width: rectangle width
4328 * @height: rectangle height
4330 * Renders an activity area (Such as in #GtkSpinner or the
4331 * fill line in #GtkRange), the state %GTK_STATE_FLAG_ACTIVE
4332 * determines whether there is activity going on.
4337 gtk_render_activity (GtkStyleContext *context,
4344 GtkStyleContextPrivate *priv;
4345 GtkThemingEngineClass *engine_class;
4347 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4348 g_return_if_fail (cr != NULL);
4350 if (width <= 0 || height <= 0)
4353 priv = context->priv;
4354 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4358 store_animation_region (context, x, y, width, height);
4360 _gtk_theming_engine_set_context (priv->theming_engine, context);
4361 engine_class->render_activity (priv->theming_engine, cr, x, y, width, height);
4367 * gtk_render_icon_pixbuf:
4368 * @context: a #GtkStyleContext
4369 * @source: the #GtkIconSource specifying the icon to render
4370 * @size: (type int): the size to render the icon at. A size of (GtkIconSize) -1
4371 * means render at the size of the source and don't scale.
4373 * Renders the icon specified by @source at the given @size, returning the result
4376 * Returns: (transfer full): a newly-created #GdkPixbuf containing the rendered icon
4381 gtk_render_icon_pixbuf (GtkStyleContext *context,
4382 const GtkIconSource *source,
4385 GtkStyleContextPrivate *priv;
4386 GtkThemingEngineClass *engine_class;
4388 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
4389 g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
4390 g_return_val_if_fail (source != NULL, NULL);
4392 priv = context->priv;
4393 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4395 _gtk_theming_engine_set_context (priv->theming_engine, context);
4396 return engine_class->render_icon_pixbuf (priv->theming_engine, source, size);