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 };
510 static void gtk_style_context_finalize (GObject *object);
512 static void gtk_style_context_impl_set_property (GObject *object,
516 static void gtk_style_context_impl_get_property (GObject *object,
522 G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
525 gtk_style_context_class_init (GtkStyleContextClass *klass)
527 GObjectClass *object_class = G_OBJECT_CLASS (klass);
529 object_class->finalize = gtk_style_context_finalize;
530 object_class->set_property = gtk_style_context_impl_set_property;
531 object_class->get_property = gtk_style_context_impl_get_property;
534 g_signal_new (I_("changed"),
535 G_TYPE_FROM_CLASS (object_class),
537 G_STRUCT_OFFSET (GtkStyleContextClass, changed),
539 g_cclosure_marshal_VOID__VOID,
542 g_object_class_install_property (object_class,
544 g_param_spec_object ("screen",
546 P_("The associated GdkScreen"),
548 GTK_PARAM_READWRITE));
549 g_object_class_install_property (object_class,
551 g_param_spec_enum ("direction",
553 P_("Text direction"),
554 GTK_TYPE_TEXT_DIRECTION,
556 GTK_PARAM_READWRITE));
558 g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
561 static GtkStyleInfo *
562 style_info_new (void)
566 info = g_slice_new0 (GtkStyleInfo);
567 info->style_classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
568 info->regions = g_array_new (FALSE, FALSE, sizeof (GtkRegion));
574 style_info_free (GtkStyleInfo *info)
576 g_array_free (info->style_classes, TRUE);
577 g_array_free (info->regions, TRUE);
578 g_slice_free (GtkStyleInfo, info);
581 static GtkStyleInfo *
582 style_info_copy (const GtkStyleInfo *info)
586 copy = style_info_new ();
587 g_array_insert_vals (copy->style_classes, 0,
588 info->style_classes->data,
589 info->style_classes->len);
591 g_array_insert_vals (copy->regions, 0,
595 copy->junction_sides = info->junction_sides;
596 copy->state_flags = info->state_flags;
602 style_info_hash (gconstpointer elem)
604 const GtkStyleInfo *info;
609 for (i = 0; i < info->style_classes->len; i++)
611 hash += g_array_index (info->style_classes, GQuark, i);
615 for (i = 0; i < info->regions->len; i++)
619 region = &g_array_index (info->regions, GtkRegion, i);
620 hash += region->class_quark;
621 hash += region->flags;
629 style_info_equal (gconstpointer elem1,
632 const GtkStyleInfo *info1, *info2;
637 if (info1->junction_sides != info2->junction_sides)
640 if (info1->style_classes->len != info2->style_classes->len)
643 if (memcmp (info1->style_classes->data,
644 info2->style_classes->data,
645 info1->style_classes->len * sizeof (GQuark)) != 0)
648 if (info1->regions->len != info2->regions->len)
651 if (memcmp (info1->regions->data,
652 info2->regions->data,
653 info1->regions->len * sizeof (GtkRegion)) != 0)
660 style_data_new (void)
664 data = g_slice_new0 (StyleData);
665 data->store = gtk_style_properties_new ();
671 clear_property_cache (StyleData *data)
675 if (!data->property_cache)
678 for (i = 0; i < data->property_cache->len; i++)
680 PropertyValue *node = &g_array_index (data->property_cache, PropertyValue, i);
682 g_param_spec_unref (node->pspec);
683 g_value_unset (&node->value);
686 g_array_free (data->property_cache, TRUE);
687 data->property_cache = NULL;
691 style_data_free (StyleData *data)
693 g_object_unref (data->store);
694 clear_property_cache (data);
696 g_slist_foreach (data->icon_factories, (GFunc) g_object_unref, NULL);
697 g_slist_free (data->icon_factories);
699 g_slice_free (StyleData, data);
703 gtk_style_context_init (GtkStyleContext *style_context)
705 GtkStyleContextPrivate *priv;
708 priv = style_context->priv = G_TYPE_INSTANCE_GET_PRIVATE (style_context,
709 GTK_TYPE_STYLE_CONTEXT,
710 GtkStyleContextPrivate);
712 priv->style_data = g_hash_table_new_full (style_info_hash,
714 (GDestroyNotify) style_info_free,
715 (GDestroyNotify) style_data_free);
716 priv->theming_engine = g_object_ref ((gpointer) gtk_theming_engine_load (NULL));
718 priv->direction = GTK_TEXT_DIR_LTR;
720 priv->screen = gdk_screen_get_default ();
722 /* Create default info store */
723 info = style_info_new ();
724 priv->info_stack = g_slist_prepend (priv->info_stack, info);
727 static GtkStyleProviderData *
728 style_provider_data_new (GtkStyleProvider *provider,
731 GtkStyleProviderData *data;
733 data = g_slice_new (GtkStyleProviderData);
734 data->provider = g_object_ref (provider);
735 data->priority = priority;
741 style_provider_data_free (GtkStyleProviderData *data)
743 g_object_unref (data->provider);
744 g_slice_free (GtkStyleProviderData, data);
748 animation_info_free (AnimationInfo *info)
750 g_object_unref (info->timeline);
751 g_object_unref (info->window);
753 if (info->invalidation_region)
754 cairo_region_destroy (info->invalidation_region);
756 g_array_free (info->rectangles, TRUE);
757 g_slist_free (info->parent_regions);
758 g_slice_free (AnimationInfo, info);
761 static AnimationInfo *
762 animation_info_lookup_by_timeline (GtkStyleContext *context,
763 GtkTimeline *timeline)
765 GtkStyleContextPrivate *priv;
769 priv = context->priv;
771 for (l = priv->animations; l; l = l->next)
775 if (info->timeline == timeline)
783 timeline_frame_cb (GtkTimeline *timeline,
787 GtkStyleContextPrivate *priv;
788 GtkStyleContext *context;
792 priv = context->priv;
793 info = animation_info_lookup_by_timeline (context, timeline);
795 g_assert (info != NULL);
797 /* Cancel transition if window is gone */
798 if (gdk_window_is_destroyed (info->window) ||
799 !gdk_window_is_visible (info->window))
801 priv->animations = g_slist_remove (priv->animations, info);
802 animation_info_free (info);
806 if (info->invalidation_region &&
807 !cairo_region_is_empty (info->invalidation_region))
808 gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
810 gdk_window_invalidate_rect (info->window, NULL, TRUE);
814 timeline_finished_cb (GtkTimeline *timeline,
817 GtkStyleContextPrivate *priv;
818 GtkStyleContext *context;
822 priv = context->priv;
823 info = animation_info_lookup_by_timeline (context, timeline);
825 g_assert (info != NULL);
827 priv->animations = g_slist_remove (priv->animations, info);
829 /* Invalidate one last time the area, so the final content is painted */
830 if (info->invalidation_region &&
831 !cairo_region_is_empty (info->invalidation_region))
832 gdk_window_invalidate_region (info->window, info->invalidation_region, TRUE);
834 gdk_window_invalidate_rect (info->window, NULL, TRUE);
836 animation_info_free (info);
839 static AnimationInfo *
840 animation_info_new (GtkStyleContext *context,
843 GtkTimelineProgressType progress_type,
846 gboolean target_value,
851 info = g_slice_new0 (AnimationInfo);
853 info->rectangles = g_array_new (FALSE, FALSE, sizeof (cairo_rectangle_int_t));
854 info->timeline = _gtk_timeline_new (duration);
855 info->window = g_object_ref (window);
857 info->target_value = target_value;
858 info->region_id = region_id;
860 _gtk_timeline_set_progress_type (info->timeline, progress_type);
861 _gtk_timeline_set_loop (info->timeline, loop);
863 if (!loop && !target_value)
865 _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
866 _gtk_timeline_rewind (info->timeline);
869 g_signal_connect (info->timeline, "frame",
870 G_CALLBACK (timeline_frame_cb), context);
871 g_signal_connect (info->timeline, "finished",
872 G_CALLBACK (timeline_finished_cb), context);
874 _gtk_timeline_start (info->timeline);
879 static AnimationInfo *
880 animation_info_lookup (GtkStyleContext *context,
884 GtkStyleContextPrivate *priv;
887 priv = context->priv;
889 for (l = priv->animations; l; l = l->next)
895 if (info->state == state &&
896 info->region_id == region_id)
904 gtk_style_context_finalize (GObject *object)
906 GtkStyleContextPrivate *priv;
907 GtkStyleContext *style_context;
910 style_context = GTK_STYLE_CONTEXT (object);
911 priv = style_context->priv;
913 if (priv->widget_path)
914 gtk_widget_path_free (priv->widget_path);
916 g_hash_table_destroy (priv->style_data);
918 g_list_foreach (priv->providers, (GFunc) style_provider_data_free, NULL);
919 g_list_free (priv->providers);
921 g_slist_foreach (priv->info_stack, (GFunc) style_info_free, NULL);
922 g_slist_free (priv->info_stack);
924 g_slist_free (priv->animation_regions);
926 for (l = priv->animations; l; l = l->next)
927 animation_info_free ((AnimationInfo *) l->data);
929 g_slist_free (priv->animations);
931 if (priv->theming_engine)
932 g_object_unref (priv->theming_engine);
934 G_OBJECT_CLASS (gtk_style_context_parent_class)->finalize (object);
938 gtk_style_context_impl_set_property (GObject *object,
943 GtkStyleContext *style_context;
945 style_context = GTK_STYLE_CONTEXT (object);
950 gtk_style_context_set_screen (style_context,
951 g_value_get_object (value));
954 gtk_style_context_set_direction (style_context,
955 g_value_get_enum (value));
958 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
964 gtk_style_context_impl_get_property (GObject *object,
969 GtkStyleContext *style_context;
970 GtkStyleContextPrivate *priv;
972 style_context = GTK_STYLE_CONTEXT (object);
973 priv = style_context->priv;
978 g_value_set_object (value, priv->screen);
981 g_value_set_enum (value, priv->direction);
984 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
990 find_next_candidate (GList *local,
996 GtkStyleProviderData *local_data, *global_data;
998 local_data = local->data;
999 global_data = global->data;
1001 if (local_data->priority < global_data->priority)
1002 return (ascending) ? local : global;
1004 return (ascending) ? global : local;
1015 build_properties (GtkStyleContext *context,
1016 StyleData *style_data,
1017 GtkWidgetPath *path)
1019 GtkStyleContextPrivate *priv;
1020 GList *elem, *list, *global_list = NULL;
1022 priv = context->priv;
1023 list = priv->providers;
1026 global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
1028 while ((elem = find_next_candidate (list, global_list, TRUE)) != NULL)
1030 GtkStyleProviderData *data;
1031 GtkStyleProperties *provider_style;
1038 global_list = global_list->next;
1040 provider_style = gtk_style_provider_get_style (data->provider, path);
1044 gtk_style_properties_merge (style_data->store, provider_style, TRUE);
1045 g_object_unref (provider_style);
1051 build_icon_factories (GtkStyleContext *context,
1052 StyleData *style_data,
1053 GtkWidgetPath *path)
1055 GtkStyleContextPrivate *priv;
1056 GList *elem, *list, *global_list = NULL;
1058 priv = context->priv;
1059 list = priv->providers_last;
1063 global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
1064 global_list = g_list_last (global_list);
1067 while ((elem = find_next_candidate (list, global_list, FALSE)) != NULL)
1069 GtkIconFactory *factory;
1070 GtkStyleProviderData *data;
1077 global_list = global_list->prev;
1079 factory = gtk_style_provider_get_icon_factory (data->provider, path);
1082 style_data->icon_factories = g_slist_prepend (style_data->icon_factories, factory);
1086 static GtkWidgetPath *
1087 create_query_path (GtkStyleContext *context)
1089 GtkStyleContextPrivate *priv;
1090 GtkWidgetPath *path;
1094 priv = context->priv;
1095 path = gtk_widget_path_copy (priv->widget_path);
1096 pos = gtk_widget_path_length (path) - 1;
1098 info = priv->info_stack->data;
1100 /* Set widget regions */
1101 for (i = 0; i < info->regions->len; i++)
1105 region = &g_array_index (info->regions, GtkRegion, i);
1106 gtk_widget_path_iter_add_region (path, pos,
1107 g_quark_to_string (region->class_quark),
1111 /* Set widget classes */
1112 for (i = 0; i < info->style_classes->len; i++)
1116 quark = g_array_index (info->style_classes, GQuark, i);
1117 gtk_widget_path_iter_add_class (path, pos,
1118 g_quark_to_string (quark));
1125 style_data_lookup (GtkStyleContext *context)
1127 GtkStyleContextPrivate *priv;
1130 priv = context->priv;
1132 /* Current data in use is cached, just return it */
1133 if (priv->current_data)
1134 return priv->current_data;
1136 g_assert (priv->widget_path != NULL);
1138 data = g_hash_table_lookup (priv->style_data, priv->info_stack->data);
1142 GtkWidgetPath *path;
1144 data = style_data_new ();
1145 path = create_query_path (context);
1147 build_properties (context, data, path);
1148 build_icon_factories (context, data, path);
1150 g_hash_table_insert (priv->style_data,
1151 style_info_copy (priv->info_stack->data),
1154 gtk_widget_path_free (path);
1157 priv->current_data = data;
1159 if (priv->theming_engine)
1160 g_object_unref (priv->theming_engine);
1162 gtk_style_properties_get (data->store, 0,
1163 "engine", &priv->theming_engine,
1166 if (!priv->theming_engine)
1167 priv->theming_engine = g_object_ref (gtk_theming_engine_load (NULL));
1173 style_provider_add (GList **list,
1174 GtkStyleProvider *provider,
1177 GtkStyleProviderData *new_data;
1178 gboolean added = FALSE;
1181 new_data = style_provider_data_new (provider, priority);
1185 GtkStyleProviderData *data;
1189 /* Provider was already attached to the style
1190 * context, remove in order to add the new data
1192 if (data->provider == provider)
1199 /* Remove and free link */
1200 *list = g_list_remove_link (*list, link);
1201 style_provider_data_free (link->data);
1202 g_list_free_1 (link);
1208 data->priority > priority)
1210 *list = g_list_insert_before (*list, l, new_data);
1218 *list = g_list_append (*list, new_data);
1222 style_provider_remove (GList **list,
1223 GtkStyleProvider *provider)
1229 GtkStyleProviderData *data;
1233 if (data->provider == provider)
1235 *list = g_list_remove_link (*list, l);
1236 style_provider_data_free (l->data);
1249 * gtk_style_context_new:
1251 * Creates a standalone #GtkStyleContext, this style context
1252 * won't be attached to any widget, so you may want
1253 * to call gtk_style_context_set_path() yourself.
1256 * This function is only useful when using the theming layer
1257 * separated from GTK+, if you are using #GtkStyleContext to
1258 * theme #GtkWidget<!-- -->s, use gtk_widget_get_style_context()
1259 * in order to get a style context ready to theme the widget.
1262 * Returns: A newly created #GtkStyleContext.
1265 gtk_style_context_new (void)
1267 return g_object_new (GTK_TYPE_STYLE_CONTEXT, NULL);
1271 * gtk_style_context_add_provider:
1272 * @context: a #GtkStyleContext
1273 * @provider: a #GtkStyleProvider
1274 * @priority: the priority of the style provider. The lower
1275 * it is, the earlier it will be used in the style
1276 * construction. Typically this will be in the range
1277 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1278 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1280 * Adds a style provider to @context, to be used in style construction.
1282 * <note><para>If both priorities are the same, A #GtkStyleProvider
1283 * added through this function takes precedence over another added
1284 * through gtk_style_context_add_provider_for_screen().</para></note>
1289 gtk_style_context_add_provider (GtkStyleContext *context,
1290 GtkStyleProvider *provider,
1293 GtkStyleContextPrivate *priv;
1295 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1296 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1298 priv = context->priv;
1299 style_provider_add (&priv->providers, provider, priority);
1300 priv->providers_last = g_list_last (priv->providers);
1302 gtk_style_context_invalidate (context);
1306 * gtk_style_context_remove_provider:
1307 * @context: a #GtkStyleContext
1308 * @provider: a #GtkStyleProvider
1310 * Removes @provider from the style providers list in @context.
1315 gtk_style_context_remove_provider (GtkStyleContext *context,
1316 GtkStyleProvider *provider)
1318 GtkStyleContextPrivate *priv;
1320 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1321 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1323 priv = context->priv;
1325 if (style_provider_remove (&priv->providers, provider))
1327 priv->providers_last = g_list_last (priv->providers);
1329 gtk_style_context_invalidate (context);
1334 * gtk_style_context_reset_widgets:
1335 * @screen: a #GdkScreen
1337 * This function recomputes the styles for all widgets under a particular
1338 * #GdkScreen. This is useful when some global parameter has changed that
1339 * affects the appearance of all widgets, because when a widget gets a new
1340 * style, it will both redraw and recompute any cached information about
1341 * its appearance. As an example, it is used when the color scheme changes
1342 * in the related #GtkSettings object.
1347 gtk_style_context_reset_widgets (GdkScreen *screen)
1349 GList *list, *toplevels;
1351 _gtk_icon_set_invalidate_caches ();
1353 toplevels = gtk_window_list_toplevels ();
1354 g_list_foreach (toplevels, (GFunc) g_object_ref, NULL);
1356 for (list = toplevels; list; list = list->next)
1358 if (gtk_widget_get_screen (list->data) == screen)
1359 gtk_widget_reset_style (list->data);
1361 g_object_unref (list->data);
1364 g_list_free (toplevels);
1368 * gtk_style_context_add_provider_for_screen:
1369 * @screen: a #GdkScreen
1370 * @provider: a #GtkStyleProvider
1371 * @priority: the priority of the style provider. The lower
1372 * it is, the earlier it will be used in the style
1373 * construction. Typically this will be in the range
1374 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1375 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1377 * Adds a global style provider to @screen, which will be used
1378 * in style construction for all #GtkStyleContext<!-- -->s under
1381 * GTK+ uses this to make styling information from #GtkSettings
1384 * <note><para>If both priorities are the same, A #GtkStyleProvider
1385 * added through gtk_style_context_add_provider() takes precedence
1386 * over another added through this function.</para></note>
1391 gtk_style_context_add_provider_for_screen (GdkScreen *screen,
1392 GtkStyleProvider *provider,
1395 GList *providers, *list;
1397 g_return_if_fail (GDK_IS_SCREEN (screen));
1398 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1400 if (G_UNLIKELY (!provider_list_quark))
1401 provider_list_quark = g_quark_from_static_string ("gtk-provider-list-quark");
1403 list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
1404 style_provider_add (&list, provider, priority);
1406 if (list != providers)
1407 g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
1409 gtk_style_context_reset_widgets (screen);
1413 * gtk_style_context_remove_provider_for_screen:
1414 * @screen: a #GdkScreen
1415 * @provider: a #GtkStyleProvider
1417 * Removes @provider from the global style providers list in @screen.
1422 gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
1423 GtkStyleProvider *provider)
1425 GList *providers, *list;
1427 g_return_if_fail (GDK_IS_SCREEN (screen));
1428 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1430 if (G_UNLIKELY (!provider_list_quark))
1433 list = providers = g_object_get_qdata (G_OBJECT (screen), provider_list_quark);
1435 if (style_provider_remove (&list, provider))
1437 if (list != providers)
1438 g_object_set_qdata (G_OBJECT (screen), provider_list_quark, list);
1440 gtk_style_context_reset_widgets (screen);
1445 * gtk_style_context_get_property:
1446 * @context: a #GtkStyleContext
1447 * @property: style property name
1448 * @state: state to retrieve the property value for
1449 * @value: (out) (transfer full): return location for the style property value
1451 * Gets a style property from @context for the given state.
1453 * When @value is no longer needed, g_value_unset() must be called
1454 * to free any allocated memory.
1459 gtk_style_context_get_property (GtkStyleContext *context,
1460 const gchar *property,
1461 GtkStateFlags state,
1464 GtkStyleContextPrivate *priv;
1467 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1468 g_return_if_fail (property != NULL);
1469 g_return_if_fail (value != NULL);
1471 priv = context->priv;
1473 g_return_if_fail (priv->widget_path != NULL);
1475 data = style_data_lookup (context);
1476 gtk_style_properties_get_property (data->store, property, state, value);
1480 * gtk_style_context_get_valist:
1481 * @context: a #GtkStyleContext
1482 * @state: state to retrieve the property values for
1483 * @args: va_list of property name/return location pairs, followed by %NULL
1485 * Retrieves several style property values from @context for a given state.
1490 gtk_style_context_get_valist (GtkStyleContext *context,
1491 GtkStateFlags state,
1494 GtkStyleContextPrivate *priv;
1497 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1499 priv = context->priv;
1500 g_return_if_fail (priv->widget_path != NULL);
1502 data = style_data_lookup (context);
1503 gtk_style_properties_get_valist (data->store, state, args);
1507 * gtk_style_context_get:
1508 * @context: a #GtkStyleContext
1509 * @state: state to retrieve the property values for
1510 * @...: property name /return value pairs, followed by %NULL
1512 * Retrieves several style property values from @context for a
1518 gtk_style_context_get (GtkStyleContext *context,
1519 GtkStateFlags state,
1522 GtkStyleContextPrivate *priv;
1526 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1528 priv = context->priv;
1529 g_return_if_fail (priv->widget_path != NULL);
1531 data = style_data_lookup (context);
1533 va_start (args, state);
1534 gtk_style_properties_get_valist (data->store, state, args);
1539 * gtk_style_context_set_state:
1540 * @context: a #GtkStyleContext
1541 * @flags: state to represent
1543 * Sets the state to be used when rendering with any
1544 * of the gtk_render_*() functions.
1549 gtk_style_context_set_state (GtkStyleContext *context,
1550 GtkStateFlags flags)
1552 GtkStyleContextPrivate *priv;
1555 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1557 priv = context->priv;
1558 info = priv->info_stack->data;
1559 info->state_flags = flags;
1563 * gtk_style_context_get_state:
1564 * @context: a #GtkStyleContext
1566 * Returns the state used when rendering.
1568 * Returns: the state flags
1573 gtk_style_context_get_state (GtkStyleContext *context)
1575 GtkStyleContextPrivate *priv;
1578 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
1580 priv = context->priv;
1581 info = priv->info_stack->data;
1583 return info->state_flags;
1587 context_has_animatable_region (GtkStyleContext *context,
1590 GtkStyleContextPrivate *priv;
1592 /* NULL region_id means everything
1593 * rendered through the style context
1598 priv = context->priv;
1599 return g_slist_find (priv->animation_regions, region_id) != NULL;
1603 * gtk_style_context_state_is_running:
1604 * @context: a #GtkStyleContext
1605 * @state: a widget state
1606 * @progress: (out): return location for the transition progress
1608 * Returns %TRUE if there is a transition animation running for the
1609 * current region (see gtk_style_context_push_animatable_region()).
1611 * If @progress is not %NULL, the animation progress will be returned
1612 * there, 0.0 means the state is closest to being unset, while 1.0 means
1613 * it's closest to being set. This means transition animation will
1614 * run from 0 to 1 when @state is being set and from 1 to 0 when
1617 * Returns: %TRUE if there is a running transition animation for @state.
1622 gtk_style_context_state_is_running (GtkStyleContext *context,
1626 GtkStyleContextPrivate *priv;
1627 AnimationInfo *info;
1630 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1632 priv = context->priv;
1634 for (l = priv->animations; l; l = l->next)
1638 if (info->state == state &&
1639 context_has_animatable_region (context, info->region_id))
1642 *progress = _gtk_timeline_get_progress (info->timeline);
1652 * gtk_style_context_set_path:
1653 * @context: a #GtkStyleContext
1654 * @path: a #GtkWidgetPath
1656 * Sets the #GtkWidgetPath used for style matching. As a
1657 * consequence, the style will be regenerated to match
1658 * the new given path.
1660 * If you are using a #GtkStyleContext returned from
1661 * gtk_widget_get_style_context(), you do not need to call
1667 gtk_style_context_set_path (GtkStyleContext *context,
1668 GtkWidgetPath *path)
1670 GtkStyleContextPrivate *priv;
1672 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1673 g_return_if_fail (path != NULL);
1675 priv = context->priv;
1677 if (priv->widget_path)
1679 gtk_widget_path_free (priv->widget_path);
1680 priv->widget_path = NULL;
1684 priv->widget_path = gtk_widget_path_copy (path);
1686 gtk_style_context_invalidate (context);
1690 * gtk_style_context_get_path:
1691 * @context: a #GtkStyleContext
1693 * Returns the widget path used for style matching.
1695 * Returns: (transfer none): A #GtkWidgetPath
1699 G_CONST_RETURN GtkWidgetPath *
1700 gtk_style_context_get_path (GtkStyleContext *context)
1702 GtkStyleContextPrivate *priv;
1704 priv = context->priv;
1705 return priv->widget_path;
1709 * gtk_style_context_save:
1710 * @context: a #GtkStyleContext
1712 * Saves the @context state, so all modifications done through
1713 * gtk_style_context_add_class(), gtk_style_context_remove_class(),
1714 * gtk_style_context_add_region(), gtk_style_context_remove_region()
1715 * or gtk_style_context_set_junction_sides() can be reverted in one
1716 * go through gtk_style_context_restore().
1721 gtk_style_context_save (GtkStyleContext *context)
1723 GtkStyleContextPrivate *priv;
1726 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1728 priv = context->priv;
1730 g_assert (priv->info_stack != NULL);
1732 info = style_info_copy (priv->info_stack->data);
1733 priv->info_stack = g_slist_prepend (priv->info_stack, info);
1737 * gtk_style_context_restore:
1738 * @context: a #GtkStyleContext
1740 * Restores @context state to a previous stage.
1741 * See gtk_style_context_save().
1746 gtk_style_context_restore (GtkStyleContext *context)
1748 GtkStyleContextPrivate *priv;
1751 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1753 priv = context->priv;
1755 if (priv->info_stack)
1757 info = priv->info_stack->data;
1758 priv->info_stack = g_slist_remove (priv->info_stack, info);
1759 style_info_free (info);
1762 if (!priv->info_stack)
1764 g_warning ("Unpaired gtk_style_context_restore() call");
1766 /* Create default region */
1767 info = style_info_new ();
1768 priv->info_stack = g_slist_prepend (priv->info_stack, info);
1771 priv->current_data = NULL;
1775 style_class_find (GArray *array,
1780 gboolean found = FALSE;
1786 if (!array || array->len == 0)
1790 max = array->len - 1;
1796 mid = (min + max) / 2;
1797 item = g_array_index (array, GQuark, mid);
1799 if (class_quark == item)
1804 else if (class_quark > item)
1805 min = pos = mid + 1;
1812 while (!found && min <= max);
1821 region_find (GArray *array,
1826 gboolean found = FALSE;
1832 if (!array || array->len == 0)
1836 max = array->len - 1;
1842 mid = (min + max) / 2;
1843 region = &g_array_index (array, GtkRegion, mid);
1845 if (region->class_quark == class_quark)
1850 else if (region->class_quark > class_quark)
1851 min = pos = mid + 1;
1858 while (!found && min <= max);
1867 * gtk_style_context_add_class:
1868 * @context: a #GtkStyleContext
1869 * @class_name: class name to use in styling
1871 * Adds a style class to @context, so posterior calls to
1872 * gtk_style_context_get() or any of the gtk_render_*()
1873 * functions will make use of this new class for styling.
1875 * In the CSS file format, a #GtkEntry defining an "entry"
1876 * class, would be matched by:
1879 * GtkEntry.entry { ... }
1882 * While any widget defining an "entry" class would be
1891 gtk_style_context_add_class (GtkStyleContext *context,
1892 const gchar *class_name)
1894 GtkStyleContextPrivate *priv;
1899 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1900 g_return_if_fail (class_name != NULL);
1902 priv = context->priv;
1903 class_quark = g_quark_from_string (class_name);
1905 g_assert (priv->info_stack != NULL);
1906 info = priv->info_stack->data;
1908 if (!style_class_find (info->style_classes, class_quark, &position))
1910 g_array_insert_val (info->style_classes, position, class_quark);
1912 /* Unset current data, as it likely changed due to the class change */
1913 priv->current_data = NULL;
1918 * gtk_style_context_remove_class:
1919 * @context: a #GtkStyleContext
1920 * @class_name: class name to remove
1922 * Removes @class_name from @context.
1927 gtk_style_context_remove_class (GtkStyleContext *context,
1928 const gchar *class_name)
1930 GtkStyleContextPrivate *priv;
1935 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1936 g_return_if_fail (class_name != NULL);
1938 class_quark = g_quark_try_string (class_name);
1943 priv = context->priv;
1945 g_assert (priv->info_stack != NULL);
1946 info = priv->info_stack->data;
1948 if (style_class_find (info->style_classes, class_quark, &position))
1950 g_array_remove_index (info->style_classes, position);
1952 /* Unset current data, as it likely changed due to the class change */
1953 priv->current_data = NULL;
1958 * gtk_style_context_has_class:
1959 * @context: a #GtkStyleContext
1960 * @class_name: a class name
1962 * Returns %TRUE if @context currently has defined the
1965 * Returns: %TRUE if @context has @class_name defined
1970 gtk_style_context_has_class (GtkStyleContext *context,
1971 const gchar *class_name)
1973 GtkStyleContextPrivate *priv;
1977 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1978 g_return_val_if_fail (class_name != NULL, FALSE);
1980 class_quark = g_quark_try_string (class_name);
1985 priv = context->priv;
1987 g_assert (priv->info_stack != NULL);
1988 info = priv->info_stack->data;
1990 if (style_class_find (info->style_classes, class_quark, NULL))
1997 * gtk_style_context_list_classes:
1998 * @context: a #GtkStyleContext
2000 * Returns the list of classes currently defined in @context.
2002 * Returns: (transfer container) (element-type utf8): a #GList of
2003 * strings with the currently defined classes. The contents
2004 * of the list are owned by GTK+, but you must free the list
2005 * itself with g_list_free() when you are done with it.
2010 gtk_style_context_list_classes (GtkStyleContext *context)
2012 GtkStyleContextPrivate *priv;
2014 GList *classes = NULL;
2017 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2019 priv = context->priv;
2021 g_assert (priv->info_stack != NULL);
2022 info = priv->info_stack->data;
2024 for (i = 0; i < info->style_classes->len; i++)
2028 quark = g_array_index (info->style_classes, GQuark, i);
2029 classes = g_list_prepend (classes, (gchar *) g_quark_to_string (quark));
2036 * gtk_style_context_list_regions:
2037 * @context: a #GtkStyleContext
2039 * Returns the list of regions currently defined in @context.
2041 * Returns: (transfer container) (element-type utf8): a #GList of
2042 * strings with the currently defined regions. The contents
2043 * of the list are owned by GTK+, but you must free the list
2044 * itself with g_list_free() when you are done with it.
2049 gtk_style_context_list_regions (GtkStyleContext *context)
2051 GtkStyleContextPrivate *priv;
2053 GList *classes = NULL;
2056 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2058 priv = context->priv;
2060 g_assert (priv->info_stack != NULL);
2061 info = priv->info_stack->data;
2063 for (i = 0; i < info->regions->len; i++)
2066 const gchar *class_name;
2068 region = &g_array_index (info->regions, GtkRegion, i);
2070 class_name = g_quark_to_string (region->class_quark);
2071 classes = g_list_prepend (classes, (gchar *) class_name);
2078 _gtk_style_context_check_region_name (const gchar *str)
2080 g_return_val_if_fail (str != NULL, FALSE);
2082 if (!g_ascii_islower (str[0]))
2088 !g_ascii_islower (*str))
2098 * gtk_style_context_add_region:
2099 * @context: a #GtkStyleContext
2100 * @region_name: region name to use in styling
2101 * @flags: flags that apply to the region
2103 * Adds a region to @context, so posterior calls to
2104 * gtk_style_context_get() or any of the gtk_render_*()
2105 * functions will make use of this new region for styling.
2107 * In the CSS file format, a #GtkTreeView defining a "row"
2108 * region, would be matched by:
2111 * GtkTreeView row { ... }
2114 * Pseudo-classes are used for matching @flags, so the two
2117 * GtkTreeView row:nth-child (even) { ... }
2118 * GtkTreeView row:nth-child (odd) { ... }
2121 * would apply to even and odd rows, respectively.
2123 * <note><para>Region names must only contain lowercase letters
2124 * and '-', starting always with a lowercase letter.</para></note>
2129 gtk_style_context_add_region (GtkStyleContext *context,
2130 const gchar *region_name,
2131 GtkRegionFlags flags)
2133 GtkStyleContextPrivate *priv;
2135 GQuark region_quark;
2138 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2139 g_return_if_fail (region_name != NULL);
2140 g_return_if_fail (_gtk_style_context_check_region_name (region_name));
2142 priv = context->priv;
2143 region_quark = g_quark_from_string (region_name);
2145 g_assert (priv->info_stack != NULL);
2146 info = priv->info_stack->data;
2148 if (!region_find (info->regions, region_quark, &position))
2152 region.class_quark = region_quark;
2153 region.flags = flags;
2155 g_array_insert_val (info->regions, position, region);
2157 /* Unset current data, as it likely changed due to the region change */
2158 priv->current_data = NULL;
2163 * gtk_style_context_remove_region:
2164 * @context: a #GtkStyleContext
2165 * @region_name: region name to unset
2167 * Removes a region from @context.
2172 gtk_style_context_remove_region (GtkStyleContext *context,
2173 const gchar *region_name)
2175 GtkStyleContextPrivate *priv;
2177 GQuark region_quark;
2180 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2181 g_return_if_fail (region_name != NULL);
2183 region_quark = g_quark_try_string (region_name);
2188 priv = context->priv;
2190 g_assert (priv->info_stack != NULL);
2191 info = priv->info_stack->data;
2193 if (region_find (info->regions, region_quark, &position))
2195 g_array_remove_index (info->regions, position);
2197 /* Unset current data, as it likely changed due to the region change */
2198 priv->current_data = NULL;
2203 * gtk_style_context_has_region:
2204 * @context: a #GtkStyleContext
2205 * @region_name: a region name
2206 * @flags_return: (out) (allow-none): return location for region flags
2208 * Returns %TRUE if @context has the region defined.
2209 * If @flags_return is not %NULL, it is set to the flags
2210 * affecting the region.
2212 * Returns: %TRUE if region is defined
2217 gtk_style_context_has_region (GtkStyleContext *context,
2218 const gchar *region_name,
2219 GtkRegionFlags *flags_return)
2221 GtkStyleContextPrivate *priv;
2223 GQuark region_quark;
2226 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2227 g_return_val_if_fail (region_name != NULL, FALSE);
2232 region_quark = g_quark_try_string (region_name);
2237 priv = context->priv;
2239 g_assert (priv->info_stack != NULL);
2240 info = priv->info_stack->data;
2242 if (region_find (info->regions, region_quark, &position))
2248 region = &g_array_index (info->regions, GtkRegion, position);
2249 *flags_return = region->flags;
2258 style_property_values_cmp (gconstpointer bsearch_node1,
2259 gconstpointer bsearch_node2)
2261 const PropertyValue *val1 = bsearch_node1;
2262 const PropertyValue *val2 = bsearch_node2;
2264 if (val1->widget_type != val2->widget_type)
2265 return val1->widget_type < val2->widget_type ? -1 : 1;
2267 if (val1->pspec != val2->pspec)
2268 return val1->pspec < val2->pspec ? -1 : 1;
2270 if (val1->state != val2->state)
2271 return val1->state < val2->state ? -1 : 1;
2277 _gtk_style_context_peek_style_property (GtkStyleContext *context,
2279 GtkStateFlags state,
2282 GtkStyleContextPrivate *priv;
2283 PropertyValue *pcache, key = { 0 };
2284 GList *global_list = NULL;
2288 priv = context->priv;
2289 data = style_data_lookup (context);
2291 key.widget_type = widget_type;
2295 /* need value cache array */
2296 if (!data->property_cache)
2297 data->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
2300 pcache = bsearch (&key,
2301 data->property_cache->data, data->property_cache->len,
2302 sizeof (PropertyValue), style_property_values_cmp);
2304 return &pcache->value;
2308 while (i < data->property_cache->len &&
2309 style_property_values_cmp (&key, &g_array_index (data->property_cache, PropertyValue, i)) >= 0)
2312 g_array_insert_val (data->property_cache, i, key);
2313 pcache = &g_array_index (data->property_cache, PropertyValue, i);
2315 /* cache miss, initialize value type, then set contents */
2316 g_param_spec_ref (pcache->pspec);
2317 g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
2321 global_list = g_object_get_qdata (G_OBJECT (priv->screen), provider_list_quark);
2322 global_list = g_list_last (global_list);
2325 if (priv->widget_path)
2327 GList *list, *global, *elem;
2329 list = priv->providers_last;
2330 global = global_list;
2332 while ((elem = find_next_candidate (list, global, FALSE)) != NULL)
2334 GtkStyleProviderData *provider_data;
2336 provider_data = elem->data;
2341 global = global->prev;
2343 if (gtk_style_provider_get_style_property (provider_data->provider,
2344 priv->widget_path, state,
2345 pspec, &pcache->value))
2347 /* Resolve symbolic colors to GdkColor/GdkRGBA */
2348 if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
2350 GtkSymbolicColor *color;
2353 color = g_value_dup_boxed (&pcache->value);
2355 g_value_unset (&pcache->value);
2357 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2358 g_value_init (&pcache->value, GDK_TYPE_RGBA);
2360 g_value_init (&pcache->value, GDK_TYPE_COLOR);
2362 if (gtk_symbolic_color_resolve (color, data->store, &rgba))
2364 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2365 g_value_set_boxed (&pcache->value, &rgba);
2370 rgb.red = rgba.red * 65535. + 0.5;
2371 rgb.green = rgba.green * 65535. + 0.5;
2372 rgb.blue = rgba.blue * 65535. + 0.5;
2374 g_value_set_boxed (&pcache->value, &rgb);
2378 g_param_value_set_default (pspec, &pcache->value);
2380 gtk_symbolic_color_unref (color);
2383 return &pcache->value;
2388 /* not supplied by any provider, revert to default */
2389 g_param_value_set_default (pspec, &pcache->value);
2391 return &pcache->value;
2395 * gtk_style_context_get_style_property:
2396 * @context: a #GtkStyleContext
2397 * @property_name: the name of the widget style property
2398 * @value: Return location for the property value
2400 * Gets the value for a widget style property.
2402 * When @value is no longer needed, g_value_unset() must be called
2403 * to free any allocated memory.
2406 gtk_style_context_get_style_property (GtkStyleContext *context,
2407 const gchar *property_name,
2410 GtkStyleContextPrivate *priv;
2411 GtkWidgetClass *widget_class;
2412 GtkStateFlags state;
2414 const GValue *peek_value;
2417 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2418 g_return_if_fail (property_name != NULL);
2419 g_return_if_fail (value != NULL);
2421 priv = context->priv;
2423 if (!priv->widget_path)
2426 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2428 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2430 g_warning ("%s: can't get style properties for non-widget class `%s'",
2432 g_type_name (widget_type));
2436 widget_class = g_type_class_ref (widget_type);
2437 pspec = gtk_widget_class_find_style_property (widget_class, property_name);
2438 g_type_class_unref (widget_class);
2442 g_warning ("%s: widget class `%s' has no style property named `%s'",
2444 g_type_name (widget_type),
2449 state = gtk_style_context_get_state (context);
2450 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2453 if (G_VALUE_TYPE (value) == G_VALUE_TYPE (peek_value))
2454 g_value_copy (peek_value, value);
2455 else if (g_value_type_transformable (G_VALUE_TYPE (peek_value), G_VALUE_TYPE (value)))
2456 g_value_transform (peek_value, value);
2458 g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
2460 G_VALUE_TYPE_NAME (peek_value),
2461 G_VALUE_TYPE_NAME (value));
2465 * gtk_style_context_get_style_valist:
2466 * @context: a #GtkStyleContext
2467 * @args: va_list of property name/return location pairs, followed by %NULL
2469 * Retrieves several widget style properties from @context according to the
2475 gtk_style_context_get_style_valist (GtkStyleContext *context,
2478 GtkStyleContextPrivate *priv;
2479 const gchar *prop_name;
2480 GtkStateFlags state;
2483 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2485 prop_name = va_arg (args, const gchar *);
2486 priv = context->priv;
2488 if (!priv->widget_path)
2491 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2493 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2495 g_warning ("%s: can't get style properties for non-widget class `%s'",
2497 g_type_name (widget_type));
2501 state = gtk_style_context_get_state (context);
2505 GtkWidgetClass *widget_class;
2507 const GValue *peek_value;
2510 widget_class = g_type_class_ref (widget_type);
2511 pspec = gtk_widget_class_find_style_property (widget_class, prop_name);
2512 g_type_class_unref (widget_class);
2516 g_warning ("%s: widget class `%s' has no style property named `%s'",
2518 g_type_name (widget_type),
2523 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2526 G_VALUE_LCOPY (peek_value, args, 0, &error);
2530 g_warning ("can't retrieve style property `%s' of type `%s': %s",
2532 G_VALUE_TYPE_NAME (peek_value),
2537 prop_name = va_arg (args, const gchar *);
2542 * gtk_style_context_get_style:
2543 * @context: a #GtkStyleContext
2544 * @...: property name /return value pairs, followed by %NULL
2546 * Retrieves several widget style properties from @context according to the
2552 gtk_style_context_get_style (GtkStyleContext *context,
2557 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2559 va_start (args, context);
2560 gtk_style_context_get_style_valist (context, args);
2566 * gtk_style_context_lookup_icon_set:
2567 * @context: a #GtkStyleContext
2568 * @stock_id: an icon name
2570 * Looks up @stock_id in the icon factories associated to @context and
2571 * the default icon factory, returning an icon set if found, otherwise
2574 * Returns: (transfer none): The looked up %GtkIconSet, or %NULL
2577 gtk_style_context_lookup_icon_set (GtkStyleContext *context,
2578 const gchar *stock_id)
2580 GtkStyleContextPrivate *priv;
2584 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2585 g_return_val_if_fail (stock_id != NULL, NULL);
2587 priv = context->priv;
2588 g_return_val_if_fail (priv->widget_path != NULL, NULL);
2590 data = style_data_lookup (context);
2592 for (list = data->icon_factories; list; list = list->next)
2594 GtkIconFactory *factory;
2595 GtkIconSet *icon_set;
2597 factory = list->data;
2598 icon_set = gtk_icon_factory_lookup (factory, stock_id);
2604 return gtk_icon_factory_lookup_default (stock_id);
2608 * gtk_style_context_set_screen:
2609 * @context: a #GtkStyleContext
2610 * @screen: a #GdkScreen
2612 * Attaches @context to the given screen.
2614 * The screen is used to add style information from 'global' style
2615 * providers, such as the screens #GtkSettings instance.
2617 * If you are using a #GtkStyleContext returned from
2618 * gtk_widget_get_style_context(), you do not need to
2619 * call this yourself.
2624 gtk_style_context_set_screen (GtkStyleContext *context,
2627 GtkStyleContextPrivate *priv;
2629 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2630 g_return_if_fail (GDK_IS_SCREEN (screen));
2632 priv = context->priv;
2633 if (priv->screen == screen)
2636 priv->screen = screen;
2638 g_object_notify (G_OBJECT (context), "screen");
2640 gtk_style_context_invalidate (context);
2644 * gtk_style_context_get_screen:
2645 * @context: a #GtkStyleContext
2647 * Returns the #GdkScreen to which @context is attached.
2649 * Returns: (transfer none): a #GdkScreen.
2652 gtk_style_context_get_screen (GtkStyleContext *context)
2654 GtkStyleContextPrivate *priv;
2656 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2658 priv = context->priv;
2659 return priv->screen;
2663 * gtk_style_context_set_direction:
2664 * @context: a #GtkStyleContext
2665 * @direction: the new direction.
2667 * Sets the reading direction for rendering purposes.
2669 * If you are using a #GtkStyleContext returned from
2670 * gtk_widget_get_style_context(), you do not need to
2671 * call this yourself.
2676 gtk_style_context_set_direction (GtkStyleContext *context,
2677 GtkTextDirection direction)
2679 GtkStyleContextPrivate *priv;
2681 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2683 priv = context->priv;
2684 priv->direction = direction;
2686 g_object_notify (G_OBJECT (context), "direction");
2690 * gtk_style_context_get_direction:
2691 * @context: a #GtkStyleContext
2693 * Returns the widget direction used for rendering.
2695 * Returns: the widget direction
2700 gtk_style_context_get_direction (GtkStyleContext *context)
2702 GtkStyleContextPrivate *priv;
2704 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), GTK_TEXT_DIR_LTR);
2706 priv = context->priv;
2707 return priv->direction;
2711 * gtk_style_context_set_junction_sides:
2712 * @context: a #GtkStyleContext
2713 * @sides: sides where rendered elements are visually connected to
2716 * Sets the sides where rendered elements (mostly through
2717 * gtk_render_frame()) will visually connect with other visual elements.
2719 * This is merely a hint that may or may not be honored
2720 * by theming engines.
2722 * Container widgets are expected to set junction hints as appropriate
2723 * for their children, so it should not normally be necessary to call
2724 * this function manually.
2729 gtk_style_context_set_junction_sides (GtkStyleContext *context,
2730 GtkJunctionSides sides)
2732 GtkStyleContextPrivate *priv;
2735 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2737 priv = context->priv;
2738 info = priv->info_stack->data;
2739 info->junction_sides = sides;
2743 * gtk_style_context_get_junction_sides:
2744 * @context: a #GtkStyleContext
2746 * Returns the sides where rendered elements connect visually with others.
2748 * Returns: the junction sides
2753 gtk_style_context_get_junction_sides (GtkStyleContext *context)
2755 GtkStyleContextPrivate *priv;
2758 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
2760 priv = context->priv;
2761 info = priv->info_stack->data;
2762 return info->junction_sides;
2766 * gtk_style_context_lookup_color:
2767 * @context: a #GtkStyleContext
2768 * @color_name: color name to lookup
2769 * @color: (out): Return location for the looked up color
2771 * Looks up and resolves a color name in the @context color map.
2773 * Returns: %TRUE if @color_name was found and resolved, %FALSE otherwise
2776 gtk_style_context_lookup_color (GtkStyleContext *context,
2777 const gchar *color_name,
2780 GtkStyleContextPrivate *priv;
2781 GtkSymbolicColor *sym_color;
2784 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2785 g_return_val_if_fail (color_name != NULL, FALSE);
2786 g_return_val_if_fail (color != NULL, FALSE);
2788 priv = context->priv;
2789 g_return_val_if_fail (priv->widget_path != NULL, FALSE);
2791 data = style_data_lookup (context);
2792 sym_color = gtk_style_properties_lookup_color (data->store, color_name);
2797 return gtk_symbolic_color_resolve (sym_color, data->store, color);
2801 * gtk_style_context_notify_state_change:
2802 * @context: a #GtkStyleContext
2803 * @window: a #GdkWindow
2804 * @region_id: (allow-none): animatable region to notify on, or %NULL.
2805 * See gtk_style_context_push_animatable_region()
2806 * @state: state to trigger transition for
2807 * @state_value: %TRUE if @state is the state we are changing to,
2808 * %FALSE if we are changing away from it
2810 * Notifies a state change on @context, so if the current style makes use
2811 * of transition animations, one will be started so all rendered elements
2812 * under @region_id are animated for state @state being set to value
2815 * The @window parameter is used in order to invalidate the rendered area
2816 * as the animation runs, so make sure it is the same window that is being
2817 * rendered on by the gtk_render_*() functions.
2819 * If @region_id is %NULL, all rendered elements using @context will be
2820 * affected by this state transition.
2822 * As a practical example, a #GtkButton notifying a state transition on
2823 * the prelight state:
2825 * gtk_style_context_notify_state_change (context,
2826 * gtk_widget_get_window (widget),
2828 * GTK_STATE_PRELIGHT,
2829 * button->in_button);
2832 * Can be handled in the CSS file like this:
2835 * background-color: #f00
2839 * background-color: #fff;
2840 * transition: 200ms linear
2844 * This combination will animate the button background from red to white
2845 * if a pointer enters the button, and back to red if the pointer leaves
2848 * Note that @state is used when finding the transition parameters, which
2849 * is why the style places the transition under the :hover pseudo-class.
2854 gtk_style_context_notify_state_change (GtkStyleContext *context,
2858 gboolean state_value)
2860 GtkStyleContextPrivate *priv;
2861 GtkAnimationDescription *desc;
2862 AnimationInfo *info;
2863 GtkStateFlags flags;
2866 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2867 g_return_if_fail (GDK_IS_WINDOW (window));
2868 g_return_if_fail (state > GTK_STATE_NORMAL && state <= GTK_STATE_FOCUSED);
2870 priv = context->priv;
2871 g_return_if_fail (priv->widget_path != NULL);
2873 state_value = (state_value == TRUE);
2877 case GTK_STATE_ACTIVE:
2878 flags = GTK_STATE_FLAG_ACTIVE;
2880 case GTK_STATE_PRELIGHT:
2881 flags = GTK_STATE_FLAG_PRELIGHT;
2883 case GTK_STATE_SELECTED:
2884 flags = GTK_STATE_FLAG_SELECTED;
2886 case GTK_STATE_INSENSITIVE:
2887 flags = GTK_STATE_FLAG_INSENSITIVE;
2889 case GTK_STATE_INCONSISTENT:
2890 flags = GTK_STATE_FLAG_INCONSISTENT;
2892 case GTK_STATE_FOCUSED:
2893 flags = GTK_STATE_FLAG_FOCUSED;
2895 case GTK_STATE_NORMAL:
2901 /* Find out if there is any animation description for the given
2902 * state, it will fallback to the normal state as well if necessary.
2904 data = style_data_lookup (context);
2905 gtk_style_properties_get (data->store, flags,
2906 "transition", &desc,
2912 if (_gtk_animation_description_get_duration (desc) == 0)
2914 _gtk_animation_description_unref (desc);
2918 info = animation_info_lookup (context, region_id, state);
2921 info->target_value != state_value)
2923 /* Target values are the opposite */
2924 if (!_gtk_timeline_get_loop (info->timeline))
2926 /* Reverse the animation */
2927 if (_gtk_timeline_get_direction (info->timeline) == GTK_TIMELINE_DIRECTION_FORWARD)
2928 _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_BACKWARD);
2930 _gtk_timeline_set_direction (info->timeline, GTK_TIMELINE_DIRECTION_FORWARD);
2932 info->target_value = state_value;
2936 /* Take it out of its looping state */
2937 _gtk_timeline_set_loop (info->timeline, FALSE);
2941 (!_gtk_animation_description_get_loop (desc) ||
2944 info = animation_info_new (context, region_id,
2945 _gtk_animation_description_get_duration (desc),
2946 _gtk_animation_description_get_progress_type (desc),
2947 _gtk_animation_description_get_loop (desc),
2948 state, state_value, window);
2950 priv->animations = g_slist_prepend (priv->animations, info);
2951 priv->animations_invalidated = TRUE;
2954 _gtk_animation_description_unref (desc);
2958 * gtk_style_context_cancel_animations:
2959 * @context: a #GtkStyleContext
2960 * @region_id: (allow-none): animatable region to stop, or %NULL.
2961 * See gtk_style_context_push_animatable_region()
2963 * Stops all running animations for @region_id and all animatable
2964 * regions underneath.
2966 * A %NULL @region_id will stop all ongoing animations in @context,
2967 * when dealing with a #GtkStyleContext obtained through
2968 * gtk_widget_get_style_context(), this is normally done for you
2969 * in all circumstances you would expect all widget to be stopped,
2970 * so this should be only used in complex widgets with different
2971 * animatable regions.
2976 gtk_style_context_cancel_animations (GtkStyleContext *context,
2979 GtkStyleContextPrivate *priv;
2980 AnimationInfo *info;
2983 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2985 priv = context->priv;
2986 l = priv->animations;
2994 info->region_id == region_id ||
2995 g_slist_find (info->parent_regions, region_id))
2997 priv->animations = g_slist_remove (priv->animations, info);
2998 animation_info_free (info);
3004 is_parent_of (GdkWindow *parent,
3007 GtkWidget *child_widget, *parent_widget;
3010 gdk_window_get_user_data (child, (gpointer *) &child_widget);
3011 gdk_window_get_user_data (parent, (gpointer *) &parent_widget);
3013 if (child_widget != parent_widget &&
3014 !gtk_widget_is_ancestor (child_widget, parent_widget))
3021 if (window == parent)
3024 window = gdk_window_get_parent (window);
3031 * gtk_style_context_scroll_animations:
3032 * @context: a #GtkStyleContext
3033 * @window: a #GdkWindow used previously in
3034 * gtk_style_context_notify_state_change()
3035 * @dx: Amount to scroll in the X axis
3036 * @dy: Amount to scroll in the Y axis
3038 * This function is analogous to gdk_window_scroll(), and
3039 * should be called together with it so the invalidation
3040 * areas for any ongoing animation are scrolled together
3046 gtk_style_context_scroll_animations (GtkStyleContext *context,
3051 GtkStyleContextPrivate *priv;
3052 AnimationInfo *info;
3055 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3056 g_return_if_fail (GDK_IS_WINDOW (window));
3058 priv = context->priv;
3059 l = priv->animations;
3066 if (info->invalidation_region &&
3067 (window == info->window ||
3068 is_parent_of (window, info->window)))
3069 cairo_region_translate (info->invalidation_region, dx, dy);
3074 * gtk_style_context_push_animatable_region:
3075 * @context: a #GtkStyleContext
3076 * @region_id: unique identifier for the animatable region
3078 * Pushes an animatable region, so all further gtk_render_*() calls between
3079 * this call and the following gtk_style_context_pop_animatable_region()
3080 * will potentially show transition animations for this region if
3081 * gtk_style_context_notify_state_change() is called for a given state,
3082 * and the current theme/style defines transition animations for state
3085 * The @region_id used must be unique in @context so the theming engine
3086 * can uniquely identify rendered elements subject to a state transition.
3091 gtk_style_context_push_animatable_region (GtkStyleContext *context,
3094 GtkStyleContextPrivate *priv;
3096 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3097 g_return_if_fail (region_id != NULL);
3099 priv = context->priv;
3100 priv->animation_regions = g_slist_prepend (priv->animation_regions, region_id);
3104 * gtk_style_context_pop_animatable_region:
3105 * @context: a #GtkStyleContext
3107 * Pops an animatable region from @context.
3108 * See gtk_style_context_push_animatable_region().
3113 gtk_style_context_pop_animatable_region (GtkStyleContext *context)
3115 GtkStyleContextPrivate *priv;
3117 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3119 priv = context->priv;
3120 priv->animation_regions = g_slist_delete_link (priv->animation_regions,
3121 priv->animation_regions);
3125 _gtk_style_context_invalidate_animation_areas (GtkStyleContext *context)
3127 GtkStyleContextPrivate *priv;
3130 priv = context->priv;
3132 for (l = priv->animations; l; l = l->next)
3134 AnimationInfo *info;
3138 /* A NULL invalidation region means it has to be recreated on
3139 * the next expose event, this happens usually after a widget
3140 * allocation change, so the next expose after it will update
3141 * the invalidation region.
3143 if (info->invalidation_region)
3145 cairo_region_destroy (info->invalidation_region);
3146 info->invalidation_region = NULL;
3150 priv->animations_invalidated = TRUE;
3154 _gtk_style_context_coalesce_animation_areas (GtkStyleContext *context,
3157 GtkStyleContextPrivate *priv;
3160 priv = context->priv;
3162 if (!priv->animations_invalidated)
3165 l = priv->animations;
3169 AnimationInfo *info;
3178 if (info->invalidation_region)
3181 if (info->rectangles->len == 0)
3184 info->invalidation_region = cairo_region_create ();
3185 _gtk_widget_get_translation_to_window (widget, info->window, &rel_x, &rel_y);
3187 for (i = 0; i < info->rectangles->len; i++)
3189 cairo_rectangle_int_t *rect;
3191 rect = &g_array_index (info->rectangles, cairo_rectangle_int_t, i);
3193 /* These are widget relative coordinates,
3194 * so have them inverted to be window relative
3199 cairo_region_union_rectangle (info->invalidation_region, rect);
3202 g_array_remove_range (info->rectangles, 0, info->rectangles->len);
3205 priv->animations_invalidated = FALSE;
3209 store_animation_region (GtkStyleContext *context,
3215 GtkStyleContextPrivate *priv;
3218 priv = context->priv;
3220 if (!priv->animations_invalidated)
3223 for (l = priv->animations; l; l = l->next)
3225 AnimationInfo *info;
3229 /* The animation doesn't need updating
3230 * the invalidation area, bail out.
3232 if (info->invalidation_region)
3235 if (context_has_animatable_region (context, info->region_id))
3237 cairo_rectangle_int_t rect;
3241 rect.width = (gint) width;
3242 rect.height = (gint) height;
3244 g_array_append_val (info->rectangles, rect);
3246 if (!info->parent_regions)
3248 GSList *parent_regions;
3250 parent_regions = g_slist_find (priv->animation_regions, info->region_id);
3251 info->parent_regions = g_slist_copy (parent_regions);
3258 * gtk_style_context_invalidate:
3259 * @context: a #GtkStyleContext.
3261 * Invalidates @context style information, so it will be reconstructed
3264 * If you're using a #GtkStyleContext returned from
3265 * gtk_widget_get_style_context(), you do not need to
3266 * call this yourself.
3271 gtk_style_context_invalidate (GtkStyleContext *context)
3273 GtkStyleContextPrivate *priv;
3275 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3277 priv = context->priv;
3279 /* Avoid reentrancy */
3280 if (priv->invalidating_context)
3283 priv->invalidating_context = TRUE;
3285 g_hash_table_remove_all (priv->style_data);
3286 priv->current_data = NULL;
3288 g_signal_emit (context, signals[CHANGED], 0);
3290 priv->invalidating_context = FALSE;
3294 * gtk_style_context_set_background:
3295 * @context: a #GtkStyleContext
3296 * @window: a #GdkWindow
3298 * Sets the background of @window to the background pattern or
3299 * color specified in @context for its current state.
3304 gtk_style_context_set_background (GtkStyleContext *context,
3307 GtkStateFlags state;
3308 cairo_pattern_t *pattern;
3311 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3312 g_return_if_fail (GDK_IS_WINDOW (window));
3314 state = gtk_style_context_get_state (context);
3315 gtk_style_context_get (context, state,
3316 "background-image", &pattern,
3320 gdk_window_set_background_pattern (window, pattern);
3321 cairo_pattern_destroy (pattern);
3325 gtk_style_context_get (context, state,
3326 "background-color", &color,
3330 gdk_window_set_background_rgba (window, color);
3331 gdk_rgba_free (color);
3336 * gtk_style_context_get_color:
3337 * @context: a #GtkStyleContext
3338 * @state: state to retrieve the color for
3339 * @color: (out): return value for the foreground color
3341 * Gets the foreground color for a given state.
3346 gtk_style_context_get_color (GtkStyleContext *context,
3347 GtkStateFlags state,
3350 GtkStyleContextPrivate *priv;
3352 const GValue *value;
3355 g_return_if_fail (color != NULL);
3356 *color = fallback_color;
3358 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3360 priv = context->priv;
3361 g_return_if_fail (priv->widget_path != NULL);
3363 data = style_data_lookup (context);
3364 value = _gtk_style_properties_peek_property (data->store,
3371 c = g_value_get_boxed (value);
3377 * gtk_style_context_get_background_color:
3378 * @context: a #GtkStyleContext
3379 * @state: state to retrieve the color for
3380 * @color: (out): return value for the background color
3382 * Gets the background color for a given state.
3387 gtk_style_context_get_background_color (GtkStyleContext *context,
3388 GtkStateFlags state,
3391 GtkStyleContextPrivate *priv;
3393 const GValue *value;
3396 g_return_if_fail (color != NULL);
3397 *color = fallback_color;
3399 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3401 priv = context->priv;
3402 g_return_if_fail (priv->widget_path != NULL);
3404 data = style_data_lookup (context);
3405 value = _gtk_style_properties_peek_property (data->store,
3412 c = g_value_get_boxed (value);
3418 * gtk_style_context_get_border_color:
3419 * @context: a #GtkStyleContext
3420 * @state: state to retrieve the color for
3421 * @color: (out): return value for the border color
3423 * Gets the border color for a given state.
3428 gtk_style_context_get_border_color (GtkStyleContext *context,
3429 GtkStateFlags state,
3432 GtkStyleContextPrivate *priv;
3434 const GValue *value;
3437 g_return_if_fail (color != NULL);
3438 *color = fallback_color;
3440 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3442 priv = context->priv;
3443 g_return_if_fail (priv->widget_path != NULL);
3445 data = style_data_lookup (context);
3446 value = _gtk_style_properties_peek_property (data->store,
3453 c = g_value_get_boxed (value);
3459 * gtk_style_context_get_border:
3460 * @context: a #GtkStyleContext
3461 * @state: state to retrieve the border for
3462 * @border: (out): return value for the border settings
3464 * Gets the border for a given state as a #GtkBorder.
3465 * See %GTK_STYLE_PROPERTY_BORDER_WIDTH.
3470 gtk_style_context_get_border (GtkStyleContext *context,
3471 GtkStateFlags state,
3474 GtkStyleContextPrivate *priv;
3476 int top, left, bottom, right;
3478 g_return_if_fail (border != NULL);
3479 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3481 priv = context->priv;
3482 g_return_if_fail (priv->widget_path != NULL);
3484 data = style_data_lookup (context);
3485 gtk_style_properties_get (data->store,
3487 "border-top-width", &top,
3488 "border-left-width", &left,
3489 "border-bottom-width", &bottom,
3490 "border-right-width", &right,
3494 border->left = left;
3495 border->bottom = bottom;
3496 border->right = right;
3500 * gtk_style_context_get_padding:
3501 * @context: a #GtkStyleContext
3502 * @state: state to retrieve the padding for
3503 * @padding: (out): return value for the padding settings
3505 * Gets the padding for a given state as a #GtkBorder.
3506 * See %GTK_STYLE_PROPERTY_PADDING.
3511 gtk_style_context_get_padding (GtkStyleContext *context,
3512 GtkStateFlags state,
3515 GtkStyleContextPrivate *priv;
3517 int top, left, bottom, right;
3519 g_return_if_fail (padding != NULL);
3520 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3522 priv = context->priv;
3523 g_return_if_fail (priv->widget_path != NULL);
3525 data = style_data_lookup (context);
3526 gtk_style_properties_get (data->store,
3528 "padding-top", &top,
3529 "padding-left", &left,
3530 "padding-bottom", &bottom,
3531 "padding-right", &right,
3535 padding->left = left;
3536 padding->bottom = bottom;
3537 padding->right = right;
3541 * gtk_style_context_get_margin:
3542 * @context: a #GtkStyleContext
3543 * @state: state to retrieve the border for
3544 * @margin: (out): return value for the margin settings
3546 * Gets the margin for a given state as a #GtkBorder.
3547 * See %GTK_STYLE_PROPERTY_MARGIN.
3552 gtk_style_context_get_margin (GtkStyleContext *context,
3553 GtkStateFlags state,
3556 GtkStyleContextPrivate *priv;
3558 int top, left, bottom, right;
3560 g_return_if_fail (margin != NULL);
3561 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3563 priv = context->priv;
3564 g_return_if_fail (priv->widget_path != NULL);
3566 data = style_data_lookup (context);
3567 gtk_style_properties_get (data->store,
3570 "margin-left", &left,
3571 "margin-bottom", &bottom,
3572 "margin-right", &right,
3576 margin->left = left;
3577 margin->bottom = bottom;
3578 margin->right = right;
3582 * gtk_style_context_get_font:
3583 * @context: a #GtkStyleContext
3584 * @state: state to retrieve the font for
3586 * Returns the font description for a given state. The returned
3587 * object is const and will remain valid until the
3588 * #GtkStyleContext::changed signal happens.
3590 * Returns: (transfer none): the #PangoFontDescription for the given
3591 * state. This object is owned by GTK+ and should not be
3596 const PangoFontDescription *
3597 gtk_style_context_get_font (GtkStyleContext *context,
3598 GtkStateFlags state)
3600 GtkStyleContextPrivate *priv;
3602 const GValue *value;
3604 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
3606 priv = context->priv;
3607 g_return_val_if_fail (priv->widget_path != NULL, NULL);
3609 data = style_data_lookup (context);
3610 value = _gtk_style_properties_peek_property (data->store, "font", state, NULL);
3613 return g_value_get_boxed (value);
3619 get_cursor_color (GtkStyleContext *context,
3623 GdkColor *style_color;
3625 gtk_style_context_get_style (context,
3626 primary ? "cursor-color" : "secondary-cursor-color",
3632 color->red = style_color->red / 65535.0;
3633 color->green = style_color->green / 65535.0;
3634 color->blue = style_color->blue / 65535.0;
3637 gdk_color_free (style_color);
3641 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, color);
3647 gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
3649 color->red = (color->red + bg.red) * 0.5;
3650 color->green = (color->green + bg.green) * 0.5;
3651 color->blue = (color->blue + bg.blue) * 0.5;
3657 _gtk_style_context_get_cursor_color (GtkStyleContext *context,
3658 GdkRGBA *primary_color,
3659 GdkRGBA *secondary_color)
3662 get_cursor_color (context, TRUE, primary_color);
3664 if (secondary_color)
3665 get_cursor_color (context, FALSE, secondary_color);
3672 * @context: a #GtkStyleContext
3674 * @x: X origin of the rectangle
3675 * @y: Y origin of the rectangle
3676 * @width: rectangle width
3677 * @height: rectangle height
3679 * Renders a checkmark (as in a #GtkCheckButton).
3681 * The %GTK_STATE_FLAG_ACTIVE state determines whether the check is
3682 * on or off, and %GTK_STATE_FLAG_INCONSISTENT determines whether it
3683 * should be marked as undefined.
3686 * <title>Typical checkmark rendering</title>
3687 * <inlinegraphic fileref="checks.png" format="PNG"/>
3693 gtk_render_check (GtkStyleContext *context,
3700 GtkStyleContextPrivate *priv;
3701 GtkThemingEngineClass *engine_class;
3703 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3704 g_return_if_fail (cr != NULL);
3706 if (width <= 0 || height <= 0)
3709 priv = context->priv;
3710 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3714 store_animation_region (context, x, y, width, height);
3716 _gtk_theming_engine_set_context (priv->theming_engine, context);
3717 engine_class->render_check (priv->theming_engine, cr,
3718 x, y, width, height);
3724 * gtk_render_option:
3725 * @context: a #GtkStyleContext
3727 * @x: X origin of the rectangle
3728 * @y: Y origin of the rectangle
3729 * @width: rectangle width
3730 * @height: rectangle height
3732 * Renders an option mark (as in a #GtkRadioButton), the %GTK_STATE_FLAG_ACTIVE
3733 * state will determine whether the option is on or off, and
3734 * %GTK_STATE_FLAG_INCONSISTENT whether it should be marked as undefined.
3737 * <title>Typical option mark rendering</title>
3738 * <inlinegraphic fileref="options.png" format="PNG"/>
3744 gtk_render_option (GtkStyleContext *context,
3751 GtkStyleContextPrivate *priv;
3752 GtkThemingEngineClass *engine_class;
3754 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3755 g_return_if_fail (cr != NULL);
3757 if (width <= 0 || height <= 0)
3760 priv = context->priv;
3761 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3765 store_animation_region (context, x, y, width, height);
3767 _gtk_theming_engine_set_context (priv->theming_engine, context);
3768 engine_class->render_option (priv->theming_engine, cr,
3769 x, y, width, height);
3776 * @context: a #GtkStyleContext
3778 * @angle: arrow angle from 0 to 2 * %G_PI, being 0 the arrow pointing to the north
3779 * @x: Center X for the render area
3780 * @y: Center Y for the render area
3781 * @size: square side for render area
3783 * Renders an arrow pointing to @angle.
3786 * <title>Typical arrow rendering at 0, 1&solidus;2 π, π and 3&solidus;2 π</title>
3787 * <inlinegraphic fileref="arrows.png" format="PNG"/>
3793 gtk_render_arrow (GtkStyleContext *context,
3800 GtkStyleContextPrivate *priv;
3801 GtkThemingEngineClass *engine_class;
3803 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3804 g_return_if_fail (cr != NULL);
3809 priv = context->priv;
3810 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3814 store_animation_region (context, x, y, size, size);
3816 _gtk_theming_engine_set_context (priv->theming_engine, context);
3817 engine_class->render_arrow (priv->theming_engine, cr,
3824 * gtk_render_background:
3825 * @context: a #GtkStyleContext
3827 * @x: X origin of the rectangle
3828 * @y: Y origin of the rectangle
3829 * @width: rectangle width
3830 * @height: rectangle height
3832 * Renders the background of an element.
3835 * <title>Typical background rendering, showing the effect of
3836 * <parameter>background-image</parameter>,
3837 * <parameter>border-width</parameter> and
3838 * <parameter>border-radius</parameter></title>
3839 * <inlinegraphic fileref="background.png" format="PNG"/>
3845 gtk_render_background (GtkStyleContext *context,
3852 GtkStyleContextPrivate *priv;
3853 GtkThemingEngineClass *engine_class;
3855 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3856 g_return_if_fail (cr != NULL);
3858 if (width <= 0 || height <= 0)
3861 priv = context->priv;
3862 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3866 store_animation_region (context, x, y, width, height);
3868 _gtk_theming_engine_set_context (priv->theming_engine, context);
3869 engine_class->render_background (priv->theming_engine, cr, x, y, width, height);
3876 * @context: a #GtkStyleContext
3878 * @x: X origin of the rectangle
3879 * @y: Y origin of the rectangle
3880 * @width: rectangle width
3881 * @height: rectangle height
3883 * Renders a frame around the rectangle defined by @x, @y, @width, @height.
3886 * <title>Examples of frame rendering, showing the effect of
3887 * <parameter>border-image</parameter>,
3888 * <parameter>border-color</parameter>,
3889 * <parameter>border-width</parameter>,
3890 * <parameter>border-radius</parameter> and
3892 * <inlinegraphic fileref="frames.png" format="PNG"/>
3898 gtk_render_frame (GtkStyleContext *context,
3905 GtkStyleContextPrivate *priv;
3906 GtkThemingEngineClass *engine_class;
3908 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3909 g_return_if_fail (cr != NULL);
3911 if (width <= 0 || height <= 0)
3914 priv = context->priv;
3915 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3919 store_animation_region (context, x, y, width, height);
3921 _gtk_theming_engine_set_context (priv->theming_engine, context);
3922 engine_class->render_frame (priv->theming_engine, cr, x, y, width, height);
3928 * gtk_render_expander:
3929 * @context: a #GtkStyleContext
3931 * @x: X origin of the rectangle
3932 * @y: Y origin of the rectangle
3933 * @width: rectangle width
3934 * @height: rectangle height
3936 * Renders an expander (as used in #GtkTreeView and #GtkExpander) in the area
3937 * defined by @x, @y, @width, @height. The state %GTK_STATE_FLAG_ACTIVE
3938 * determines whether the expander is collapsed or expanded.
3941 * <title>Typical expander rendering</title>
3942 * <inlinegraphic fileref="expanders.png" format="PNG"/>
3948 gtk_render_expander (GtkStyleContext *context,
3955 GtkStyleContextPrivate *priv;
3956 GtkThemingEngineClass *engine_class;
3958 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3959 g_return_if_fail (cr != NULL);
3961 if (width <= 0 || height <= 0)
3964 priv = context->priv;
3965 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
3969 store_animation_region (context, x, y, width, height);
3971 _gtk_theming_engine_set_context (priv->theming_engine, context);
3972 engine_class->render_expander (priv->theming_engine, cr, x, y, width, height);
3979 * @context: a #GtkStyleContext
3981 * @x: X origin of the rectangle
3982 * @y: Y origin of the rectangle
3983 * @width: rectangle width
3984 * @height: rectangle height
3986 * Renders a focus indicator on the rectangle determined by @x, @y, @width, @height.
3988 * <title>Typical focus rendering</title>
3989 * <inlinegraphic fileref="focus.png" format="PNG"/>
3995 gtk_render_focus (GtkStyleContext *context,
4002 GtkStyleContextPrivate *priv;
4003 GtkThemingEngineClass *engine_class;
4005 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4006 g_return_if_fail (cr != NULL);
4008 if (width <= 0 || height <= 0)
4011 priv = context->priv;
4012 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4016 store_animation_region (context, x, y, width, height);
4018 _gtk_theming_engine_set_context (priv->theming_engine, context);
4019 engine_class->render_focus (priv->theming_engine, cr, x, y, width, height);
4025 * gtk_render_layout:
4026 * @context: a #GtkStyleContext
4030 * @layout: the #PangoLayout to render
4032 * Renders @layout on the coordinates @x, @y
4037 gtk_render_layout (GtkStyleContext *context,
4041 PangoLayout *layout)
4043 GtkStyleContextPrivate *priv;
4044 GtkThemingEngineClass *engine_class;
4045 PangoRectangle extents;
4047 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4048 g_return_if_fail (PANGO_IS_LAYOUT (layout));
4049 g_return_if_fail (cr != NULL);
4051 priv = context->priv;
4052 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4056 pango_layout_get_extents (layout, &extents, NULL);
4058 store_animation_region (context,
4064 _gtk_theming_engine_set_context (priv->theming_engine, context);
4065 engine_class->render_layout (priv->theming_engine, cr, x, y, layout);
4072 * @context: a #GtkStyleContext
4074 * @x0: X coordinate for the origin of the line
4075 * @y0: Y coordinate for the origin of the line
4076 * @x1: X coordinate for the end of the line
4077 * @y1: Y coordinate for the end of the line
4079 * Renders a line from (x0, y0) to (x1, y1).
4084 gtk_render_line (GtkStyleContext *context,
4091 GtkStyleContextPrivate *priv;
4092 GtkThemingEngineClass *engine_class;
4094 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4095 g_return_if_fail (cr != NULL);
4097 priv = context->priv;
4098 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4102 _gtk_theming_engine_set_context (priv->theming_engine, context);
4103 engine_class->render_line (priv->theming_engine, cr, x0, y0, x1, y1);
4109 * gtk_render_slider:
4110 * @context: a #GtkStyleContext
4112 * @x: X origin of the rectangle
4113 * @y: Y origin of the rectangle
4114 * @width: rectangle width
4115 * @height: rectangle height
4116 * @orientation: orientation of the slider
4118 * Renders a slider (as in #GtkScale) in the rectangle defined by @x, @y,
4119 * @width, @height. @orientation defines whether the slider is vertical
4123 * <title>Typical slider rendering</title>
4124 * <inlinegraphic fileref="sliders.png" format="PNG"/>
4130 gtk_render_slider (GtkStyleContext *context,
4136 GtkOrientation orientation)
4138 GtkStyleContextPrivate *priv;
4139 GtkThemingEngineClass *engine_class;
4141 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4142 g_return_if_fail (cr != NULL);
4144 if (width <= 0 || height <= 0)
4147 priv = context->priv;
4148 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4152 store_animation_region (context, x, y, width, height);
4154 _gtk_theming_engine_set_context (priv->theming_engine, context);
4155 engine_class->render_slider (priv->theming_engine, cr, x, y, width, height, orientation);
4161 * gtk_render_frame_gap:
4162 * @context: a #GtkStyleContext
4164 * @x: X origin of the rectangle
4165 * @y: Y origin of the rectangle
4166 * @width: rectangle width
4167 * @height: rectangle height
4168 * @gap_side: side where the gap is
4169 * @xy0_gap: initial coordinate (X or Y depending on @gap_side) for the gap
4170 * @xy1_gap: end coordinate (X or Y depending on @gap_side) for the gap
4172 * Renders a frame around the rectangle defined by (@x, @y, @width, @height),
4173 * leaving a gap on one side. @xy0_gap and @xy1_gap will mean X coordinates
4174 * for %GTK_POS_TOP and %GTK_POS_BOTTOM gap sides, and Y coordinates for
4175 * %GTK_POS_LEFT and %GTK_POS_RIGHT.
4178 * <title>Typical rendering of a frame with a gap</title>
4179 * <inlinegraphic fileref="frame-gap.png" format="PNG"/>
4185 gtk_render_frame_gap (GtkStyleContext *context,
4191 GtkPositionType gap_side,
4195 GtkStyleContextPrivate *priv;
4196 GtkThemingEngineClass *engine_class;
4198 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4199 g_return_if_fail (cr != NULL);
4200 g_return_if_fail (xy0_gap <= xy1_gap);
4201 g_return_if_fail (xy0_gap >= 0);
4203 if (width <= 0 || height <= 0)
4206 if (gap_side == GTK_POS_LEFT ||
4207 gap_side == GTK_POS_RIGHT)
4208 g_return_if_fail (xy1_gap <= height);
4210 g_return_if_fail (xy1_gap <= width);
4212 priv = context->priv;
4213 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4217 store_animation_region (context, x, y, width, height);
4219 _gtk_theming_engine_set_context (priv->theming_engine, context);
4220 engine_class->render_frame_gap (priv->theming_engine, cr,
4221 x, y, width, height, gap_side,
4228 * gtk_render_extension:
4229 * @context: a #GtkStyleContext
4231 * @x: X origin of the rectangle
4232 * @y: Y origin of the rectangle
4233 * @width: rectangle width
4234 * @height: rectangle height
4235 * @gap_side: side where the gap is
4237 * Renders a extension (as in a #GtkNotebook tab) in the rectangle
4238 * defined by @x, @y, @width, @height. The side where the extension
4239 * connects to is defined by @gap_side.
4242 * <title>Typical extension rendering</title>
4243 * <inlinegraphic fileref="extensions.png" format="PNG"/>
4249 gtk_render_extension (GtkStyleContext *context,
4255 GtkPositionType gap_side)
4257 GtkStyleContextPrivate *priv;
4258 GtkThemingEngineClass *engine_class;
4260 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4261 g_return_if_fail (cr != NULL);
4263 if (width <= 0 || height <= 0)
4266 priv = context->priv;
4267 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4271 store_animation_region (context, x, y, width, height);
4273 _gtk_theming_engine_set_context (priv->theming_engine, context);
4274 engine_class->render_extension (priv->theming_engine, cr, x, y, width, height, gap_side);
4280 * gtk_render_handle:
4281 * @context: a #GtkStyleContext
4283 * @x: X origin of the rectangle
4284 * @y: Y origin of the rectangle
4285 * @width: rectangle width
4286 * @height: rectangle height
4288 * Renders a handle (as in #GtkHandleBox, #GtkPaned and
4289 * #GtkWindow<!-- -->'s resize grip), in the rectangle
4290 * determined by @x, @y, @width, @height.
4293 * <title>Handles rendered for the paned and grip classes</title>
4294 * <inlinegraphic fileref="handles.png" format="PNG"/>
4300 gtk_render_handle (GtkStyleContext *context,
4307 GtkStyleContextPrivate *priv;
4308 GtkThemingEngineClass *engine_class;
4310 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4311 g_return_if_fail (cr != NULL);
4313 if (width <= 0 || height <= 0)
4316 priv = context->priv;
4317 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4321 store_animation_region (context, x, y, width, height);
4323 _gtk_theming_engine_set_context (priv->theming_engine, context);
4324 engine_class->render_handle (priv->theming_engine, cr, x, y, width, height);
4330 * gtk_render_activity:
4331 * @context: a #GtkStyleContext
4333 * @x: X origin of the rectangle
4334 * @y: Y origin of the rectangle
4335 * @width: rectangle width
4336 * @height: rectangle height
4338 * Renders an activity area (Such as in #GtkSpinner or the
4339 * fill line in #GtkRange), the state %GTK_STATE_FLAG_ACTIVE
4340 * determines whether there is activity going on.
4345 gtk_render_activity (GtkStyleContext *context,
4352 GtkStyleContextPrivate *priv;
4353 GtkThemingEngineClass *engine_class;
4355 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4356 g_return_if_fail (cr != NULL);
4358 if (width <= 0 || height <= 0)
4361 priv = context->priv;
4362 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4366 store_animation_region (context, x, y, width, height);
4368 _gtk_theming_engine_set_context (priv->theming_engine, context);
4369 engine_class->render_activity (priv->theming_engine, cr, x, y, width, height);
4375 * gtk_render_icon_pixbuf:
4376 * @context: a #GtkStyleContext
4377 * @source: the #GtkIconSource specifying the icon to render
4378 * @size: (type int): the size to render the icon at. A size of (GtkIconSize) -1
4379 * means render at the size of the source and don't scale.
4381 * Renders the icon specified by @source at the given @size, returning the result
4384 * Returns: (transfer full): a newly-created #GdkPixbuf containing the rendered icon
4389 gtk_render_icon_pixbuf (GtkStyleContext *context,
4390 const GtkIconSource *source,
4393 GtkStyleContextPrivate *priv;
4394 GtkThemingEngineClass *engine_class;
4396 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
4397 g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
4398 g_return_val_if_fail (source != NULL, NULL);
4400 priv = context->priv;
4401 engine_class = GTK_THEMING_ENGINE_GET_CLASS (priv->theming_engine);
4403 _gtk_theming_engine_set_context (priv->theming_engine, context);
4404 return engine_class->render_icon_pixbuf (priv->theming_engine, source, size);