1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2000 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "gtkmodules.h"
21 #include "gtksettings.h"
24 #include "gtkwidget.h"
25 #include "gtkprivate.h"
28 typedef struct _GtkSettingsValuePrivate GtkSettingsValuePrivate;
32 GTK_SETTINGS_SOURCE_DEFAULT,
33 GTK_SETTINGS_SOURCE_RC_FILE,
34 GTK_SETTINGS_SOURCE_APPLICATION
37 struct _GtkSettingsValuePrivate
39 GtkSettingsValue public;
40 GtkSettingsSource source;
43 struct _GtkSettingsPropertyValue
46 GtkSettingsSource source;
50 #include <pango/pangoxft.h>
51 #include <gdk/x11/gdkx.h>
56 PROP_DOUBLE_CLICK_TIME,
57 PROP_DOUBLE_CLICK_DISTANCE,
59 PROP_CURSOR_BLINK_TIME,
65 PROP_DND_DRAG_THRESHOLD,
69 #ifdef GDK_WINDOWING_X11
76 PROP_ALTERNATIVE_BUTTON_ORDER
80 /* --- prototypes --- */
81 static void gtk_settings_init (GtkSettings *settings);
82 static void gtk_settings_class_init (GtkSettingsClass *class);
83 static void gtk_settings_finalize (GObject *object);
84 static void gtk_settings_get_property (GObject *object,
88 static void gtk_settings_set_property (GObject *object,
92 static void gtk_settings_notify (GObject *object,
94 static guint settings_install_property_parser (GtkSettingsClass *class,
96 GtkRcPropertyParser parser);
97 static void settings_update_double_click (GtkSettings *settings);
98 static void settings_update_modules (GtkSettings *settings);
102 /* --- variables --- */
103 static gpointer parent_class = NULL;
104 static GQuark quark_property_parser = 0;
105 static GSList *object_list = NULL;
106 static guint class_n_properties = 0;
109 /* --- functions --- */
111 gtk_settings_get_type (void)
113 static GType settings_type = 0;
117 static const GTypeInfo settings_info =
119 sizeof (GtkSettingsClass),
120 NULL, /* base_init */
121 NULL, /* base_finalize */
122 (GClassInitFunc) gtk_settings_class_init,
123 NULL, /* class_finalize */
124 NULL, /* class_data */
125 sizeof (GtkSettings),
127 (GInstanceInitFunc) gtk_settings_init,
130 settings_type = g_type_register_static (G_TYPE_OBJECT, "GtkSettings",
134 return settings_type;
139 gtk_default_substitute (FcPattern *pattern,
142 GtkSettings *settings = data;
150 g_object_get (settings,
151 "gtk-xft-antialias", &antialias,
152 "gtk-xft-hinting", &hinting,
153 "gtk-xft-hintstyle", &hintstyle,
154 "gtk-xft-rgba", &rgba,
158 if (antialias >= 0 &&
159 FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
160 FcPatternAddBool (pattern, FC_ANTIALIAS, antialias != 0);
163 FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
164 FcPatternAddBool (pattern, FC_HINTING, hinting != 0);
167 if (hintstyle && FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
169 int val = FC_HINT_FULL; /* Quiet GCC */
170 gboolean found = TRUE;
172 if (strcmp (hintstyle, "hintnone") == 0)
174 else if (strcmp (hintstyle, "hintslight") == 0)
175 val = FC_HINT_SLIGHT;
176 else if (strcmp (hintstyle, "hintmedium") == 0)
177 val = FC_HINT_MEDIUM;
178 else if (strcmp (hintstyle, "hintfull") == 0)
184 FcPatternAddInteger (pattern, FC_HINT_STYLE, val);
186 #endif /* FC_HINT_STYLE */
188 if (rgba && FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
190 int val = FC_RGBA_NONE; /* Quiet GCC */
191 gboolean found = TRUE;
193 if (strcmp (rgba, "none") == 0)
195 else if (strcmp (rgba, "rgb") == 0)
197 else if (strcmp (rgba, "bgr") == 0)
199 else if (strcmp (rgba, "vrgb") == 0)
201 else if (strcmp (rgba, "vbgr") == 0)
207 FcPatternAddInteger (pattern, FC_RGBA, val);
210 if (dpi >= 0 && FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch)
211 FcPatternAddDouble (pattern, FC_DPI, dpi / 1024.);
216 #endif /* GDK_WINDOWING_X11 */
219 gtk_settings_init (GtkSettings *settings)
221 GParamSpec **pspecs, **p;
224 g_datalist_init (&settings->queued_settings);
225 object_list = g_slist_prepend (object_list, settings);
227 /* build up property array for all yet existing properties and queue
228 * notification for them (at least notification for internal properties
229 * will instantly be caught)
231 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
232 for (p = pspecs; *p; p++)
233 if ((*p)->owner_type == G_OBJECT_TYPE (settings))
235 settings->property_values = g_new0 (GtkSettingsPropertyValue, i);
237 g_object_freeze_notify (G_OBJECT (settings));
238 for (p = pspecs; *p; p++)
240 GParamSpec *pspec = *p;
242 if (pspec->owner_type != G_OBJECT_TYPE (settings))
244 g_value_init (&settings->property_values[i].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
245 g_param_value_set_default (pspec, &settings->property_values[i].value);
246 g_object_notify (G_OBJECT (settings), pspec->name);
247 settings->property_values[i].source = GTK_SETTINGS_SOURCE_DEFAULT;
250 g_object_thaw_notify (G_OBJECT (settings));
255 gtk_settings_class_init (GtkSettingsClass *class)
257 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
260 parent_class = g_type_class_peek_parent (class);
262 gobject_class->finalize = gtk_settings_finalize;
263 gobject_class->get_property = gtk_settings_get_property;
264 gobject_class->set_property = gtk_settings_set_property;
265 gobject_class->notify = gtk_settings_notify;
267 quark_property_parser = g_quark_from_static_string ("gtk-rc-property-parser");
269 result = settings_install_property_parser (class,
270 g_param_spec_int ("gtk-double-click-time",
271 P_("Double Click Time"),
272 P_("Maximum time allowed between two clicks for them to be considered a double click (in milliseconds)"),
274 GTK_PARAM_READWRITE),
276 g_assert (result == PROP_DOUBLE_CLICK_TIME);
277 result = settings_install_property_parser (class,
278 g_param_spec_int ("gtk-double-click-distance",
279 P_("Double Click Distance"),
280 P_("Maximum distance allowed between two clicks for them to be considered a double click (in pixels)"),
282 GTK_PARAM_READWRITE),
284 g_assert (result == PROP_DOUBLE_CLICK_DISTANCE);
285 result = settings_install_property_parser (class,
286 g_param_spec_boolean ("gtk-cursor-blink",
288 P_("Whether the cursor should blink"),
290 GTK_PARAM_READWRITE),
292 g_assert (result == PROP_CURSOR_BLINK);
293 result = settings_install_property_parser (class,
294 g_param_spec_int ("gtk-cursor-blink-time",
295 P_("Cursor Blink Time"),
296 P_("Length of the cursor blink cycle, in milleseconds"),
298 GTK_PARAM_READWRITE),
300 g_assert (result == PROP_CURSOR_BLINK_TIME);
301 result = settings_install_property_parser (class,
302 g_param_spec_boolean ("gtk-split-cursor",
304 P_("Whether two cursors should be displayed for mixed left-to-right and right-to-left text"),
306 GTK_PARAM_READWRITE),
308 g_assert (result == PROP_SPLIT_CURSOR);
309 result = settings_install_property_parser (class,
310 g_param_spec_string ("gtk-theme-name",
312 P_("Name of theme RC file to load"),
314 GTK_PARAM_READWRITE),
316 g_assert (result == PROP_THEME_NAME);
317 result = settings_install_property_parser (class,
318 g_param_spec_string ("gtk-icon-theme-name",
319 P_("Icon Theme Name"),
320 P_("Name of icon theme to use"),
322 GTK_PARAM_READWRITE),
324 g_assert (result == PROP_ICON_THEME_NAME);
326 result = settings_install_property_parser (class,
327 g_param_spec_string ("gtk-key-theme-name",
328 P_("Key Theme Name"),
329 P_("Name of key theme RC file to load"),
331 GTK_PARAM_READWRITE),
333 g_assert (result == PROP_KEY_THEME_NAME);
335 result = settings_install_property_parser (class,
336 g_param_spec_string ("gtk-menu-bar-accel",
337 P_("Menu bar accelerator"),
338 P_("Keybinding to activate the menu bar"),
340 GTK_PARAM_READWRITE),
342 g_assert (result == PROP_MENU_BAR_ACCEL);
344 result = settings_install_property_parser (class,
345 g_param_spec_int ("gtk-dnd-drag-threshold",
346 P_("Drag threshold"),
347 P_("Number of pixels the cursor can move before dragging"),
349 GTK_PARAM_READWRITE),
351 g_assert (result == PROP_DND_DRAG_THRESHOLD);
353 result = settings_install_property_parser (class,
354 g_param_spec_string ("gtk-font-name",
356 P_("Name of default font to use"),
358 GTK_PARAM_READWRITE),
360 g_assert (result == PROP_FONT_NAME);
362 result = settings_install_property_parser (class,
363 g_param_spec_string ("gtk-icon-sizes",
365 P_("List of icon sizes (gtk-menu=16,16;gtk-button=20,20..."),
367 GTK_PARAM_READWRITE),
369 g_assert (result == PROP_ICON_SIZES);
371 result = settings_install_property_parser (class,
372 g_param_spec_string ("gtk-modules",
374 P_("List of currently active GTK modules"),
376 GTK_PARAM_READWRITE),
378 g_assert (result == PROP_MODULES);
380 #ifdef GDK_WINDOWING_X11
381 result = settings_install_property_parser (class,
382 g_param_spec_int ("gtk-xft-antialias",
384 P_("Whether to antialias Xft fonts; 0=no, 1=yes, -1=default"),
386 GTK_PARAM_READWRITE),
389 g_assert (result == PROP_XFT_ANTIALIAS);
391 result = settings_install_property_parser (class,
392 g_param_spec_int ("gtk-xft-hinting",
394 P_("Whether to hint Xft fonts; 0=no, 1=yes, -1=default"),
396 GTK_PARAM_READWRITE),
399 g_assert (result == PROP_XFT_HINTING);
401 result = settings_install_property_parser (class,
402 g_param_spec_string ("gtk-xft-hintstyle",
403 P_("Xft Hint Style"),
404 P_("What degree of hinting to use; none, slight, medium, or full"),
406 GTK_PARAM_READWRITE),
409 g_assert (result == PROP_XFT_HINTSTYLE);
411 result = settings_install_property_parser (class,
412 g_param_spec_string ("gtk-xft-rgba",
414 P_("Type of subpixel antialiasing; none, rgb, bgr, vrgb, vbgr"),
416 GTK_PARAM_READWRITE),
419 g_assert (result == PROP_XFT_RGBA);
421 result = settings_install_property_parser (class,
422 g_param_spec_int ("gtk-xft-dpi",
424 P_("Resolution for Xft, in 1024 * dots/inch. -1 to use default value"),
426 GTK_PARAM_READWRITE),
429 g_assert (result == PROP_XFT_DPI);
430 #endif /* GDK_WINDOWING_X11 */
431 result = settings_install_property_parser (class,
432 g_param_spec_boolean ("gtk-alternative-button-order",
433 P_("Alternative button order"),
434 P_("Whether buttons in dialogs should use the alternative button order"),
436 GTK_PARAM_READWRITE),
438 g_assert (result == PROP_ALTERNATIVE_BUTTON_ORDER);
442 gtk_settings_finalize (GObject *object)
444 GtkSettings *settings = GTK_SETTINGS (object);
447 object_list = g_slist_remove (object_list, settings);
449 for (i = 0; i < class_n_properties; i++)
450 g_value_unset (&settings->property_values[i].value);
451 g_free (settings->property_values);
453 g_datalist_clear (&settings->queued_settings);
455 G_OBJECT_CLASS (parent_class)->finalize (object);
459 * gtk_settings_get_for_screen:
460 * @screen : a #GdkScreen.
462 * Gets the #GtkSettings object for @screen, creating it if necessary.
464 * Return value: a #GtkSettings object.
469 gtk_settings_get_for_screen (GdkScreen *screen)
471 GtkSettings *settings;
473 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
475 settings = g_object_get_data (G_OBJECT (screen), "gtk-settings");
478 settings = g_object_new (GTK_TYPE_SETTINGS, NULL);
479 settings->screen = screen;
480 g_object_set_data (G_OBJECT (screen), "gtk-settings", settings);
483 /* Set the default substitution function for the Pango fontmap.
485 pango_xft_set_default_substitute (GDK_SCREEN_XDISPLAY (screen),
486 GDK_SCREEN_XNUMBER (screen),
487 gtk_default_substitute,
489 #endif /* GDK_WINDOWING_X11 */
491 gtk_rc_reparse_all_for_settings (settings, TRUE);
492 settings_update_double_click (settings);
499 * gtk_settings_get_default:
501 * Gets the #GtkSettings object for the default GDK screen, creating
502 * it if necessary. See gtk_settings_get_for_screen().
504 * Return value: a #GtkSettings object. If there is no default
505 * screen, then returns %NULL.
508 gtk_settings_get_default (void)
510 GdkScreen *screen = gdk_screen_get_default ();
513 return gtk_settings_get_for_screen (screen);
519 gtk_settings_set_property (GObject *object,
524 GtkSettings *settings = GTK_SETTINGS (object);
526 g_value_copy (value, &settings->property_values[property_id - 1].value);
527 settings->property_values[property_id - 1].source = GTK_SETTINGS_SOURCE_APPLICATION;
531 gtk_settings_get_property (GObject *object,
536 GtkSettings *settings = GTK_SETTINGS (object);
537 GType value_type = G_VALUE_TYPE (value);
538 GType fundamental_type = G_TYPE_FUNDAMENTAL (value_type);
540 /* For enums and strings, we need to get the value as a string,
541 * not as an int, since we support using names/nicks as the setting
544 if ((g_value_type_transformable (G_TYPE_INT, value_type) &&
545 !(fundamental_type == G_TYPE_ENUM || fundamental_type == G_TYPE_FLAGS)) ||
546 g_value_type_transformable (G_TYPE_STRING, G_VALUE_TYPE (value)) ||
547 g_value_type_transformable (GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
549 if (settings->property_values[property_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION ||
550 !gdk_screen_get_setting (settings->screen, pspec->name, value))
551 g_value_copy (&settings->property_values[property_id - 1].value, value);
553 g_param_value_validate (pspec, value);
559 /* Try to get xsetting as a string and parse it. */
561 g_value_init (&val, G_TYPE_STRING);
563 if (settings->property_values[property_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION ||
564 !gdk_screen_get_setting (settings->screen, pspec->name, &val))
566 g_value_copy (&settings->property_values[property_id - 1].value, value);
570 GValue tmp_value = { 0, };
571 GValue gstring_value = { 0, };
572 GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
574 g_value_init (&gstring_value, G_TYPE_GSTRING);
576 g_value_take_boxed (&gstring_value,
577 g_string_new (g_value_get_string (&val)));
579 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
581 if (parser && _gtk_settings_parse_convert (parser, &gstring_value,
584 g_value_copy (&tmp_value, value);
585 g_param_value_validate (pspec, value);
589 g_value_copy (&settings->property_values[property_id - 1].value, value);
592 g_value_unset (&gstring_value);
593 g_value_unset (&tmp_value);
596 g_value_unset (&val);
601 gtk_settings_notify (GObject *object,
604 GtkSettings *settings = GTK_SETTINGS (object);
605 guint property_id = pspec->param_id;
607 if (settings->screen == NULL) /* initialization */
613 settings_update_modules (settings);
615 case PROP_DOUBLE_CLICK_TIME:
616 case PROP_DOUBLE_CLICK_DISTANCE:
617 settings_update_double_click (settings);
620 case PROP_XFT_ANTIALIAS:
621 case PROP_XFT_HINTING:
622 case PROP_XFT_HINTSTYLE:
625 pango_xft_substitute_changed (GDK_SCREEN_XDISPLAY (settings->screen),
626 GDK_SCREEN_XNUMBER (settings->screen));
627 /* This is a hack because with gtk_rc_reset_styles() doesn't get
628 * widgets with gtk_widget_style_set(), and also causes more
629 * recomputation than necessary.
631 gtk_rc_reset_styles (GTK_SETTINGS (object));
633 #endif /* GDK_WINDOWING_X11 */
638 _gtk_settings_parse_convert (GtkRcPropertyParser parser,
639 const GValue *src_value,
643 gboolean success = FALSE;
645 g_return_val_if_fail (G_VALUE_HOLDS (dest_value, G_PARAM_SPEC_VALUE_TYPE (pspec)), FALSE);
650 gboolean free_gstring = TRUE;
652 if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
654 gstring = g_value_get_boxed (src_value);
655 free_gstring = FALSE;
657 else if (G_VALUE_HOLDS_LONG (src_value))
659 gstring = g_string_new (NULL);
660 g_string_append_printf (gstring, "%ld", g_value_get_long (src_value));
662 else if (G_VALUE_HOLDS_DOUBLE (src_value))
664 gstring = g_string_new (NULL);
665 g_string_append_printf (gstring, "%f", g_value_get_double (src_value));
667 else if (G_VALUE_HOLDS_STRING (src_value))
669 gchar *tstr = g_strescape (g_value_get_string (src_value), NULL);
671 gstring = g_string_new ("\"");
672 g_string_append (gstring, tstr);
673 g_string_append_c (gstring, '\"');
678 g_return_val_if_fail (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING), FALSE);
679 gstring = NULL; /* silence compiler */
682 success = (parser (pspec, gstring, dest_value) &&
683 !g_param_value_validate (pspec, dest_value));
686 g_string_free (gstring, TRUE);
688 else if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
690 if (G_VALUE_HOLDS (dest_value, G_TYPE_STRING))
692 GString *gstring = g_value_get_boxed (src_value);
694 g_value_set_string (dest_value, gstring ? gstring->str : NULL);
695 success = !g_param_value_validate (pspec, dest_value);
698 else if (g_value_type_transformable (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)))
699 success = g_param_value_convert (pspec, src_value, dest_value, TRUE);
705 apply_queued_setting (GtkSettings *data,
707 GtkSettingsValuePrivate *qvalue)
709 GValue tmp_value = { 0, };
710 GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
712 g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
713 if (_gtk_settings_parse_convert (parser, &qvalue->public.value,
716 if (data->property_values[pspec->param_id - 1].source <= qvalue->source)
718 g_object_set_property (G_OBJECT (data), pspec->name, &tmp_value);
719 data->property_values[pspec->param_id - 1].source = qvalue->source;
724 gchar *debug = g_strdup_value_contents (&qvalue->public.value);
726 g_message ("%s: failed to retrieve property `%s' of type `%s' from rc file value \"%s\" of type `%s'",
727 qvalue->public.origin,
729 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
731 G_VALUE_TYPE_NAME (&tmp_value));
734 g_value_unset (&tmp_value);
738 settings_install_property_parser (GtkSettingsClass *class,
740 GtkRcPropertyParser parser)
744 switch (G_TYPE_FUNDAMENTAL (G_PARAM_SPEC_VALUE_TYPE (pspec)))
760 g_warning (G_STRLOC ": parser needs to be specified for property \"%s\" of type `%s'",
761 pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
765 if (g_object_class_find_property (G_OBJECT_CLASS (class), pspec->name))
767 g_warning (G_STRLOC ": an rc-data property \"%s\" already exists",
772 for (node = object_list; node; node = node->next)
773 g_object_freeze_notify (node->data);
775 g_object_class_install_property (G_OBJECT_CLASS (class), ++class_n_properties, pspec);
776 g_param_spec_set_qdata (pspec, quark_property_parser, (gpointer) parser);
778 for (node = object_list; node; node = node->next)
780 GtkSettings *settings = node->data;
781 GtkSettingsValuePrivate *qvalue;
783 settings->property_values = g_renew (GtkSettingsPropertyValue, settings->property_values, class_n_properties);
784 settings->property_values[class_n_properties - 1].value.g_type = 0;
785 g_value_init (&settings->property_values[class_n_properties - 1].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
786 g_param_value_set_default (pspec, &settings->property_values[class_n_properties - 1].value);
787 settings->property_values[class_n_properties - 1].source = GTK_SETTINGS_SOURCE_DEFAULT;
788 g_object_notify (G_OBJECT (settings), pspec->name);
790 qvalue = g_datalist_get_data (&settings->queued_settings, pspec->name);
792 apply_queued_setting (settings, pspec, qvalue);
795 for (node = object_list; node; node = next)
798 g_object_thaw_notify (node->data);
801 return class_n_properties;
805 _gtk_rc_property_parser_from_type (GType type)
807 if (type == GDK_TYPE_COLOR)
808 return gtk_rc_property_parse_color;
809 else if (type == GTK_TYPE_REQUISITION)
810 return gtk_rc_property_parse_requisition;
811 else if (type == GTK_TYPE_BORDER)
812 return gtk_rc_property_parse_border;
813 else if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_ENUM && G_TYPE_IS_DERIVED (type))
814 return gtk_rc_property_parse_enum;
815 else if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_FLAGS && G_TYPE_IS_DERIVED (type))
816 return gtk_rc_property_parse_flags;
822 gtk_settings_install_property (GParamSpec *pspec)
824 GtkRcPropertyParser parser;
826 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
828 parser = _gtk_rc_property_parser_from_type (G_PARAM_SPEC_VALUE_TYPE (pspec));
830 settings_install_property_parser (gtk_type_class (GTK_TYPE_SETTINGS), pspec, parser);
834 gtk_settings_install_property_parser (GParamSpec *pspec,
835 GtkRcPropertyParser parser)
837 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
838 g_return_if_fail (parser != NULL);
840 settings_install_property_parser (gtk_type_class (GTK_TYPE_SETTINGS), pspec, parser);
844 free_value (gpointer data)
846 GtkSettingsValuePrivate *qvalue = data;
848 g_value_unset (&qvalue->public.value);
849 g_free (qvalue->public.origin);
854 gtk_settings_set_property_value_internal (GtkSettings *settings,
855 const gchar *prop_name,
856 const GtkSettingsValue *new_value,
857 GtkSettingsSource source)
859 GtkSettingsValuePrivate *qvalue;
864 if (!G_VALUE_HOLDS_LONG (&new_value->value) &&
865 !G_VALUE_HOLDS_DOUBLE (&new_value->value) &&
866 !G_VALUE_HOLDS_STRING (&new_value->value) &&
867 !G_VALUE_HOLDS (&new_value->value, G_TYPE_GSTRING))
869 g_warning (G_STRLOC ": value type invalid");
873 name = g_strdup (prop_name);
874 g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
875 name_quark = g_quark_from_string (name);
878 qvalue = g_datalist_id_get_data (&settings->queued_settings, name_quark);
881 qvalue = g_new0 (GtkSettingsValuePrivate, 1);
882 g_datalist_id_set_data_full (&settings->queued_settings, name_quark, qvalue, free_value);
886 g_free (qvalue->public.origin);
887 g_value_unset (&qvalue->public.value);
889 qvalue->public.origin = g_strdup (new_value->origin);
890 g_value_init (&qvalue->public.value, G_VALUE_TYPE (&new_value->value));
891 g_value_copy (&new_value->value, &qvalue->public.value);
892 qvalue->source = source;
893 pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), g_quark_to_string (name_quark));
895 apply_queued_setting (settings, pspec, qvalue);
899 gtk_settings_set_property_value (GtkSettings *settings,
900 const gchar *prop_name,
901 const GtkSettingsValue *new_value)
903 g_return_if_fail (GTK_SETTINGS (settings));
904 g_return_if_fail (prop_name != NULL);
905 g_return_if_fail (new_value != NULL);
906 g_return_if_fail (new_value->origin != NULL);
908 gtk_settings_set_property_value_internal (settings, prop_name, new_value,
909 GTK_SETTINGS_SOURCE_APPLICATION);
913 _gtk_settings_set_property_value_from_rc (GtkSettings *settings,
914 const gchar *prop_name,
915 const GtkSettingsValue *new_value)
917 g_return_if_fail (GTK_SETTINGS (settings));
918 g_return_if_fail (prop_name != NULL);
919 g_return_if_fail (new_value != NULL);
920 g_return_if_fail (new_value->origin != NULL);
922 gtk_settings_set_property_value_internal (settings, prop_name, new_value,
923 GTK_SETTINGS_SOURCE_RC_FILE);
927 gtk_settings_set_string_property (GtkSettings *settings,
929 const gchar *v_string,
932 GtkSettingsValue svalue = { NULL, { 0, }, };
934 g_return_if_fail (GTK_SETTINGS (settings));
935 g_return_if_fail (name != NULL);
936 g_return_if_fail (v_string != NULL);
937 g_return_if_fail (origin != NULL);
939 svalue.origin = (gchar*) origin;
940 g_value_init (&svalue.value, G_TYPE_STRING);
941 g_value_set_static_string (&svalue.value, v_string);
942 gtk_settings_set_property_value (settings, name, &svalue);
943 g_value_unset (&svalue.value);
947 gtk_settings_set_long_property (GtkSettings *settings,
952 GtkSettingsValue svalue = { NULL, { 0, }, };
954 g_return_if_fail (GTK_SETTINGS (settings));
955 g_return_if_fail (name != NULL);
956 g_return_if_fail (origin != NULL);
958 svalue.origin = (gchar*) origin;
959 g_value_init (&svalue.value, G_TYPE_LONG);
960 g_value_set_long (&svalue.value, v_long);
961 gtk_settings_set_property_value (settings, name, &svalue);
962 g_value_unset (&svalue.value);
966 gtk_settings_set_double_property (GtkSettings *settings,
971 GtkSettingsValue svalue = { NULL, { 0, }, };
973 g_return_if_fail (GTK_SETTINGS (settings));
974 g_return_if_fail (name != NULL);
975 g_return_if_fail (origin != NULL);
977 svalue.origin = (gchar*) origin;
978 g_value_init (&svalue.value, G_TYPE_DOUBLE);
979 g_value_set_double (&svalue.value, v_double);
980 gtk_settings_set_property_value (settings, name, &svalue);
981 g_value_unset (&svalue.value);
985 * gtk_rc_property_parse_color:
986 * @pspec: a #GParamSpec
987 * @gstring: the #GString to be parsed
988 * @property_value: a #GValue which must hold #GdkColor values.
990 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
991 * or gtk_widget_class_install_style_property_parser() which parses a
992 * color given either by its name or in the form
993 * <literal>{ red, green, blue }</literal> where %red, %green and
994 * %blue are integers between 0 and 65535 or floating-point numbers
997 * Return value: %TRUE if @gstring could be parsed and @property_value
998 * has been set to the resulting #GdkColor.
1001 gtk_rc_property_parse_color (const GParamSpec *pspec,
1002 const GString *gstring,
1003 GValue *property_value)
1005 GdkColor color = { 0, 0, 0, 0, };
1009 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1010 g_return_val_if_fail (G_VALUE_HOLDS (property_value, GDK_TYPE_COLOR), FALSE);
1012 scanner = gtk_rc_scanner_new ();
1013 g_scanner_input_text (scanner, gstring->str, gstring->len);
1014 if (gtk_rc_parse_color (scanner, &color) == G_TOKEN_NONE &&
1015 g_scanner_get_next_token (scanner) == G_TOKEN_EOF)
1017 g_value_set_boxed (property_value, &color);
1022 g_scanner_destroy (scanner);
1028 * gtk_rc_property_parse_enum:
1029 * @pspec: a #GParamSpec
1030 * @gstring: the #GString to be parsed
1031 * @property_value: a #GValue which must hold enum values.
1033 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
1034 * or gtk_widget_class_install_style_property_parser() which parses a single
1035 * enumeration value.
1037 * The enumeration value can be specified by its name, its nickname or
1038 * its numeric value. For consistency with flags parsing, the value
1039 * may be surrounded by parentheses.
1041 * Return value: %TRUE if @gstring could be parsed and @property_value
1042 * has been set to the resulting #GEnumValue.
1045 gtk_rc_property_parse_enum (const GParamSpec *pspec,
1046 const GString *gstring,
1047 GValue *property_value)
1049 gboolean need_closing_brace = FALSE, success = FALSE;
1051 GEnumValue *enum_value = NULL;
1053 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1054 g_return_val_if_fail (G_VALUE_HOLDS_ENUM (property_value), FALSE);
1056 scanner = gtk_rc_scanner_new ();
1057 g_scanner_input_text (scanner, gstring->str, gstring->len);
1059 /* we just want to parse _one_ value, but for consistency with flags parsing
1060 * we support optional parenthesis
1062 g_scanner_get_next_token (scanner);
1063 if (scanner->token == '(')
1065 need_closing_brace = TRUE;
1066 g_scanner_get_next_token (scanner);
1068 if (scanner->token == G_TOKEN_IDENTIFIER)
1070 GEnumClass *class = G_PARAM_SPEC_ENUM (pspec)->enum_class;
1072 enum_value = g_enum_get_value_by_name (class, scanner->value.v_identifier);
1074 enum_value = g_enum_get_value_by_nick (class, scanner->value.v_identifier);
1077 g_value_set_enum (property_value, enum_value->value);
1081 else if (scanner->token == G_TOKEN_INT)
1083 g_value_set_enum (property_value, scanner->value.v_int);
1086 if (need_closing_brace && g_scanner_get_next_token (scanner) != ')')
1088 if (g_scanner_get_next_token (scanner) != G_TOKEN_EOF)
1091 g_scanner_destroy (scanner);
1097 parse_flags_value (GScanner *scanner,
1101 g_scanner_get_next_token (scanner);
1102 if (scanner->token == G_TOKEN_IDENTIFIER)
1104 GFlagsValue *flags_value;
1106 flags_value = g_flags_get_value_by_name (class, scanner->value.v_identifier);
1108 flags_value = g_flags_get_value_by_nick (class, scanner->value.v_identifier);
1111 *number |= flags_value->value;
1112 return G_TOKEN_NONE;
1115 else if (scanner->token == G_TOKEN_INT)
1117 *number |= scanner->value.v_int;
1118 return G_TOKEN_NONE;
1120 return G_TOKEN_IDENTIFIER;
1124 * gtk_rc_property_parse_flags:
1125 * @pspec: a #GParamSpec
1126 * @gstring: the #GString to be parsed
1127 * @property_value: a #GValue which must hold flags values.
1129 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
1130 * or gtk_widget_class_install_style_property_parser() which parses flags.
1132 * Flags can be specified by their name, their nickname or
1133 * numerically. Multiple flags can be specified in the form
1134 * <literal>"( flag1 | flag2 | ... )"</literal>.
1136 * Return value: %TRUE if @gstring could be parsed and @property_value
1137 * has been set to the resulting flags value.
1140 gtk_rc_property_parse_flags (const GParamSpec *pspec,
1141 const GString *gstring,
1142 GValue *property_value)
1145 gboolean success = FALSE;
1148 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1149 g_return_val_if_fail (G_VALUE_HOLDS_FLAGS (property_value), FALSE);
1151 class = G_PARAM_SPEC_FLAGS (pspec)->flags_class;
1152 scanner = gtk_rc_scanner_new ();
1153 g_scanner_input_text (scanner, gstring->str, gstring->len);
1155 /* parse either a single flags value or a "\( ... [ \| ... ] \)" compound */
1156 if (g_scanner_peek_next_token (scanner) == G_TOKEN_IDENTIFIER ||
1157 scanner->next_token == G_TOKEN_INT)
1159 guint token, flags_value = 0;
1161 token = parse_flags_value (scanner, class, &flags_value);
1163 if (token == G_TOKEN_NONE && g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1166 g_value_set_flags (property_value, flags_value);
1170 else if (g_scanner_get_next_token (scanner) == '(')
1172 guint token, flags_value = 0;
1174 /* parse first value */
1175 token = parse_flags_value (scanner, class, &flags_value);
1177 /* parse nth values, preceeded by '|' */
1178 while (token == G_TOKEN_NONE && g_scanner_get_next_token (scanner) == '|')
1179 token = parse_flags_value (scanner, class, &flags_value);
1181 /* done, last token must have closed expression */
1182 if (token == G_TOKEN_NONE && scanner->token == ')' &&
1183 g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
1185 g_value_set_flags (property_value, flags_value);
1189 g_scanner_destroy (scanner);
1195 get_braced_int (GScanner *scanner,
1202 g_scanner_get_next_token (scanner);
1203 if (scanner->token != '{')
1207 g_scanner_get_next_token (scanner);
1208 if (scanner->token != G_TOKEN_INT)
1211 *value = scanner->value.v_int;
1215 g_scanner_get_next_token (scanner);
1216 if (scanner->token != '}')
1221 g_scanner_get_next_token (scanner);
1222 if (scanner->token != ',')
1230 * gtk_rc_property_parse_requisition:
1231 * @pspec: a #GParamSpec
1232 * @gstring: the #GString to be parsed
1233 * @property_value: a #GValue which must hold boxed values.
1235 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
1236 * or gtk_widget_class_install_style_property_parser() which parses a
1237 * requisition in the form
1238 * <literal>"{ width, height }"</literal> for integers %width and %height.
1240 * Return value: %TRUE if @gstring could be parsed and @property_value
1241 * has been set to the resulting #GtkRequisition.
1244 gtk_rc_property_parse_requisition (const GParamSpec *pspec,
1245 const GString *gstring,
1246 GValue *property_value)
1248 GtkRequisition requisition;
1250 gboolean success = FALSE;
1252 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1253 g_return_val_if_fail (G_VALUE_HOLDS_BOXED (property_value), FALSE);
1255 scanner = gtk_rc_scanner_new ();
1256 g_scanner_input_text (scanner, gstring->str, gstring->len);
1258 if (get_braced_int (scanner, TRUE, FALSE, &requisition.width) &&
1259 get_braced_int (scanner, FALSE, TRUE, &requisition.height))
1261 g_value_set_boxed (property_value, &requisition);
1265 g_scanner_destroy (scanner);
1271 * gtk_rc_property_parse_border:
1272 * @pspec: a #GParamSpec
1273 * @gstring: the #GString to be parsed
1274 * @property_value: a #GValue which must hold boxed values.
1276 * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
1277 * or gtk_widget_class_install_style_property_parser() which parses
1278 * borders in the form
1279 * <literal>"{ left, right, top, bottom }"</literal> for integers
1280 * %left, %right, %top and %bottom.
1282 * Return value: %TRUE if @gstring could be parsed and @property_value
1283 * has been set to the resulting #GtkBorder.
1286 gtk_rc_property_parse_border (const GParamSpec *pspec,
1287 const GString *gstring,
1288 GValue *property_value)
1292 gboolean success = FALSE;
1294 g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1295 g_return_val_if_fail (G_VALUE_HOLDS_BOXED (property_value), FALSE);
1297 scanner = gtk_rc_scanner_new ();
1298 g_scanner_input_text (scanner, gstring->str, gstring->len);
1300 if (get_braced_int (scanner, TRUE, FALSE, &border.left) &&
1301 get_braced_int (scanner, FALSE, FALSE, &border.right) &&
1302 get_braced_int (scanner, FALSE, FALSE, &border.top) &&
1303 get_braced_int (scanner, FALSE, TRUE, &border.bottom))
1305 g_value_set_boxed (property_value, &border);
1309 g_scanner_destroy (scanner);
1315 _gtk_settings_handle_event (GdkEventSetting *event)
1317 GtkSettings *settings = gtk_settings_get_for_screen (gdk_drawable_get_screen (event->window));
1319 if (g_object_class_find_property (G_OBJECT_GET_CLASS (settings), event->name))
1320 g_object_notify (G_OBJECT (settings), event->name);
1324 reset_rc_values_foreach (GQuark key_id,
1328 GtkSettingsValuePrivate *qvalue = data;
1329 GSList **to_reset = user_data;
1331 if (qvalue->source == GTK_SETTINGS_SOURCE_RC_FILE)
1332 *to_reset = g_slist_prepend (*to_reset, GUINT_TO_POINTER (key_id));
1336 _gtk_settings_reset_rc_values (GtkSettings *settings)
1338 GSList *to_reset = NULL;
1340 GParamSpec **pspecs, **p;
1343 /* Remove any queued settings
1345 g_datalist_foreach (&settings->queued_settings,
1346 reset_rc_values_foreach,
1349 for (tmp_list = to_reset; tmp_list; tmp_list = tmp_list->next)
1351 GQuark key_id = GPOINTER_TO_UINT (tmp_list->data);
1352 g_datalist_id_remove_data (&settings->queued_settings, key_id);
1355 /* Now reset the active settings
1357 pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
1360 g_object_freeze_notify (G_OBJECT (settings));
1361 for (p = pspecs; *p; p++)
1363 if (settings->property_values[i].source == GTK_SETTINGS_SOURCE_RC_FILE)
1365 GParamSpec *pspec = *p;
1367 g_param_value_set_default (pspec, &settings->property_values[i].value);
1368 g_object_notify (G_OBJECT (settings), pspec->name);
1372 g_object_thaw_notify (G_OBJECT (settings));
1377 settings_update_double_click (GtkSettings *settings)
1379 if (gdk_screen_get_number (settings->screen) == 0)
1381 GdkDisplay *display = gdk_screen_get_display (settings->screen);
1382 gint double_click_time;
1383 gint double_click_distance;
1385 g_object_get (settings,
1386 "gtk-double-click-time", &double_click_time,
1387 "gtk-double-click-distance", &double_click_distance,
1390 gdk_display_set_double_click_time (display, double_click_time);
1391 gdk_display_set_double_click_distance (display, double_click_distance);
1396 settings_update_modules (GtkSettings *settings)
1400 g_object_get (settings,
1401 "gtk-modules", &modules,
1404 _gtk_modules_settings_changed (settings, modules);
1409 #define __GTK_SETTINGS_C__
1410 #include "gtkaliasdef.c"