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, see <http://www.gnu.org/licenses/>.
23 #include <gobject/gvaluecollector.h>
25 #include "gtkstylecontextprivate.h"
26 #include "gtkcontainerprivate.h"
27 #include "gtkcssenginevalueprivate.h"
28 #include "gtkcssrgbavalueprivate.h"
29 #include "gtkstylepropertiesprivate.h"
30 #include "gtktypebuiltins.h"
31 #include "gtkthemingengineprivate.h"
33 #include "gtkwidget.h"
34 #include "gtkwindow.h"
35 #include "gtkprivate.h"
36 #include "gtksymboliccolorprivate.h"
37 #include "gtkcssnumbervalueprivate.h"
38 #include "gtkiconfactory.h"
39 #include "gtkwidgetpath.h"
40 #include "gtkwidgetprivate.h"
41 #include "gtkstylecascadeprivate.h"
42 #include "gtkstyleproviderprivate.h"
43 #include "gtksettings.h"
46 * SECTION:gtkstylecontext
47 * @Short_description: Rendering UI elements
48 * @Title: GtkStyleContext
50 * #GtkStyleContext is an object that stores styling information affecting
51 * a widget defined by #GtkWidgetPath.
53 * In order to construct the final style information, #GtkStyleContext
54 * queries information from all attached #GtkStyleProviders. Style providers
55 * can be either attached explicitly to the context through
56 * gtk_style_context_add_provider(), or to the screen through
57 * gtk_style_context_add_provider_for_screen(). The resulting style is a
58 * combination of all providers' information in priority order.
60 * For GTK+ widgets, any #GtkStyleContext returned by
61 * gtk_widget_get_style_context() will already have a #GtkWidgetPath, a
62 * #GdkScreen and RTL/LTR information set. The style context will be also
63 * updated automatically if any of these settings change on the widget.
65 * If you are using the theming layer standalone, you will need to set a
66 * widget path and a screen yourself to the created style context through
67 * gtk_style_context_set_path() and gtk_style_context_set_screen(), as well
68 * as updating the context yourself using gtk_style_context_invalidate()
69 * whenever any of the conditions change, such as a change in the
70 * #GtkSettings:gtk-theme-name setting or a hierarchy change in the rendered
73 * <refsect2 id="gtkstylecontext-animations">
74 * <title>Transition animations</title>
76 * #GtkStyleContext has built-in support for state change transitions.
77 * Note that these animations respect the #GtkSettings:gtk-enable-animations
81 * For simple widgets where state changes affect the whole widget area,
82 * calling gtk_style_context_notify_state_change() with a %NULL region
83 * is sufficient to trigger the transition animation. And GTK+ already
84 * does that when gtk_widget_set_state() or gtk_widget_set_state_flags()
88 * If a widget needs to declare several animatable regions (i.e. not
89 * affecting the whole widget area), its #GtkWidget::draw signal handler
90 * needs to wrap the render operations for the different regions with
91 * calls to gtk_style_context_push_animatable_region() and
92 * gtk_style_context_pop_animatable_region(). These functions take an
93 * identifier for the region which must be unique within the style context.
94 * For simple widgets with a fixed set of animatable regions, using an
95 * enumeration works well:
98 * <title>Using an enumeration to identify animatable regions</title>
109 * spin_button_draw (GtkWidget *widget,
112 * GtkStyleContext *context;
114 * context = gtk_widget_get_style_context (widget);
116 * gtk_style_context_push_animatable_region (context,
117 * GUINT_TO_POINTER (REGION_ENTRY));
119 * gtk_render_background (cr, 0, 0, 100, 30);
120 * gtk_render_frame (cr, 0, 0, 100, 30);
122 * gtk_style_context_pop_animatable_region (context);
129 * For complex widgets with an arbitrary number of animatable regions, it
130 * is up to the implementation to come up with a way to uniquely identify
131 * each animatable region. Using pointers to internal structs is one way
135 * <title>Using struct pointers to identify animatable regions</title>
138 * notebook_draw_tab (GtkWidget *widget,
139 * NotebookPage *page,
142 * gtk_style_context_push_animatable_region (context, page);
143 * gtk_render_extension (cr, page->x, page->y, page->width, page->height);
144 * gtk_style_context_pop_animatable_region (context);
149 * The widget also needs to notify the style context about a state change
150 * for a given animatable region so the animation is triggered.
153 * <title>Triggering a state change animation on a region</title>
156 * notebook_motion_notify (GtkWidget *widget,
157 * GdkEventMotion *event)
159 * GtkStyleContext *context;
160 * NotebookPage *page;
162 * context = gtk_widget_get_style_context (widget);
163 * page = find_page_under_pointer (widget, event);
164 * gtk_style_context_notify_state_change (context,
165 * gtk_widget_get_window (widget),
167 * GTK_STATE_PRELIGHT,
174 * gtk_style_context_notify_state_change() accepts %NULL region IDs as a
175 * special value, in this case, the whole widget area will be updated
179 * <refsect2 id="gtkstylecontext-classes">
180 * <title>Style classes and regions</title>
182 * Widgets can add style classes to their context, which can be used
183 * to associate different styles by class (see <xref linkend="gtkcssprovider-selectors"/>). Theme engines can also use style classes to vary their
184 * rendering. GTK+ has a number of predefined style classes:
185 * #GTK_STYLE_CLASS_CELL,
186 * #GTK_STYLE_CLASS_ENTRY,
187 * #GTK_STYLE_CLASS_BUTTON,
188 * #GTK_STYLE_CLASS_COMBOBOX_ENTRY,
189 * #GTK_STYLE_CLASS_CALENDAR,
190 * #GTK_STYLE_CLASS_SLIDER,
191 * #GTK_STYLE_CLASS_BACKGROUND,
192 * #GTK_STYLE_CLASS_RUBBERBAND,
193 * #GTK_STYLE_CLASS_TOOLTIP,
194 * #GTK_STYLE_CLASS_MENU,
195 * #GTK_STYLE_CLASS_MENUBAR,
196 * #GTK_STYLE_CLASS_MENUITEM,
197 * #GTK_STYLE_CLASS_TOOLBAR,
198 * #GTK_STYLE_CLASS_PRIMARY_TOOLBAR,
199 * #GTK_STYLE_CLASS_INLINE_TOOLBAR,
200 * #GTK_STYLE_CLASS_RADIO,
201 * #GTK_STYLE_CLASS_CHECK,
202 * #GTK_STYLE_CLASS_TROUGH,
203 * #GTK_STYLE_CLASS_SCROLLBAR,
204 * #GTK_STYLE_CLASS_SCALE,
205 * #GTK_STYLE_CLASS_SCALE_HAS_MARKS_ABOVE,
206 * #GTK_STYLE_CLASS_SCALE_HAS_MARKS_BELOW,
207 * #GTK_STYLE_CLASS_HEADER,
208 * #GTK_STYLE_CLASS_ACCELERATOR,
209 * #GTK_STYLE_CLASS_GRIP,
210 * #GTK_STYLE_CLASS_DOCK,
211 * #GTK_STYLE_CLASS_PROGRESSBAR,
212 * #GTK_STYLE_CLASS_SPINNER,
213 * #GTK_STYLE_CLASS_EXPANDER,
214 * #GTK_STYLE_CLASS_SPINBUTTON,
215 * #GTK_STYLE_CLASS_NOTEBOOK,
216 * #GTK_STYLE_CLASS_VIEW,
217 * #GTK_STYLE_CLASS_SIDEBAR,
218 * #GTK_STYLE_CLASS_IMAGE,
219 * #GTK_STYLE_CLASS_HIGHLIGHT,
220 * #GTK_STYLE_CLASS_FRAME,
221 * #GTK_STYLE_CLASS_DND,
222 * #GTK_STYLE_CLASS_PANE_SEPARATOR,
223 * #GTK_STYLE_CLASS_SEPARATOR,
224 * #GTK_STYLE_CLASS_INFO,
225 * #GTK_STYLE_CLASS_WARNING,
226 * #GTK_STYLE_CLASS_QUESTION,
227 * #GTK_STYLE_CLASS_ERROR,
228 * #GTK_STYLE_CLASS_HORIZONTAL,
229 * #GTK_STYLE_CLASS_VERTICAL,
230 * #GTK_STYLE_CLASS_TOP,
231 * #GTK_STYLE_CLASS_BOTTOM,
232 * #GTK_STYLE_CLASS_LEFT,
233 * #GTK_STYLE_CLASS_RIGHT,
236 * Widgets can also add regions with flags to their context.
237 * The regions used by GTK+ widgets are:
242 * <entry>Region</entry>
243 * <entry>Flags</entry>
244 * <entry>Macro</entry>
245 * <entry>Used by</entry>
251 * <entry>even, odd</entry>
252 * <entry>GTK_STYLE_REGION_ROW</entry>
253 * <entry>#GtkTreeView</entry>
256 * <entry>column</entry>
257 * <entry>first, last, sorted</entry>
258 * <entry>GTK_STYLE_REGION_COLUMN</entry>
259 * <entry>#GtkTreeView</entry>
262 * <entry>column-header</entry>
264 * <entry>GTK_STYLE_REGION_COLUMN_HEADER</entry>
269 * <entry>even, odd, first, last</entry>
270 * <entry>GTK_STYLE_REGION_TAB</entry>
271 * <entry>#GtkNotebook</entry>
278 * <refsect2 id="gtkstylecontext-custom-styling">
279 * <title>Custom styling in UI libraries and applications</title>
281 * If you are developing a library with custom #GtkWidget<!-- -->s that
282 * render differently than standard components, you may need to add a
283 * #GtkStyleProvider yourself with the %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK
284 * priority, either a #GtkCssProvider or a custom object implementing the
285 * #GtkStyleProvider interface. This way theming engines may still attempt
286 * to style your UI elements in a different way if needed so.
289 * If you are using custom styling on an applications, you probably want then
290 * to make your style information prevail to the theme's, so you must use
291 * a #GtkStyleProvider with the %GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
292 * priority, keep in mind that the user settings in
293 * <filename><replaceable>XDG_CONFIG_HOME</replaceable>/gtk-3.0/gtk.css</filename> will
294 * still take precedence over your changes, as it uses the
295 * %GTK_STYLE_PROVIDER_PRIORITY_USER priority.
298 * If a custom theming engine is needed, you probably want to implement a
299 * #GtkStyleProvider yourself so it points to your #GtkThemingEngine
300 * implementation, as #GtkCssProvider uses gtk_theming_engine_load()
301 * which loads the theming engine module from the standard paths.
306 /* When these change we do a full restyling. Otherwise we try to figure out
307 * if we need to change things. */
308 #define GTK_STYLE_CONTEXT_RADICAL_CHANGE (GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_SOURCE)
309 /* When these change we don't clear the cache. This takes more memory but makes
310 * things go faster. */
311 #define GTK_STYLE_CONTEXT_CACHED_CHANGE (GTK_CSS_CHANGE_STATE)
313 typedef struct GtkStyleInfo GtkStyleInfo;
314 typedef struct GtkRegion GtkRegion;
315 typedef struct PropertyValue PropertyValue;
316 typedef struct StyleData StyleData;
321 GtkRegionFlags flags;
334 GArray *style_classes;
336 GtkJunctionSides junction_sides;
337 GtkStateFlags state_flags;
343 GtkCssComputedValues *store;
344 GArray *property_cache;
348 struct _GtkStyleContextPrivate
352 GtkStyleCascade *cascade;
354 GtkStyleContext *animation_list_prev;
355 GtkStyleContext *animation_list_next;
357 GtkStyleContext *parent;
360 GtkWidgetPath *widget_path;
361 GHashTable *style_data;
364 GtkTextDirection direction;
366 GtkCssChange relevant_changes;
367 GtkCssChange pending_changes;
369 guint invalidating_context : 1;
385 static guint signals[LAST_SIGNAL] = { 0 };
386 static GtkStyleContext *_running_animations = NULL;
387 guint _running_animations_timer_id = 0;
389 static void gtk_style_context_finalize (GObject *object);
391 static void gtk_style_context_impl_set_property (GObject *object,
395 static void gtk_style_context_impl_get_property (GObject *object,
399 static GtkSymbolicColor *
400 gtk_style_context_color_lookup_func (gpointer contextp,
404 G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
407 gtk_style_context_real_changed (GtkStyleContext *context)
409 GtkStyleContextPrivate *priv = context->priv;
412 _gtk_widget_style_context_invalidated (priv->widget);
416 gtk_style_context_class_init (GtkStyleContextClass *klass)
418 GObjectClass *object_class = G_OBJECT_CLASS (klass);
420 object_class->finalize = gtk_style_context_finalize;
421 object_class->set_property = gtk_style_context_impl_set_property;
422 object_class->get_property = gtk_style_context_impl_get_property;
424 klass->changed = gtk_style_context_real_changed;
427 g_signal_new (I_("changed"),
428 G_TYPE_FROM_CLASS (object_class),
430 G_STRUCT_OFFSET (GtkStyleContextClass, changed),
432 g_cclosure_marshal_VOID__VOID,
435 g_object_class_install_property (object_class,
437 g_param_spec_object ("screen",
439 P_("The associated GdkScreen"),
441 GTK_PARAM_READWRITE));
442 g_object_class_install_property (object_class,
444 g_param_spec_enum ("direction",
446 P_("Text direction"),
447 GTK_TYPE_TEXT_DIRECTION,
449 GTK_PARAM_READWRITE));
451 * GtkStyleContext:parent:
453 * Sets or gets the style context's parent. See gtk_style_context_set_parent()
458 g_object_class_install_property (object_class,
460 g_param_spec_object ("parent",
462 P_("The parent style context"),
463 GTK_TYPE_STYLE_CONTEXT,
464 GTK_PARAM_READWRITE));
466 g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
470 style_data_new (void)
474 data = g_slice_new0 (StyleData);
481 clear_property_cache (StyleData *data)
485 if (!data->property_cache)
488 for (i = 0; i < data->property_cache->len; i++)
490 PropertyValue *node = &g_array_index (data->property_cache, PropertyValue, i);
492 g_param_spec_unref (node->pspec);
493 g_value_unset (&node->value);
496 g_array_free (data->property_cache, TRUE);
497 data->property_cache = NULL;
501 style_data_ref (StyleData *style_data)
503 style_data->ref_count++;
509 style_data_unref (StyleData *data)
513 if (data->ref_count > 0)
516 g_object_unref (data->store);
517 clear_property_cache (data);
519 g_slice_free (StyleData, data);
522 static GtkStyleInfo *
523 style_info_new (void)
527 info = g_slice_new0 (GtkStyleInfo);
528 info->style_classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
529 info->regions = g_array_new (FALSE, FALSE, sizeof (GtkRegion));
535 style_info_free (GtkStyleInfo *info)
538 style_data_unref (info->data);
539 g_array_free (info->style_classes, TRUE);
540 g_array_free (info->regions, TRUE);
541 g_slice_free (GtkStyleInfo, info);
544 static GtkStyleInfo *
545 style_info_copy (const GtkStyleInfo *info)
549 copy = style_info_new ();
550 g_array_insert_vals (copy->style_classes, 0,
551 info->style_classes->data,
552 info->style_classes->len);
554 g_array_insert_vals (copy->regions, 0,
558 copy->junction_sides = info->junction_sides;
559 copy->state_flags = info->state_flags;
561 copy->data = style_data_ref (info->data);
567 style_info_hash (gconstpointer elem)
569 const GtkStyleInfo *info;
574 for (i = 0; i < info->style_classes->len; i++)
576 hash += g_array_index (info->style_classes, GQuark, i);
580 for (i = 0; i < info->regions->len; i++)
584 region = &g_array_index (info->regions, GtkRegion, i);
585 hash += region->class_quark;
586 hash += region->flags;
590 return hash ^ info->state_flags;
594 style_info_equal (gconstpointer elem1,
597 const GtkStyleInfo *info1, *info2;
602 if (info1->state_flags != info2->state_flags)
605 if (info1->junction_sides != info2->junction_sides)
608 if (info1->style_classes->len != info2->style_classes->len)
611 if (memcmp (info1->style_classes->data,
612 info2->style_classes->data,
613 info1->style_classes->len * sizeof (GQuark)) != 0)
616 if (info1->regions->len != info2->regions->len)
619 if (memcmp (info1->regions->data,
620 info2->regions->data,
621 info1->regions->len * sizeof (GtkRegion)) != 0)
628 gtk_style_context_cascade_changed (GtkStyleCascade *cascade,
629 GtkStyleContext *context)
631 GtkStyleContextPrivate *priv = context->priv;
634 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_SOURCE);
636 gtk_style_context_invalidate (context);
640 gtk_style_context_set_cascade (GtkStyleContext *context,
641 GtkStyleCascade *cascade)
643 GtkStyleContextPrivate *priv;
645 priv = context->priv;
647 if (priv->cascade == cascade)
652 g_object_ref (cascade);
653 g_signal_connect (cascade,
654 "-gtk-private-changed",
655 G_CALLBACK (gtk_style_context_cascade_changed),
661 g_signal_handlers_disconnect_by_func (priv->cascade,
662 gtk_style_context_cascade_changed,
664 g_object_unref (priv->cascade);
667 priv->cascade = cascade;
670 gtk_style_context_cascade_changed (cascade, context);
674 gtk_style_context_init (GtkStyleContext *style_context)
676 GtkStyleContextPrivate *priv;
679 priv = style_context->priv = G_TYPE_INSTANCE_GET_PRIVATE (style_context,
680 GTK_TYPE_STYLE_CONTEXT,
681 GtkStyleContextPrivate);
683 priv->style_data = g_hash_table_new_full (style_info_hash,
685 (GDestroyNotify) style_info_free,
686 (GDestroyNotify) style_data_unref);
688 priv->direction = GTK_TEXT_DIR_LTR;
690 priv->screen = gdk_screen_get_default ();
691 priv->relevant_changes = GTK_CSS_CHANGE_ANY;
693 /* Create default info store */
694 info = style_info_new ();
695 priv->info_stack = g_slist_prepend (priv->info_stack, info);
697 gtk_style_context_set_cascade (style_context,
698 _gtk_style_cascade_get_for_screen (priv->screen));
702 gtk_style_context_do_animations (gpointer unused)
704 GtkStyleContext *context;
706 for (context = _running_animations;
708 context = context->priv->animation_list_next)
710 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANIMATE);
717 gtk_style_context_is_animating (GtkStyleContext *context)
719 GtkStyleContextPrivate *priv = context->priv;
721 return priv->animation_list_prev != NULL
722 || _running_animations == context;
726 gtk_style_context_stop_animating (GtkStyleContext *context)
728 GtkStyleContextPrivate *priv = context->priv;
730 if (!gtk_style_context_is_animating (context))
733 if (priv->animation_list_prev == NULL)
735 _running_animations = priv->animation_list_next;
737 if (_running_animations == NULL)
739 /* we were the last animation */
740 g_source_remove (_running_animations_timer_id);
741 _running_animations_timer_id = 0;
745 priv->animation_list_prev->priv->animation_list_next = priv->animation_list_next;
747 if (priv->animation_list_next)
748 priv->animation_list_next->priv->animation_list_prev = priv->animation_list_prev;
750 priv->animation_list_next = NULL;
751 priv->animation_list_prev = NULL;
754 static void G_GNUC_UNUSED
755 gtk_style_context_start_animating (GtkStyleContext *context)
757 GtkStyleContextPrivate *priv = context->priv;
759 if (gtk_style_context_is_animating (context))
762 if (_running_animations == NULL)
764 _running_animations_timer_id = gdk_threads_add_timeout (25,
765 gtk_style_context_do_animations,
767 _running_animations = context;
771 priv->animation_list_next = _running_animations;
772 _running_animations->priv->animation_list_prev = context;
773 _running_animations = context;
778 gtk_style_context_finalize (GObject *object)
780 GtkStyleContextPrivate *priv;
781 GtkStyleContext *style_context;
783 style_context = GTK_STYLE_CONTEXT (object);
784 priv = style_context->priv;
786 _gtk_style_context_stop_animations (style_context);
788 /* children hold a reference to us */
789 g_assert (priv->children == NULL);
791 gtk_style_context_set_parent (style_context, NULL);
793 gtk_style_context_set_cascade (style_context, NULL);
795 if (priv->widget_path)
796 gtk_widget_path_free (priv->widget_path);
798 g_hash_table_destroy (priv->style_data);
800 g_slist_free_full (priv->info_stack, (GDestroyNotify) style_info_free);
802 G_OBJECT_CLASS (gtk_style_context_parent_class)->finalize (object);
806 gtk_style_context_impl_set_property (GObject *object,
811 GtkStyleContext *style_context;
813 style_context = GTK_STYLE_CONTEXT (object);
818 gtk_style_context_set_screen (style_context,
819 g_value_get_object (value));
822 gtk_style_context_set_direction (style_context,
823 g_value_get_enum (value));
826 gtk_style_context_set_parent (style_context,
827 g_value_get_object (value));
830 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
836 gtk_style_context_impl_get_property (GObject *object,
841 GtkStyleContext *style_context;
842 GtkStyleContextPrivate *priv;
844 style_context = GTK_STYLE_CONTEXT (object);
845 priv = style_context->priv;
850 g_value_set_object (value, priv->screen);
853 g_value_set_enum (value, priv->direction);
856 g_value_set_object (value, priv->parent);
859 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
865 build_properties (GtkStyleContext *context,
866 StyleData *style_data,
870 GtkStyleContextPrivate *priv;
871 GtkCssMatcher matcher;
872 GtkCssLookup *lookup;
874 priv = context->priv;
876 _gtk_css_matcher_init (&matcher, path, state);
877 lookup = _gtk_css_lookup_new ();
879 _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
883 style_data->store = _gtk_css_computed_values_new ();
884 _gtk_css_lookup_resolve (lookup, context, style_data->store);
885 _gtk_css_lookup_free (lookup);
888 static GtkWidgetPath *
889 create_query_path (GtkStyleContext *context)
891 GtkStyleContextPrivate *priv;
896 priv = context->priv;
897 path = priv->widget ? _gtk_widget_create_path (priv->widget) : gtk_widget_path_copy (priv->widget_path);
898 pos = gtk_widget_path_length (path) - 1;
900 info = priv->info_stack->data;
902 /* Set widget regions */
903 for (i = 0; i < info->regions->len; i++)
907 region = &g_array_index (info->regions, GtkRegion, i);
908 gtk_widget_path_iter_add_region (path, pos,
909 g_quark_to_string (region->class_quark),
913 /* Set widget classes */
914 for (i = 0; i < info->style_classes->len; i++)
918 quark = g_array_index (info->style_classes, GQuark, i);
919 gtk_widget_path_iter_add_class (path, pos,
920 g_quark_to_string (quark));
927 style_data_lookup (GtkStyleContext *context)
929 GtkStyleContextPrivate *priv;
932 priv = context->priv;
933 info = priv->info_stack->data;
935 /* Current data in use is cached, just return it */
939 g_assert (priv->widget != NULL || priv->widget_path != NULL);
941 info->data = g_hash_table_lookup (priv->style_data, info);
945 style_data_ref (info->data);
951 path = create_query_path (context);
953 info->data = style_data_new ();
954 g_hash_table_insert (priv->style_data,
955 style_info_copy (info),
956 style_data_ref (info->data));
958 build_properties (context, info->data, path, info->state_flags);
960 gtk_widget_path_free (path);
967 gtk_style_context_set_invalid (GtkStyleContext *context,
970 GtkStyleContextPrivate *priv;
972 priv = context->priv;
974 if (priv->invalid == invalid)
977 priv->invalid = invalid;
982 gtk_style_context_set_invalid (priv->parent, TRUE);
983 else if (GTK_IS_RESIZE_CONTAINER (priv->widget))
984 _gtk_container_queue_resize_handler (GTK_CONTAINER (priv->widget));
988 /* returns TRUE if someone called gtk_style_context_save() but hasn't
989 * called gtk_style_context_restore() yet.
990 * In those situations we don't invalidate the context when somebody
991 * changes state/regions/classes.
994 gtk_style_context_is_saved (GtkStyleContext *context)
996 return context->priv->info_stack->next != NULL;
1000 gtk_style_context_queue_invalidate_internal (GtkStyleContext *context,
1001 GtkCssChange change)
1003 GtkStyleContextPrivate *priv = context->priv;
1004 GtkStyleInfo *info = priv->info_stack->data;
1006 if (gtk_style_context_is_saved (context))
1010 style_data_unref (info->data);
1016 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_STATE);
1017 /* XXX: We need to invalidate siblings here somehow */
1022 * gtk_style_context_new:
1024 * Creates a standalone #GtkStyleContext, this style context
1025 * won't be attached to any widget, so you may want
1026 * to call gtk_style_context_set_path() yourself.
1029 * This function is only useful when using the theming layer
1030 * separated from GTK+, if you are using #GtkStyleContext to
1031 * theme #GtkWidget<!-- -->s, use gtk_widget_get_style_context()
1032 * in order to get a style context ready to theme the widget.
1035 * Returns: A newly created #GtkStyleContext.
1038 gtk_style_context_new (void)
1040 return g_object_new (GTK_TYPE_STYLE_CONTEXT, NULL);
1044 _gtk_style_context_set_widget (GtkStyleContext *context,
1047 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1048 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
1050 context->priv->widget = widget;
1052 _gtk_style_context_stop_animations (context);
1054 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_SELF);
1058 * gtk_style_context_add_provider:
1059 * @context: a #GtkStyleContext
1060 * @provider: a #GtkStyleProvider
1061 * @priority: the priority of the style provider. The lower
1062 * it is, the earlier it will be used in the style
1063 * construction. Typically this will be in the range
1064 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1065 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1067 * Adds a style provider to @context, to be used in style construction.
1069 * <note><para>If both priorities are the same, A #GtkStyleProvider
1070 * added through this function takes precedence over another added
1071 * through gtk_style_context_add_provider_for_screen().</para></note>
1076 gtk_style_context_add_provider (GtkStyleContext *context,
1077 GtkStyleProvider *provider,
1080 GtkStyleContextPrivate *priv;
1082 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1083 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1085 priv = context->priv;
1087 if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
1089 GtkStyleCascade *new_cascade;
1091 new_cascade = _gtk_style_cascade_new ();
1092 _gtk_style_cascade_set_parent (new_cascade, priv->cascade);
1093 _gtk_style_cascade_add_provider (new_cascade, provider, priority);
1094 gtk_style_context_set_cascade (context, new_cascade);
1095 g_object_unref (new_cascade);
1099 _gtk_style_cascade_add_provider (priv->cascade, provider, priority);
1104 * gtk_style_context_remove_provider:
1105 * @context: a #GtkStyleContext
1106 * @provider: a #GtkStyleProvider
1108 * Removes @provider from the style providers list in @context.
1113 gtk_style_context_remove_provider (GtkStyleContext *context,
1114 GtkStyleProvider *provider)
1116 GtkStyleContextPrivate *priv;
1118 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1119 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1121 priv = context->priv;
1123 if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
1126 _gtk_style_cascade_remove_provider (priv->cascade, provider);
1130 * gtk_style_context_reset_widgets:
1131 * @screen: a #GdkScreen
1133 * This function recomputes the styles for all widgets under a particular
1134 * #GdkScreen. This is useful when some global parameter has changed that
1135 * affects the appearance of all widgets, because when a widget gets a new
1136 * style, it will both redraw and recompute any cached information about
1137 * its appearance. As an example, it is used when the color scheme changes
1138 * in the related #GtkSettings object.
1143 gtk_style_context_reset_widgets (GdkScreen *screen)
1145 GList *list, *toplevels;
1147 _gtk_icon_set_invalidate_caches ();
1149 toplevels = gtk_window_list_toplevels ();
1150 g_list_foreach (toplevels, (GFunc) g_object_ref, NULL);
1152 for (list = toplevels; list; list = list->next)
1154 if (gtk_widget_get_screen (list->data) == screen)
1155 gtk_widget_reset_style (list->data);
1157 g_object_unref (list->data);
1160 g_list_free (toplevels);
1164 * gtk_style_context_add_provider_for_screen:
1165 * @screen: a #GdkScreen
1166 * @provider: a #GtkStyleProvider
1167 * @priority: the priority of the style provider. The lower
1168 * it is, the earlier it will be used in the style
1169 * construction. Typically this will be in the range
1170 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1171 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1173 * Adds a global style provider to @screen, which will be used
1174 * in style construction for all #GtkStyleContext<!-- -->s under
1177 * GTK+ uses this to make styling information from #GtkSettings
1180 * <note><para>If both priorities are the same, A #GtkStyleProvider
1181 * added through gtk_style_context_add_provider() takes precedence
1182 * over another added through this function.</para></note>
1187 gtk_style_context_add_provider_for_screen (GdkScreen *screen,
1188 GtkStyleProvider *provider,
1191 GtkStyleCascade *cascade;
1193 g_return_if_fail (GDK_IS_SCREEN (screen));
1194 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1196 cascade = _gtk_style_cascade_get_for_screen (screen);
1197 _gtk_style_cascade_add_provider (cascade, provider, priority);
1201 * gtk_style_context_remove_provider_for_screen:
1202 * @screen: a #GdkScreen
1203 * @provider: a #GtkStyleProvider
1205 * Removes @provider from the global style providers list in @screen.
1210 gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
1211 GtkStyleProvider *provider)
1213 GtkStyleCascade *cascade;
1215 g_return_if_fail (GDK_IS_SCREEN (screen));
1216 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1218 cascade = _gtk_style_cascade_get_for_screen (screen);
1219 _gtk_style_cascade_remove_provider (cascade, provider);
1223 * gtk_style_context_get_section:
1224 * @context: a #GtkStyleContext
1225 * @property: style property name
1227 * Queries the location in the CSS where @property was defined for the
1228 * current @context. Note that the state to be queried is taken from
1229 * gtk_style_context_get_state().
1231 * If the location is not available, %NULL will be returned. The
1232 * location might not be available for various reasons, such as the
1233 * property being overridden, @property not naming a supported CSS
1234 * property or tracking of definitions being disabled for performance
1237 * Shorthand CSS properties cannot be queried for a location and will
1238 * always return %NULL.
1240 * Returns: %NULL or the section where value was defined
1243 gtk_style_context_get_section (GtkStyleContext *context,
1244 const gchar *property)
1246 GtkStyleContextPrivate *priv;
1247 GtkStyleProperty *prop;
1250 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
1251 g_return_val_if_fail (property != NULL, NULL);
1253 priv = context->priv;
1254 g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
1256 prop = _gtk_style_property_lookup (property);
1257 if (!GTK_IS_CSS_STYLE_PROPERTY (prop))
1260 data = style_data_lookup (context);
1261 return _gtk_css_computed_values_get_section (data->store, _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (prop)));
1264 static GtkCssValue *
1265 gtk_style_context_query_func (guint id,
1268 return _gtk_css_computed_values_get_value (values, id);
1272 * gtk_style_context_get_property:
1273 * @context: a #GtkStyleContext
1274 * @property: style property name
1275 * @state: state to retrieve the property value for
1276 * @value: (out) (transfer full): return location for the style property value
1278 * Gets a style property from @context for the given state.
1280 * When @value is no longer needed, g_value_unset() must be called
1281 * to free any allocated memory.
1286 gtk_style_context_get_property (GtkStyleContext *context,
1287 const gchar *property,
1288 GtkStateFlags state,
1291 GtkStyleContextPrivate *priv;
1292 GtkStyleProperty *prop;
1295 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1296 g_return_if_fail (property != NULL);
1297 g_return_if_fail (value != NULL);
1299 priv = context->priv;
1300 g_return_if_fail (priv->widget != NULL || priv->widget_path != NULL);
1302 prop = _gtk_style_property_lookup (property);
1305 g_warning ("Style property \"%s\" is not registered", property);
1308 if (_gtk_style_property_get_value_type (prop) == G_TYPE_NONE)
1310 g_warning ("Style property \"%s\" is not gettable", property);
1314 gtk_style_context_save (context);
1315 gtk_style_context_set_state (context, state);
1316 data = style_data_lookup (context);
1317 _gtk_style_property_query (prop, value, gtk_style_context_query_func, data->store);
1318 gtk_style_context_restore (context);
1322 * gtk_style_context_get_valist:
1323 * @context: a #GtkStyleContext
1324 * @state: state to retrieve the property values for
1325 * @args: va_list of property name/return location pairs, followed by %NULL
1327 * Retrieves several style property values from @context for a given state.
1332 gtk_style_context_get_valist (GtkStyleContext *context,
1333 GtkStateFlags state,
1336 const gchar *property_name;
1338 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1340 property_name = va_arg (args, const gchar *);
1342 while (property_name)
1344 gchar *error = NULL;
1345 GValue value = G_VALUE_INIT;
1347 gtk_style_context_get_property (context,
1352 G_VALUE_LCOPY (&value, args, 0, &error);
1353 g_value_unset (&value);
1357 g_warning ("Could not get style property \"%s\": %s", property_name, error);
1362 property_name = va_arg (args, const gchar *);
1367 * gtk_style_context_get:
1368 * @context: a #GtkStyleContext
1369 * @state: state to retrieve the property values for
1370 * @...: property name /return value pairs, followed by %NULL
1372 * Retrieves several style property values from @context for a
1378 gtk_style_context_get (GtkStyleContext *context,
1379 GtkStateFlags state,
1384 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1386 va_start (args, state);
1387 gtk_style_context_get_valist (context, state, args);
1392 * gtk_style_context_set_state:
1393 * @context: a #GtkStyleContext
1394 * @flags: state to represent
1396 * Sets the state to be used when rendering with any
1397 * of the gtk_render_*() functions.
1402 gtk_style_context_set_state (GtkStyleContext *context,
1403 GtkStateFlags flags)
1405 GtkStyleContextPrivate *priv;
1408 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1410 priv = context->priv;
1411 info = priv->info_stack->data;
1412 info->state_flags = flags;
1414 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_STATE);
1418 * gtk_style_context_get_state:
1419 * @context: a #GtkStyleContext
1421 * Returns the state used when rendering.
1423 * Returns: the state flags
1428 gtk_style_context_get_state (GtkStyleContext *context)
1430 GtkStyleContextPrivate *priv;
1433 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
1435 priv = context->priv;
1436 info = priv->info_stack->data;
1438 return info->state_flags;
1442 * gtk_style_context_state_is_running:
1443 * @context: a #GtkStyleContext
1444 * @state: a widget state
1445 * @progress: (out): return location for the transition progress
1447 * Returns %TRUE if there is a transition animation running for the
1448 * current region (see gtk_style_context_push_animatable_region()).
1450 * If @progress is not %NULL, the animation progress will be returned
1451 * there, 0.0 means the state is closest to being unset, while 1.0 means
1452 * it's closest to being set. This means transition animation will
1453 * run from 0 to 1 when @state is being set and from 1 to 0 when
1456 * Returns: %TRUE if there is a running transition animation for @state.
1460 * Deprecated: 3.6: This function always returns %FALSE
1463 gtk_style_context_state_is_running (GtkStyleContext *context,
1467 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1473 * gtk_style_context_set_path:
1474 * @context: a #GtkStyleContext
1475 * @path: a #GtkWidgetPath
1477 * Sets the #GtkWidgetPath used for style matching. As a
1478 * consequence, the style will be regenerated to match
1479 * the new given path.
1481 * If you are using a #GtkStyleContext returned from
1482 * gtk_widget_get_style_context(), you do not need to call
1488 gtk_style_context_set_path (GtkStyleContext *context,
1489 GtkWidgetPath *path)
1491 GtkStyleContextPrivate *priv;
1493 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1494 g_return_if_fail (path != NULL);
1496 priv = context->priv;
1497 g_return_if_fail (priv->widget == NULL);
1499 if (priv->widget_path)
1501 gtk_widget_path_free (priv->widget_path);
1502 priv->widget_path = NULL;
1506 priv->widget_path = gtk_widget_path_copy (path);
1508 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY);
1512 * gtk_style_context_get_path:
1513 * @context: a #GtkStyleContext
1515 * Returns the widget path used for style matching.
1517 * Returns: (transfer none): A #GtkWidgetPath
1521 const GtkWidgetPath *
1522 gtk_style_context_get_path (GtkStyleContext *context)
1524 GtkStyleContextPrivate *priv;
1526 priv = context->priv;
1528 return gtk_widget_get_path (priv->widget);
1530 return priv->widget_path;
1534 * gtk_style_context_set_parent:
1535 * @context: a #GtkStyleContext
1536 * @parent: (allow-none): the new parent or %NULL
1538 * Sets the parent style context for @context. The parent style
1539 * context is used to implement
1540 * <ulink url="http://www.w3.org/TR/css3-cascade/#inheritance">inheritance</ulink>
1543 * If you are using a #GtkStyleContext returned from
1544 * gtk_widget_get_style_context(), the parent will be set for you.
1549 gtk_style_context_set_parent (GtkStyleContext *context,
1550 GtkStyleContext *parent)
1552 GtkStyleContextPrivate *priv;
1554 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1555 g_return_if_fail (parent == NULL || GTK_IS_STYLE_CONTEXT (parent));
1557 priv = context->priv;
1559 if (priv->parent == parent)
1564 parent->priv->children = g_slist_prepend (parent->priv->children, context);
1565 g_object_ref (parent);
1567 gtk_style_context_set_invalid (parent, TRUE);
1572 priv->parent->priv->children = g_slist_remove (priv->parent->priv->children, context);
1573 g_object_unref (priv->parent);
1576 priv->parent = parent;
1578 g_object_notify (G_OBJECT (context), "parent");
1579 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_PARENT | GTK_CSS_CHANGE_ANY_SIBLING);
1583 * gtk_style_context_get_parent:
1584 * @context: a #GtkStyleContext
1586 * Gets the parent context set via gtk_style_context_set_parent().
1587 * See that function for details.
1589 * Returns: (transfer none): the parent context or %NULL
1594 gtk_style_context_get_parent (GtkStyleContext *context)
1596 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
1598 return context->priv->parent;
1602 * gtk_style_context_save:
1603 * @context: a #GtkStyleContext
1605 * Saves the @context state, so all modifications done through
1606 * gtk_style_context_add_class(), gtk_style_context_remove_class(),
1607 * gtk_style_context_add_region(), gtk_style_context_remove_region()
1608 * or gtk_style_context_set_junction_sides() can be reverted in one
1609 * go through gtk_style_context_restore().
1614 gtk_style_context_save (GtkStyleContext *context)
1616 GtkStyleContextPrivate *priv;
1619 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1621 priv = context->priv;
1623 g_assert (priv->info_stack != NULL);
1625 info = style_info_copy (priv->info_stack->data);
1626 priv->info_stack = g_slist_prepend (priv->info_stack, info);
1630 * gtk_style_context_restore:
1631 * @context: a #GtkStyleContext
1633 * Restores @context state to a previous stage.
1634 * See gtk_style_context_save().
1639 gtk_style_context_restore (GtkStyleContext *context)
1641 GtkStyleContextPrivate *priv;
1644 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1646 priv = context->priv;
1648 if (priv->info_stack)
1650 info = priv->info_stack->data;
1651 priv->info_stack = g_slist_remove (priv->info_stack, info);
1652 style_info_free (info);
1655 if (!priv->info_stack)
1657 g_warning ("Unpaired gtk_style_context_restore() call");
1659 /* Create default region */
1660 info = style_info_new ();
1661 priv->info_stack = g_slist_prepend (priv->info_stack, info);
1666 style_class_find (GArray *array,
1671 gboolean found = FALSE;
1677 if (!array || array->len == 0)
1681 max = array->len - 1;
1687 mid = (min + max) / 2;
1688 item = g_array_index (array, GQuark, mid);
1690 if (class_quark == item)
1695 else if (class_quark > item)
1696 min = pos = mid + 1;
1703 while (!found && min <= max);
1712 region_find (GArray *array,
1717 gboolean found = FALSE;
1723 if (!array || array->len == 0)
1727 max = array->len - 1;
1733 mid = (min + max) / 2;
1734 region = &g_array_index (array, GtkRegion, mid);
1736 if (region->class_quark == class_quark)
1741 else if (region->class_quark > class_quark)
1742 min = pos = mid + 1;
1749 while (!found && min <= max);
1758 * gtk_style_context_add_class:
1759 * @context: a #GtkStyleContext
1760 * @class_name: class name to use in styling
1762 * Adds a style class to @context, so posterior calls to
1763 * gtk_style_context_get() or any of the gtk_render_*()
1764 * functions will make use of this new class for styling.
1766 * In the CSS file format, a #GtkEntry defining an "entry"
1767 * class, would be matched by:
1770 * GtkEntry.entry { ... }
1773 * While any widget defining an "entry" class would be
1782 gtk_style_context_add_class (GtkStyleContext *context,
1783 const gchar *class_name)
1785 GtkStyleContextPrivate *priv;
1790 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1791 g_return_if_fail (class_name != NULL);
1793 priv = context->priv;
1794 class_quark = g_quark_from_string (class_name);
1796 g_assert (priv->info_stack != NULL);
1797 info = priv->info_stack->data;
1799 if (!style_class_find (info->style_classes, class_quark, &position))
1801 g_array_insert_val (info->style_classes, position, class_quark);
1803 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
1808 * gtk_style_context_remove_class:
1809 * @context: a #GtkStyleContext
1810 * @class_name: class name to remove
1812 * Removes @class_name from @context.
1817 gtk_style_context_remove_class (GtkStyleContext *context,
1818 const gchar *class_name)
1820 GtkStyleContextPrivate *priv;
1825 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1826 g_return_if_fail (class_name != NULL);
1828 class_quark = g_quark_try_string (class_name);
1833 priv = context->priv;
1835 g_assert (priv->info_stack != NULL);
1836 info = priv->info_stack->data;
1838 if (style_class_find (info->style_classes, class_quark, &position))
1840 g_array_remove_index (info->style_classes, position);
1842 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
1847 * gtk_style_context_has_class:
1848 * @context: a #GtkStyleContext
1849 * @class_name: a class name
1851 * Returns %TRUE if @context currently has defined the
1854 * Returns: %TRUE if @context has @class_name defined
1859 gtk_style_context_has_class (GtkStyleContext *context,
1860 const gchar *class_name)
1862 GtkStyleContextPrivate *priv;
1866 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1867 g_return_val_if_fail (class_name != NULL, FALSE);
1869 class_quark = g_quark_try_string (class_name);
1874 priv = context->priv;
1876 g_assert (priv->info_stack != NULL);
1877 info = priv->info_stack->data;
1879 if (style_class_find (info->style_classes, class_quark, NULL))
1886 * gtk_style_context_list_classes:
1887 * @context: a #GtkStyleContext
1889 * Returns the list of classes currently defined in @context.
1891 * Returns: (transfer container) (element-type utf8): a #GList of
1892 * strings with the currently defined classes. The contents
1893 * of the list are owned by GTK+, but you must free the list
1894 * itself with g_list_free() when you are done with it.
1899 gtk_style_context_list_classes (GtkStyleContext *context)
1901 GtkStyleContextPrivate *priv;
1903 GList *classes = NULL;
1906 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
1908 priv = context->priv;
1910 g_assert (priv->info_stack != NULL);
1911 info = priv->info_stack->data;
1913 for (i = 0; i < info->style_classes->len; i++)
1917 quark = g_array_index (info->style_classes, GQuark, i);
1918 classes = g_list_prepend (classes, (gchar *) g_quark_to_string (quark));
1925 * gtk_style_context_list_regions:
1926 * @context: a #GtkStyleContext
1928 * Returns the list of regions currently defined in @context.
1930 * Returns: (transfer container) (element-type utf8): a #GList of
1931 * strings with the currently defined regions. The contents
1932 * of the list are owned by GTK+, but you must free the list
1933 * itself with g_list_free() when you are done with it.
1938 gtk_style_context_list_regions (GtkStyleContext *context)
1940 GtkStyleContextPrivate *priv;
1942 GList *classes = NULL;
1945 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
1947 priv = context->priv;
1949 g_assert (priv->info_stack != NULL);
1950 info = priv->info_stack->data;
1952 for (i = 0; i < info->regions->len; i++)
1955 const gchar *class_name;
1957 region = &g_array_index (info->regions, GtkRegion, i);
1959 class_name = g_quark_to_string (region->class_quark);
1960 classes = g_list_prepend (classes, (gchar *) class_name);
1967 _gtk_style_context_check_region_name (const gchar *str)
1969 g_return_val_if_fail (str != NULL, FALSE);
1971 if (!g_ascii_islower (str[0]))
1977 !g_ascii_islower (*str))
1987 * gtk_style_context_add_region:
1988 * @context: a #GtkStyleContext
1989 * @region_name: region name to use in styling
1990 * @flags: flags that apply to the region
1992 * Adds a region to @context, so posterior calls to
1993 * gtk_style_context_get() or any of the gtk_render_*()
1994 * functions will make use of this new region for styling.
1996 * In the CSS file format, a #GtkTreeView defining a "row"
1997 * region, would be matched by:
2000 * GtkTreeView row { ... }
2003 * Pseudo-classes are used for matching @flags, so the two
2006 * GtkTreeView row:nth-child(even) { ... }
2007 * GtkTreeView row:nth-child(odd) { ... }
2010 * would apply to even and odd rows, respectively.
2012 * <note><para>Region names must only contain lowercase letters
2013 * and '-', starting always with a lowercase letter.</para></note>
2018 gtk_style_context_add_region (GtkStyleContext *context,
2019 const gchar *region_name,
2020 GtkRegionFlags flags)
2022 GtkStyleContextPrivate *priv;
2024 GQuark region_quark;
2027 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2028 g_return_if_fail (region_name != NULL);
2029 g_return_if_fail (_gtk_style_context_check_region_name (region_name));
2031 priv = context->priv;
2032 region_quark = g_quark_from_string (region_name);
2034 g_assert (priv->info_stack != NULL);
2035 info = priv->info_stack->data;
2037 if (!region_find (info->regions, region_quark, &position))
2041 region.class_quark = region_quark;
2042 region.flags = flags;
2044 g_array_insert_val (info->regions, position, region);
2046 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
2051 * gtk_style_context_remove_region:
2052 * @context: a #GtkStyleContext
2053 * @region_name: region name to unset
2055 * Removes a region from @context.
2060 gtk_style_context_remove_region (GtkStyleContext *context,
2061 const gchar *region_name)
2063 GtkStyleContextPrivate *priv;
2065 GQuark region_quark;
2068 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2069 g_return_if_fail (region_name != NULL);
2071 region_quark = g_quark_try_string (region_name);
2076 priv = context->priv;
2078 g_assert (priv->info_stack != NULL);
2079 info = priv->info_stack->data;
2081 if (region_find (info->regions, region_quark, &position))
2083 g_array_remove_index (info->regions, position);
2085 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
2090 * gtk_style_context_has_region:
2091 * @context: a #GtkStyleContext
2092 * @region_name: a region name
2093 * @flags_return: (out) (allow-none): return location for region flags
2095 * Returns %TRUE if @context has the region defined.
2096 * If @flags_return is not %NULL, it is set to the flags
2097 * affecting the region.
2099 * Returns: %TRUE if region is defined
2104 gtk_style_context_has_region (GtkStyleContext *context,
2105 const gchar *region_name,
2106 GtkRegionFlags *flags_return)
2108 GtkStyleContextPrivate *priv;
2110 GQuark region_quark;
2113 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2114 g_return_val_if_fail (region_name != NULL, FALSE);
2119 region_quark = g_quark_try_string (region_name);
2124 priv = context->priv;
2126 g_assert (priv->info_stack != NULL);
2127 info = priv->info_stack->data;
2129 if (region_find (info->regions, region_quark, &position))
2135 region = &g_array_index (info->regions, GtkRegion, position);
2136 *flags_return = region->flags;
2145 style_property_values_cmp (gconstpointer bsearch_node1,
2146 gconstpointer bsearch_node2)
2148 const PropertyValue *val1 = bsearch_node1;
2149 const PropertyValue *val2 = bsearch_node2;
2151 if (val1->widget_type != val2->widget_type)
2152 return val1->widget_type < val2->widget_type ? -1 : 1;
2154 if (val1->pspec != val2->pspec)
2155 return val1->pspec < val2->pspec ? -1 : 1;
2157 if (val1->state != val2->state)
2158 return val1->state < val2->state ? -1 : 1;
2164 _gtk_style_context_peek_property (GtkStyleContext *context,
2167 StyleData *data = style_data_lookup (context);
2169 return _gtk_css_computed_values_get_value (data->store, property_id);
2173 _gtk_style_context_get_number (GtkStyleContext *context,
2175 double one_hundred_percent)
2179 value = _gtk_style_context_peek_property (context, property_id);
2180 return _gtk_css_number_value_get (value, one_hundred_percent);
2184 _gtk_style_context_peek_style_property (GtkStyleContext *context,
2186 GtkStateFlags state,
2189 GtkStyleContextPrivate *priv;
2190 PropertyValue *pcache, key = { 0 };
2194 priv = context->priv;
2196 gtk_style_context_save (context);
2197 gtk_style_context_set_state (context, state);
2198 data = style_data_lookup (context);
2199 gtk_style_context_restore (context);
2201 key.widget_type = widget_type;
2205 /* need value cache array */
2206 if (!data->property_cache)
2207 data->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
2210 pcache = bsearch (&key,
2211 data->property_cache->data, data->property_cache->len,
2212 sizeof (PropertyValue), style_property_values_cmp);
2214 return &pcache->value;
2218 while (i < data->property_cache->len &&
2219 style_property_values_cmp (&key, &g_array_index (data->property_cache, PropertyValue, i)) >= 0)
2222 g_array_insert_val (data->property_cache, i, key);
2223 pcache = &g_array_index (data->property_cache, PropertyValue, i);
2225 /* cache miss, initialize value type, then set contents */
2226 g_param_spec_ref (pcache->pspec);
2227 g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
2229 if (priv->widget || priv->widget_path)
2231 GtkWidgetPath *widget_path = priv->widget ? _gtk_widget_create_path (priv->widget) : priv->widget_path;
2233 if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
2235 state, pspec, &pcache->value))
2237 /* Resolve symbolic colors to GdkColor/GdkRGBA */
2238 if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
2240 GtkSymbolicColor *color;
2243 color = g_value_dup_boxed (&pcache->value);
2245 g_value_unset (&pcache->value);
2247 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2248 g_value_init (&pcache->value, GDK_TYPE_RGBA);
2250 g_value_init (&pcache->value, GDK_TYPE_COLOR);
2252 if (_gtk_style_context_resolve_color (context, color, &rgba))
2254 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2255 g_value_set_boxed (&pcache->value, &rgba);
2260 rgb.red = rgba.red * 65535. + 0.5;
2261 rgb.green = rgba.green * 65535. + 0.5;
2262 rgb.blue = rgba.blue * 65535. + 0.5;
2264 g_value_set_boxed (&pcache->value, &rgb);
2268 g_param_value_set_default (pspec, &pcache->value);
2270 gtk_symbolic_color_unref (color);
2274 gtk_widget_path_free (widget_path);
2276 return &pcache->value;
2280 gtk_widget_path_free (widget_path);
2283 /* not supplied by any provider, revert to default */
2284 g_param_value_set_default (pspec, &pcache->value);
2286 return &pcache->value;
2290 * gtk_style_context_get_style_property:
2291 * @context: a #GtkStyleContext
2292 * @property_name: the name of the widget style property
2293 * @value: Return location for the property value
2295 * Gets the value for a widget style property.
2297 * When @value is no longer needed, g_value_unset() must be called
2298 * to free any allocated memory.
2301 gtk_style_context_get_style_property (GtkStyleContext *context,
2302 const gchar *property_name,
2305 GtkStyleContextPrivate *priv;
2306 GtkWidgetClass *widget_class;
2307 GtkStateFlags state;
2309 const GValue *peek_value;
2312 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2313 g_return_if_fail (property_name != NULL);
2314 g_return_if_fail (value != NULL);
2316 priv = context->priv;
2320 widget_type = G_OBJECT_TYPE (priv->widget);
2324 if (!priv->widget_path)
2327 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2329 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2331 g_warning ("%s: can't get style properties for non-widget class `%s'",
2333 g_type_name (widget_type));
2338 widget_class = g_type_class_ref (widget_type);
2339 pspec = gtk_widget_class_find_style_property (widget_class, property_name);
2340 g_type_class_unref (widget_class);
2344 g_warning ("%s: widget class `%s' has no style property named `%s'",
2346 g_type_name (widget_type),
2351 state = gtk_style_context_get_state (context);
2352 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2355 if (G_VALUE_TYPE (value) == G_VALUE_TYPE (peek_value))
2356 g_value_copy (peek_value, value);
2357 else if (g_value_type_transformable (G_VALUE_TYPE (peek_value), G_VALUE_TYPE (value)))
2358 g_value_transform (peek_value, value);
2360 g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
2362 G_VALUE_TYPE_NAME (peek_value),
2363 G_VALUE_TYPE_NAME (value));
2367 * gtk_style_context_get_style_valist:
2368 * @context: a #GtkStyleContext
2369 * @args: va_list of property name/return location pairs, followed by %NULL
2371 * Retrieves several widget style properties from @context according to the
2377 gtk_style_context_get_style_valist (GtkStyleContext *context,
2380 GtkStyleContextPrivate *priv;
2381 const gchar *prop_name;
2382 GtkStateFlags state;
2385 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2387 prop_name = va_arg (args, const gchar *);
2388 priv = context->priv;
2392 widget_type = G_OBJECT_TYPE (priv->widget);
2396 if (!priv->widget_path)
2399 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2401 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2403 g_warning ("%s: can't get style properties for non-widget class `%s'",
2405 g_type_name (widget_type));
2410 state = gtk_style_context_get_state (context);
2414 GtkWidgetClass *widget_class;
2416 const GValue *peek_value;
2419 widget_class = g_type_class_ref (widget_type);
2420 pspec = gtk_widget_class_find_style_property (widget_class, prop_name);
2421 g_type_class_unref (widget_class);
2425 g_warning ("%s: widget class `%s' has no style property named `%s'",
2427 g_type_name (widget_type),
2432 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2435 G_VALUE_LCOPY (peek_value, args, 0, &error);
2439 g_warning ("can't retrieve style property `%s' of type `%s': %s",
2441 G_VALUE_TYPE_NAME (peek_value),
2447 prop_name = va_arg (args, const gchar *);
2452 * gtk_style_context_get_style:
2453 * @context: a #GtkStyleContext
2454 * @...: property name /return value pairs, followed by %NULL
2456 * Retrieves several widget style properties from @context according to the
2462 gtk_style_context_get_style (GtkStyleContext *context,
2467 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2469 va_start (args, context);
2470 gtk_style_context_get_style_valist (context, args);
2476 * gtk_style_context_lookup_icon_set:
2477 * @context: a #GtkStyleContext
2478 * @stock_id: an icon name
2480 * Looks up @stock_id in the icon factories associated to @context and
2481 * the default icon factory, returning an icon set if found, otherwise
2484 * Returns: (transfer none): The looked up %GtkIconSet, or %NULL
2487 gtk_style_context_lookup_icon_set (GtkStyleContext *context,
2488 const gchar *stock_id)
2490 GtkStyleContextPrivate *priv;
2492 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2493 g_return_val_if_fail (stock_id != NULL, NULL);
2495 priv = context->priv;
2496 g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
2498 return gtk_icon_factory_lookup_default (stock_id);
2502 * gtk_style_context_set_screen:
2503 * @context: a #GtkStyleContext
2504 * @screen: a #GdkScreen
2506 * Attaches @context to the given screen.
2508 * The screen is used to add style information from 'global' style
2509 * providers, such as the screens #GtkSettings instance.
2511 * If you are using a #GtkStyleContext returned from
2512 * gtk_widget_get_style_context(), you do not need to
2513 * call this yourself.
2518 gtk_style_context_set_screen (GtkStyleContext *context,
2521 GtkStyleContextPrivate *priv;
2523 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2524 g_return_if_fail (GDK_IS_SCREEN (screen));
2526 priv = context->priv;
2527 if (priv->screen == screen)
2530 if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
2532 gtk_style_context_set_cascade (context, _gtk_style_cascade_get_for_screen (screen));
2536 _gtk_style_cascade_set_parent (priv->cascade, _gtk_style_cascade_get_for_screen (screen));
2539 priv->screen = screen;
2541 g_object_notify (G_OBJECT (context), "screen");
2543 gtk_style_context_invalidate (context);
2547 * gtk_style_context_get_screen:
2548 * @context: a #GtkStyleContext
2550 * Returns the #GdkScreen to which @context is attached.
2552 * Returns: (transfer none): a #GdkScreen.
2555 gtk_style_context_get_screen (GtkStyleContext *context)
2557 GtkStyleContextPrivate *priv;
2559 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2561 priv = context->priv;
2562 return priv->screen;
2566 * gtk_style_context_set_direction:
2567 * @context: a #GtkStyleContext
2568 * @direction: the new direction.
2570 * Sets the reading direction for rendering purposes.
2572 * If you are using a #GtkStyleContext returned from
2573 * gtk_widget_get_style_context(), you do not need to
2574 * call this yourself.
2579 gtk_style_context_set_direction (GtkStyleContext *context,
2580 GtkTextDirection direction)
2582 GtkStyleContextPrivate *priv;
2584 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2586 priv = context->priv;
2587 priv->direction = direction;
2589 g_object_notify (G_OBJECT (context), "direction");
2593 * gtk_style_context_get_direction:
2594 * @context: a #GtkStyleContext
2596 * Returns the widget direction used for rendering.
2598 * Returns: the widget direction
2603 gtk_style_context_get_direction (GtkStyleContext *context)
2605 GtkStyleContextPrivate *priv;
2607 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), GTK_TEXT_DIR_LTR);
2609 priv = context->priv;
2610 return priv->direction;
2614 * gtk_style_context_set_junction_sides:
2615 * @context: a #GtkStyleContext
2616 * @sides: sides where rendered elements are visually connected to
2619 * Sets the sides where rendered elements (mostly through
2620 * gtk_render_frame()) will visually connect with other visual elements.
2622 * This is merely a hint that may or may not be honored
2623 * by theming engines.
2625 * Container widgets are expected to set junction hints as appropriate
2626 * for their children, so it should not normally be necessary to call
2627 * this function manually.
2632 gtk_style_context_set_junction_sides (GtkStyleContext *context,
2633 GtkJunctionSides sides)
2635 GtkStyleContextPrivate *priv;
2638 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2640 priv = context->priv;
2641 info = priv->info_stack->data;
2642 info->junction_sides = sides;
2646 * gtk_style_context_get_junction_sides:
2647 * @context: a #GtkStyleContext
2649 * Returns the sides where rendered elements connect visually with others.
2651 * Returns: the junction sides
2656 gtk_style_context_get_junction_sides (GtkStyleContext *context)
2658 GtkStyleContextPrivate *priv;
2661 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
2663 priv = context->priv;
2664 info = priv->info_stack->data;
2665 return info->junction_sides;
2668 static GtkSymbolicColor *
2669 gtk_style_context_color_lookup_func (gpointer contextp,
2672 GtkStyleContext *context = contextp;
2674 return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade), name);
2678 _gtk_style_context_resolve_color_value (GtkStyleContext *context,
2679 GtkCssValue *current,
2682 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2683 g_return_val_if_fail (current != NULL, FALSE);
2684 g_return_val_if_fail (color != NULL, FALSE);
2686 return _gtk_symbolic_color_resolve_full ((GtkSymbolicColor *) color,
2688 gtk_style_context_color_lookup_func,
2694 _gtk_style_context_resolve_color (GtkStyleContext *context,
2695 GtkSymbolicColor *color,
2700 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2701 g_return_val_if_fail (color != NULL, FALSE);
2702 g_return_val_if_fail (result != NULL, FALSE);
2704 val = _gtk_symbolic_color_resolve_full (color,
2705 _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR),
2706 gtk_style_context_color_lookup_func,
2711 *result = *_gtk_css_rgba_value_get_rgba (val);
2712 _gtk_css_value_unref (val);
2717 * gtk_style_context_lookup_color:
2718 * @context: a #GtkStyleContext
2719 * @color_name: color name to lookup
2720 * @color: (out): Return location for the looked up color
2722 * Looks up and resolves a color name in the @context color map.
2724 * Returns: %TRUE if @color_name was found and resolved, %FALSE otherwise
2727 gtk_style_context_lookup_color (GtkStyleContext *context,
2728 const gchar *color_name,
2731 GtkSymbolicColor *sym_color;
2733 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2734 g_return_val_if_fail (color_name != NULL, FALSE);
2735 g_return_val_if_fail (color != NULL, FALSE);
2737 sym_color = gtk_style_context_color_lookup_func (context, color_name);
2738 if (sym_color == NULL)
2741 return _gtk_style_context_resolve_color (context, sym_color, color);
2745 * gtk_style_context_notify_state_change:
2746 * @context: a #GtkStyleContext
2747 * @window: a #GdkWindow
2748 * @region_id: (allow-none): animatable region to notify on, or %NULL.
2749 * See gtk_style_context_push_animatable_region()
2750 * @state: state to trigger transition for
2751 * @state_value: %TRUE if @state is the state we are changing to,
2752 * %FALSE if we are changing away from it
2754 * Notifies a state change on @context, so if the current style makes use
2755 * of transition animations, one will be started so all rendered elements
2756 * under @region_id are animated for state @state being set to value
2759 * The @window parameter is used in order to invalidate the rendered area
2760 * as the animation runs, so make sure it is the same window that is being
2761 * rendered on by the gtk_render_*() functions.
2763 * If @region_id is %NULL, all rendered elements using @context will be
2764 * affected by this state transition.
2766 * As a practical example, a #GtkButton notifying a state transition on
2767 * the prelight state:
2769 * gtk_style_context_notify_state_change (context,
2770 * gtk_widget_get_window (widget),
2772 * GTK_STATE_PRELIGHT,
2773 * button->in_button);
2776 * Can be handled in the CSS file like this:
2779 * background-color: #f00
2783 * background-color: #fff;
2784 * transition: 200ms linear
2788 * This combination will animate the button background from red to white
2789 * if a pointer enters the button, and back to red if the pointer leaves
2792 * Note that @state is used when finding the transition parameters, which
2793 * is why the style places the transition under the :hover pseudo-class.
2797 * Deprecated: 3.6: This function does nothing.
2800 gtk_style_context_notify_state_change (GtkStyleContext *context,
2804 gboolean state_value)
2806 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2807 g_return_if_fail (GDK_IS_WINDOW (window));
2808 g_return_if_fail (state > GTK_STATE_NORMAL && state <= GTK_STATE_FOCUSED);
2809 g_return_if_fail (context->priv->widget != NULL || context->priv->widget_path != NULL);
2813 * gtk_style_context_cancel_animations:
2814 * @context: a #GtkStyleContext
2815 * @region_id: (allow-none): animatable region to stop, or %NULL.
2816 * See gtk_style_context_push_animatable_region()
2818 * Stops all running animations for @region_id and all animatable
2819 * regions underneath.
2821 * A %NULL @region_id will stop all ongoing animations in @context,
2822 * when dealing with a #GtkStyleContext obtained through
2823 * gtk_widget_get_style_context(), this is normally done for you
2824 * in all circumstances you would expect all widget to be stopped,
2825 * so this should be only used in complex widgets with different
2826 * animatable regions.
2830 * Deprecated: 3.6: This function does nothing.
2833 gtk_style_context_cancel_animations (GtkStyleContext *context,
2836 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2840 * gtk_style_context_scroll_animations:
2841 * @context: a #GtkStyleContext
2842 * @window: a #GdkWindow used previously in
2843 * gtk_style_context_notify_state_change()
2844 * @dx: Amount to scroll in the X axis
2845 * @dy: Amount to scroll in the Y axis
2847 * This function is analogous to gdk_window_scroll(), and
2848 * should be called together with it so the invalidation
2849 * areas for any ongoing animation are scrolled together
2854 * Deprecated: 3.6: This function does nothing.
2857 gtk_style_context_scroll_animations (GtkStyleContext *context,
2862 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2863 g_return_if_fail (GDK_IS_WINDOW (window));
2867 * gtk_style_context_push_animatable_region:
2868 * @context: a #GtkStyleContext
2869 * @region_id: unique identifier for the animatable region
2871 * Pushes an animatable region, so all further gtk_render_*() calls between
2872 * this call and the following gtk_style_context_pop_animatable_region()
2873 * will potentially show transition animations for this region if
2874 * gtk_style_context_notify_state_change() is called for a given state,
2875 * and the current theme/style defines transition animations for state
2878 * The @region_id used must be unique in @context so the theming engine
2879 * can uniquely identify rendered elements subject to a state transition.
2883 * Deprecated: 3.6: This function does nothing.
2886 gtk_style_context_push_animatable_region (GtkStyleContext *context,
2889 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2890 g_return_if_fail (region_id != NULL);
2894 * gtk_style_context_pop_animatable_region:
2895 * @context: a #GtkStyleContext
2897 * Pops an animatable region from @context.
2898 * See gtk_style_context_push_animatable_region().
2902 * Deprecated: 3.6: This function does nothing.
2905 gtk_style_context_pop_animatable_region (GtkStyleContext *context)
2907 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2911 gtk_style_context_clear_cache (GtkStyleContext *context)
2913 GtkStyleContextPrivate *priv;
2916 priv = context->priv;
2918 for (list = priv->info_stack; list; list = list->next)
2920 GtkStyleInfo *info = list->data;
2923 style_data_unref (info->data);
2927 g_hash_table_remove_all (priv->style_data);
2931 gtk_style_context_do_invalidate (GtkStyleContext *context)
2933 GtkStyleContextPrivate *priv;
2935 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2937 priv = context->priv;
2939 /* Avoid reentrancy */
2940 if (priv->invalidating_context)
2943 priv->invalidating_context = TRUE;
2945 g_signal_emit (context, signals[CHANGED], 0);
2947 priv->invalidating_context = FALSE;
2951 _gtk_style_context_stop_animations (GtkStyleContext *context)
2953 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2955 if (!gtk_style_context_is_animating (context))
2958 gtk_style_context_stop_animating (context);
2962 _gtk_style_context_validate (GtkStyleContext *context,
2964 GtkCssChange change)
2966 GtkStyleContextPrivate *priv;
2969 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2971 priv = context->priv;
2973 change |= priv->pending_changes;
2975 if (!priv->invalid && change == 0)
2978 priv->pending_changes = 0;
2979 gtk_style_context_set_invalid (context, FALSE);
2981 /* Try to avoid invalidating if we can */
2982 if (change & GTK_STYLE_CONTEXT_RADICAL_CHANGE)
2984 priv->relevant_changes = GTK_CSS_CHANGE_ANY;
2988 if (priv->relevant_changes == GTK_CSS_CHANGE_ANY)
2990 GtkWidgetPath *path;
2991 GtkCssMatcher matcher;
2993 path = create_query_path (context);
2994 _gtk_css_matcher_init (&matcher, path, ((GtkStyleInfo *) priv->info_stack->data)->state_flags);
2996 priv->relevant_changes = _gtk_style_provider_private_get_change (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
2998 priv->relevant_changes &= ~GTK_STYLE_CONTEXT_RADICAL_CHANGE;
3000 gtk_widget_path_unref (path);
3004 if (priv->relevant_changes & change)
3006 GtkStyleInfo *info = priv->info_stack->data;
3007 GtkCssComputedValues *old, *new;
3009 old = info->data ? g_object_ref (info->data->store) : NULL;
3011 if ((priv->relevant_changes & change) & ~GTK_STYLE_CONTEXT_CACHED_CHANGE)
3012 gtk_style_context_clear_cache (context);
3018 GtkBitmask *bitmask;
3020 new = style_data_lookup (context)->store;
3022 bitmask = _gtk_css_computed_values_get_difference (new, old);
3023 if (!_gtk_bitmask_is_empty (bitmask))
3024 gtk_style_context_do_invalidate (context);
3026 _gtk_bitmask_free (bitmask);
3027 g_object_unref (old);
3030 gtk_style_context_do_invalidate (context);
3034 change = _gtk_css_change_for_child (change);
3035 for (list = priv->children; list; list = list->next)
3037 _gtk_style_context_validate (list->data, timestamp, change);
3042 _gtk_style_context_queue_invalidate (GtkStyleContext *context,
3043 GtkCssChange change)
3045 GtkStyleContextPrivate *priv;
3047 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3048 g_return_if_fail (change != 0);
3050 priv = context->priv;
3052 if (priv->widget == NULL && priv->widget_path == NULL)
3055 priv->pending_changes |= change;
3056 gtk_style_context_set_invalid (context, TRUE);
3060 * gtk_style_context_invalidate:
3061 * @context: a #GtkStyleContext.
3063 * Invalidates @context style information, so it will be reconstructed
3066 * If you're using a #GtkStyleContext returned from
3067 * gtk_widget_get_style_context(), you do not need to
3068 * call this yourself.
3073 gtk_style_context_invalidate (GtkStyleContext *context)
3075 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3077 gtk_style_context_clear_cache (context);
3078 gtk_style_context_do_invalidate (context);
3082 * gtk_style_context_set_background:
3083 * @context: a #GtkStyleContext
3084 * @window: a #GdkWindow
3086 * Sets the background of @window to the background pattern or
3087 * color specified in @context for its current state.
3092 gtk_style_context_set_background (GtkStyleContext *context,
3095 GtkStateFlags state;
3096 cairo_pattern_t *pattern;
3099 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3100 g_return_if_fail (GDK_IS_WINDOW (window));
3102 state = gtk_style_context_get_state (context);
3103 gtk_style_context_get (context, state,
3104 "background-image", &pattern,
3108 gdk_window_set_background_pattern (window, pattern);
3109 cairo_pattern_destroy (pattern);
3113 gtk_style_context_get (context, state,
3114 "background-color", &color,
3118 gdk_window_set_background_rgba (window, color);
3119 gdk_rgba_free (color);
3124 * gtk_style_context_get_color:
3125 * @context: a #GtkStyleContext
3126 * @state: state to retrieve the color for
3127 * @color: (out): return value for the foreground color
3129 * Gets the foreground color for a given state.
3134 gtk_style_context_get_color (GtkStyleContext *context,
3135 GtkStateFlags state,
3140 g_return_if_fail (color != NULL);
3141 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3143 gtk_style_context_get (context,
3153 * gtk_style_context_get_background_color:
3154 * @context: a #GtkStyleContext
3155 * @state: state to retrieve the color for
3156 * @color: (out): return value for the background color
3158 * Gets the background color for a given state.
3163 gtk_style_context_get_background_color (GtkStyleContext *context,
3164 GtkStateFlags state,
3169 g_return_if_fail (color != NULL);
3170 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3172 gtk_style_context_get (context,
3174 "background-color", &c,
3182 * gtk_style_context_get_border_color:
3183 * @context: a #GtkStyleContext
3184 * @state: state to retrieve the color for
3185 * @color: (out): return value for the border color
3187 * Gets the border color for a given state.
3192 gtk_style_context_get_border_color (GtkStyleContext *context,
3193 GtkStateFlags state,
3198 g_return_if_fail (color != NULL);
3199 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3201 gtk_style_context_get (context,
3211 * gtk_style_context_get_border:
3212 * @context: a #GtkStyleContext
3213 * @state: state to retrieve the border for
3214 * @border: (out): return value for the border settings
3216 * Gets the border for a given state as a #GtkBorder.
3217 * See %GTK_STYLE_PROPERTY_BORDER_WIDTH.
3222 gtk_style_context_get_border (GtkStyleContext *context,
3223 GtkStateFlags state,
3226 int top, left, bottom, right;
3228 g_return_if_fail (border != NULL);
3229 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3231 gtk_style_context_get (context,
3233 "border-top-width", &top,
3234 "border-left-width", &left,
3235 "border-bottom-width", &bottom,
3236 "border-right-width", &right,
3240 border->left = left;
3241 border->bottom = bottom;
3242 border->right = right;
3246 * gtk_style_context_get_padding:
3247 * @context: a #GtkStyleContext
3248 * @state: state to retrieve the padding for
3249 * @padding: (out): return value for the padding settings
3251 * Gets the padding for a given state as a #GtkBorder.
3252 * See %GTK_STYLE_PROPERTY_PADDING.
3257 gtk_style_context_get_padding (GtkStyleContext *context,
3258 GtkStateFlags state,
3261 int top, left, bottom, right;
3263 g_return_if_fail (padding != NULL);
3264 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3266 gtk_style_context_get (context,
3268 "padding-top", &top,
3269 "padding-left", &left,
3270 "padding-bottom", &bottom,
3271 "padding-right", &right,
3275 padding->left = left;
3276 padding->bottom = bottom;
3277 padding->right = right;
3281 * gtk_style_context_get_margin:
3282 * @context: a #GtkStyleContext
3283 * @state: state to retrieve the border for
3284 * @margin: (out): return value for the margin settings
3286 * Gets the margin for a given state as a #GtkBorder.
3287 * See %GTK_STYLE_PROPERTY_MARGIN.
3292 gtk_style_context_get_margin (GtkStyleContext *context,
3293 GtkStateFlags state,
3296 int top, left, bottom, right;
3298 g_return_if_fail (margin != NULL);
3299 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3301 gtk_style_context_get (context,
3304 "margin-left", &left,
3305 "margin-bottom", &bottom,
3306 "margin-right", &right,
3310 margin->left = left;
3311 margin->bottom = bottom;
3312 margin->right = right;
3316 * gtk_style_context_get_font:
3317 * @context: a #GtkStyleContext
3318 * @state: state to retrieve the font for
3320 * Returns the font description for a given state. The returned
3321 * object is const and will remain valid until the
3322 * #GtkStyleContext::changed signal happens.
3324 * Returns: (transfer none): the #PangoFontDescription for the given
3325 * state. This object is owned by GTK+ and should not be
3330 const PangoFontDescription *
3331 gtk_style_context_get_font (GtkStyleContext *context,
3332 GtkStateFlags state)
3334 GtkStyleContextPrivate *priv;
3336 PangoFontDescription *description;
3338 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
3340 priv = context->priv;
3341 g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
3343 gtk_style_context_save (context);
3344 gtk_style_context_set_state (context, state);
3345 data = style_data_lookup (context);
3346 gtk_style_context_restore (context);
3348 /* Yuck, fonts are created on-demand but we don't return a ref.
3349 * Do bad things to achieve this requirement */
3350 description = g_object_get_data (G_OBJECT (data->store), "font-cache-for-get_font");
3351 if (description == NULL)
3353 gtk_style_context_get (context, state, "font", &description, NULL);
3354 g_object_set_data_full (G_OBJECT (data->store),
3355 "font-cache-for-get_font",
3357 (GDestroyNotify) pango_font_description_free);
3363 get_cursor_color (GtkStyleContext *context,
3367 GdkColor *style_color;
3369 gtk_style_context_get_style (context,
3370 primary ? "cursor-color" : "secondary-cursor-color",
3376 color->red = style_color->red / 65535.0;
3377 color->green = style_color->green / 65535.0;
3378 color->blue = style_color->blue / 65535.0;
3381 gdk_color_free (style_color);
3385 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, color);
3391 gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
3393 color->red = (color->red + bg.red) * 0.5;
3394 color->green = (color->green + bg.green) * 0.5;
3395 color->blue = (color->blue + bg.blue) * 0.5;
3401 _gtk_style_context_get_cursor_color (GtkStyleContext *context,
3402 GdkRGBA *primary_color,
3403 GdkRGBA *secondary_color)
3406 get_cursor_color (context, TRUE, primary_color);
3408 if (secondary_color)
3409 get_cursor_color (context, FALSE, secondary_color);
3416 * @context: a #GtkStyleContext
3418 * @x: X origin of the rectangle
3419 * @y: Y origin of the rectangle
3420 * @width: rectangle width
3421 * @height: rectangle height
3423 * Renders a checkmark (as in a #GtkCheckButton).
3425 * The %GTK_STATE_FLAG_ACTIVE state determines whether the check is
3426 * on or off, and %GTK_STATE_FLAG_INCONSISTENT determines whether it
3427 * should be marked as undefined.
3430 * <title>Typical checkmark rendering</title>
3431 * <inlinegraphic fileref="checks.png" format="PNG"/>
3437 gtk_render_check (GtkStyleContext *context,
3444 GtkThemingEngineClass *engine_class;
3445 GtkThemingEngine *engine;
3447 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3448 g_return_if_fail (cr != NULL);
3450 if (width <= 0 || height <= 0)
3453 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3454 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3459 _gtk_theming_engine_set_context (engine, context);
3460 engine_class->render_check (engine, cr,
3461 x, y, width, height);
3467 * gtk_render_option:
3468 * @context: a #GtkStyleContext
3470 * @x: X origin of the rectangle
3471 * @y: Y origin of the rectangle
3472 * @width: rectangle width
3473 * @height: rectangle height
3475 * Renders an option mark (as in a #GtkRadioButton), the %GTK_STATE_FLAG_ACTIVE
3476 * state will determine whether the option is on or off, and
3477 * %GTK_STATE_FLAG_INCONSISTENT whether it should be marked as undefined.
3480 * <title>Typical option mark rendering</title>
3481 * <inlinegraphic fileref="options.png" format="PNG"/>
3487 gtk_render_option (GtkStyleContext *context,
3494 GtkThemingEngineClass *engine_class;
3495 GtkThemingEngine *engine;
3497 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3498 g_return_if_fail (cr != NULL);
3500 if (width <= 0 || height <= 0)
3503 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3504 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3508 _gtk_theming_engine_set_context (engine, context);
3509 engine_class->render_option (engine, cr,
3510 x, y, width, height);
3517 * @context: a #GtkStyleContext
3519 * @angle: arrow angle from 0 to 2 * %G_PI, being 0 the arrow pointing to the north
3520 * @x: X origin of the render area
3521 * @y: Y origin of the render area
3522 * @size: square side for render area
3524 * Renders an arrow pointing to @angle.
3527 * <title>Typical arrow rendering at 0, 1&solidus;2 π, π and 3&solidus;2 π</title>
3528 * <inlinegraphic fileref="arrows.png" format="PNG"/>
3534 gtk_render_arrow (GtkStyleContext *context,
3541 GtkThemingEngineClass *engine_class;
3542 GtkThemingEngine *engine;
3544 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3545 g_return_if_fail (cr != NULL);
3550 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3551 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3555 gtk_style_context_save (context);
3556 gtk_style_context_add_class (context, GTK_STYLE_CLASS_ARROW);
3558 _gtk_theming_engine_set_context (engine, context);
3559 engine_class->render_arrow (engine, cr,
3562 gtk_style_context_restore (context);
3567 * gtk_render_background:
3568 * @context: a #GtkStyleContext
3570 * @x: X origin of the rectangle
3571 * @y: Y origin of the rectangle
3572 * @width: rectangle width
3573 * @height: rectangle height
3575 * Renders the background of an element.
3578 * <title>Typical background rendering, showing the effect of
3579 * <parameter>background-image</parameter>,
3580 * <parameter>border-width</parameter> and
3581 * <parameter>border-radius</parameter></title>
3582 * <inlinegraphic fileref="background.png" format="PNG"/>
3588 gtk_render_background (GtkStyleContext *context,
3595 GtkThemingEngineClass *engine_class;
3596 GtkThemingEngine *engine;
3598 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3599 g_return_if_fail (cr != NULL);
3601 if (width <= 0 || height <= 0)
3604 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3605 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3609 _gtk_theming_engine_set_context (engine, context);
3610 engine_class->render_background (engine, cr, x, y, width, height);
3617 * @context: a #GtkStyleContext
3619 * @x: X origin of the rectangle
3620 * @y: Y origin of the rectangle
3621 * @width: rectangle width
3622 * @height: rectangle height
3624 * Renders a frame around the rectangle defined by @x, @y, @width, @height.
3627 * <title>Examples of frame rendering, showing the effect of
3628 * <parameter>border-image</parameter>,
3629 * <parameter>border-color</parameter>,
3630 * <parameter>border-width</parameter>,
3631 * <parameter>border-radius</parameter> and
3633 * <inlinegraphic fileref="frames.png" format="PNG"/>
3639 gtk_render_frame (GtkStyleContext *context,
3646 GtkThemingEngineClass *engine_class;
3647 GtkThemingEngine *engine;
3649 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3650 g_return_if_fail (cr != NULL);
3652 if (width <= 0 || height <= 0)
3655 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3656 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3660 _gtk_theming_engine_set_context (engine, context);
3661 engine_class->render_frame (engine, cr, x, y, width, height);
3667 * gtk_render_expander:
3668 * @context: a #GtkStyleContext
3670 * @x: X origin of the rectangle
3671 * @y: Y origin of the rectangle
3672 * @width: rectangle width
3673 * @height: rectangle height
3675 * Renders an expander (as used in #GtkTreeView and #GtkExpander) in the area
3676 * defined by @x, @y, @width, @height. The state %GTK_STATE_FLAG_ACTIVE
3677 * determines whether the expander is collapsed or expanded.
3680 * <title>Typical expander rendering</title>
3681 * <inlinegraphic fileref="expanders.png" format="PNG"/>
3687 gtk_render_expander (GtkStyleContext *context,
3694 GtkThemingEngineClass *engine_class;
3695 GtkThemingEngine *engine;
3697 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3698 g_return_if_fail (cr != NULL);
3700 if (width <= 0 || height <= 0)
3703 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3704 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3708 _gtk_theming_engine_set_context (engine, context);
3709 engine_class->render_expander (engine, cr, x, y, width, height);
3716 * @context: a #GtkStyleContext
3718 * @x: X origin of the rectangle
3719 * @y: Y origin of the rectangle
3720 * @width: rectangle width
3721 * @height: rectangle height
3723 * Renders a focus indicator on the rectangle determined by @x, @y, @width, @height.
3725 * <title>Typical focus rendering</title>
3726 * <inlinegraphic fileref="focus.png" format="PNG"/>
3732 gtk_render_focus (GtkStyleContext *context,
3739 GtkThemingEngineClass *engine_class;
3740 GtkThemingEngine *engine;
3742 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3743 g_return_if_fail (cr != NULL);
3745 if (width <= 0 || height <= 0)
3748 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3749 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3753 _gtk_theming_engine_set_context (engine, context);
3754 engine_class->render_focus (engine, cr, x, y, width, height);
3760 * gtk_render_layout:
3761 * @context: a #GtkStyleContext
3765 * @layout: the #PangoLayout to render
3767 * Renders @layout on the coordinates @x, @y
3772 gtk_render_layout (GtkStyleContext *context,
3776 PangoLayout *layout)
3778 GtkThemingEngineClass *engine_class;
3779 GtkThemingEngine *engine;
3780 PangoRectangle extents;
3782 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3783 g_return_if_fail (PANGO_IS_LAYOUT (layout));
3784 g_return_if_fail (cr != NULL);
3786 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3787 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3791 pango_layout_get_extents (layout, &extents, NULL);
3793 _gtk_theming_engine_set_context (engine, context);
3794 engine_class->render_layout (engine, cr, x, y, layout);
3801 * @context: a #GtkStyleContext
3803 * @x0: X coordinate for the origin of the line
3804 * @y0: Y coordinate for the origin of the line
3805 * @x1: X coordinate for the end of the line
3806 * @y1: Y coordinate for the end of the line
3808 * Renders a line from (x0, y0) to (x1, y1).
3813 gtk_render_line (GtkStyleContext *context,
3820 GtkThemingEngineClass *engine_class;
3821 GtkThemingEngine *engine;
3823 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3824 g_return_if_fail (cr != NULL);
3826 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3827 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3831 _gtk_theming_engine_set_context (engine, context);
3832 engine_class->render_line (engine, cr, x0, y0, x1, y1);
3838 * gtk_render_slider:
3839 * @context: a #GtkStyleContext
3841 * @x: X origin of the rectangle
3842 * @y: Y origin of the rectangle
3843 * @width: rectangle width
3844 * @height: rectangle height
3845 * @orientation: orientation of the slider
3847 * Renders a slider (as in #GtkScale) in the rectangle defined by @x, @y,
3848 * @width, @height. @orientation defines whether the slider is vertical
3852 * <title>Typical slider rendering</title>
3853 * <inlinegraphic fileref="sliders.png" format="PNG"/>
3859 gtk_render_slider (GtkStyleContext *context,
3865 GtkOrientation orientation)
3867 GtkThemingEngineClass *engine_class;
3868 GtkThemingEngine *engine;
3870 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3871 g_return_if_fail (cr != NULL);
3873 if (width <= 0 || height <= 0)
3876 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3877 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3881 _gtk_theming_engine_set_context (engine, context);
3882 engine_class->render_slider (engine, cr, x, y, width, height, orientation);
3888 * gtk_render_frame_gap:
3889 * @context: a #GtkStyleContext
3891 * @x: X origin of the rectangle
3892 * @y: Y origin of the rectangle
3893 * @width: rectangle width
3894 * @height: rectangle height
3895 * @gap_side: side where the gap is
3896 * @xy0_gap: initial coordinate (X or Y depending on @gap_side) for the gap
3897 * @xy1_gap: end coordinate (X or Y depending on @gap_side) for the gap
3899 * Renders a frame around the rectangle defined by (@x, @y, @width, @height),
3900 * leaving a gap on one side. @xy0_gap and @xy1_gap will mean X coordinates
3901 * for %GTK_POS_TOP and %GTK_POS_BOTTOM gap sides, and Y coordinates for
3902 * %GTK_POS_LEFT and %GTK_POS_RIGHT.
3905 * <title>Typical rendering of a frame with a gap</title>
3906 * <inlinegraphic fileref="frame-gap.png" format="PNG"/>
3912 gtk_render_frame_gap (GtkStyleContext *context,
3918 GtkPositionType gap_side,
3922 GtkThemingEngineClass *engine_class;
3923 GtkThemingEngine *engine;
3925 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3926 g_return_if_fail (cr != NULL);
3927 g_return_if_fail (xy0_gap <= xy1_gap);
3928 g_return_if_fail (xy0_gap >= 0);
3930 if (width <= 0 || height <= 0)
3933 if (gap_side == GTK_POS_LEFT ||
3934 gap_side == GTK_POS_RIGHT)
3935 g_return_if_fail (xy1_gap <= height);
3937 g_return_if_fail (xy1_gap <= width);
3939 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3940 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3944 _gtk_theming_engine_set_context (engine, context);
3945 engine_class->render_frame_gap (engine, cr,
3946 x, y, width, height, gap_side,
3953 * gtk_render_extension:
3954 * @context: a #GtkStyleContext
3956 * @x: X origin of the rectangle
3957 * @y: Y origin of the rectangle
3958 * @width: rectangle width
3959 * @height: rectangle height
3960 * @gap_side: side where the gap is
3962 * Renders a extension (as in a #GtkNotebook tab) in the rectangle
3963 * defined by @x, @y, @width, @height. The side where the extension
3964 * connects to is defined by @gap_side.
3967 * <title>Typical extension rendering</title>
3968 * <inlinegraphic fileref="extensions.png" format="PNG"/>
3974 gtk_render_extension (GtkStyleContext *context,
3980 GtkPositionType gap_side)
3982 GtkThemingEngineClass *engine_class;
3983 GtkThemingEngine *engine;
3985 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3986 g_return_if_fail (cr != NULL);
3988 if (width <= 0 || height <= 0)
3991 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3992 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3996 _gtk_theming_engine_set_context (engine, context);
3997 engine_class->render_extension (engine, cr, x, y, width, height, gap_side);
4003 * gtk_render_handle:
4004 * @context: a #GtkStyleContext
4006 * @x: X origin of the rectangle
4007 * @y: Y origin of the rectangle
4008 * @width: rectangle width
4009 * @height: rectangle height
4011 * Renders a handle (as in #GtkHandleBox, #GtkPaned and
4012 * #GtkWindow<!-- -->'s resize grip), in the rectangle
4013 * determined by @x, @y, @width, @height.
4016 * <title>Handles rendered for the paned and grip classes</title>
4017 * <inlinegraphic fileref="handles.png" format="PNG"/>
4023 gtk_render_handle (GtkStyleContext *context,
4030 GtkThemingEngineClass *engine_class;
4031 GtkThemingEngine *engine;
4033 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4034 g_return_if_fail (cr != NULL);
4036 if (width <= 0 || height <= 0)
4039 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4040 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4044 _gtk_theming_engine_set_context (engine, context);
4045 engine_class->render_handle (engine, cr, x, y, width, height);
4051 * gtk_render_activity:
4052 * @context: a #GtkStyleContext
4054 * @x: X origin of the rectangle
4055 * @y: Y origin of the rectangle
4056 * @width: rectangle width
4057 * @height: rectangle height
4059 * Renders an activity area (Such as in #GtkSpinner or the
4060 * fill line in #GtkRange), the state %GTK_STATE_FLAG_ACTIVE
4061 * determines whether there is activity going on.
4066 gtk_render_activity (GtkStyleContext *context,
4073 GtkThemingEngineClass *engine_class;
4074 GtkThemingEngine *engine;
4076 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4077 g_return_if_fail (cr != NULL);
4079 if (width <= 0 || height <= 0)
4082 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4083 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4087 _gtk_theming_engine_set_context (engine, context);
4088 engine_class->render_activity (engine, cr, x, y, width, height);
4094 * gtk_render_icon_pixbuf:
4095 * @context: a #GtkStyleContext
4096 * @source: the #GtkIconSource specifying the icon to render
4097 * @size: (type int): the size to render the icon at. A size of (GtkIconSize) -1
4098 * means render at the size of the source and don't scale.
4100 * Renders the icon specified by @source at the given @size, returning the result
4103 * Returns: (transfer full): a newly-created #GdkPixbuf containing the rendered icon
4108 gtk_render_icon_pixbuf (GtkStyleContext *context,
4109 const GtkIconSource *source,
4112 GtkThemingEngineClass *engine_class;
4113 GtkThemingEngine *engine;
4115 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
4116 g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
4117 g_return_val_if_fail (source != NULL, NULL);
4119 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4120 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4122 _gtk_theming_engine_set_context (engine, context);
4123 return engine_class->render_icon_pixbuf (engine, source, size);
4128 * @context: a #GtkStyleContext
4130 * @pixbuf: a #GdkPixbuf containing the icon to draw
4131 * @x: X position for the @pixbuf
4132 * @y: Y position for the @pixbuf
4134 * Renders the icon in @pixbuf at the specified @x and @y coordinates.
4139 gtk_render_icon (GtkStyleContext *context,
4145 GtkThemingEngineClass *engine_class;
4146 GtkThemingEngine *engine;
4148 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4149 g_return_if_fail (cr != NULL);
4151 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4152 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4156 _gtk_theming_engine_set_context (engine, context);
4157 engine_class->render_icon (engine, cr, pixbuf, x, y);
4163 draw_insertion_cursor (GtkStyleContext *context,
4168 gboolean is_primary,
4169 PangoDirection direction,
4170 gboolean draw_arrow)
4173 GdkRGBA primary_color;
4174 GdkRGBA secondary_color;
4175 gfloat cursor_aspect_ratio;
4181 _gtk_style_context_get_cursor_color (context, &primary_color, &secondary_color);
4182 gdk_cairo_set_source_rgba (cr, is_primary ? &primary_color : &secondary_color);
4184 /* When changing the shape or size of the cursor here,
4185 * propagate the changes to gtktextview.c:text_window_invalidate_cursors().
4188 gtk_style_context_get_style (context,
4189 "cursor-aspect-ratio", &cursor_aspect_ratio,
4192 stem_width = height * cursor_aspect_ratio + 1;
4194 /* put (stem_width % 2) on the proper side of the cursor */
4195 if (direction == PANGO_DIRECTION_LTR)
4196 offset = stem_width / 2;
4198 offset = stem_width - stem_width / 2;
4200 cairo_rectangle (cr, x - offset, y, stem_width, height);
4208 arrow_width = stem_width + 1;
4210 if (direction == PANGO_DIRECTION_RTL)
4212 ax = x - offset - 1;
4213 ay = y + height - arrow_width * 2 - arrow_width + 1;
4215 cairo_move_to (cr, ax, ay + 1);
4216 cairo_line_to (cr, ax - arrow_width, ay + arrow_width);
4217 cairo_line_to (cr, ax, ay + 2 * arrow_width);
4220 else if (direction == PANGO_DIRECTION_LTR)
4222 ax = x + stem_width - offset;
4223 ay = y + height - arrow_width * 2 - arrow_width + 1;
4225 cairo_move_to (cr, ax, ay + 1);
4226 cairo_line_to (cr, ax + arrow_width, ay + arrow_width);
4227 cairo_line_to (cr, ax, ay + 2 * arrow_width);
4231 g_assert_not_reached();
4238 * gtk_render_insertion_cursor:
4239 * @context: a #GtkStyleContext
4243 * @layout: the #PangoLayout of the text
4244 * @index: the index in the #PangoLayout
4245 * @direction: the #PangoDirection of the text
4247 * Draws a text caret on @cr at the specified index of @layout.
4252 gtk_render_insertion_cursor (GtkStyleContext *context,
4256 PangoLayout *layout,
4258 PangoDirection direction)
4260 GtkStyleContextPrivate *priv;
4261 gboolean split_cursor;
4262 PangoRectangle strong_pos, weak_pos;
4263 PangoRectangle *cursor1, *cursor2;
4264 PangoDirection keymap_direction;
4265 PangoDirection direction2;
4267 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4268 g_return_if_fail (cr != NULL);
4269 g_return_if_fail (PANGO_IS_LAYOUT (layout));
4270 g_return_if_fail (index >= 0);
4272 priv = context->priv;
4274 g_object_get (gtk_settings_get_for_screen (priv->screen),
4275 "gtk-split-cursor", &split_cursor,
4278 keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gdk_screen_get_display (priv->screen)));
4280 pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
4282 direction2 = PANGO_DIRECTION_NEUTRAL;
4286 cursor1 = &strong_pos;
4288 if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
4290 direction2 = (direction == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
4291 cursor2 = &weak_pos;
4296 if (keymap_direction == direction)
4297 cursor1 = &strong_pos;
4299 cursor1 = &weak_pos;
4302 draw_insertion_cursor (context,
4304 x + PANGO_PIXELS (cursor1->x),
4305 y + PANGO_PIXELS (cursor1->y),
4306 PANGO_PIXELS (cursor1->height),
4309 direction2 != PANGO_DIRECTION_NEUTRAL);
4311 if (direction2 != PANGO_DIRECTION_NEUTRAL)
4313 draw_insertion_cursor (context,
4315 x + PANGO_PIXELS (cursor2->x),
4316 y + PANGO_PIXELS (cursor2->y),
4317 PANGO_PIXELS (cursor2->height),
4325 * gtk_draw_insertion_cursor:
4326 * @widget: a #GtkWidget
4327 * @cr: cairo context to draw to
4328 * @location: location where to draw the cursor (@location->width is ignored)
4329 * @is_primary: if the cursor should be the primary cursor color.
4330 * @direction: whether the cursor is left-to-right or
4331 * right-to-left. Should never be #GTK_TEXT_DIR_NONE
4332 * @draw_arrow: %TRUE to draw a directional arrow on the
4333 * cursor. Should be %FALSE unless the cursor is split.
4335 * Draws a text caret on @cr at @location. This is not a style function
4336 * but merely a convenience function for drawing the standard cursor shape.
4339 * Deprecated: 3.4: Use gtk_render_insertion_cursor() instead.
4342 gtk_draw_insertion_cursor (GtkWidget *widget,
4344 const GdkRectangle *location,
4345 gboolean is_primary,
4346 GtkTextDirection direction,
4347 gboolean draw_arrow)
4349 GtkStyleContext *context;
4351 g_return_if_fail (GTK_IS_WIDGET (widget));
4352 g_return_if_fail (cr != NULL);
4353 g_return_if_fail (location != NULL);
4354 g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
4356 context = gtk_widget_get_style_context (widget);
4358 draw_insertion_cursor (context, cr,
4359 location->x, location->y, location->height,
4361 (direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR,
4365 static AtkAttributeSet *
4366 add_attribute (AtkAttributeSet *attributes,
4367 AtkTextAttribute attr,
4372 at = g_new (AtkAttribute, 1);
4373 at->name = g_strdup (atk_text_attribute_get_name (attr));
4374 at->value = g_strdup (value);
4376 return g_slist_prepend (attributes, at);
4380 * _gtk_style_context_get_attributes:
4381 * @attributes: a #AtkAttributeSet to add attributes to
4382 * @context: the #GtkStyleContext to get attributes from
4383 * @flags: the state to use with @context
4385 * Adds the foreground and background color from @context to
4386 * @attributes, after translating them to ATK attributes.
4388 * This is a convenience function that can be used in
4389 * implementing the #AtkText interface in widgets.
4391 * Returns: the modified #AtkAttributeSet
4394 _gtk_style_context_get_attributes (AtkAttributeSet *attributes,
4395 GtkStyleContext *context,
4396 GtkStateFlags flags)
4401 gtk_style_context_get_background_color (context, flags, &color);
4402 value = g_strdup_printf ("%u,%u,%u",
4403 (guint) ceil (color.red * 65536 - color.red),
4404 (guint) ceil (color.green * 65536 - color.green),
4405 (guint) ceil (color.blue * 65536 - color.blue));
4406 attributes = add_attribute (attributes, ATK_TEXT_ATTR_BG_COLOR, value);
4409 gtk_style_context_get_color (context, flags, &color);
4410 value = g_strdup_printf ("%u,%u,%u",
4411 (guint) ceil (color.red * 65536 - color.red),
4412 (guint) ceil (color.green * 65536 - color.green),
4413 (guint) ceil (color.blue * 65536 - color.blue));
4414 attributes = add_attribute (attributes, ATK_TEXT_ATTR_FG_COLOR, value);