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 "gtkcssnumbervalueprivate.h"
29 #include "gtkcssrgbavalueprivate.h"
31 #include "gtkstylepropertiesprivate.h"
32 #include "gtktypebuiltins.h"
33 #include "gtkthemingengineprivate.h"
35 #include "gtkwidget.h"
36 #include "gtkwindow.h"
37 #include "gtkprivate.h"
38 #include "gtksymboliccolorprivate.h"
39 #include "gtkiconfactory.h"
40 #include "gtkwidgetpath.h"
41 #include "gtkwidgetprivate.h"
42 #include "gtkstylecascadeprivate.h"
43 #include "gtkstyleproviderprivate.h"
44 #include "gtksettings.h"
45 #include "gtksettingsprivate.h"
48 * SECTION:gtkstylecontext
49 * @Short_description: Rendering UI elements
50 * @Title: GtkStyleContext
52 * #GtkStyleContext is an object that stores styling information affecting
53 * a widget defined by #GtkWidgetPath.
55 * In order to construct the final style information, #GtkStyleContext
56 * queries information from all attached #GtkStyleProviders. Style providers
57 * can be either attached explicitly to the context through
58 * gtk_style_context_add_provider(), or to the screen through
59 * gtk_style_context_add_provider_for_screen(). The resulting style is a
60 * combination of all providers' information in priority order.
62 * For GTK+ widgets, any #GtkStyleContext returned by
63 * gtk_widget_get_style_context() will already have a #GtkWidgetPath, a
64 * #GdkScreen and RTL/LTR information set. The style context will be also
65 * updated automatically if any of these settings change on the widget.
67 * If you are using the theming layer standalone, you will need to set a
68 * widget path and a screen yourself to the created style context through
69 * gtk_style_context_set_path() and gtk_style_context_set_screen(), as well
70 * as updating the context yourself using gtk_style_context_invalidate()
71 * whenever any of the conditions change, such as a change in the
72 * #GtkSettings:gtk-theme-name setting or a hierarchy change in the rendered
75 * <refsect2 id="gtkstylecontext-animations">
76 * <title>Transition animations</title>
78 * #GtkStyleContext has built-in support for state change transitions.
79 * Note that these animations respect the #GtkSettings:gtk-enable-animations
83 * For simple widgets where state changes affect the whole widget area,
84 * calling gtk_style_context_notify_state_change() with a %NULL region
85 * is sufficient to trigger the transition animation. And GTK+ already
86 * does that when gtk_widget_set_state() or gtk_widget_set_state_flags()
90 * If a widget needs to declare several animatable regions (i.e. not
91 * affecting the whole widget area), its #GtkWidget::draw signal handler
92 * needs to wrap the render operations for the different regions with
93 * calls to gtk_style_context_push_animatable_region() and
94 * gtk_style_context_pop_animatable_region(). These functions take an
95 * identifier for the region which must be unique within the style context.
96 * For simple widgets with a fixed set of animatable regions, using an
97 * enumeration works well:
100 * <title>Using an enumeration to identify animatable regions</title>
111 * spin_button_draw (GtkWidget *widget,
114 * GtkStyleContext *context;
116 * context = gtk_widget_get_style_context (widget);
118 * gtk_style_context_push_animatable_region (context,
119 * GUINT_TO_POINTER (REGION_ENTRY));
121 * gtk_render_background (cr, 0, 0, 100, 30);
122 * gtk_render_frame (cr, 0, 0, 100, 30);
124 * gtk_style_context_pop_animatable_region (context);
131 * For complex widgets with an arbitrary number of animatable regions, it
132 * is up to the implementation to come up with a way to uniquely identify
133 * each animatable region. Using pointers to internal structs is one way
137 * <title>Using struct pointers to identify animatable regions</title>
140 * notebook_draw_tab (GtkWidget *widget,
141 * NotebookPage *page,
144 * gtk_style_context_push_animatable_region (context, page);
145 * gtk_render_extension (cr, page->x, page->y, page->width, page->height);
146 * gtk_style_context_pop_animatable_region (context);
151 * The widget also needs to notify the style context about a state change
152 * for a given animatable region so the animation is triggered.
155 * <title>Triggering a state change animation on a region</title>
158 * notebook_motion_notify (GtkWidget *widget,
159 * GdkEventMotion *event)
161 * GtkStyleContext *context;
162 * NotebookPage *page;
164 * context = gtk_widget_get_style_context (widget);
165 * page = find_page_under_pointer (widget, event);
166 * gtk_style_context_notify_state_change (context,
167 * gtk_widget_get_window (widget),
169 * GTK_STATE_PRELIGHT,
176 * gtk_style_context_notify_state_change() accepts %NULL region IDs as a
177 * special value, in this case, the whole widget area will be updated
181 * <refsect2 id="gtkstylecontext-classes">
182 * <title>Style classes and regions</title>
184 * Widgets can add style classes to their context, which can be used
185 * to associate different styles by class (see <xref linkend="gtkcssprovider-selectors"/>). Theme engines can also use style classes to vary their
186 * rendering. GTK+ has a number of predefined style classes:
187 * #GTK_STYLE_CLASS_CELL,
188 * #GTK_STYLE_CLASS_ENTRY,
189 * #GTK_STYLE_CLASS_BUTTON,
190 * #GTK_STYLE_CLASS_COMBOBOX_ENTRY,
191 * #GTK_STYLE_CLASS_CALENDAR,
192 * #GTK_STYLE_CLASS_SLIDER,
193 * #GTK_STYLE_CLASS_BACKGROUND,
194 * #GTK_STYLE_CLASS_RUBBERBAND,
195 * #GTK_STYLE_CLASS_TOOLTIP,
196 * #GTK_STYLE_CLASS_MENU,
197 * #GTK_STYLE_CLASS_MENUBAR,
198 * #GTK_STYLE_CLASS_MENUITEM,
199 * #GTK_STYLE_CLASS_TOOLBAR,
200 * #GTK_STYLE_CLASS_PRIMARY_TOOLBAR,
201 * #GTK_STYLE_CLASS_INLINE_TOOLBAR,
202 * #GTK_STYLE_CLASS_RADIO,
203 * #GTK_STYLE_CLASS_CHECK,
204 * #GTK_STYLE_CLASS_TROUGH,
205 * #GTK_STYLE_CLASS_SCROLLBAR,
206 * #GTK_STYLE_CLASS_SCALE,
207 * #GTK_STYLE_CLASS_SCALE_HAS_MARKS_ABOVE,
208 * #GTK_STYLE_CLASS_SCALE_HAS_MARKS_BELOW,
209 * #GTK_STYLE_CLASS_HEADER,
210 * #GTK_STYLE_CLASS_ACCELERATOR,
211 * #GTK_STYLE_CLASS_GRIP,
212 * #GTK_STYLE_CLASS_DOCK,
213 * #GTK_STYLE_CLASS_PROGRESSBAR,
214 * #GTK_STYLE_CLASS_SPINNER,
215 * #GTK_STYLE_CLASS_EXPANDER,
216 * #GTK_STYLE_CLASS_SPINBUTTON,
217 * #GTK_STYLE_CLASS_NOTEBOOK,
218 * #GTK_STYLE_CLASS_VIEW,
219 * #GTK_STYLE_CLASS_SIDEBAR,
220 * #GTK_STYLE_CLASS_IMAGE,
221 * #GTK_STYLE_CLASS_HIGHLIGHT,
222 * #GTK_STYLE_CLASS_FRAME,
223 * #GTK_STYLE_CLASS_DND,
224 * #GTK_STYLE_CLASS_PANE_SEPARATOR,
225 * #GTK_STYLE_CLASS_SEPARATOR,
226 * #GTK_STYLE_CLASS_INFO,
227 * #GTK_STYLE_CLASS_WARNING,
228 * #GTK_STYLE_CLASS_QUESTION,
229 * #GTK_STYLE_CLASS_ERROR,
230 * #GTK_STYLE_CLASS_HORIZONTAL,
231 * #GTK_STYLE_CLASS_VERTICAL,
232 * #GTK_STYLE_CLASS_TOP,
233 * #GTK_STYLE_CLASS_BOTTOM,
234 * #GTK_STYLE_CLASS_LEFT,
235 * #GTK_STYLE_CLASS_RIGHT,
238 * Widgets can also add regions with flags to their context.
239 * The regions used by GTK+ widgets are:
244 * <entry>Region</entry>
245 * <entry>Flags</entry>
246 * <entry>Macro</entry>
247 * <entry>Used by</entry>
253 * <entry>even, odd</entry>
254 * <entry>GTK_STYLE_REGION_ROW</entry>
255 * <entry>#GtkTreeView</entry>
258 * <entry>column</entry>
259 * <entry>first, last, sorted</entry>
260 * <entry>GTK_STYLE_REGION_COLUMN</entry>
261 * <entry>#GtkTreeView</entry>
264 * <entry>column-header</entry>
266 * <entry>GTK_STYLE_REGION_COLUMN_HEADER</entry>
271 * <entry>even, odd, first, last</entry>
272 * <entry>GTK_STYLE_REGION_TAB</entry>
273 * <entry>#GtkNotebook</entry>
280 * <refsect2 id="gtkstylecontext-custom-styling">
281 * <title>Custom styling in UI libraries and applications</title>
283 * If you are developing a library with custom #GtkWidget<!-- -->s that
284 * render differently than standard components, you may need to add a
285 * #GtkStyleProvider yourself with the %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK
286 * priority, either a #GtkCssProvider or a custom object implementing the
287 * #GtkStyleProvider interface. This way theming engines may still attempt
288 * to style your UI elements in a different way if needed so.
291 * If you are using custom styling on an applications, you probably want then
292 * to make your style information prevail to the theme's, so you must use
293 * a #GtkStyleProvider with the %GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
294 * priority, keep in mind that the user settings in
295 * <filename><replaceable>XDG_CONFIG_HOME</replaceable>/gtk-3.0/gtk.css</filename> will
296 * still take precedence over your changes, as it uses the
297 * %GTK_STYLE_PROVIDER_PRIORITY_USER priority.
300 * If a custom theming engine is needed, you probably want to implement a
301 * #GtkStyleProvider yourself so it points to your #GtkThemingEngine
302 * implementation, as #GtkCssProvider uses gtk_theming_engine_load()
303 * which loads the theming engine module from the standard paths.
308 /* When these change we do a full restyling. Otherwise we try to figure out
309 * if we need to change things. */
310 #define GTK_STYLE_CONTEXT_RADICAL_CHANGE (GTK_CSS_CHANGE_NAME | GTK_CSS_CHANGE_CLASS | GTK_CSS_CHANGE_SOURCE)
311 /* When these change we don't clear the cache. This takes more memory but makes
312 * things go faster. */
313 #define GTK_STYLE_CONTEXT_CACHED_CHANGE (GTK_CSS_CHANGE_STATE)
315 typedef struct GtkStyleInfo GtkStyleInfo;
316 typedef struct GtkRegion GtkRegion;
317 typedef struct PropertyValue PropertyValue;
318 typedef struct StyleData StyleData;
323 GtkRegionFlags flags;
337 GArray *style_classes;
339 GtkJunctionSides junction_sides;
340 GtkStateFlags state_flags;
346 GtkCssComputedValues *store;
347 GArray *property_cache;
351 struct _GtkStyleContextPrivate
355 GtkStyleCascade *cascade;
357 GtkStyleContext *animation_list_prev;
358 GtkStyleContext *animation_list_next;
360 GtkStyleContext *parent;
363 GtkWidgetPath *widget_path;
364 GHashTable *style_data;
367 GtkTextDirection direction;
369 GtkCssChange relevant_changes;
370 GtkCssChange pending_changes;
372 guint invalidating_context : 1;
388 static guint signals[LAST_SIGNAL] = { 0 };
389 static GtkStyleContext *_running_animations = NULL;
390 guint _running_animations_timer_id = 0;
392 static void gtk_style_context_finalize (GObject *object);
394 static void gtk_style_context_impl_set_property (GObject *object,
398 static void gtk_style_context_impl_get_property (GObject *object,
402 static StyleData *style_data_lookup (GtkStyleContext *context);
405 G_DEFINE_TYPE (GtkStyleContext, gtk_style_context, G_TYPE_OBJECT)
408 gtk_style_context_real_changed (GtkStyleContext *context)
410 GtkStyleContextPrivate *priv = context->priv;
413 _gtk_widget_style_context_invalidated (priv->widget);
417 gtk_style_context_class_init (GtkStyleContextClass *klass)
419 GObjectClass *object_class = G_OBJECT_CLASS (klass);
421 object_class->finalize = gtk_style_context_finalize;
422 object_class->set_property = gtk_style_context_impl_set_property;
423 object_class->get_property = gtk_style_context_impl_get_property;
425 klass->changed = gtk_style_context_real_changed;
428 g_signal_new (I_("changed"),
429 G_TYPE_FROM_CLASS (object_class),
431 G_STRUCT_OFFSET (GtkStyleContextClass, changed),
433 g_cclosure_marshal_VOID__VOID,
436 g_object_class_install_property (object_class,
438 g_param_spec_object ("screen",
440 P_("The associated GdkScreen"),
442 GTK_PARAM_READWRITE));
443 g_object_class_install_property (object_class,
445 g_param_spec_enum ("direction",
447 P_("Text direction"),
448 GTK_TYPE_TEXT_DIRECTION,
450 GTK_PARAM_READWRITE));
452 * GtkStyleContext:parent:
454 * Sets or gets the style context's parent. See gtk_style_context_set_parent()
459 g_object_class_install_property (object_class,
461 g_param_spec_object ("parent",
463 P_("The parent style context"),
464 GTK_TYPE_STYLE_CONTEXT,
465 GTK_PARAM_READWRITE));
467 g_type_class_add_private (object_class, sizeof (GtkStyleContextPrivate));
471 style_data_new (void)
475 data = g_slice_new0 (StyleData);
482 clear_property_cache (StyleData *data)
486 if (!data->property_cache)
489 for (i = 0; i < data->property_cache->len; i++)
491 PropertyValue *node = &g_array_index (data->property_cache, PropertyValue, i);
493 g_param_spec_unref (node->pspec);
494 g_value_unset (&node->value);
497 g_array_free (data->property_cache, TRUE);
498 data->property_cache = NULL;
502 style_data_ref (StyleData *style_data)
504 style_data->ref_count++;
510 style_data_unref (StyleData *data)
514 if (data->ref_count > 0)
517 g_object_unref (data->store);
518 clear_property_cache (data);
520 g_slice_free (StyleData, data);
524 style_data_is_animating (StyleData *style_data)
526 return !_gtk_css_computed_values_is_static (style_data->store);
529 static GtkStyleInfo *
530 style_info_new (void)
534 info = g_slice_new0 (GtkStyleInfo);
535 info->style_classes = g_array_new (FALSE, FALSE, sizeof (GQuark));
536 info->regions = g_array_new (FALSE, FALSE, sizeof (GtkRegion));
542 style_info_set_data (GtkStyleInfo *info,
545 if (info->data == data)
549 style_data_ref (data);
552 style_data_unref (info->data);
558 style_info_free (GtkStyleInfo *info)
560 style_info_set_data (info, NULL);
561 g_array_free (info->style_classes, TRUE);
562 g_array_free (info->regions, TRUE);
563 g_slice_free (GtkStyleInfo, info);
566 static GtkStyleInfo *
567 style_info_pop (GtkStyleInfo *info)
569 GtkStyleInfo *next = info->next;
571 style_info_free (info);
576 static GtkStyleInfo *
577 style_info_copy (GtkStyleInfo *info)
581 copy = style_info_new ();
582 g_array_insert_vals (copy->style_classes, 0,
583 info->style_classes->data,
584 info->style_classes->len);
586 g_array_insert_vals (copy->regions, 0,
591 copy->junction_sides = info->junction_sides;
592 copy->state_flags = info->state_flags;
593 style_info_set_data (copy, info->data);
599 style_info_hash (gconstpointer elem)
601 const GtkStyleInfo *info;
606 for (i = 0; i < info->style_classes->len; i++)
608 hash += g_array_index (info->style_classes, GQuark, i);
612 for (i = 0; i < info->regions->len; i++)
616 region = &g_array_index (info->regions, GtkRegion, i);
617 hash += region->class_quark;
618 hash += region->flags;
622 return hash ^ info->state_flags;
626 style_info_equal (gconstpointer elem1,
629 const GtkStyleInfo *info1, *info2;
634 if (info1->state_flags != info2->state_flags)
637 if (info1->junction_sides != info2->junction_sides)
640 if (info1->style_classes->len != info2->style_classes->len)
643 if (memcmp (info1->style_classes->data,
644 info2->style_classes->data,
645 info1->style_classes->len * sizeof (GQuark)) != 0)
648 if (info1->regions->len != info2->regions->len)
651 if (memcmp (info1->regions->data,
652 info2->regions->data,
653 info1->regions->len * sizeof (GtkRegion)) != 0)
660 gtk_style_context_cascade_changed (GtkStyleCascade *cascade,
661 GtkStyleContext *context)
663 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_SOURCE);
667 gtk_style_context_set_cascade (GtkStyleContext *context,
668 GtkStyleCascade *cascade)
670 GtkStyleContextPrivate *priv;
672 priv = context->priv;
674 if (priv->cascade == cascade)
679 g_object_ref (cascade);
680 g_signal_connect (cascade,
681 "-gtk-private-changed",
682 G_CALLBACK (gtk_style_context_cascade_changed),
688 g_signal_handlers_disconnect_by_func (priv->cascade,
689 gtk_style_context_cascade_changed,
691 g_object_unref (priv->cascade);
694 priv->cascade = cascade;
697 gtk_style_context_cascade_changed (cascade, context);
701 gtk_style_context_init (GtkStyleContext *style_context)
703 GtkStyleContextPrivate *priv;
705 priv = style_context->priv = G_TYPE_INSTANCE_GET_PRIVATE (style_context,
706 GTK_TYPE_STYLE_CONTEXT,
707 GtkStyleContextPrivate);
709 priv->style_data = g_hash_table_new_full (style_info_hash,
711 (GDestroyNotify) style_info_free,
712 (GDestroyNotify) style_data_unref);
714 priv->direction = GTK_TEXT_DIR_LTR;
716 priv->screen = gdk_screen_get_default ();
717 priv->relevant_changes = GTK_CSS_CHANGE_ANY;
719 /* Create default info store */
720 priv->info = style_info_new ();
722 gtk_style_context_set_cascade (style_context,
723 _gtk_style_cascade_get_for_screen (priv->screen));
727 gtk_style_context_do_animations (gpointer unused)
729 GtkStyleContext *context;
731 for (context = _running_animations;
733 context = context->priv->animation_list_next)
735 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANIMATE);
742 gtk_style_context_is_animating (GtkStyleContext *context)
744 GtkStyleContextPrivate *priv = context->priv;
746 return priv->animation_list_prev != NULL
747 || _running_animations == context;
751 gtk_style_context_stop_animating (GtkStyleContext *context)
753 GtkStyleContextPrivate *priv = context->priv;
755 if (!gtk_style_context_is_animating (context))
758 if (priv->animation_list_prev == NULL)
760 _running_animations = priv->animation_list_next;
762 if (_running_animations == NULL)
764 /* we were the last animation */
765 g_source_remove (_running_animations_timer_id);
766 _running_animations_timer_id = 0;
770 priv->animation_list_prev->priv->animation_list_next = priv->animation_list_next;
772 if (priv->animation_list_next)
773 priv->animation_list_next->priv->animation_list_prev = priv->animation_list_prev;
775 priv->animation_list_next = NULL;
776 priv->animation_list_prev = NULL;
780 gtk_style_context_start_animating (GtkStyleContext *context)
782 GtkStyleContextPrivate *priv = context->priv;
784 if (gtk_style_context_is_animating (context))
787 if (_running_animations == NULL)
789 _running_animations_timer_id = gdk_threads_add_timeout (25,
790 gtk_style_context_do_animations,
792 _running_animations = context;
796 priv->animation_list_next = _running_animations;
797 _running_animations->priv->animation_list_prev = context;
798 _running_animations = context;
803 gtk_style_context_should_animate (GtkStyleContext *context)
805 GtkStyleContextPrivate *priv;
809 priv = context->priv;
811 if (priv->widget == NULL)
814 if (!gtk_widget_get_mapped (priv->widget))
817 data = style_data_lookup (context);
818 if (!style_data_is_animating (data))
821 g_object_get (gtk_widget_get_settings (context->priv->widget),
822 "gtk-enable-animations", &animate,
829 _gtk_style_context_update_animating (GtkStyleContext *context)
831 if (gtk_style_context_should_animate (context))
832 gtk_style_context_start_animating (context);
834 gtk_style_context_stop_animating (context);
838 gtk_style_context_finalize (GObject *object)
840 GtkStyleContextPrivate *priv;
841 GtkStyleContext *style_context;
843 style_context = GTK_STYLE_CONTEXT (object);
844 priv = style_context->priv;
846 gtk_style_context_stop_animating (style_context);
848 /* children hold a reference to us */
849 g_assert (priv->children == NULL);
851 gtk_style_context_set_parent (style_context, NULL);
853 gtk_style_context_set_cascade (style_context, NULL);
855 if (priv->widget_path)
856 gtk_widget_path_free (priv->widget_path);
858 g_hash_table_destroy (priv->style_data);
861 priv->info = style_info_pop (priv->info);
863 G_OBJECT_CLASS (gtk_style_context_parent_class)->finalize (object);
867 gtk_style_context_impl_set_property (GObject *object,
872 GtkStyleContext *style_context;
874 style_context = GTK_STYLE_CONTEXT (object);
879 gtk_style_context_set_screen (style_context,
880 g_value_get_object (value));
883 gtk_style_context_set_direction (style_context,
884 g_value_get_enum (value));
887 gtk_style_context_set_parent (style_context,
888 g_value_get_object (value));
891 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
897 gtk_style_context_impl_get_property (GObject *object,
902 GtkStyleContext *style_context;
903 GtkStyleContextPrivate *priv;
905 style_context = GTK_STYLE_CONTEXT (object);
906 priv = style_context->priv;
911 g_value_set_object (value, priv->screen);
914 g_value_set_enum (value, priv->direction);
917 g_value_set_object (value, priv->parent);
920 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
925 static GtkWidgetPath *
926 create_query_path (GtkStyleContext *context,
929 GtkStyleContextPrivate *priv;
933 priv = context->priv;
934 path = priv->widget ? _gtk_widget_create_path (priv->widget) : gtk_widget_path_copy (priv->widget_path);
935 pos = gtk_widget_path_length (path) - 1;
937 /* Set widget regions */
938 for (i = 0; i < info->regions->len; i++)
942 region = &g_array_index (info->regions, GtkRegion, i);
943 gtk_widget_path_iter_add_region (path, pos,
944 g_quark_to_string (region->class_quark),
948 /* Set widget classes */
949 for (i = 0; i < info->style_classes->len; i++)
953 quark = g_array_index (info->style_classes, GQuark, i);
954 gtk_widget_path_iter_add_class (path, pos,
955 g_quark_to_string (quark));
962 build_properties (GtkStyleContext *context,
963 GtkCssComputedValues *values,
965 const GtkBitmask *relevant_changes)
967 GtkStyleContextPrivate *priv;
968 GtkCssMatcher matcher;
970 GtkCssLookup *lookup;
972 priv = context->priv;
974 path = create_query_path (context, info);
975 lookup = _gtk_css_lookup_new (relevant_changes);
977 if (_gtk_css_matcher_init (&matcher, path, info->state_flags))
978 _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
982 _gtk_css_lookup_resolve (lookup,
983 GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
985 priv->parent ? style_data_lookup (priv->parent)->store : NULL);
987 _gtk_css_lookup_free (lookup);
988 gtk_widget_path_free (path);
992 style_data_lookup (GtkStyleContext *context)
994 GtkStyleContextPrivate *priv;
998 priv = context->priv;
1001 /* Current data in use is cached, just return it */
1005 g_assert (priv->widget != NULL || priv->widget_path != NULL);
1007 data = g_hash_table_lookup (priv->style_data, info);
1010 style_info_set_data (info, data);
1014 data = style_data_new ();
1015 data->store = _gtk_css_computed_values_new ();
1016 style_info_set_data (info, data);
1017 g_hash_table_insert (priv->style_data,
1018 style_info_copy (info),
1021 build_properties (context, data->store, info, NULL);
1027 style_data_lookup_for_state (GtkStyleContext *context,
1028 GtkStateFlags state)
1032 if (context->priv->info->state_flags == state)
1033 return style_data_lookup (context);
1035 gtk_style_context_save (context);
1036 gtk_style_context_set_state (context, state);
1037 data = style_data_lookup (context);
1038 gtk_style_context_restore (context);
1044 gtk_style_context_set_invalid (GtkStyleContext *context,
1047 GtkStyleContextPrivate *priv;
1049 priv = context->priv;
1051 if (priv->invalid == invalid)
1054 priv->invalid = invalid;
1059 gtk_style_context_set_invalid (priv->parent, TRUE);
1060 else if (GTK_IS_RESIZE_CONTAINER (priv->widget))
1061 _gtk_container_queue_restyle (GTK_CONTAINER (priv->widget));
1065 /* returns TRUE if someone called gtk_style_context_save() but hasn't
1066 * called gtk_style_context_restore() yet.
1067 * In those situations we don't invalidate the context when somebody
1068 * changes state/regions/classes.
1071 gtk_style_context_is_saved (GtkStyleContext *context)
1073 return context->priv->info->next != NULL;
1077 gtk_style_context_queue_invalidate_internal (GtkStyleContext *context,
1078 GtkCssChange change)
1080 GtkStyleContextPrivate *priv = context->priv;
1081 GtkStyleInfo *info = priv->info;
1083 if (gtk_style_context_is_saved (context))
1085 style_info_set_data (info, NULL);
1089 _gtk_style_context_queue_invalidate (context, change);
1090 /* XXX: We need to invalidate siblings here somehow */
1095 * gtk_style_context_new:
1097 * Creates a standalone #GtkStyleContext, this style context
1098 * won't be attached to any widget, so you may want
1099 * to call gtk_style_context_set_path() yourself.
1102 * This function is only useful when using the theming layer
1103 * separated from GTK+, if you are using #GtkStyleContext to
1104 * theme #GtkWidget<!-- -->s, use gtk_widget_get_style_context()
1105 * in order to get a style context ready to theme the widget.
1108 * Returns: A newly created #GtkStyleContext.
1111 gtk_style_context_new (void)
1113 return g_object_new (GTK_TYPE_STYLE_CONTEXT, NULL);
1117 _gtk_style_context_set_widget (GtkStyleContext *context,
1120 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1121 g_return_if_fail (widget == NULL || GTK_IS_WIDGET (widget));
1123 context->priv->widget = widget;
1125 _gtk_style_context_update_animating (context);
1127 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_SELF);
1131 * gtk_style_context_add_provider:
1132 * @context: a #GtkStyleContext
1133 * @provider: a #GtkStyleProvider
1134 * @priority: the priority of the style provider. The lower
1135 * it is, the earlier it will be used in the style
1136 * construction. Typically this will be in the range
1137 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1138 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1140 * Adds a style provider to @context, to be used in style construction.
1141 * Note that a style provider added by this function only affects
1142 * the style of the widget to which @context belongs. If you want
1143 * to affect the style of all widgets, use
1144 * gtk_style_context_add_provider_for_screen().
1146 * <note><para>If both priorities are the same, A #GtkStyleProvider
1147 * added through this function takes precedence over another added
1148 * through gtk_style_context_add_provider_for_screen().</para></note>
1153 gtk_style_context_add_provider (GtkStyleContext *context,
1154 GtkStyleProvider *provider,
1157 GtkStyleContextPrivate *priv;
1159 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1160 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1162 priv = context->priv;
1164 if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
1166 GtkStyleCascade *new_cascade;
1168 new_cascade = _gtk_style_cascade_new ();
1169 _gtk_style_cascade_set_parent (new_cascade, priv->cascade);
1170 _gtk_style_cascade_add_provider (new_cascade, provider, priority);
1171 gtk_style_context_set_cascade (context, new_cascade);
1172 g_object_unref (new_cascade);
1176 _gtk_style_cascade_add_provider (priv->cascade, provider, priority);
1181 * gtk_style_context_remove_provider:
1182 * @context: a #GtkStyleContext
1183 * @provider: a #GtkStyleProvider
1185 * Removes @provider from the style providers list in @context.
1190 gtk_style_context_remove_provider (GtkStyleContext *context,
1191 GtkStyleProvider *provider)
1193 GtkStyleContextPrivate *priv;
1195 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1196 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1198 priv = context->priv;
1200 if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
1203 _gtk_style_cascade_remove_provider (priv->cascade, provider);
1207 * gtk_style_context_reset_widgets:
1208 * @screen: a #GdkScreen
1210 * This function recomputes the styles for all widgets under a particular
1211 * #GdkScreen. This is useful when some global parameter has changed that
1212 * affects the appearance of all widgets, because when a widget gets a new
1213 * style, it will both redraw and recompute any cached information about
1214 * its appearance. As an example, it is used when the color scheme changes
1215 * in the related #GtkSettings object.
1220 gtk_style_context_reset_widgets (GdkScreen *screen)
1222 GList *list, *toplevels;
1224 _gtk_icon_set_invalidate_caches ();
1226 toplevels = gtk_window_list_toplevels ();
1227 g_list_foreach (toplevels, (GFunc) g_object_ref, NULL);
1229 for (list = toplevels; list; list = list->next)
1231 if (gtk_widget_get_screen (list->data) == screen)
1232 gtk_widget_reset_style (list->data);
1234 g_object_unref (list->data);
1237 g_list_free (toplevels);
1241 * gtk_style_context_add_provider_for_screen:
1242 * @screen: a #GdkScreen
1243 * @provider: a #GtkStyleProvider
1244 * @priority: the priority of the style provider. The lower
1245 * it is, the earlier it will be used in the style
1246 * construction. Typically this will be in the range
1247 * between %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK and
1248 * %GTK_STYLE_PROVIDER_PRIORITY_USER
1250 * Adds a global style provider to @screen, which will be used
1251 * in style construction for all #GtkStyleContexts under @screen.
1253 * GTK+ uses this to make styling information from #GtkSettings
1256 * <note><para>If both priorities are the same, A #GtkStyleProvider
1257 * added through gtk_style_context_add_provider() takes precedence
1258 * over another added through this function.</para></note>
1263 gtk_style_context_add_provider_for_screen (GdkScreen *screen,
1264 GtkStyleProvider *provider,
1267 GtkStyleCascade *cascade;
1269 g_return_if_fail (GDK_IS_SCREEN (screen));
1270 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1271 g_return_if_fail (!GTK_IS_SETTINGS (provider) || _gtk_settings_get_screen (GTK_SETTINGS (provider)) == screen);
1273 cascade = _gtk_style_cascade_get_for_screen (screen);
1274 _gtk_style_cascade_add_provider (cascade, provider, priority);
1278 * gtk_style_context_remove_provider_for_screen:
1279 * @screen: a #GdkScreen
1280 * @provider: a #GtkStyleProvider
1282 * Removes @provider from the global style providers list in @screen.
1287 gtk_style_context_remove_provider_for_screen (GdkScreen *screen,
1288 GtkStyleProvider *provider)
1290 GtkStyleCascade *cascade;
1292 g_return_if_fail (GDK_IS_SCREEN (screen));
1293 g_return_if_fail (GTK_IS_STYLE_PROVIDER (provider));
1294 g_return_if_fail (!GTK_IS_SETTINGS (provider));
1296 cascade = _gtk_style_cascade_get_for_screen (screen);
1297 _gtk_style_cascade_remove_provider (cascade, provider);
1301 * gtk_style_context_get_section:
1302 * @context: a #GtkStyleContext
1303 * @property: style property name
1305 * Queries the location in the CSS where @property was defined for the
1306 * current @context. Note that the state to be queried is taken from
1307 * gtk_style_context_get_state().
1309 * If the location is not available, %NULL will be returned. The
1310 * location might not be available for various reasons, such as the
1311 * property being overridden, @property not naming a supported CSS
1312 * property or tracking of definitions being disabled for performance
1315 * Shorthand CSS properties cannot be queried for a location and will
1316 * always return %NULL.
1318 * Returns: %NULL or the section where value was defined
1321 gtk_style_context_get_section (GtkStyleContext *context,
1322 const gchar *property)
1324 GtkStyleContextPrivate *priv;
1325 GtkStyleProperty *prop;
1328 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
1329 g_return_val_if_fail (property != NULL, NULL);
1331 priv = context->priv;
1332 g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
1334 prop = _gtk_style_property_lookup (property);
1335 if (!GTK_IS_CSS_STYLE_PROPERTY (prop))
1338 data = style_data_lookup (context);
1339 return _gtk_css_computed_values_get_section (data->store, _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (prop)));
1342 static GtkCssValue *
1343 gtk_style_context_query_func (guint id,
1346 return _gtk_css_computed_values_get_value (values, id);
1350 * gtk_style_context_get_property:
1351 * @context: a #GtkStyleContext
1352 * @property: style property name
1353 * @state: state to retrieve the property value for
1354 * @value: (out) (transfer full): return location for the style property value
1356 * Gets a style property from @context for the given state.
1358 * When @value is no longer needed, g_value_unset() must be called
1359 * to free any allocated memory.
1364 gtk_style_context_get_property (GtkStyleContext *context,
1365 const gchar *property,
1366 GtkStateFlags state,
1369 GtkStyleContextPrivate *priv;
1370 GtkStyleProperty *prop;
1373 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1374 g_return_if_fail (property != NULL);
1375 g_return_if_fail (value != NULL);
1377 priv = context->priv;
1378 g_return_if_fail (priv->widget != NULL || priv->widget_path != NULL);
1380 prop = _gtk_style_property_lookup (property);
1383 g_warning ("Style property \"%s\" is not registered", property);
1386 if (_gtk_style_property_get_value_type (prop) == G_TYPE_NONE)
1388 g_warning ("Style property \"%s\" is not gettable", property);
1392 data = style_data_lookup_for_state (context, state);
1393 _gtk_style_property_query (prop, value, gtk_style_context_query_func, data->store);
1397 * gtk_style_context_get_valist:
1398 * @context: a #GtkStyleContext
1399 * @state: state to retrieve the property values for
1400 * @args: va_list of property name/return location pairs, followed by %NULL
1402 * Retrieves several style property values from @context for a given state.
1407 gtk_style_context_get_valist (GtkStyleContext *context,
1408 GtkStateFlags state,
1411 const gchar *property_name;
1413 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1415 property_name = va_arg (args, const gchar *);
1417 while (property_name)
1419 gchar *error = NULL;
1420 GValue value = G_VALUE_INIT;
1422 gtk_style_context_get_property (context,
1427 G_VALUE_LCOPY (&value, args, 0, &error);
1428 g_value_unset (&value);
1432 g_warning ("Could not get style property \"%s\": %s", property_name, error);
1437 property_name = va_arg (args, const gchar *);
1442 * gtk_style_context_get:
1443 * @context: a #GtkStyleContext
1444 * @state: state to retrieve the property values for
1445 * @...: property name /return value pairs, followed by %NULL
1447 * Retrieves several style property values from @context for a
1453 gtk_style_context_get (GtkStyleContext *context,
1454 GtkStateFlags state,
1459 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1461 va_start (args, state);
1462 gtk_style_context_get_valist (context, state, args);
1467 * gtk_style_context_set_state:
1468 * @context: a #GtkStyleContext
1469 * @flags: state to represent
1471 * Sets the state to be used when rendering with any
1472 * of the gtk_render_*() functions.
1477 gtk_style_context_set_state (GtkStyleContext *context,
1478 GtkStateFlags flags)
1480 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1482 context->priv->info->state_flags = flags;
1484 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_STATE);
1488 * gtk_style_context_get_state:
1489 * @context: a #GtkStyleContext
1491 * Returns the state used when rendering.
1493 * Returns: the state flags
1498 gtk_style_context_get_state (GtkStyleContext *context)
1500 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
1502 return context->priv->info->state_flags;
1506 * gtk_style_context_state_is_running:
1507 * @context: a #GtkStyleContext
1508 * @state: a widget state
1509 * @progress: (out): return location for the transition progress
1511 * Returns %TRUE if there is a transition animation running for the
1512 * current region (see gtk_style_context_push_animatable_region()).
1514 * If @progress is not %NULL, the animation progress will be returned
1515 * there, 0.0 means the state is closest to being unset, while 1.0 means
1516 * it's closest to being set. This means transition animation will
1517 * run from 0 to 1 when @state is being set and from 1 to 0 when
1520 * Returns: %TRUE if there is a running transition animation for @state.
1524 * Deprecated: 3.6: This function always returns %FALSE
1527 gtk_style_context_state_is_running (GtkStyleContext *context,
1531 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1537 * gtk_style_context_set_path:
1538 * @context: a #GtkStyleContext
1539 * @path: a #GtkWidgetPath
1541 * Sets the #GtkWidgetPath used for style matching. As a
1542 * consequence, the style will be regenerated to match
1543 * the new given path.
1545 * If you are using a #GtkStyleContext returned from
1546 * gtk_widget_get_style_context(), you do not need to call
1552 gtk_style_context_set_path (GtkStyleContext *context,
1553 GtkWidgetPath *path)
1555 GtkStyleContextPrivate *priv;
1557 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1558 g_return_if_fail (path != NULL);
1560 priv = context->priv;
1561 g_return_if_fail (priv->widget == NULL);
1563 if (priv->widget_path)
1565 gtk_widget_path_free (priv->widget_path);
1566 priv->widget_path = NULL;
1570 priv->widget_path = gtk_widget_path_copy (path);
1572 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY);
1576 * gtk_style_context_get_path:
1577 * @context: a #GtkStyleContext
1579 * Returns the widget path used for style matching.
1581 * Returns: (transfer none): A #GtkWidgetPath
1585 const GtkWidgetPath *
1586 gtk_style_context_get_path (GtkStyleContext *context)
1588 GtkStyleContextPrivate *priv;
1590 priv = context->priv;
1592 return gtk_widget_get_path (priv->widget);
1594 return priv->widget_path;
1598 * gtk_style_context_set_parent:
1599 * @context: a #GtkStyleContext
1600 * @parent: (allow-none): the new parent or %NULL
1602 * Sets the parent style context for @context. The parent style
1603 * context is used to implement
1604 * <ulink url="http://www.w3.org/TR/css3-cascade/#inheritance">inheritance</ulink>
1607 * If you are using a #GtkStyleContext returned from
1608 * gtk_widget_get_style_context(), the parent will be set for you.
1613 gtk_style_context_set_parent (GtkStyleContext *context,
1614 GtkStyleContext *parent)
1616 GtkStyleContextPrivate *priv;
1618 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1619 g_return_if_fail (parent == NULL || GTK_IS_STYLE_CONTEXT (parent));
1621 priv = context->priv;
1623 if (priv->parent == parent)
1628 parent->priv->children = g_slist_prepend (parent->priv->children, context);
1629 g_object_ref (parent);
1631 gtk_style_context_set_invalid (parent, TRUE);
1636 priv->parent->priv->children = g_slist_remove (priv->parent->priv->children, context);
1637 g_object_unref (priv->parent);
1640 priv->parent = parent;
1642 g_object_notify (G_OBJECT (context), "parent");
1643 _gtk_style_context_queue_invalidate (context, GTK_CSS_CHANGE_ANY_PARENT | GTK_CSS_CHANGE_ANY_SIBLING);
1647 * gtk_style_context_get_parent:
1648 * @context: a #GtkStyleContext
1650 * Gets the parent context set via gtk_style_context_set_parent().
1651 * See that function for details.
1653 * Returns: (transfer none): the parent context or %NULL
1658 gtk_style_context_get_parent (GtkStyleContext *context)
1660 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
1662 return context->priv->parent;
1666 * gtk_style_context_save:
1667 * @context: a #GtkStyleContext
1669 * Saves the @context state, so all modifications done through
1670 * gtk_style_context_add_class(), gtk_style_context_remove_class(),
1671 * gtk_style_context_add_region(), gtk_style_context_remove_region()
1672 * or gtk_style_context_set_junction_sides() can be reverted in one
1673 * go through gtk_style_context_restore().
1678 gtk_style_context_save (GtkStyleContext *context)
1680 GtkStyleContextPrivate *priv;
1682 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1684 priv = context->priv;
1686 priv->info = style_info_copy (priv->info);
1687 /* Need to unset animations here because we can not know what style
1688 * class potential transitions came from once we save().
1690 if (priv->info->data && style_data_is_animating (priv->info->data))
1691 style_info_set_data (priv->info, NULL);
1695 * gtk_style_context_restore:
1696 * @context: a #GtkStyleContext
1698 * Restores @context state to a previous stage.
1699 * See gtk_style_context_save().
1704 gtk_style_context_restore (GtkStyleContext *context)
1706 GtkStyleContextPrivate *priv;
1708 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1710 priv = context->priv;
1712 priv->info = style_info_pop (priv->info);
1716 g_warning ("Unpaired gtk_style_context_restore() call");
1718 /* Create default region */
1719 priv->info = style_info_new ();
1724 style_class_find (GArray *array,
1729 gboolean found = FALSE;
1735 if (!array || array->len == 0)
1739 max = array->len - 1;
1745 mid = (min + max) / 2;
1746 item = g_array_index (array, GQuark, mid);
1748 if (class_quark == item)
1753 else if (class_quark > item)
1754 min = pos = mid + 1;
1761 while (!found && min <= max);
1770 region_find (GArray *array,
1775 gboolean found = FALSE;
1781 if (!array || array->len == 0)
1785 max = array->len - 1;
1791 mid = (min + max) / 2;
1792 region = &g_array_index (array, GtkRegion, mid);
1794 if (region->class_quark == class_quark)
1799 else if (region->class_quark > class_quark)
1800 min = pos = mid + 1;
1807 while (!found && min <= max);
1816 * gtk_style_context_add_class:
1817 * @context: a #GtkStyleContext
1818 * @class_name: class name to use in styling
1820 * Adds a style class to @context, so posterior calls to
1821 * gtk_style_context_get() or any of the gtk_render_*()
1822 * functions will make use of this new class for styling.
1824 * In the CSS file format, a #GtkEntry defining an "entry"
1825 * class, would be matched by:
1828 * GtkEntry.entry { ... }
1831 * While any widget defining an "entry" class would be
1840 gtk_style_context_add_class (GtkStyleContext *context,
1841 const gchar *class_name)
1843 GtkStyleContextPrivate *priv;
1848 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1849 g_return_if_fail (class_name != NULL);
1851 priv = context->priv;
1852 class_quark = g_quark_from_string (class_name);
1856 if (!style_class_find (info->style_classes, class_quark, &position))
1858 g_array_insert_val (info->style_classes, position, class_quark);
1860 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
1865 * gtk_style_context_remove_class:
1866 * @context: a #GtkStyleContext
1867 * @class_name: class name to remove
1869 * Removes @class_name from @context.
1874 gtk_style_context_remove_class (GtkStyleContext *context,
1875 const gchar *class_name)
1877 GtkStyleContextPrivate *priv;
1882 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
1883 g_return_if_fail (class_name != NULL);
1885 class_quark = g_quark_try_string (class_name);
1890 priv = context->priv;
1894 if (style_class_find (info->style_classes, class_quark, &position))
1896 g_array_remove_index (info->style_classes, position);
1898 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_CLASS);
1903 * gtk_style_context_has_class:
1904 * @context: a #GtkStyleContext
1905 * @class_name: a class name
1907 * Returns %TRUE if @context currently has defined the
1910 * Returns: %TRUE if @context has @class_name defined
1915 gtk_style_context_has_class (GtkStyleContext *context,
1916 const gchar *class_name)
1918 GtkStyleContextPrivate *priv;
1922 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
1923 g_return_val_if_fail (class_name != NULL, FALSE);
1925 class_quark = g_quark_try_string (class_name);
1930 priv = context->priv;
1934 if (style_class_find (info->style_classes, class_quark, NULL))
1941 * gtk_style_context_list_classes:
1942 * @context: a #GtkStyleContext
1944 * Returns the list of classes currently defined in @context.
1946 * Returns: (transfer container) (element-type utf8): a #GList of
1947 * strings with the currently defined classes. The contents
1948 * of the list are owned by GTK+, but you must free the list
1949 * itself with g_list_free() when you are done with it.
1954 gtk_style_context_list_classes (GtkStyleContext *context)
1956 GtkStyleContextPrivate *priv;
1958 GList *classes = NULL;
1961 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
1963 priv = context->priv;
1967 for (i = 0; i < info->style_classes->len; i++)
1971 quark = g_array_index (info->style_classes, GQuark, i);
1972 classes = g_list_prepend (classes, (gchar *) g_quark_to_string (quark));
1979 * gtk_style_context_list_regions:
1980 * @context: a #GtkStyleContext
1982 * Returns the list of regions currently defined in @context.
1984 * Returns: (transfer container) (element-type utf8): a #GList of
1985 * strings with the currently defined regions. The contents
1986 * of the list are owned by GTK+, but you must free the list
1987 * itself with g_list_free() when you are done with it.
1992 gtk_style_context_list_regions (GtkStyleContext *context)
1994 GtkStyleContextPrivate *priv;
1996 GList *classes = NULL;
1999 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2001 priv = context->priv;
2005 for (i = 0; i < info->regions->len; i++)
2008 const gchar *class_name;
2010 region = &g_array_index (info->regions, GtkRegion, i);
2012 class_name = g_quark_to_string (region->class_quark);
2013 classes = g_list_prepend (classes, (gchar *) class_name);
2020 _gtk_style_context_check_region_name (const gchar *str)
2022 g_return_val_if_fail (str != NULL, FALSE);
2024 if (!g_ascii_islower (str[0]))
2030 !g_ascii_islower (*str))
2040 * gtk_style_context_add_region:
2041 * @context: a #GtkStyleContext
2042 * @region_name: region name to use in styling
2043 * @flags: flags that apply to the region
2045 * Adds a region to @context, so posterior calls to
2046 * gtk_style_context_get() or any of the gtk_render_*()
2047 * functions will make use of this new region for styling.
2049 * In the CSS file format, a #GtkTreeView defining a "row"
2050 * region, would be matched by:
2053 * GtkTreeView row { ... }
2056 * Pseudo-classes are used for matching @flags, so the two
2059 * GtkTreeView row:nth-child(even) { ... }
2060 * GtkTreeView row:nth-child(odd) { ... }
2063 * would apply to even and odd rows, respectively.
2065 * <note><para>Region names must only contain lowercase letters
2066 * and '-', starting always with a lowercase letter.</para></note>
2071 gtk_style_context_add_region (GtkStyleContext *context,
2072 const gchar *region_name,
2073 GtkRegionFlags flags)
2075 GtkStyleContextPrivate *priv;
2077 GQuark region_quark;
2080 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2081 g_return_if_fail (region_name != NULL);
2082 g_return_if_fail (_gtk_style_context_check_region_name (region_name));
2084 priv = context->priv;
2085 region_quark = g_quark_from_string (region_name);
2089 if (!region_find (info->regions, region_quark, &position))
2093 region.class_quark = region_quark;
2094 region.flags = flags;
2096 g_array_insert_val (info->regions, position, region);
2098 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
2103 * gtk_style_context_remove_region:
2104 * @context: a #GtkStyleContext
2105 * @region_name: region name to unset
2107 * Removes a region from @context.
2112 gtk_style_context_remove_region (GtkStyleContext *context,
2113 const gchar *region_name)
2115 GtkStyleContextPrivate *priv;
2117 GQuark region_quark;
2120 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2121 g_return_if_fail (region_name != NULL);
2123 region_quark = g_quark_try_string (region_name);
2128 priv = context->priv;
2132 if (region_find (info->regions, region_quark, &position))
2134 g_array_remove_index (info->regions, position);
2136 gtk_style_context_queue_invalidate_internal (context, GTK_CSS_CHANGE_REGION);
2141 * gtk_style_context_has_region:
2142 * @context: a #GtkStyleContext
2143 * @region_name: a region name
2144 * @flags_return: (out) (allow-none): return location for region flags
2146 * Returns %TRUE if @context has the region defined.
2147 * If @flags_return is not %NULL, it is set to the flags
2148 * affecting the region.
2150 * Returns: %TRUE if region is defined
2155 gtk_style_context_has_region (GtkStyleContext *context,
2156 const gchar *region_name,
2157 GtkRegionFlags *flags_return)
2159 GtkStyleContextPrivate *priv;
2161 GQuark region_quark;
2164 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2165 g_return_val_if_fail (region_name != NULL, FALSE);
2170 region_quark = g_quark_try_string (region_name);
2175 priv = context->priv;
2179 if (region_find (info->regions, region_quark, &position))
2185 region = &g_array_index (info->regions, GtkRegion, position);
2186 *flags_return = region->flags;
2195 style_property_values_cmp (gconstpointer bsearch_node1,
2196 gconstpointer bsearch_node2)
2198 const PropertyValue *val1 = bsearch_node1;
2199 const PropertyValue *val2 = bsearch_node2;
2201 if (val1->widget_type != val2->widget_type)
2202 return val1->widget_type < val2->widget_type ? -1 : 1;
2204 if (val1->pspec != val2->pspec)
2205 return val1->pspec < val2->pspec ? -1 : 1;
2207 if (val1->state != val2->state)
2208 return val1->state < val2->state ? -1 : 1;
2214 _gtk_style_context_peek_property (GtkStyleContext *context,
2217 StyleData *data = style_data_lookup (context);
2219 return _gtk_css_computed_values_get_value (data->store, property_id);
2223 _gtk_style_context_get_number (GtkStyleContext *context,
2225 double one_hundred_percent)
2229 value = _gtk_style_context_peek_property (context, property_id);
2230 return _gtk_css_number_value_get (value, one_hundred_percent);
2234 _gtk_style_context_peek_style_property (GtkStyleContext *context,
2236 GtkStateFlags state,
2239 GtkStyleContextPrivate *priv;
2240 PropertyValue *pcache, key = { 0 };
2244 priv = context->priv;
2246 data = style_data_lookup_for_state (context, state);
2248 key.widget_type = widget_type;
2252 /* need value cache array */
2253 if (!data->property_cache)
2254 data->property_cache = g_array_new (FALSE, FALSE, sizeof (PropertyValue));
2257 pcache = bsearch (&key,
2258 data->property_cache->data, data->property_cache->len,
2259 sizeof (PropertyValue), style_property_values_cmp);
2261 return &pcache->value;
2265 while (i < data->property_cache->len &&
2266 style_property_values_cmp (&key, &g_array_index (data->property_cache, PropertyValue, i)) >= 0)
2269 g_array_insert_val (data->property_cache, i, key);
2270 pcache = &g_array_index (data->property_cache, PropertyValue, i);
2272 /* cache miss, initialize value type, then set contents */
2273 g_param_spec_ref (pcache->pspec);
2274 g_value_init (&pcache->value, G_PARAM_SPEC_VALUE_TYPE (pspec));
2276 if (priv->widget || priv->widget_path)
2278 GtkWidgetPath *widget_path = priv->widget ? _gtk_widget_create_path (priv->widget) : priv->widget_path;
2280 if (gtk_style_provider_get_style_property (GTK_STYLE_PROVIDER (priv->cascade),
2282 state, pspec, &pcache->value))
2284 /* Resolve symbolic colors to GdkColor/GdkRGBA */
2285 if (G_VALUE_TYPE (&pcache->value) == GTK_TYPE_SYMBOLIC_COLOR)
2287 GtkSymbolicColor *color;
2290 color = g_value_dup_boxed (&pcache->value);
2292 g_value_unset (&pcache->value);
2294 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2295 g_value_init (&pcache->value, GDK_TYPE_RGBA);
2297 g_value_init (&pcache->value, GDK_TYPE_COLOR);
2299 if (_gtk_style_context_resolve_color (context, color, &rgba, NULL))
2301 if (G_PARAM_SPEC_VALUE_TYPE (pspec) == GDK_TYPE_RGBA)
2302 g_value_set_boxed (&pcache->value, &rgba);
2307 rgb.red = rgba.red * 65535. + 0.5;
2308 rgb.green = rgba.green * 65535. + 0.5;
2309 rgb.blue = rgba.blue * 65535. + 0.5;
2311 g_value_set_boxed (&pcache->value, &rgb);
2315 g_param_value_set_default (pspec, &pcache->value);
2317 gtk_symbolic_color_unref (color);
2321 gtk_widget_path_free (widget_path);
2323 return &pcache->value;
2327 gtk_widget_path_free (widget_path);
2330 /* not supplied by any provider, revert to default */
2331 g_param_value_set_default (pspec, &pcache->value);
2333 return &pcache->value;
2337 * gtk_style_context_get_style_property:
2338 * @context: a #GtkStyleContext
2339 * @property_name: the name of the widget style property
2340 * @value: Return location for the property value
2342 * Gets the value for a widget style property.
2344 * When @value is no longer needed, g_value_unset() must be called
2345 * to free any allocated memory.
2348 gtk_style_context_get_style_property (GtkStyleContext *context,
2349 const gchar *property_name,
2352 GtkStyleContextPrivate *priv;
2353 GtkWidgetClass *widget_class;
2354 GtkStateFlags state;
2356 const GValue *peek_value;
2359 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2360 g_return_if_fail (property_name != NULL);
2361 g_return_if_fail (value != NULL);
2363 priv = context->priv;
2367 widget_type = G_OBJECT_TYPE (priv->widget);
2371 if (!priv->widget_path)
2374 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2376 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2378 g_warning ("%s: can't get style properties for non-widget class `%s'",
2380 g_type_name (widget_type));
2385 widget_class = g_type_class_ref (widget_type);
2386 pspec = gtk_widget_class_find_style_property (widget_class, property_name);
2387 g_type_class_unref (widget_class);
2391 g_warning ("%s: widget class `%s' has no style property named `%s'",
2393 g_type_name (widget_type),
2398 state = gtk_style_context_get_state (context);
2399 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2402 if (G_VALUE_TYPE (value) == G_VALUE_TYPE (peek_value))
2403 g_value_copy (peek_value, value);
2404 else if (g_value_type_transformable (G_VALUE_TYPE (peek_value), G_VALUE_TYPE (value)))
2405 g_value_transform (peek_value, value);
2407 g_warning ("can't retrieve style property `%s' of type `%s' as value of type `%s'",
2409 G_VALUE_TYPE_NAME (peek_value),
2410 G_VALUE_TYPE_NAME (value));
2414 * gtk_style_context_get_style_valist:
2415 * @context: a #GtkStyleContext
2416 * @args: va_list of property name/return location pairs, followed by %NULL
2418 * Retrieves several widget style properties from @context according to the
2424 gtk_style_context_get_style_valist (GtkStyleContext *context,
2427 GtkStyleContextPrivate *priv;
2428 const gchar *prop_name;
2429 GtkStateFlags state;
2432 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2434 prop_name = va_arg (args, const gchar *);
2435 priv = context->priv;
2439 widget_type = G_OBJECT_TYPE (priv->widget);
2443 if (!priv->widget_path)
2446 widget_type = gtk_widget_path_get_object_type (priv->widget_path);
2448 if (!g_type_is_a (widget_type, GTK_TYPE_WIDGET))
2450 g_warning ("%s: can't get style properties for non-widget class `%s'",
2452 g_type_name (widget_type));
2457 state = gtk_style_context_get_state (context);
2461 GtkWidgetClass *widget_class;
2463 const GValue *peek_value;
2466 widget_class = g_type_class_ref (widget_type);
2467 pspec = gtk_widget_class_find_style_property (widget_class, prop_name);
2468 g_type_class_unref (widget_class);
2472 g_warning ("%s: widget class `%s' has no style property named `%s'",
2474 g_type_name (widget_type),
2479 peek_value = _gtk_style_context_peek_style_property (context, widget_type,
2482 G_VALUE_LCOPY (peek_value, args, 0, &error);
2486 g_warning ("can't retrieve style property `%s' of type `%s': %s",
2488 G_VALUE_TYPE_NAME (peek_value),
2494 prop_name = va_arg (args, const gchar *);
2499 * gtk_style_context_get_style:
2500 * @context: a #GtkStyleContext
2501 * @...: property name /return value pairs, followed by %NULL
2503 * Retrieves several widget style properties from @context according to the
2509 gtk_style_context_get_style (GtkStyleContext *context,
2514 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2516 va_start (args, context);
2517 gtk_style_context_get_style_valist (context, args);
2523 * gtk_style_context_lookup_icon_set:
2524 * @context: a #GtkStyleContext
2525 * @stock_id: an icon name
2527 * Looks up @stock_id in the icon factories associated to @context and
2528 * the default icon factory, returning an icon set if found, otherwise
2531 * Returns: (transfer none): The looked up %GtkIconSet, or %NULL
2534 gtk_style_context_lookup_icon_set (GtkStyleContext *context,
2535 const gchar *stock_id)
2537 GtkStyleContextPrivate *priv;
2539 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2540 g_return_val_if_fail (stock_id != NULL, NULL);
2542 priv = context->priv;
2543 g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
2545 return gtk_icon_factory_lookup_default (stock_id);
2549 * gtk_style_context_set_screen:
2550 * @context: a #GtkStyleContext
2551 * @screen: a #GdkScreen
2553 * Attaches @context to the given screen.
2555 * The screen is used to add style information from 'global' style
2556 * providers, such as the screens #GtkSettings instance.
2558 * If you are using a #GtkStyleContext returned from
2559 * gtk_widget_get_style_context(), you do not need to
2560 * call this yourself.
2565 gtk_style_context_set_screen (GtkStyleContext *context,
2568 GtkStyleContextPrivate *priv;
2570 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2571 g_return_if_fail (GDK_IS_SCREEN (screen));
2573 priv = context->priv;
2574 if (priv->screen == screen)
2577 if (priv->cascade == _gtk_style_cascade_get_for_screen (priv->screen))
2579 gtk_style_context_set_cascade (context, _gtk_style_cascade_get_for_screen (screen));
2583 _gtk_style_cascade_set_parent (priv->cascade, _gtk_style_cascade_get_for_screen (screen));
2586 priv->screen = screen;
2588 g_object_notify (G_OBJECT (context), "screen");
2592 * gtk_style_context_get_screen:
2593 * @context: a #GtkStyleContext
2595 * Returns the #GdkScreen to which @context is attached.
2597 * Returns: (transfer none): a #GdkScreen.
2600 gtk_style_context_get_screen (GtkStyleContext *context)
2602 GtkStyleContextPrivate *priv;
2604 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
2606 priv = context->priv;
2607 return priv->screen;
2611 * gtk_style_context_set_direction:
2612 * @context: a #GtkStyleContext
2613 * @direction: the new direction.
2615 * Sets the reading direction for rendering purposes.
2617 * If you are using a #GtkStyleContext returned from
2618 * gtk_widget_get_style_context(), you do not need to
2619 * call this yourself.
2624 gtk_style_context_set_direction (GtkStyleContext *context,
2625 GtkTextDirection direction)
2627 GtkStyleContextPrivate *priv;
2629 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2631 priv = context->priv;
2632 priv->direction = direction;
2634 g_object_notify (G_OBJECT (context), "direction");
2638 * gtk_style_context_get_direction:
2639 * @context: a #GtkStyleContext
2641 * Returns the widget direction used for rendering.
2643 * Returns: the widget direction
2648 gtk_style_context_get_direction (GtkStyleContext *context)
2650 GtkStyleContextPrivate *priv;
2652 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), GTK_TEXT_DIR_LTR);
2654 priv = context->priv;
2655 return priv->direction;
2659 * gtk_style_context_set_junction_sides:
2660 * @context: a #GtkStyleContext
2661 * @sides: sides where rendered elements are visually connected to
2664 * Sets the sides where rendered elements (mostly through
2665 * gtk_render_frame()) will visually connect with other visual elements.
2667 * This is merely a hint that may or may not be honored
2668 * by theming engines.
2670 * Container widgets are expected to set junction hints as appropriate
2671 * for their children, so it should not normally be necessary to call
2672 * this function manually.
2677 gtk_style_context_set_junction_sides (GtkStyleContext *context,
2678 GtkJunctionSides sides)
2680 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2682 context->priv->info->junction_sides = sides;
2686 * gtk_style_context_get_junction_sides:
2687 * @context: a #GtkStyleContext
2689 * Returns the sides where rendered elements connect visually with others.
2691 * Returns: the junction sides
2696 gtk_style_context_get_junction_sides (GtkStyleContext *context)
2698 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), 0);
2700 return context->priv->info->junction_sides;
2704 _gtk_style_context_resolve_color_value (GtkStyleContext *context,
2705 GtkCssValue *current,
2706 GtkCssDependencies current_deps,
2708 GtkCssDependencies *dependencies)
2710 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2711 g_return_val_if_fail (current != NULL, FALSE);
2712 g_return_val_if_fail (color != NULL, FALSE);
2714 return _gtk_symbolic_color_resolve_full ((GtkSymbolicColor *) color,
2715 GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade),
2723 _gtk_style_context_resolve_color (GtkStyleContext *context,
2724 GtkSymbolicColor *color,
2726 GtkCssDependencies *dependencies)
2730 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2731 g_return_val_if_fail (color != NULL, FALSE);
2732 g_return_val_if_fail (result != NULL, FALSE);
2734 val = _gtk_symbolic_color_resolve_full (color,
2735 GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade),
2736 _gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_COLOR),
2737 GTK_CSS_DEPENDS_ON_COLOR,
2742 *result = *_gtk_css_rgba_value_get_rgba (val);
2743 _gtk_css_value_unref (val);
2748 * gtk_style_context_lookup_color:
2749 * @context: a #GtkStyleContext
2750 * @color_name: color name to lookup
2751 * @color: (out): Return location for the looked up color
2753 * Looks up and resolves a color name in the @context color map.
2755 * Returns: %TRUE if @color_name was found and resolved, %FALSE otherwise
2758 gtk_style_context_lookup_color (GtkStyleContext *context,
2759 const gchar *color_name,
2762 GtkSymbolicColor *sym_color;
2764 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), FALSE);
2765 g_return_val_if_fail (color_name != NULL, FALSE);
2766 g_return_val_if_fail (color != NULL, FALSE);
2768 sym_color = _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (context->priv->cascade), color_name);
2769 if (sym_color == NULL)
2772 return _gtk_style_context_resolve_color (context, sym_color, color, NULL);
2776 * gtk_style_context_notify_state_change:
2777 * @context: a #GtkStyleContext
2778 * @window: a #GdkWindow
2779 * @region_id: (allow-none): animatable region to notify on, or %NULL.
2780 * See gtk_style_context_push_animatable_region()
2781 * @state: state to trigger transition for
2782 * @state_value: %TRUE if @state is the state we are changing to,
2783 * %FALSE if we are changing away from it
2785 * Notifies a state change on @context, so if the current style makes use
2786 * of transition animations, one will be started so all rendered elements
2787 * under @region_id are animated for state @state being set to value
2790 * The @window parameter is used in order to invalidate the rendered area
2791 * as the animation runs, so make sure it is the same window that is being
2792 * rendered on by the gtk_render_*() functions.
2794 * If @region_id is %NULL, all rendered elements using @context will be
2795 * affected by this state transition.
2797 * As a practical example, a #GtkButton notifying a state transition on
2798 * the prelight state:
2800 * gtk_style_context_notify_state_change (context,
2801 * gtk_widget_get_window (widget),
2803 * GTK_STATE_PRELIGHT,
2804 * button->in_button);
2807 * Can be handled in the CSS file like this:
2810 * background-color: #f00
2814 * background-color: #fff;
2815 * transition: 200ms linear
2819 * This combination will animate the button background from red to white
2820 * if a pointer enters the button, and back to red if the pointer leaves
2823 * Note that @state is used when finding the transition parameters, which
2824 * is why the style places the transition under the :hover pseudo-class.
2828 * Deprecated: 3.6: This function does nothing.
2831 gtk_style_context_notify_state_change (GtkStyleContext *context,
2835 gboolean state_value)
2837 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2838 g_return_if_fail (GDK_IS_WINDOW (window));
2839 g_return_if_fail (state > GTK_STATE_NORMAL && state <= GTK_STATE_FOCUSED);
2840 g_return_if_fail (context->priv->widget != NULL || context->priv->widget_path != NULL);
2844 * gtk_style_context_cancel_animations:
2845 * @context: a #GtkStyleContext
2846 * @region_id: (allow-none): animatable region to stop, or %NULL.
2847 * See gtk_style_context_push_animatable_region()
2849 * Stops all running animations for @region_id and all animatable
2850 * regions underneath.
2852 * A %NULL @region_id will stop all ongoing animations in @context,
2853 * when dealing with a #GtkStyleContext obtained through
2854 * gtk_widget_get_style_context(), this is normally done for you
2855 * in all circumstances you would expect all widget to be stopped,
2856 * so this should be only used in complex widgets with different
2857 * animatable regions.
2861 * Deprecated: 3.6: This function does nothing.
2864 gtk_style_context_cancel_animations (GtkStyleContext *context,
2867 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2871 * gtk_style_context_scroll_animations:
2872 * @context: a #GtkStyleContext
2873 * @window: a #GdkWindow used previously in
2874 * gtk_style_context_notify_state_change()
2875 * @dx: Amount to scroll in the X axis
2876 * @dy: Amount to scroll in the Y axis
2878 * This function is analogous to gdk_window_scroll(), and
2879 * should be called together with it so the invalidation
2880 * areas for any ongoing animation are scrolled together
2885 * Deprecated: 3.6: This function does nothing.
2888 gtk_style_context_scroll_animations (GtkStyleContext *context,
2893 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2894 g_return_if_fail (GDK_IS_WINDOW (window));
2898 * gtk_style_context_push_animatable_region:
2899 * @context: a #GtkStyleContext
2900 * @region_id: unique identifier for the animatable region
2902 * Pushes an animatable region, so all further gtk_render_*() calls between
2903 * this call and the following gtk_style_context_pop_animatable_region()
2904 * will potentially show transition animations for this region if
2905 * gtk_style_context_notify_state_change() is called for a given state,
2906 * and the current theme/style defines transition animations for state
2909 * The @region_id used must be unique in @context so the theming engine
2910 * can uniquely identify rendered elements subject to a state transition.
2914 * Deprecated: 3.6: This function does nothing.
2917 gtk_style_context_push_animatable_region (GtkStyleContext *context,
2920 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2921 g_return_if_fail (region_id != NULL);
2925 * gtk_style_context_pop_animatable_region:
2926 * @context: a #GtkStyleContext
2928 * Pops an animatable region from @context.
2929 * See gtk_style_context_push_animatable_region().
2933 * Deprecated: 3.6: This function does nothing.
2936 gtk_style_context_pop_animatable_region (GtkStyleContext *context)
2938 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2942 gtk_style_context_clear_cache (GtkStyleContext *context)
2944 GtkStyleContextPrivate *priv;
2947 priv = context->priv;
2949 for (info = priv->info; info; info = info->next)
2951 style_info_set_data (info, NULL);
2953 g_hash_table_remove_all (priv->style_data);
2957 gtk_style_context_update_cache (GtkStyleContext *context,
2958 const GtkBitmask *parent_changes)
2960 GtkStyleContextPrivate *priv;
2961 GHashTableIter iter;
2962 gpointer key, value;
2964 priv = context->priv;
2966 g_hash_table_iter_init (&iter, priv->style_data);
2967 while (g_hash_table_iter_next (&iter, &key, &value))
2969 GtkStyleInfo *info = key;
2970 StyleData *data = value;
2971 GtkBitmask *changes;
2973 changes = _gtk_bitmask_copy (parent_changes);
2974 changes = _gtk_bitmask_intersect (changes, data->store->depends_on_parent);
2975 if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
2976 changes = _gtk_bitmask_union (changes, data->store->depends_on_color);
2977 if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
2978 changes = _gtk_bitmask_union (changes, data->store->depends_on_font_size);
2980 build_properties (context, data->store, info, changes);
2985 gtk_style_context_do_invalidate (GtkStyleContext *context)
2987 GtkStyleContextPrivate *priv;
2989 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
2991 priv = context->priv;
2993 /* Avoid reentrancy */
2994 if (priv->invalidating_context)
2997 priv->invalidating_context = TRUE;
2999 g_signal_emit (context, signals[CHANGED], 0);
3001 priv->invalidating_context = FALSE;
3005 gtk_style_context_update_animations (GtkStyleContext *context,
3008 GtkBitmask *differences;
3009 StyleData *style_data;
3011 style_data = style_data_lookup (context);
3013 differences = _gtk_css_computed_values_advance (style_data->store,
3016 if (_gtk_css_computed_values_is_static (style_data->store))
3017 _gtk_style_context_update_animating (context);
3023 gtk_style_context_needs_full_revalidate (GtkStyleContext *context,
3024 GtkCssChange change)
3026 GtkStyleContextPrivate *priv = context->priv;
3028 /* Try to avoid invalidating if we can */
3029 if (change & GTK_STYLE_CONTEXT_RADICAL_CHANGE)
3031 priv->relevant_changes = GTK_CSS_CHANGE_ANY;
3035 if (priv->relevant_changes == GTK_CSS_CHANGE_ANY)
3037 GtkWidgetPath *path;
3038 GtkCssMatcher matcher;
3040 path = create_query_path (context, priv->info);
3041 if (_gtk_css_matcher_init (&matcher, path, priv->info->state_flags))
3042 priv->relevant_changes = _gtk_style_provider_private_get_change (GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
3045 priv->relevant_changes = 0;
3047 priv->relevant_changes &= ~GTK_STYLE_CONTEXT_RADICAL_CHANGE;
3049 gtk_widget_path_unref (path);
3053 if (priv->relevant_changes & change)
3060 gtk_style_context_should_create_transitions (GtkStyleContext *context)
3062 GtkStyleContextPrivate *priv;
3065 priv = context->priv;
3067 if (priv->widget == NULL)
3070 if (!gtk_widget_get_mapped (priv->widget))
3073 g_object_get (gtk_widget_get_settings (context->priv->widget),
3074 "gtk-enable-animations", &animate,
3081 _gtk_style_context_validate (GtkStyleContext *context,
3083 GtkCssChange change,
3084 const GtkBitmask *parent_changes)
3086 GtkStyleContextPrivate *priv;
3089 GtkBitmask *changes;
3092 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3094 priv = context->priv;
3096 change |= priv->pending_changes;
3098 /* If you run your application with
3099 * GTK_DEBUG=no-css-cache
3100 * every invalidation will purge the cache and completely query
3101 * everything anew form the cache. This is slow (in particular
3102 * when animating), but useful for figuring out bugs.
3104 * We achieve that by pretending that everything that could have
3105 * changed has and so we of course totally need to redo everything.
3107 * Note that this also completely revalidates child widgets all
3110 if (G_UNLIKELY (gtk_get_debug_flags () & GTK_DEBUG_NO_CSS_CACHE))
3111 change = GTK_CSS_CHANGE_ANY;
3113 if (!priv->invalid && change == 0 && _gtk_bitmask_is_empty (parent_changes))
3116 priv->pending_changes = 0;
3117 gtk_style_context_set_invalid (context, FALSE);
3121 current = style_data_ref (info->data);
3125 /* Try to avoid invalidating if we can */
3126 if (current == NULL ||
3127 gtk_style_context_needs_full_revalidate (context, change))
3131 if ((priv->relevant_changes & change) & ~GTK_STYLE_CONTEXT_CACHED_CHANGE)
3133 gtk_style_context_clear_cache (context);
3137 gtk_style_context_update_cache (context, parent_changes);
3138 style_info_set_data (info, NULL);
3141 data = style_data_lookup (context);
3143 _gtk_css_computed_values_create_animations (data->store,
3144 priv->parent ? style_data_lookup (priv->parent)->store : NULL,
3146 GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
3147 current && gtk_style_context_should_create_transitions (context) ? current->store : NULL);
3148 if (_gtk_css_computed_values_is_static (data->store))
3149 change &= ~GTK_CSS_CHANGE_ANIMATE;
3151 change |= GTK_CSS_CHANGE_ANIMATE;
3152 _gtk_style_context_update_animating (context);
3156 changes = _gtk_css_computed_values_get_difference (data->store, current->store);
3158 /* In the case where we keep the cache, we want unanimated values */
3159 _gtk_css_computed_values_cancel_animations (current->store);
3163 changes = _gtk_bitmask_new ();
3164 changes = _gtk_bitmask_invert_range (changes, 0, _gtk_css_style_property_get_n_properties ());
3169 changes = _gtk_bitmask_copy (parent_changes);
3170 changes = _gtk_bitmask_intersect (changes, current->store->depends_on_parent);
3171 if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_COLOR))
3172 changes = _gtk_bitmask_union (changes, current->store->depends_on_color);
3173 if (_gtk_bitmask_get (changes, GTK_CSS_PROPERTY_FONT_SIZE))
3174 changes = _gtk_bitmask_union (changes, current->store->depends_on_font_size);
3176 gtk_style_context_update_cache (context, parent_changes);
3180 style_data_unref (current);
3182 if (change & GTK_CSS_CHANGE_ANIMATE &&
3183 gtk_style_context_is_animating (context))
3185 GtkBitmask *animation_changes;
3187 animation_changes = gtk_style_context_update_animations (context, timestamp);
3188 changes = _gtk_bitmask_union (changes, animation_changes);
3189 _gtk_bitmask_free (animation_changes);
3192 if (!_gtk_bitmask_is_empty (changes))
3193 gtk_style_context_do_invalidate (context);
3195 change = _gtk_css_change_for_child (change);
3196 for (list = priv->children; list; list = list->next)
3198 _gtk_style_context_validate (list->data, timestamp, change, changes);
3201 _gtk_bitmask_free (changes);
3205 _gtk_style_context_queue_invalidate (GtkStyleContext *context,
3206 GtkCssChange change)
3208 GtkStyleContextPrivate *priv;
3210 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3211 g_return_if_fail (change != 0);
3213 priv = context->priv;
3215 if (priv->widget != NULL)
3217 priv->pending_changes |= change;
3218 gtk_style_context_set_invalid (context, TRUE);
3220 else if (priv->widget_path == NULL)
3222 gtk_style_context_invalidate (context);
3227 * gtk_style_context_invalidate:
3228 * @context: a #GtkStyleContext.
3230 * Invalidates @context style information, so it will be reconstructed
3233 * If you're using a #GtkStyleContext returned from
3234 * gtk_widget_get_style_context(), you do not need to
3235 * call this yourself.
3240 gtk_style_context_invalidate (GtkStyleContext *context)
3242 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3244 gtk_style_context_clear_cache (context);
3245 gtk_style_context_do_invalidate (context);
3249 * gtk_style_context_set_background:
3250 * @context: a #GtkStyleContext
3251 * @window: a #GdkWindow
3253 * Sets the background of @window to the background pattern or
3254 * color specified in @context for its current state.
3259 gtk_style_context_set_background (GtkStyleContext *context,
3262 GtkStateFlags state;
3263 cairo_pattern_t *pattern;
3266 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3267 g_return_if_fail (GDK_IS_WINDOW (window));
3269 state = gtk_style_context_get_state (context);
3270 gtk_style_context_get (context, state,
3271 "background-image", &pattern,
3275 gdk_window_set_background_pattern (window, pattern);
3276 cairo_pattern_destroy (pattern);
3280 gtk_style_context_get (context, state,
3281 "background-color", &color,
3285 gdk_window_set_background_rgba (window, color);
3286 gdk_rgba_free (color);
3291 * gtk_style_context_get_color:
3292 * @context: a #GtkStyleContext
3293 * @state: state to retrieve the color for
3294 * @color: (out): return value for the foreground color
3296 * Gets the foreground color for a given state.
3301 gtk_style_context_get_color (GtkStyleContext *context,
3302 GtkStateFlags state,
3307 g_return_if_fail (color != NULL);
3308 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3310 gtk_style_context_get (context,
3320 * gtk_style_context_get_background_color:
3321 * @context: a #GtkStyleContext
3322 * @state: state to retrieve the color for
3323 * @color: (out): return value for the background color
3325 * Gets the background color for a given state.
3330 gtk_style_context_get_background_color (GtkStyleContext *context,
3331 GtkStateFlags state,
3336 g_return_if_fail (color != NULL);
3337 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3339 gtk_style_context_get (context,
3341 "background-color", &c,
3349 * gtk_style_context_get_border_color:
3350 * @context: a #GtkStyleContext
3351 * @state: state to retrieve the color for
3352 * @color: (out): return value for the border color
3354 * Gets the border color for a given state.
3359 gtk_style_context_get_border_color (GtkStyleContext *context,
3360 GtkStateFlags state,
3365 g_return_if_fail (color != NULL);
3366 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3368 gtk_style_context_get (context,
3378 * gtk_style_context_get_border:
3379 * @context: a #GtkStyleContext
3380 * @state: state to retrieve the border for
3381 * @border: (out): return value for the border settings
3383 * Gets the border for a given state as a #GtkBorder.
3384 * See %GTK_STYLE_PROPERTY_BORDER_WIDTH.
3389 gtk_style_context_get_border (GtkStyleContext *context,
3390 GtkStateFlags state,
3393 int top, left, bottom, right;
3395 g_return_if_fail (border != NULL);
3396 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3398 gtk_style_context_get (context,
3400 "border-top-width", &top,
3401 "border-left-width", &left,
3402 "border-bottom-width", &bottom,
3403 "border-right-width", &right,
3407 border->left = left;
3408 border->bottom = bottom;
3409 border->right = right;
3413 * gtk_style_context_get_padding:
3414 * @context: a #GtkStyleContext
3415 * @state: state to retrieve the padding for
3416 * @padding: (out): return value for the padding settings
3418 * Gets the padding for a given state as a #GtkBorder.
3419 * See %GTK_STYLE_PROPERTY_PADDING.
3424 gtk_style_context_get_padding (GtkStyleContext *context,
3425 GtkStateFlags state,
3428 int top, left, bottom, right;
3430 g_return_if_fail (padding != NULL);
3431 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3433 gtk_style_context_get (context,
3435 "padding-top", &top,
3436 "padding-left", &left,
3437 "padding-bottom", &bottom,
3438 "padding-right", &right,
3442 padding->left = left;
3443 padding->bottom = bottom;
3444 padding->right = right;
3448 * gtk_style_context_get_margin:
3449 * @context: a #GtkStyleContext
3450 * @state: state to retrieve the border for
3451 * @margin: (out): return value for the margin settings
3453 * Gets the margin for a given state as a #GtkBorder.
3454 * See %GTK_STYLE_PROPERTY_MARGIN.
3459 gtk_style_context_get_margin (GtkStyleContext *context,
3460 GtkStateFlags state,
3463 int top, left, bottom, right;
3465 g_return_if_fail (margin != NULL);
3466 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3468 gtk_style_context_get (context,
3471 "margin-left", &left,
3472 "margin-bottom", &bottom,
3473 "margin-right", &right,
3477 margin->left = left;
3478 margin->bottom = bottom;
3479 margin->right = right;
3483 * gtk_style_context_get_font:
3484 * @context: a #GtkStyleContext
3485 * @state: state to retrieve the font for
3487 * Returns the font description for a given state. The returned
3488 * object is const and will remain valid until the
3489 * #GtkStyleContext::changed signal happens.
3491 * Returns: (transfer none): the #PangoFontDescription for the given
3492 * state. This object is owned by GTK+ and should not be
3497 const PangoFontDescription *
3498 gtk_style_context_get_font (GtkStyleContext *context,
3499 GtkStateFlags state)
3501 GtkStyleContextPrivate *priv;
3503 PangoFontDescription *description;
3505 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
3507 priv = context->priv;
3508 g_return_val_if_fail (priv->widget != NULL || priv->widget_path != NULL, NULL);
3510 data = style_data_lookup_for_state (context, state);
3512 /* Yuck, fonts are created on-demand but we don't return a ref.
3513 * Do bad things to achieve this requirement */
3514 description = g_object_get_data (G_OBJECT (data->store), "font-cache-for-get_font");
3515 if (description == NULL)
3517 gtk_style_context_get (context, state, "font", &description, NULL);
3518 g_object_set_data_full (G_OBJECT (data->store),
3519 "font-cache-for-get_font",
3521 (GDestroyNotify) pango_font_description_free);
3527 get_cursor_color (GtkStyleContext *context,
3531 GdkColor *style_color;
3533 gtk_style_context_get_style (context,
3534 primary ? "cursor-color" : "secondary-cursor-color",
3540 color->red = style_color->red / 65535.0;
3541 color->green = style_color->green / 65535.0;
3542 color->blue = style_color->blue / 65535.0;
3545 gdk_color_free (style_color);
3549 gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, color);
3555 gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bg);
3557 color->red = (color->red + bg.red) * 0.5;
3558 color->green = (color->green + bg.green) * 0.5;
3559 color->blue = (color->blue + bg.blue) * 0.5;
3565 _gtk_style_context_get_cursor_color (GtkStyleContext *context,
3566 GdkRGBA *primary_color,
3567 GdkRGBA *secondary_color)
3570 get_cursor_color (context, TRUE, primary_color);
3572 if (secondary_color)
3573 get_cursor_color (context, FALSE, secondary_color);
3580 * @context: a #GtkStyleContext
3582 * @x: X origin of the rectangle
3583 * @y: Y origin of the rectangle
3584 * @width: rectangle width
3585 * @height: rectangle height
3587 * Renders a checkmark (as in a #GtkCheckButton).
3589 * The %GTK_STATE_FLAG_ACTIVE state determines whether the check is
3590 * on or off, and %GTK_STATE_FLAG_INCONSISTENT determines whether it
3591 * should be marked as undefined.
3594 * <title>Typical checkmark rendering</title>
3595 * <inlinegraphic fileref="checks.png" format="PNG"/>
3601 gtk_render_check (GtkStyleContext *context,
3608 GtkThemingEngineClass *engine_class;
3609 GtkThemingEngine *engine;
3611 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3612 g_return_if_fail (cr != NULL);
3614 if (width <= 0 || height <= 0)
3617 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3618 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3623 _gtk_theming_engine_set_context (engine, context);
3624 engine_class->render_check (engine, cr,
3625 x, y, width, height);
3631 * gtk_render_option:
3632 * @context: a #GtkStyleContext
3634 * @x: X origin of the rectangle
3635 * @y: Y origin of the rectangle
3636 * @width: rectangle width
3637 * @height: rectangle height
3639 * Renders an option mark (as in a #GtkRadioButton), the %GTK_STATE_FLAG_ACTIVE
3640 * state will determine whether the option is on or off, and
3641 * %GTK_STATE_FLAG_INCONSISTENT whether it should be marked as undefined.
3644 * <title>Typical option mark rendering</title>
3645 * <inlinegraphic fileref="options.png" format="PNG"/>
3651 gtk_render_option (GtkStyleContext *context,
3658 GtkThemingEngineClass *engine_class;
3659 GtkThemingEngine *engine;
3661 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3662 g_return_if_fail (cr != NULL);
3664 if (width <= 0 || height <= 0)
3667 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3668 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3672 _gtk_theming_engine_set_context (engine, context);
3673 engine_class->render_option (engine, cr,
3674 x, y, width, height);
3681 * @context: a #GtkStyleContext
3683 * @angle: arrow angle from 0 to 2 * %G_PI, being 0 the arrow pointing to the north
3684 * @x: X origin of the render area
3685 * @y: Y origin of the render area
3686 * @size: square side for render area
3688 * Renders an arrow pointing to @angle.
3691 * <title>Typical arrow rendering at 0, 1&solidus;2 π, π and 3&solidus;2 π</title>
3692 * <inlinegraphic fileref="arrows.png" format="PNG"/>
3698 gtk_render_arrow (GtkStyleContext *context,
3705 GtkThemingEngineClass *engine_class;
3706 GtkThemingEngine *engine;
3708 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3709 g_return_if_fail (cr != NULL);
3714 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3715 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3719 gtk_style_context_save (context);
3720 gtk_style_context_add_class (context, GTK_STYLE_CLASS_ARROW);
3722 _gtk_theming_engine_set_context (engine, context);
3723 engine_class->render_arrow (engine, cr,
3726 gtk_style_context_restore (context);
3731 * gtk_render_background:
3732 * @context: a #GtkStyleContext
3734 * @x: X origin of the rectangle
3735 * @y: Y origin of the rectangle
3736 * @width: rectangle width
3737 * @height: rectangle height
3739 * Renders the background of an element.
3742 * <title>Typical background rendering, showing the effect of
3743 * <parameter>background-image</parameter>,
3744 * <parameter>border-width</parameter> and
3745 * <parameter>border-radius</parameter></title>
3746 * <inlinegraphic fileref="background.png" format="PNG"/>
3752 gtk_render_background (GtkStyleContext *context,
3759 GtkThemingEngineClass *engine_class;
3760 GtkThemingEngine *engine;
3762 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3763 g_return_if_fail (cr != NULL);
3765 if (width <= 0 || height <= 0)
3768 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3769 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3773 _gtk_theming_engine_set_context (engine, context);
3774 engine_class->render_background (engine, cr, x, y, width, height);
3781 * @context: a #GtkStyleContext
3783 * @x: X origin of the rectangle
3784 * @y: Y origin of the rectangle
3785 * @width: rectangle width
3786 * @height: rectangle height
3788 * Renders a frame around the rectangle defined by @x, @y, @width, @height.
3791 * <title>Examples of frame rendering, showing the effect of
3792 * <parameter>border-image</parameter>,
3793 * <parameter>border-color</parameter>,
3794 * <parameter>border-width</parameter>,
3795 * <parameter>border-radius</parameter> and
3797 * <inlinegraphic fileref="frames.png" format="PNG"/>
3803 gtk_render_frame (GtkStyleContext *context,
3810 GtkThemingEngineClass *engine_class;
3811 GtkThemingEngine *engine;
3813 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3814 g_return_if_fail (cr != NULL);
3816 if (width <= 0 || height <= 0)
3819 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3820 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3824 _gtk_theming_engine_set_context (engine, context);
3825 engine_class->render_frame (engine, cr, x, y, width, height);
3831 * gtk_render_expander:
3832 * @context: a #GtkStyleContext
3834 * @x: X origin of the rectangle
3835 * @y: Y origin of the rectangle
3836 * @width: rectangle width
3837 * @height: rectangle height
3839 * Renders an expander (as used in #GtkTreeView and #GtkExpander) in the area
3840 * defined by @x, @y, @width, @height. The state %GTK_STATE_FLAG_ACTIVE
3841 * determines whether the expander is collapsed or expanded.
3844 * <title>Typical expander rendering</title>
3845 * <inlinegraphic fileref="expanders.png" format="PNG"/>
3851 gtk_render_expander (GtkStyleContext *context,
3858 GtkThemingEngineClass *engine_class;
3859 GtkThemingEngine *engine;
3861 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3862 g_return_if_fail (cr != NULL);
3864 if (width <= 0 || height <= 0)
3867 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3868 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3872 _gtk_theming_engine_set_context (engine, context);
3873 engine_class->render_expander (engine, cr, x, y, width, height);
3880 * @context: a #GtkStyleContext
3882 * @x: X origin of the rectangle
3883 * @y: Y origin of the rectangle
3884 * @width: rectangle width
3885 * @height: rectangle height
3887 * Renders a focus indicator on the rectangle determined by @x, @y, @width, @height.
3889 * <title>Typical focus rendering</title>
3890 * <inlinegraphic fileref="focus.png" format="PNG"/>
3896 gtk_render_focus (GtkStyleContext *context,
3903 GtkThemingEngineClass *engine_class;
3904 GtkThemingEngine *engine;
3906 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3907 g_return_if_fail (cr != NULL);
3909 if (width <= 0 || height <= 0)
3912 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3913 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3917 _gtk_theming_engine_set_context (engine, context);
3918 engine_class->render_focus (engine, cr, x, y, width, height);
3924 * gtk_render_layout:
3925 * @context: a #GtkStyleContext
3929 * @layout: the #PangoLayout to render
3931 * Renders @layout on the coordinates @x, @y
3936 gtk_render_layout (GtkStyleContext *context,
3940 PangoLayout *layout)
3942 GtkThemingEngineClass *engine_class;
3943 GtkThemingEngine *engine;
3944 PangoRectangle extents;
3946 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3947 g_return_if_fail (PANGO_IS_LAYOUT (layout));
3948 g_return_if_fail (cr != NULL);
3950 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3951 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3955 pango_layout_get_extents (layout, &extents, NULL);
3957 _gtk_theming_engine_set_context (engine, context);
3958 engine_class->render_layout (engine, cr, x, y, layout);
3965 * @context: a #GtkStyleContext
3967 * @x0: X coordinate for the origin of the line
3968 * @y0: Y coordinate for the origin of the line
3969 * @x1: X coordinate for the end of the line
3970 * @y1: Y coordinate for the end of the line
3972 * Renders a line from (x0, y0) to (x1, y1).
3977 gtk_render_line (GtkStyleContext *context,
3984 GtkThemingEngineClass *engine_class;
3985 GtkThemingEngine *engine;
3987 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
3988 g_return_if_fail (cr != NULL);
3990 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
3991 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
3995 _gtk_theming_engine_set_context (engine, context);
3996 engine_class->render_line (engine, cr, x0, y0, x1, y1);
4002 * gtk_render_slider:
4003 * @context: a #GtkStyleContext
4005 * @x: X origin of the rectangle
4006 * @y: Y origin of the rectangle
4007 * @width: rectangle width
4008 * @height: rectangle height
4009 * @orientation: orientation of the slider
4011 * Renders a slider (as in #GtkScale) in the rectangle defined by @x, @y,
4012 * @width, @height. @orientation defines whether the slider is vertical
4016 * <title>Typical slider rendering</title>
4017 * <inlinegraphic fileref="sliders.png" format="PNG"/>
4023 gtk_render_slider (GtkStyleContext *context,
4029 GtkOrientation orientation)
4031 GtkThemingEngineClass *engine_class;
4032 GtkThemingEngine *engine;
4034 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4035 g_return_if_fail (cr != NULL);
4037 if (width <= 0 || height <= 0)
4040 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4041 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4045 _gtk_theming_engine_set_context (engine, context);
4046 engine_class->render_slider (engine, cr, x, y, width, height, orientation);
4052 * gtk_render_frame_gap:
4053 * @context: a #GtkStyleContext
4055 * @x: X origin of the rectangle
4056 * @y: Y origin of the rectangle
4057 * @width: rectangle width
4058 * @height: rectangle height
4059 * @gap_side: side where the gap is
4060 * @xy0_gap: initial coordinate (X or Y depending on @gap_side) for the gap
4061 * @xy1_gap: end coordinate (X or Y depending on @gap_side) for the gap
4063 * Renders a frame around the rectangle defined by (@x, @y, @width, @height),
4064 * leaving a gap on one side. @xy0_gap and @xy1_gap will mean X coordinates
4065 * for %GTK_POS_TOP and %GTK_POS_BOTTOM gap sides, and Y coordinates for
4066 * %GTK_POS_LEFT and %GTK_POS_RIGHT.
4069 * <title>Typical rendering of a frame with a gap</title>
4070 * <inlinegraphic fileref="frame-gap.png" format="PNG"/>
4076 gtk_render_frame_gap (GtkStyleContext *context,
4082 GtkPositionType gap_side,
4086 GtkThemingEngineClass *engine_class;
4087 GtkThemingEngine *engine;
4089 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4090 g_return_if_fail (cr != NULL);
4091 g_return_if_fail (xy0_gap <= xy1_gap);
4092 g_return_if_fail (xy0_gap >= 0);
4094 if (width <= 0 || height <= 0)
4097 if (gap_side == GTK_POS_LEFT ||
4098 gap_side == GTK_POS_RIGHT)
4099 g_return_if_fail (xy1_gap <= height);
4101 g_return_if_fail (xy1_gap <= width);
4103 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4104 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4108 _gtk_theming_engine_set_context (engine, context);
4109 engine_class->render_frame_gap (engine, cr,
4110 x, y, width, height, gap_side,
4117 * gtk_render_extension:
4118 * @context: a #GtkStyleContext
4120 * @x: X origin of the rectangle
4121 * @y: Y origin of the rectangle
4122 * @width: rectangle width
4123 * @height: rectangle height
4124 * @gap_side: side where the gap is
4126 * Renders a extension (as in a #GtkNotebook tab) in the rectangle
4127 * defined by @x, @y, @width, @height. The side where the extension
4128 * connects to is defined by @gap_side.
4131 * <title>Typical extension rendering</title>
4132 * <inlinegraphic fileref="extensions.png" format="PNG"/>
4138 gtk_render_extension (GtkStyleContext *context,
4144 GtkPositionType gap_side)
4146 GtkThemingEngineClass *engine_class;
4147 GtkThemingEngine *engine;
4149 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4150 g_return_if_fail (cr != NULL);
4152 if (width <= 0 || height <= 0)
4155 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4156 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4160 _gtk_theming_engine_set_context (engine, context);
4161 engine_class->render_extension (engine, cr, x, y, width, height, gap_side);
4167 * gtk_render_handle:
4168 * @context: a #GtkStyleContext
4170 * @x: X origin of the rectangle
4171 * @y: Y origin of the rectangle
4172 * @width: rectangle width
4173 * @height: rectangle height
4175 * Renders a handle (as in #GtkHandleBox, #GtkPaned and
4176 * #GtkWindow<!-- -->'s resize grip), in the rectangle
4177 * determined by @x, @y, @width, @height.
4180 * <title>Handles rendered for the paned and grip classes</title>
4181 * <inlinegraphic fileref="handles.png" format="PNG"/>
4187 gtk_render_handle (GtkStyleContext *context,
4194 GtkThemingEngineClass *engine_class;
4195 GtkThemingEngine *engine;
4197 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4198 g_return_if_fail (cr != NULL);
4200 if (width <= 0 || height <= 0)
4203 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4204 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4208 _gtk_theming_engine_set_context (engine, context);
4209 engine_class->render_handle (engine, cr, x, y, width, height);
4215 * gtk_render_activity:
4216 * @context: a #GtkStyleContext
4218 * @x: X origin of the rectangle
4219 * @y: Y origin of the rectangle
4220 * @width: rectangle width
4221 * @height: rectangle height
4223 * Renders an activity area (Such as in #GtkSpinner or the
4224 * fill line in #GtkRange), the state %GTK_STATE_FLAG_ACTIVE
4225 * determines whether there is activity going on.
4230 gtk_render_activity (GtkStyleContext *context,
4237 GtkThemingEngineClass *engine_class;
4238 GtkThemingEngine *engine;
4240 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4241 g_return_if_fail (cr != NULL);
4243 if (width <= 0 || height <= 0)
4246 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4247 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4251 _gtk_theming_engine_set_context (engine, context);
4252 engine_class->render_activity (engine, cr, x, y, width, height);
4258 * gtk_render_icon_pixbuf:
4259 * @context: a #GtkStyleContext
4260 * @source: the #GtkIconSource specifying the icon to render
4261 * @size: (type int): the size to render the icon at. A size of (GtkIconSize) -1
4262 * means render at the size of the source and don't scale.
4264 * Renders the icon specified by @source at the given @size, returning the result
4267 * Returns: (transfer full): a newly-created #GdkPixbuf containing the rendered icon
4272 gtk_render_icon_pixbuf (GtkStyleContext *context,
4273 const GtkIconSource *source,
4276 GtkThemingEngineClass *engine_class;
4277 GtkThemingEngine *engine;
4279 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
4280 g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
4281 g_return_val_if_fail (source != NULL, NULL);
4283 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4284 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4286 _gtk_theming_engine_set_context (engine, context);
4287 return engine_class->render_icon_pixbuf (engine, source, size);
4292 * @context: a #GtkStyleContext
4294 * @pixbuf: a #GdkPixbuf containing the icon to draw
4295 * @x: X position for the @pixbuf
4296 * @y: Y position for the @pixbuf
4298 * Renders the icon in @pixbuf at the specified @x and @y coordinates.
4303 gtk_render_icon (GtkStyleContext *context,
4309 GtkThemingEngineClass *engine_class;
4310 GtkThemingEngine *engine;
4312 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4313 g_return_if_fail (cr != NULL);
4315 engine = _gtk_css_engine_value_get_engine (_gtk_style_context_peek_property (context, GTK_CSS_PROPERTY_ENGINE));
4316 engine_class = GTK_THEMING_ENGINE_GET_CLASS (engine);
4320 _gtk_theming_engine_set_context (engine, context);
4321 engine_class->render_icon (engine, cr, pixbuf, x, y);
4327 draw_insertion_cursor (GtkStyleContext *context,
4332 gboolean is_primary,
4333 PangoDirection direction,
4334 gboolean draw_arrow)
4337 GdkRGBA primary_color;
4338 GdkRGBA secondary_color;
4339 gfloat cursor_aspect_ratio;
4345 _gtk_style_context_get_cursor_color (context, &primary_color, &secondary_color);
4346 gdk_cairo_set_source_rgba (cr, is_primary ? &primary_color : &secondary_color);
4348 /* When changing the shape or size of the cursor here,
4349 * propagate the changes to gtktextview.c:text_window_invalidate_cursors().
4352 gtk_style_context_get_style (context,
4353 "cursor-aspect-ratio", &cursor_aspect_ratio,
4356 stem_width = height * cursor_aspect_ratio + 1;
4358 /* put (stem_width % 2) on the proper side of the cursor */
4359 if (direction == PANGO_DIRECTION_LTR)
4360 offset = stem_width / 2;
4362 offset = stem_width - stem_width / 2;
4364 cairo_rectangle (cr, x - offset, y, stem_width, height);
4372 arrow_width = stem_width + 1;
4374 if (direction == PANGO_DIRECTION_RTL)
4376 ax = x - offset - 1;
4377 ay = y + height - arrow_width * 2 - arrow_width + 1;
4379 cairo_move_to (cr, ax, ay + 1);
4380 cairo_line_to (cr, ax - arrow_width, ay + arrow_width);
4381 cairo_line_to (cr, ax, ay + 2 * arrow_width);
4384 else if (direction == PANGO_DIRECTION_LTR)
4386 ax = x + stem_width - offset;
4387 ay = y + height - arrow_width * 2 - arrow_width + 1;
4389 cairo_move_to (cr, ax, ay + 1);
4390 cairo_line_to (cr, ax + arrow_width, ay + arrow_width);
4391 cairo_line_to (cr, ax, ay + 2 * arrow_width);
4395 g_assert_not_reached();
4402 * gtk_render_insertion_cursor:
4403 * @context: a #GtkStyleContext
4407 * @layout: the #PangoLayout of the text
4408 * @index: the index in the #PangoLayout
4409 * @direction: the #PangoDirection of the text
4411 * Draws a text caret on @cr at the specified index of @layout.
4416 gtk_render_insertion_cursor (GtkStyleContext *context,
4420 PangoLayout *layout,
4422 PangoDirection direction)
4424 GtkStyleContextPrivate *priv;
4425 gboolean split_cursor;
4426 PangoRectangle strong_pos, weak_pos;
4427 PangoRectangle *cursor1, *cursor2;
4428 PangoDirection keymap_direction;
4429 PangoDirection direction2;
4431 g_return_if_fail (GTK_IS_STYLE_CONTEXT (context));
4432 g_return_if_fail (cr != NULL);
4433 g_return_if_fail (PANGO_IS_LAYOUT (layout));
4434 g_return_if_fail (index >= 0);
4436 priv = context->priv;
4438 g_object_get (gtk_settings_get_for_screen (priv->screen),
4439 "gtk-split-cursor", &split_cursor,
4442 keymap_direction = gdk_keymap_get_direction (gdk_keymap_get_for_display (gdk_screen_get_display (priv->screen)));
4444 pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos);
4446 direction2 = PANGO_DIRECTION_NEUTRAL;
4450 cursor1 = &strong_pos;
4452 if (strong_pos.x != weak_pos.x || strong_pos.y != weak_pos.y)
4454 direction2 = (direction == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
4455 cursor2 = &weak_pos;
4460 if (keymap_direction == direction)
4461 cursor1 = &strong_pos;
4463 cursor1 = &weak_pos;
4466 draw_insertion_cursor (context,
4468 x + PANGO_PIXELS (cursor1->x),
4469 y + PANGO_PIXELS (cursor1->y),
4470 PANGO_PIXELS (cursor1->height),
4473 direction2 != PANGO_DIRECTION_NEUTRAL);
4475 if (direction2 != PANGO_DIRECTION_NEUTRAL)
4477 draw_insertion_cursor (context,
4479 x + PANGO_PIXELS (cursor2->x),
4480 y + PANGO_PIXELS (cursor2->y),
4481 PANGO_PIXELS (cursor2->height),
4489 * gtk_draw_insertion_cursor:
4490 * @widget: a #GtkWidget
4491 * @cr: cairo context to draw to
4492 * @location: location where to draw the cursor (@location->width is ignored)
4493 * @is_primary: if the cursor should be the primary cursor color.
4494 * @direction: whether the cursor is left-to-right or
4495 * right-to-left. Should never be #GTK_TEXT_DIR_NONE
4496 * @draw_arrow: %TRUE to draw a directional arrow on the
4497 * cursor. Should be %FALSE unless the cursor is split.
4499 * Draws a text caret on @cr at @location. This is not a style function
4500 * but merely a convenience function for drawing the standard cursor shape.
4503 * Deprecated: 3.4: Use gtk_render_insertion_cursor() instead.
4506 gtk_draw_insertion_cursor (GtkWidget *widget,
4508 const GdkRectangle *location,
4509 gboolean is_primary,
4510 GtkTextDirection direction,
4511 gboolean draw_arrow)
4513 GtkStyleContext *context;
4515 g_return_if_fail (GTK_IS_WIDGET (widget));
4516 g_return_if_fail (cr != NULL);
4517 g_return_if_fail (location != NULL);
4518 g_return_if_fail (direction != GTK_TEXT_DIR_NONE);
4520 context = gtk_widget_get_style_context (widget);
4522 draw_insertion_cursor (context, cr,
4523 location->x, location->y, location->height,
4525 (direction == GTK_TEXT_DIR_RTL) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR,
4529 static AtkAttributeSet *
4530 add_attribute (AtkAttributeSet *attributes,
4531 AtkTextAttribute attr,
4536 at = g_new (AtkAttribute, 1);
4537 at->name = g_strdup (atk_text_attribute_get_name (attr));
4538 at->value = g_strdup (value);
4540 return g_slist_prepend (attributes, at);
4544 * _gtk_style_context_get_attributes:
4545 * @attributes: a #AtkAttributeSet to add attributes to
4546 * @context: the #GtkStyleContext to get attributes from
4547 * @flags: the state to use with @context
4549 * Adds the foreground and background color from @context to
4550 * @attributes, after translating them to ATK attributes.
4552 * This is a convenience function that can be used in
4553 * implementing the #AtkText interface in widgets.
4555 * Returns: the modified #AtkAttributeSet
4558 _gtk_style_context_get_attributes (AtkAttributeSet *attributes,
4559 GtkStyleContext *context,
4560 GtkStateFlags flags)
4565 gtk_style_context_get_background_color (context, flags, &color);
4566 value = g_strdup_printf ("%u,%u,%u",
4567 (guint) ceil (color.red * 65536 - color.red),
4568 (guint) ceil (color.green * 65536 - color.green),
4569 (guint) ceil (color.blue * 65536 - color.blue));
4570 attributes = add_attribute (attributes, ATK_TEXT_ATTR_BG_COLOR, value);
4573 gtk_style_context_get_color (context, flags, &color);
4574 value = g_strdup_printf ("%u,%u,%u",
4575 (guint) ceil (color.red * 65536 - color.red),
4576 (guint) ceil (color.green * 65536 - color.green),
4577 (guint) ceil (color.blue * 65536 - color.blue));
4578 attributes = add_attribute (attributes, ATK_TEXT_ATTR_FG_COLOR, value);
4585 gtk_gradient_resolve_for_context (GtkGradient *gradient,
4586 GtkStyleContext *context)
4588 GtkStyleContextPrivate *priv = context->priv;
4589 GtkCssDependencies ignored = 0;
4591 g_return_val_if_fail (gradient != NULL, NULL);
4592 g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL);
4594 return _gtk_gradient_resolve_full (gradient,
4595 GTK_STYLE_PROVIDER_PRIVATE (priv->cascade),
4596 style_data_lookup (context)->store,
4597 priv->parent ? style_data_lookup (priv->parent)->store : NULL,