]> Pileus Git - ~andy/gtk/blob - gtk/gtksettings.c
8e50804f741c27da18c8ba2a03c7e8c086954367
[~andy/gtk] / gtk / gtksettings.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
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.
8  *
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.
13  *
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.
17  */
18
19
20 #define PANGO_ENABLE_BACKEND /* for pango_fc_font_map_cache_clear() */
21
22 #include "config.h"
23
24 #include <string.h>
25
26 #include "gtkmodules.h"
27 #include "gtksettings.h"
28 #include "gtkrc.h"
29 #include "gtkintl.h"
30 #include "gtkwidget.h"
31 #include "gtktypeutils.h"
32 #include "gtkprivate.h"
33 #include "gtkcssprovider.h"
34 #include "gtkversion.h"
35
36 #ifdef GDK_WINDOWING_X11
37 #include "x11/gdkx.h"
38 #include <pango/pangofc-fontmap.h>
39 #endif
40
41
42 /**
43  * SECTION:gtksettings
44  * @Short_description: Sharing settings between applications
45  * @Title: Settings
46  *
47  * GtkSettings provide a mechanism to share global settings between applications.
48  * On the X window system, this sharing is realized by an
49  * <ulink url="http://www.freedesktop.org/wiki/Specifications/xsettings-spec">XSettings</ulink>
50  * manager that is usually part of the desktop environment, along with utilities
51  * that let the user change these settings. In the absence of an Xsettings manager,
52  * settings can also be specified in RC files.
53  *
54  * Applications can override system-wide settings with gtk_settings_set_string_property(),
55  * gtk_settings_set_long_property(), etc. This should be restricted to special
56  * cases though; GtkSettings are not meant as an application configuration
57  * facility. When doing so, you need to be aware that settings that are specific
58  * to individual widgets may not be available before the widget type has been
59  * realized at least once. The following example demonstrates a way to do this:
60  * <informalexample><programlisting>
61  *   gtk_init (&argc, &argv);
62  *
63  *   /&ast; make sure the type is realized &ast;/
64  *   g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM));
65  *
66  *   g_object_set (gtk_settings_get_default (), "gtk-menu-images", FALSE, NULL);
67  * </programlisting></informalexample>
68  *
69  * There is one GtkSettings instance per screen. It can be obtained with
70  * gtk_settings_get_for_screen(), but in many cases, it is more convenient
71  * to use gtk_widget_get_settings(). gtk_settings_get_default() returns the
72  * GtkSettings instance for the default screen.
73  */
74
75
76 #ifdef GDK_WINDOWING_QUARTZ
77 #define DEFAULT_KEY_THEME "Mac"
78 #else
79 #define DEFAULT_KEY_THEME NULL
80 #endif
81
82 #define DEFAULT_TIMEOUT_INITIAL 200
83 #define DEFAULT_TIMEOUT_REPEAT   20
84 #define DEFAULT_TIMEOUT_EXPAND  500
85
86 typedef struct _GtkSettingsValuePrivate GtkSettingsValuePrivate;
87
88 typedef enum
89 {
90   GTK_SETTINGS_SOURCE_DEFAULT,
91   GTK_SETTINGS_SOURCE_RC_FILE,
92   GTK_SETTINGS_SOURCE_XSETTING,
93   GTK_SETTINGS_SOURCE_APPLICATION
94 } GtkSettingsSource;
95
96 struct _GtkSettingsValuePrivate
97 {
98   GtkSettingsValue public;
99   GtkSettingsSource source;
100 };
101
102 struct _GtkSettingsPropertyValue
103 {
104   GValue value;
105   GtkSettingsSource source;
106 };
107
108 enum {
109   PROP_0,
110   PROP_DOUBLE_CLICK_TIME,
111   PROP_DOUBLE_CLICK_DISTANCE,
112   PROP_CURSOR_BLINK,
113   PROP_CURSOR_BLINK_TIME,
114   PROP_CURSOR_BLINK_TIMEOUT,
115   PROP_SPLIT_CURSOR,
116   PROP_THEME_NAME,
117   PROP_ICON_THEME_NAME,
118   PROP_FALLBACK_ICON_THEME,
119   PROP_KEY_THEME_NAME,
120   PROP_MENU_BAR_ACCEL,
121   PROP_DND_DRAG_THRESHOLD,
122   PROP_FONT_NAME,
123   PROP_ICON_SIZES,
124   PROP_MODULES,
125 #ifdef GDK_WINDOWING_X11
126   PROP_XFT_ANTIALIAS,
127   PROP_XFT_HINTING,
128   PROP_XFT_HINTSTYLE,
129   PROP_XFT_RGBA,
130   PROP_XFT_DPI,
131   PROP_CURSOR_THEME_NAME,
132   PROP_CURSOR_THEME_SIZE,
133 #endif
134   PROP_ALTERNATIVE_BUTTON_ORDER,
135   PROP_ALTERNATIVE_SORT_ARROWS,
136   PROP_SHOW_INPUT_METHOD_MENU,
137   PROP_SHOW_UNICODE_MENU,
138   PROP_TIMEOUT_INITIAL,
139   PROP_TIMEOUT_REPEAT,
140   PROP_TIMEOUT_EXPAND,
141   PROP_COLOR_SCHEME,
142   PROP_ENABLE_ANIMATIONS,
143   PROP_TOUCHSCREEN_MODE,
144   PROP_TOOLTIP_TIMEOUT,
145   PROP_TOOLTIP_BROWSE_TIMEOUT,
146   PROP_TOOLTIP_BROWSE_MODE_TIMEOUT,
147   PROP_KEYNAV_CURSOR_ONLY,
148   PROP_KEYNAV_WRAP_AROUND,
149   PROP_ERROR_BELL,
150   PROP_COLOR_HASH,
151   PROP_FILE_CHOOSER_BACKEND,
152   PROP_PRINT_BACKENDS,
153   PROP_PRINT_PREVIEW_COMMAND,
154   PROP_ENABLE_MNEMONICS,
155   PROP_ENABLE_ACCELS,
156   PROP_RECENT_FILES_LIMIT,
157   PROP_IM_MODULE,
158   PROP_RECENT_FILES_MAX_AGE,
159   PROP_FONTCONFIG_TIMESTAMP,
160   PROP_SOUND_THEME_NAME,
161   PROP_ENABLE_INPUT_FEEDBACK_SOUNDS,
162   PROP_ENABLE_EVENT_SOUNDS,
163   PROP_ENABLE_TOOLTIPS,
164   PROP_TOOLBAR_STYLE,
165   PROP_TOOLBAR_ICON_SIZE,
166   PROP_AUTO_MNEMONICS,
167   PROP_APPLICATION_PREFER_DARK_THEME,
168   PROP_BUTTON_IMAGES,
169   PROP_ENTRY_SELECT_ON_FOCUS,
170   PROP_ENTRY_PASSWORD_HINT_TIMEOUT,
171   PROP_MENU_IMAGES,
172   PROP_MENU_BAR_POPUP_DELAY,
173   PROP_SCROLLED_WINDOW_PLACEMENT,
174   PROP_CAN_CHANGE_ACCELS,
175   PROP_MENU_POPUP_DELAY,
176   PROP_MENU_POPDOWN_DELAY,
177   PROP_LABEL_SELECT_ON_FOCUS,
178   PROP_COLOR_PALETTE,
179   PROP_IM_PREEDIT_STYLE,
180   PROP_IM_STATUS_STYLE
181 };
182
183 /* --- prototypes --- */
184 static void     gtk_settings_provider_iface_init (GtkStyleProviderIface *iface);
185
186 static void     gtk_settings_finalize            (GObject               *object);
187 static void     gtk_settings_get_property        (GObject               *object,
188                                                   guint                  property_id,
189                                                   GValue                *value,
190                                                   GParamSpec            *pspec);
191 static void     gtk_settings_set_property        (GObject               *object,
192                                                   guint                  property_id,
193                                                   const GValue          *value,
194                                                   GParamSpec            *pspec);
195 static void     gtk_settings_notify              (GObject               *object,
196                                                   GParamSpec            *pspec);
197 static guint    settings_install_property_parser (GtkSettingsClass      *class,
198                                                   GParamSpec            *pspec,
199                                                   GtkRcPropertyParser    parser);
200 static void    settings_update_double_click      (GtkSettings           *settings);
201 static void    settings_update_modules           (GtkSettings           *settings);
202
203 #ifdef GDK_WINDOWING_X11
204 static void    settings_update_cursor_theme      (GtkSettings           *settings);
205 static void    settings_update_resolution        (GtkSettings           *settings);
206 static void    settings_update_font_options      (GtkSettings           *settings);
207 static gboolean settings_update_fontconfig       (GtkSettings           *settings);
208 #endif
209 static void    settings_update_color_scheme      (GtkSettings *settings);
210
211 static void    merge_color_scheme                (GtkSettings           *settings, 
212                                                   const GValue          *value, 
213                                                   GtkSettingsSource      source);
214 static gchar  *get_color_scheme                  (GtkSettings           *settings);
215 static GHashTable *get_color_hash                (GtkSettings           *settings);
216
217 /* the default palette for GtkColorSelelection */
218 static const gchar default_color_palette[] =
219   "black:white:gray50:red:purple:blue:light blue:green:yellow:orange:"
220   "lavender:brown:goldenrod4:dodger blue:pink:light green:gray10:gray30:gray75:gray90";
221
222 /* --- variables --- */
223 static GQuark            quark_property_parser = 0;
224 static GSList           *object_list = NULL;
225 static guint             class_n_properties = 0;
226
227
228 G_DEFINE_TYPE_EXTENDED (GtkSettings, gtk_settings, G_TYPE_OBJECT, 0,
229                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
230                                                gtk_settings_provider_iface_init));
231
232 /* --- functions --- */
233 static void
234 gtk_settings_init (GtkSettings *settings)
235 {
236   GParamSpec **pspecs, **p;
237   guint i = 0;
238   
239   g_datalist_init (&settings->queued_settings);
240   object_list = g_slist_prepend (object_list, settings);
241
242   /* build up property array for all yet existing properties and queue
243    * notification for them (at least notification for internal properties
244    * will instantly be caught)
245    */
246   pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
247   for (p = pspecs; *p; p++)
248     if ((*p)->owner_type == G_OBJECT_TYPE (settings))
249       i++;
250   settings->property_values = g_new0 (GtkSettingsPropertyValue, i);
251   i = 0;
252   g_object_freeze_notify (G_OBJECT (settings));
253   for (p = pspecs; *p; p++)
254     {
255       GParamSpec *pspec = *p;
256
257       if (pspec->owner_type != G_OBJECT_TYPE (settings))
258         continue;
259       g_value_init (&settings->property_values[i].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
260       g_param_value_set_default (pspec, &settings->property_values[i].value);
261       g_object_notify (G_OBJECT (settings), pspec->name);
262       settings->property_values[i].source = GTK_SETTINGS_SOURCE_DEFAULT;
263       i++;
264     }
265   g_object_thaw_notify (G_OBJECT (settings));
266   g_free (pspecs);
267 }
268
269 static void
270 gtk_settings_class_init (GtkSettingsClass *class)
271 {
272   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
273   guint result;
274   
275   gobject_class->finalize = gtk_settings_finalize;
276   gobject_class->get_property = gtk_settings_get_property;
277   gobject_class->set_property = gtk_settings_set_property;
278   gobject_class->notify = gtk_settings_notify;
279
280   quark_property_parser = g_quark_from_static_string ("gtk-rc-property-parser");
281   result = settings_install_property_parser (class,
282                                              g_param_spec_int ("gtk-double-click-time",
283                                                                P_("Double Click Time"),
284                                                                P_("Maximum time allowed between two clicks for them to be considered a double click (in milliseconds)"),
285                                                                0, G_MAXINT, 250,
286                                                                GTK_PARAM_READWRITE),
287                                              NULL);
288   g_assert (result == PROP_DOUBLE_CLICK_TIME);
289   result = settings_install_property_parser (class,
290                                              g_param_spec_int ("gtk-double-click-distance",
291                                                                P_("Double Click Distance"),
292                                                                P_("Maximum distance allowed between two clicks for them to be considered a double click (in pixels)"),
293                                                                0, G_MAXINT, 5,
294                                                                GTK_PARAM_READWRITE),
295                                              NULL);
296   g_assert (result == PROP_DOUBLE_CLICK_DISTANCE);
297
298   /**
299    * GtkSettings:gtk-cursor-blink:
300    *
301    * Whether the cursor should blink. 
302    *
303    * Also see the #GtkSettings:gtk-cursor-blink-timeout setting, 
304    * which allows more flexible control over cursor blinking.
305    */
306   result = settings_install_property_parser (class,
307                                              g_param_spec_boolean ("gtk-cursor-blink",
308                                                                    P_("Cursor Blink"),
309                                                                    P_("Whether the cursor should blink"),
310                                                                    TRUE,
311                                                                    GTK_PARAM_READWRITE),
312                                              NULL);
313   g_assert (result == PROP_CURSOR_BLINK);
314   result = settings_install_property_parser (class,
315                                              g_param_spec_int ("gtk-cursor-blink-time",
316                                                                P_("Cursor Blink Time"),
317                                                                P_("Length of the cursor blink cycle, in milliseconds"),
318                                                                100, G_MAXINT, 1200,
319                                                                GTK_PARAM_READWRITE),
320                                              NULL);
321   g_assert (result == PROP_CURSOR_BLINK_TIME);
322  
323   /**
324    * GtkSettings:gtk-cursor-blink-timeout:
325    *
326    * Time after which the cursor stops blinking, in seconds.
327    * The timer is reset after each user interaction.
328    *
329    * Setting this to zero has the same effect as setting
330    * #GtkSettings:gtk-cursor-blink to %FALSE. 
331    *
332    * Since: 2.12
333    */
334   result = settings_install_property_parser (class,
335                                              g_param_spec_int ("gtk-cursor-blink-timeout",
336                                                                P_("Cursor Blink Timeout"),
337                                                                P_("Time after which the cursor stops blinking, in seconds"),
338                                                                1, G_MAXINT, G_MAXINT,
339                                                                GTK_PARAM_READWRITE),
340                                              NULL);
341   g_assert (result == PROP_CURSOR_BLINK_TIMEOUT);
342   result = settings_install_property_parser (class,
343                                              g_param_spec_boolean ("gtk-split-cursor",
344                                                                    P_("Split Cursor"),
345                                                                    P_("Whether two cursors should be displayed for mixed left-to-right and right-to-left text"),
346                                                                    TRUE,
347                                                                    GTK_PARAM_READWRITE),
348                                              NULL);
349   g_assert (result == PROP_SPLIT_CURSOR);
350   result = settings_install_property_parser (class,
351                                              g_param_spec_string ("gtk-theme-name",
352                                                                    P_("Theme Name"),
353                                                                    P_("Name of theme RC file to load"),
354                                                                   "Raleigh",
355                                                                   GTK_PARAM_READWRITE),
356                                              NULL);
357   g_assert (result == PROP_THEME_NAME);
358
359   result = settings_install_property_parser (class,
360                                              g_param_spec_string ("gtk-icon-theme-name",
361                                                                   P_("Icon Theme Name"),
362                                                                   P_("Name of icon theme to use"),
363                                                                   "hicolor",
364                                                                   GTK_PARAM_READWRITE),
365                                              NULL);
366   g_assert (result == PROP_ICON_THEME_NAME);
367
368   result = settings_install_property_parser (class,
369                                              g_param_spec_string ("gtk-fallback-icon-theme",
370                                                                   P_("Fallback Icon Theme Name"),
371                                                                   P_("Name of a icon theme to fall back to"),
372                                                                   NULL,
373                                                                   GTK_PARAM_READWRITE),
374                                              NULL);
375   g_assert (result == PROP_FALLBACK_ICON_THEME);
376   
377   result = settings_install_property_parser (class,
378                                              g_param_spec_string ("gtk-key-theme-name",
379                                                                   P_("Key Theme Name"),
380                                                                   P_("Name of key theme RC file to load"),
381                                                                   DEFAULT_KEY_THEME,
382                                                                   GTK_PARAM_READWRITE),
383                                              NULL);
384   g_assert (result == PROP_KEY_THEME_NAME);    
385
386   result = settings_install_property_parser (class,
387                                              g_param_spec_string ("gtk-menu-bar-accel",
388                                                                   P_("Menu bar accelerator"),
389                                                                   P_("Keybinding to activate the menu bar"),
390                                                                   "F10",
391                                                                   GTK_PARAM_READWRITE),
392                                              NULL);
393   g_assert (result == PROP_MENU_BAR_ACCEL);
394
395   result = settings_install_property_parser (class,
396                                              g_param_spec_int ("gtk-dnd-drag-threshold",
397                                                                P_("Drag threshold"),
398                                                                P_("Number of pixels the cursor can move before dragging"),
399                                                                1, G_MAXINT, 8,
400                                                                GTK_PARAM_READWRITE),
401                                              NULL);
402   g_assert (result == PROP_DND_DRAG_THRESHOLD);
403
404   result = settings_install_property_parser (class,
405                                              g_param_spec_string ("gtk-font-name",
406                                                                    P_("Font Name"),
407                                                                    P_("Name of default font to use"),
408                                                                   "Sans 10",
409                                                                   GTK_PARAM_READWRITE),
410                                              NULL);
411   g_assert (result == PROP_FONT_NAME);
412
413   /**
414    * GtkSettings:gtk-icon-sizes:
415    *
416    * A list of icon sizes. The list is separated by colons, and
417    * item has the form:
418    *
419    * <replaceable>size-name</replaceable> = <replaceable>width</replaceable> , <replaceable>height</replaceable>
420    *
421    * E.g. "gtk-menu=16,16:gtk-button=20,20:gtk-dialog=48,48". 
422    * GTK+ itself use the following named icon sizes: gtk-menu, 
423    * gtk-button, gtk-small-toolbar, gtk-large-toolbar, gtk-dnd, 
424    * gtk-dialog. Applications can register their own named icon 
425    * sizes with gtk_icon_size_register().
426    */
427   result = settings_install_property_parser (class,
428                                              g_param_spec_string ("gtk-icon-sizes",
429                                                                    P_("Icon Sizes"),
430                                                                    P_("List of icon sizes (gtk-menu=16,16:gtk-button=20,20..."),
431                                                                   NULL,
432                                                                   GTK_PARAM_READWRITE),
433                                              NULL);
434   g_assert (result == PROP_ICON_SIZES);
435
436   result = settings_install_property_parser (class,
437                                              g_param_spec_string ("gtk-modules",
438                                                                   P_("GTK Modules"),
439                                                                   P_("List of currently active GTK modules"),
440                                                                   NULL,
441                                                                   GTK_PARAM_READWRITE),
442                                              NULL);
443   g_assert (result == PROP_MODULES);
444
445 #ifdef GDK_WINDOWING_X11
446   result = settings_install_property_parser (class,
447                                              g_param_spec_int ("gtk-xft-antialias",
448                                                                P_("Xft Antialias"),
449                                                                P_("Whether to antialias Xft fonts; 0=no, 1=yes, -1=default"),
450                                                                -1, 1, -1,
451                                                                GTK_PARAM_READWRITE),
452                                              NULL);
453  
454   g_assert (result == PROP_XFT_ANTIALIAS);
455   
456   result = settings_install_property_parser (class,
457                                              g_param_spec_int ("gtk-xft-hinting",
458                                                                P_("Xft Hinting"),
459                                                                P_("Whether to hint Xft fonts; 0=no, 1=yes, -1=default"),
460                                                                -1, 1, -1,
461                                                                GTK_PARAM_READWRITE),
462                                              NULL);
463   
464   g_assert (result == PROP_XFT_HINTING);
465   
466   result = settings_install_property_parser (class,
467                                              g_param_spec_string ("gtk-xft-hintstyle",
468                                                                   P_("Xft Hint Style"),
469                                                                   P_("What degree of hinting to use; hintnone, hintslight, hintmedium, or hintfull"),
470                                                                   NULL,
471                                                                   GTK_PARAM_READWRITE),
472                                               NULL);
473   
474   g_assert (result == PROP_XFT_HINTSTYLE);
475   
476   result = settings_install_property_parser (class,
477                                              g_param_spec_string ("gtk-xft-rgba",
478                                                                   P_("Xft RGBA"),
479                                                                   P_("Type of subpixel antialiasing; none, rgb, bgr, vrgb, vbgr"),
480                                                                   NULL,
481                                                                   GTK_PARAM_READWRITE),
482                                              NULL);
483   
484   g_assert (result == PROP_XFT_RGBA);
485   
486   result = settings_install_property_parser (class,
487                                              g_param_spec_int ("gtk-xft-dpi",
488                                                                P_("Xft DPI"),
489                                                                P_("Resolution for Xft, in 1024 * dots/inch. -1 to use default value"),
490                                                                -1, 1024*1024, -1,
491                                                                GTK_PARAM_READWRITE),
492                                              NULL);
493   
494   g_assert (result == PROP_XFT_DPI);
495
496   result = settings_install_property_parser (class,
497                                              g_param_spec_string ("gtk-cursor-theme-name",
498                                                                   P_("Cursor theme name"),
499                                                                   P_("Name of the cursor theme to use, or NULL to use the default theme"),
500                                                                   NULL,
501                                                                   GTK_PARAM_READWRITE),
502                                              NULL);
503   g_assert (result == PROP_CURSOR_THEME_NAME);
504
505   result = settings_install_property_parser (class,
506                                              g_param_spec_int ("gtk-cursor-theme-size",
507                                                                P_("Cursor theme size"),
508                                                                P_("Size to use for cursors, or 0 to use the default size"),
509                                                                0, 128, 0,
510                                                                GTK_PARAM_READWRITE),
511                                              NULL);
512   
513   g_assert (result == PROP_CURSOR_THEME_SIZE);
514
515 #endif  /* GDK_WINDOWING_X11 */
516   result = settings_install_property_parser (class,
517                                              g_param_spec_boolean ("gtk-alternative-button-order",
518                                                                    P_("Alternative button order"),
519                                                                    P_("Whether buttons in dialogs should use the alternative button order"),
520                                                                    FALSE,
521                                                                    GTK_PARAM_READWRITE),
522                                              NULL);
523   g_assert (result == PROP_ALTERNATIVE_BUTTON_ORDER);
524
525   /**
526    * GtkSettings:gtk-alternative-sort-arrows:
527    *
528    * Controls the direction of the sort indicators in sorted list and tree
529    * views. By default an arrow pointing down means the column is sorted
530    * in ascending order. When set to %TRUE, this order will be inverted.
531    *
532    * Since: 2.12
533    */
534   result = settings_install_property_parser (class,
535                                              g_param_spec_boolean ("gtk-alternative-sort-arrows",
536                                                                    P_("Alternative sort indicator direction"),
537                                                                    P_("Whether the direction of the sort indicators in list and tree views is inverted compared to the default (where down means ascending)"),
538                                                                    FALSE,
539                                                                    GTK_PARAM_READWRITE),
540                                              NULL);
541   g_assert (result == PROP_ALTERNATIVE_SORT_ARROWS);
542
543   result = settings_install_property_parser (class,
544                                              g_param_spec_boolean ("gtk-show-input-method-menu",
545                                                                    P_("Show the 'Input Methods' menu"),
546                                                                    P_("Whether the context menus of entries and text views should offer to change the input method"),
547                                                                    TRUE,
548                                                                    GTK_PARAM_READWRITE),
549                                              NULL);
550   g_assert (result == PROP_SHOW_INPUT_METHOD_MENU);
551
552   result = settings_install_property_parser (class,
553                                              g_param_spec_boolean ("gtk-show-unicode-menu",
554                                                                    P_("Show the 'Insert Unicode Control Character' menu"),
555                                                                    P_("Whether the context menus of entries and text views should offer to insert control characters"),
556                                                                    TRUE,
557                                                                    GTK_PARAM_READWRITE),
558                                              NULL);
559   g_assert (result == PROP_SHOW_UNICODE_MENU);
560
561   result = settings_install_property_parser (class,
562                                              g_param_spec_int ("gtk-timeout-initial",
563                                                                P_("Start timeout"),
564                                                                P_("Starting value for timeouts, when button is pressed"),
565                                                                0, G_MAXINT, DEFAULT_TIMEOUT_INITIAL,
566                                                                GTK_PARAM_READWRITE),
567                                              NULL);
568
569   g_assert (result == PROP_TIMEOUT_INITIAL);
570
571   result = settings_install_property_parser (class,
572                                              g_param_spec_int ("gtk-timeout-repeat",
573                                                                P_("Repeat timeout"),
574                                                                P_("Repeat value for timeouts, when button is pressed"),
575                                                                0, G_MAXINT, DEFAULT_TIMEOUT_REPEAT,
576                                                                GTK_PARAM_READWRITE),
577                                              NULL);
578
579   g_assert (result == PROP_TIMEOUT_REPEAT);
580
581   result = settings_install_property_parser (class,
582                                              g_param_spec_int ("gtk-timeout-expand",
583                                                                P_("Expand timeout"),
584                                                                P_("Expand value for timeouts, when a widget is expanding a new region"),
585                                                                0, G_MAXINT, DEFAULT_TIMEOUT_EXPAND,
586                                                                GTK_PARAM_READWRITE),
587                                              NULL);
588
589   g_assert (result == PROP_TIMEOUT_EXPAND);
590
591   /**
592    * GtkSettings:gtk-color-scheme:
593    *
594    * A palette of named colors for use in themes. The format of the string is
595    * <programlisting>
596    * name1: color1
597    * name2: color2
598    * ...
599    * </programlisting>
600    * Color names must be acceptable as identifiers in the 
601    * <link linkend="gtk-Resource-Files">gtkrc</link> syntax, and
602    * color specifications must be in the format accepted by
603    * gdk_color_parse().
604    * 
605    * Note that due to the way the color tables from different sources are
606    * merged, color specifications will be converted to hexadecimal form
607    * when getting this property.
608    *
609    * Starting with GTK+ 2.12, the entries can alternatively be separated
610    * by ';' instead of newlines:
611    * <programlisting>
612    * name1: color1; name2: color2; ...
613    * </programlisting>
614    *
615    * Since: 2.10
616    */
617   result = settings_install_property_parser (class,
618                                              g_param_spec_string ("gtk-color-scheme",
619                                                                   P_("Color scheme"),
620                                                                   P_("A palette of named colors for use in themes"),
621                                                                   "",
622                                                                   GTK_PARAM_READWRITE),
623                                              NULL);
624
625   g_assert (result == PROP_COLOR_SCHEME);
626
627   result = settings_install_property_parser (class,
628                                              g_param_spec_boolean ("gtk-enable-animations",
629                                                                    P_("Enable Animations"),
630                                                                    P_("Whether to enable toolkit-wide animations."),
631                                                                    TRUE,
632                                                                    GTK_PARAM_READWRITE),
633                                              NULL);
634
635   g_assert (result == PROP_ENABLE_ANIMATIONS);
636
637   /**
638    * GtkSettings:gtk-touchscreen-mode:
639    *
640    * When %TRUE, there are no motion notify events delivered on this screen,
641    * and widgets can't use the pointer hovering them for any essential
642    * functionality.
643    *
644    * Since: 2.10
645    */
646   result = settings_install_property_parser (class,
647                                              g_param_spec_boolean ("gtk-touchscreen-mode",
648                                                                    P_("Enable Touchscreen Mode"),
649                                                                    P_("When TRUE, there are no motion notify events delivered on this screen"),
650                                                                    FALSE,
651                                                                    GTK_PARAM_READWRITE),
652                                              NULL);
653
654   g_assert (result == PROP_TOUCHSCREEN_MODE);
655
656   /**
657    * GtkSettings:gtk-tooltip-timeout:
658    *
659    * Time, in milliseconds, after which a tooltip could appear if the
660    * cursor is hovering on top of a widget.
661    *
662    * Since: 2.12
663    */
664   result = settings_install_property_parser (class,
665                                              g_param_spec_int ("gtk-tooltip-timeout",
666                                                                P_("Tooltip timeout"),
667                                                                P_("Timeout before tooltip is shown"),
668                                                                0, G_MAXINT,
669                                                                500,
670                                                                GTK_PARAM_READWRITE),
671                                              NULL);
672
673   g_assert (result == PROP_TOOLTIP_TIMEOUT);
674
675   /**
676    * GtkSettings:gtk-tooltip-browse-timeout:
677    *
678    * Controls the time after which tooltips will appear when
679    * browse mode is enabled, in milliseconds.
680    *
681    * Browse mode is enabled when the mouse pointer moves off an object
682    * where a tooltip was currently being displayed. If the mouse pointer
683    * hits another object before the browse mode timeout expires (see
684    * #GtkSettings:gtk-tooltip-browse-mode-timeout), it will take the 
685    * amount of milliseconds specified by this setting to popup the tooltip
686    * for the new object.
687    *
688    * Since: 2.12
689    */
690   result = settings_install_property_parser (class,
691                                              g_param_spec_int ("gtk-tooltip-browse-timeout",
692                                                                P_("Tooltip browse timeout"),
693                                                                P_("Timeout before tooltip is shown when browse mode is enabled"),
694                                                                0, G_MAXINT,
695                                                                60,
696                                                                GTK_PARAM_READWRITE),
697                                              NULL);
698
699   g_assert (result == PROP_TOOLTIP_BROWSE_TIMEOUT);
700
701   /**
702    * GtkSettings:gtk-tooltip-browse-mode-timeout:
703    *
704    * Amount of time, in milliseconds, after which the browse mode
705    * will be disabled.
706    *
707    * See #GtkSettings:gtk-tooltip-browse-timeout for more information
708    * about browse mode.
709    *
710    * Since: 2.12
711    */
712   result = settings_install_property_parser (class,
713                                              g_param_spec_int ("gtk-tooltip-browse-mode-timeout",
714                                                                P_("Tooltip browse mode timeout"),
715                                                                P_("Timeout after which browse mode is disabled"),
716                                                                0, G_MAXINT,
717                                                                500,
718                                                                GTK_PARAM_READWRITE),
719                                              NULL);
720
721   g_assert (result == PROP_TOOLTIP_BROWSE_MODE_TIMEOUT);
722
723   /**
724    * GtkSettings:gtk-keynav-cursor-only:
725    *
726    * When %TRUE, keyboard navigation should be able to reach all widgets
727    * by using the cursor keys only. Tab, Shift etc. keys can't be expected
728    * to be present on the used input device.
729    *
730    * Since: 2.12
731    */
732   result = settings_install_property_parser (class,
733                                              g_param_spec_boolean ("gtk-keynav-cursor-only",
734                                                                    P_("Keynav Cursor Only"),
735                                                                    P_("When TRUE, there are only cursor keys available to navigate widgets"),
736                                                                    FALSE,
737                                                                    GTK_PARAM_READWRITE),
738                                              NULL);
739
740   g_assert (result == PROP_KEYNAV_CURSOR_ONLY);
741
742   /**
743    * GtkSettings:gtk-keynav-wrap-around:
744    *
745    * When %TRUE, some widgets will wrap around when doing keyboard
746    * navigation, such as menus, menubars and notebooks.
747    *
748    * Since: 2.12
749    */
750   result = settings_install_property_parser (class,
751                                              g_param_spec_boolean ("gtk-keynav-wrap-around",
752                                                                    P_("Keynav Wrap Around"),
753                                                                    P_("Whether to wrap around when keyboard-navigating widgets"),
754                                                                    TRUE,
755                                                                    GTK_PARAM_READWRITE),
756                                              NULL);
757
758   g_assert (result == PROP_KEYNAV_WRAP_AROUND);
759
760   /**
761    * GtkSettings:gtk-error-bell:
762    *
763    * When %TRUE, keyboard navigation and other input-related errors
764    * will cause a beep. Since the error bell is implemented using
765    * gdk_window_beep(), the windowing system may offer ways to
766    * configure the error bell in many ways, such as flashing the
767    * window or similar visual effects.
768    *
769    * Since: 2.12
770    */
771   result = settings_install_property_parser (class,
772                                              g_param_spec_boolean ("gtk-error-bell",
773                                                                    P_("Error Bell"),
774                                                                    P_("When TRUE, keyboard navigation and other errors will cause a beep"),
775                                                                    TRUE,
776                                                                    GTK_PARAM_READWRITE),
777                                              NULL);
778
779   g_assert (result == PROP_ERROR_BELL);
780
781   /**
782    * GtkSettings:color-hash:
783    *
784    * Holds a hash table representation of the #GtkSettings:gtk-color-scheme 
785    * setting, mapping color names to #GdkColor<!-- -->s. 
786    *
787    * Since: 2.10
788    */
789   result = settings_install_property_parser (class, 
790                                              g_param_spec_boxed ("color-hash",
791                                                                  P_("Color Hash"),
792                                                                  P_("A hash table representation of the color scheme."),
793                                                                  G_TYPE_HASH_TABLE,
794                                                                  GTK_PARAM_READABLE),
795                                              NULL);
796   g_assert (result == PROP_COLOR_HASH);
797
798   result = settings_install_property_parser (class, 
799                                              g_param_spec_string ("gtk-file-chooser-backend",
800                                                                   P_("Default file chooser backend"),
801                                                                   P_("Name of the GtkFileChooser backend to use by default"),
802                                                                   NULL,
803                                                                   GTK_PARAM_READWRITE),
804                                              NULL);
805   g_assert (result == PROP_FILE_CHOOSER_BACKEND);
806
807   /**
808    * GtkSettings:gtk-print-backends:
809    *
810    * A comma-separated list of print backends to use in the print
811    * dialog. Available print backends depend on the GTK+ installation,
812    * and may include "file", "cups", "lpr" or "papi".
813    *
814    * Since: 2.10
815    */
816   result = settings_install_property_parser (class,
817                                              g_param_spec_string ("gtk-print-backends",
818                                                                   P_("Default print backend"),
819                                                                   P_("List of the GtkPrintBackend backends to use by default"),
820                                                                   GTK_PRINT_BACKENDS,
821                                                                   GTK_PARAM_READWRITE),
822                                              NULL);
823   g_assert (result == PROP_PRINT_BACKENDS);
824
825   /**
826    * GtkSettings:gtk-print-preview-command:
827    *
828    * A command to run for displaying the print preview. The command
829    * should contain a %f placeholder, which will get replaced by
830    * the path to the pdf file. The command may also contain a %s
831    * placeholder, which will get replaced by the path to a file
832    * containing the print settings in the format produced by 
833    * gtk_print_settings_to_file().
834    *
835    * The preview application is responsible for removing the pdf file
836    * and the print settings file when it is done.
837    *
838    * Since: 2.10
839    */
840   result = settings_install_property_parser (class,
841                                              g_param_spec_string ("gtk-print-preview-command",
842                                                                   P_("Default command to run when displaying a print preview"),
843                                                                   P_("Command to run when displaying a print preview"),
844                                                                   GTK_PRINT_PREVIEW_COMMAND,
845                                                                   GTK_PARAM_READWRITE),
846                                              NULL); 
847   g_assert (result == PROP_PRINT_PREVIEW_COMMAND);
848
849   /**
850    * GtkSettings:gtk-enable-mnemonics:
851    *
852    * Whether labels and menu items should have visible mnemonics which
853    * can be activated.
854    *
855    * Since: 2.12
856    */
857   result = settings_install_property_parser (class,
858                                              g_param_spec_boolean ("gtk-enable-mnemonics",
859                                                                    P_("Enable Mnemonics"),
860                                                                    P_("Whether labels should have mnemonics"),
861                                                                    TRUE,
862                                                                    GTK_PARAM_READWRITE),
863                                              NULL);
864   g_assert (result == PROP_ENABLE_MNEMONICS);
865
866   /**
867    * GtkSettings:gtk-enable-accels:
868    *
869    * Whether menu items should have visible accelerators which can be
870    * activated.
871    *
872    * Since: 2.12
873    */
874   result = settings_install_property_parser (class,
875                                              g_param_spec_boolean ("gtk-enable-accels",
876                                                                    P_("Enable Accelerators"),
877                                                                    P_("Whether menu items should have accelerators"),
878                                                                    TRUE,
879                                                                    GTK_PARAM_READWRITE),
880                                              NULL);
881   g_assert (result == PROP_ENABLE_ACCELS);
882
883   /**
884    * GtkSettings:gtk-recent-files-limit:
885    *
886    * The number of recently used files that should be displayed by default by
887    * #GtkRecentChooser implementations and by the #GtkFileChooser. A value of
888    * -1 means every recently used file stored.
889    *
890    * Since: 2.12
891    */
892   result = settings_install_property_parser (class,
893                                              g_param_spec_int ("gtk-recent-files-limit",
894                                                                P_("Recent Files Limit"),
895                                                                P_("Number of recently used files"),
896                                                                -1, G_MAXINT,
897                                                                50,
898                                                                GTK_PARAM_READWRITE),
899                                              NULL);
900   g_assert (result == PROP_RECENT_FILES_LIMIT);
901
902   /**
903    * GtkSettings:gtk-im-module:
904    *
905    * Which IM (input method) module should be used by default. This is the 
906    * input method that will be used if the user has not explicitly chosen 
907    * another input method from the IM context menu.  
908    *
909    * See #GtkIMContext and see the #GtkSettings:gtk-show-input-method-menu property.
910    */
911   result = settings_install_property_parser (class,
912                                              g_param_spec_string ("gtk-im-module",
913                                                                   P_("Default IM module"),
914                                                                   P_("Which IM module should be used by default"),
915                                                                   NULL,
916                                                                   GTK_PARAM_READWRITE),
917                                              NULL);
918   g_assert (result == PROP_IM_MODULE);
919
920   /**
921    * GtkSettings:gtk-recent-files-max-age:
922    *
923    * The maximum age, in days, of the items inside the recently used
924    * resources list. Items older than this setting will be excised
925    * from the list. If set to 0, the list will always be empty; if
926    * set to -1, no item will be removed.
927    *
928    * Since: 2.14
929    */
930   result = settings_install_property_parser (class,
931                                              g_param_spec_int ("gtk-recent-files-max-age",
932                                                                P_("Recent Files Max Age"),
933                                                                P_("Maximum age of recently used files, in days"),
934                                                                -1, G_MAXINT,
935                                                                30,
936                                                                GTK_PARAM_READWRITE),
937                                              NULL);
938   g_assert (result == PROP_RECENT_FILES_MAX_AGE);
939
940   result = settings_install_property_parser (class,
941                                              g_param_spec_uint ("gtk-fontconfig-timestamp",
942                                                                 P_("Fontconfig configuration timestamp"),
943                                                                 P_("Timestamp of current fontconfig configuration"),
944                                                                 0, G_MAXUINT, 0,
945                                                                 GTK_PARAM_READWRITE),
946                                              NULL);
947   
948   g_assert (result == PROP_FONTCONFIG_TIMESTAMP);
949
950   /**
951    * GtkSettings:gtk-sound-theme-name:
952    *
953    * The XDG sound theme to use for event sounds.
954    *
955    * See the <ulink url="http://www.freedesktop.org/wiki/Specifications/sound-theme-spec">Sound Theme spec</ulink> 
956    * for more information on event sounds and sound themes.
957    *
958    * GTK+ itself does not support event sounds, you have to use a loadable 
959    * module like the one that comes with libcanberra.
960    *
961    * Since: 2.14
962    */
963   result = settings_install_property_parser (class,
964                                              g_param_spec_string ("gtk-sound-theme-name",
965                                                                   P_("Sound Theme Name"),
966                                                                   P_("XDG sound theme name"),
967                                                                   "freedesktop",
968                                                                   GTK_PARAM_READWRITE),
969                                              NULL);
970   g_assert (result == PROP_SOUND_THEME_NAME);
971
972   /**
973    * GtkSettings:gtk-enable-input-feedback-sounds:
974    *
975    * Whether to play event sounds as feedback to user input.
976    *
977    * See the <ulink url="http://www.freedesktop.org/wiki/Specifications/sound-theme-spec">Sound Theme spec</ulink> 
978    * for more information on event sounds and sound themes.
979    *
980    * GTK+ itself does not support event sounds, you have to use a loadable 
981    * module like the one that comes with libcanberra.
982    *
983    * Since: 2.14
984    */
985   result = settings_install_property_parser (class,
986                                              g_param_spec_boolean ("gtk-enable-input-feedback-sounds",
987                                                                    /* Translators: this means sounds that are played as feedback to user input */
988                                                                    P_("Audible Input Feedback"),
989                                                                    P_("Whether to play event sounds as feedback to user input"),
990                                                                    TRUE,
991                                                                    GTK_PARAM_READWRITE),
992                                              NULL);
993   g_assert (result == PROP_ENABLE_INPUT_FEEDBACK_SOUNDS);
994
995   /**
996    * GtkSettings:gtk-enable-event-sounds:
997    *
998    * Whether to play any event sounds at all.
999    *
1000    * See the <ulink url="http://www.freedesktop.org/wiki/Specifications/sound-theme-spec">Sound Theme spec</ulink> 
1001    * for more information on event sounds and sound themes.
1002    *
1003    * GTK+ itself does not support event sounds, you have to use a loadable 
1004    * module like the one that comes with libcanberra.
1005    *
1006    * Since: 2.14
1007    */
1008   result = settings_install_property_parser (class,
1009                                              g_param_spec_boolean ("gtk-enable-event-sounds",
1010                                                                    P_("Enable Event Sounds"),
1011                                                                    P_("Whether to play any event sounds at all"),
1012                                                                    TRUE,
1013                                                                    GTK_PARAM_READWRITE),
1014                                              NULL);
1015   g_assert (result == PROP_ENABLE_EVENT_SOUNDS);
1016
1017   /**
1018    * GtkSettings:gtk-enable-tooltips:
1019    *
1020    * Whether tooltips should be shown on widgets.
1021    *
1022    * Since: 2.14
1023    */
1024   result = settings_install_property_parser (class,
1025                                              g_param_spec_boolean ("gtk-enable-tooltips",
1026                                                                    P_("Enable Tooltips"),
1027                                                                    P_("Whether tooltips should be shown on widgets"),
1028                                                                    TRUE,
1029                                                                    GTK_PARAM_READWRITE),
1030                                              NULL);
1031   g_assert (result == PROP_ENABLE_TOOLTIPS);
1032
1033   /**
1034    * GtkSettings:toolbar-style:
1035    *
1036    * The size of icons in default toolbars.
1037    */
1038   result = settings_install_property_parser (class,
1039                                              g_param_spec_enum ("gtk-toolbar-style",
1040                                                                    P_("Toolbar style"),
1041                                                                    P_("Whether default toolbars have text only, text and icons, icons only, etc."),
1042                                                                    GTK_TYPE_TOOLBAR_STYLE,
1043                                                                    GTK_TOOLBAR_BOTH,
1044                                                                    GTK_PARAM_READWRITE),
1045                                              gtk_rc_property_parse_enum);
1046   g_assert (result == PROP_TOOLBAR_STYLE);
1047
1048   /**
1049    * GtkSettings:toolbar-icon-size:
1050    *
1051    * The size of icons in default toolbars.
1052    */
1053   result = settings_install_property_parser (class,
1054                                              g_param_spec_enum ("gtk-toolbar-icon-size",
1055                                                                    P_("Toolbar Icon Size"),
1056                                                                    P_("The size of icons in default toolbars."),
1057                                                                    GTK_TYPE_ICON_SIZE,
1058                                                                    GTK_ICON_SIZE_LARGE_TOOLBAR,
1059                                                                    GTK_PARAM_READWRITE),
1060                                              gtk_rc_property_parse_enum);
1061   g_assert (result == PROP_TOOLBAR_ICON_SIZE);
1062
1063   /**
1064    * GtkSettings:gtk-auto-mnemonics:
1065    *
1066    * Whether mnemonics should be automatically shown and hidden when the user
1067    * presses the mnemonic activator.
1068    *
1069    * Since: 2.20
1070    */
1071   result = settings_install_property_parser (class,
1072                                              g_param_spec_boolean ("gtk-auto-mnemonics",
1073                                                                    P_("Auto Mnemonics"),
1074                                                                    P_("Whether mnemonics should be automatically shown and hidden when the user presses the mnemonic activator."),
1075                                                                    FALSE,
1076                                                                    GTK_PARAM_READWRITE),
1077                                              NULL);
1078   g_assert (result == PROP_AUTO_MNEMONICS);
1079
1080   /**
1081    * GtkSettings:gtk-application-prefer-dark-theme:
1082    *
1083    * Whether the application prefers to use a dark theme. If a GTK+ theme
1084    * includes a dark variant, it will be used instead of the configured
1085    * theme.
1086    *
1087    * Some applications benefit from minimizing the amount of light pollution that
1088    * interferes with the content. Good candidates for dark themes are photo and
1089    * video editors that make the actual content get all the attention and minimize
1090    * the distraction of the chrome.
1091    *
1092    * Dark themes should not be used for documents, where large spaces are white/light
1093    * and the dark chrome creates too much contrast (web browser, text editor...).
1094    *
1095    * Since: 2.22
1096    */
1097   result = settings_install_property_parser (class,
1098                                              g_param_spec_boolean ("gtk-application-prefer-dark-theme",
1099                                                                  P_("Application prefers a dark theme"),
1100                                                                  P_("Whether the application prefers to have a dark theme."),
1101                                                                  FALSE,
1102                                                                  GTK_PARAM_READWRITE),
1103                                              NULL);
1104   g_assert (result == PROP_APPLICATION_PREFER_DARK_THEME);
1105
1106   /**
1107    * GtkSettings::gtk-button-images:
1108    *
1109    * Whether images should be shown on buttons
1110    *
1111    * Since: 2.4
1112    */
1113   result = settings_install_property_parser (class,
1114                                              g_param_spec_boolean ("gtk-button-images",
1115                                                                    P_("Show button images"),
1116                                                                    P_("Whether images should be shown on buttons"),
1117                                                                    TRUE,
1118                                                                    GTK_PARAM_READWRITE),
1119                                              NULL);
1120   g_assert (result == PROP_BUTTON_IMAGES);
1121
1122   result = settings_install_property_parser (class,
1123                                              g_param_spec_boolean ("gtk-entry-select-on-focus",
1124                                                                    P_("Select on focus"),
1125                                                                    P_("Whether to select the contents of an entry when it is focused"),
1126                                                                    TRUE,
1127                                                                    GTK_PARAM_READWRITE),
1128                                              NULL);
1129   g_assert (result == PROP_ENTRY_SELECT_ON_FOCUS);
1130
1131   /**
1132    * GtkSettings:gtk-entry-password-hint-timeout:
1133    *
1134    * How long to show the last input character in hidden
1135    * entries. This value is in milliseconds. 0 disables showing the
1136    * last char. 600 is a good value for enabling it.
1137    *
1138    * Since: 2.10
1139    */
1140   result = settings_install_property_parser (class,
1141                                              g_param_spec_uint ("gtk-entry-password-hint-timeout",
1142                                                                 P_("Password Hint Timeout"),
1143                                                                 P_("How long to show the last input character in hidden entries"),
1144                                                                 0, G_MAXUINT,
1145                                                                 0,
1146                                                                 GTK_PARAM_READWRITE),
1147                                              NULL);
1148   g_assert (result == PROP_ENTRY_PASSWORD_HINT_TIMEOUT);
1149
1150   result = settings_install_property_parser (class,
1151                                              g_param_spec_boolean ("gtk-menu-images",
1152                                                                    P_("Show menu images"),
1153                                                                    P_("Whether images should be shown in menus"),
1154                                                                    TRUE,
1155                                                                    GTK_PARAM_READWRITE),
1156                                              NULL);
1157   g_assert (result == PROP_MENU_IMAGES);
1158
1159   result = settings_install_property_parser (class,
1160                                              g_param_spec_int ("gtk-menu-bar-popup-delay",
1161                                                                P_("Delay before drop down menus appear"),
1162                                                                P_("Delay before the submenus of a menu bar appear"),
1163                                                                0, G_MAXINT,
1164                                                                0,
1165                                                                GTK_PARAM_READWRITE),
1166                                              NULL);
1167   g_assert (result == PROP_MENU_BAR_POPUP_DELAY);
1168
1169   /**
1170    * GtkSettings:gtk-scrolled-window-placement:
1171    *
1172    * Where the contents of scrolled windows are located with respect to the 
1173    * scrollbars, if not overridden by the scrolled window's own placement.
1174    *
1175    * Since: 2.10
1176    */
1177   result = settings_install_property_parser (class,
1178                                              g_param_spec_enum ("gtk-scrolled-window-placement",
1179                                                                 P_("Scrolled Window Placement"),
1180                                                                 P_("Where the contents of scrolled windows are located with respect to the scrollbars, if not overridden by the scrolled window's own placement."),
1181                                                                 GTK_TYPE_CORNER_TYPE,
1182                                                                 GTK_CORNER_TOP_LEFT,
1183                                                                 GTK_PARAM_READWRITE),
1184                                              gtk_rc_property_parse_enum);
1185   g_assert (result == PROP_SCROLLED_WINDOW_PLACEMENT);
1186
1187   result = settings_install_property_parser (class,
1188                                              g_param_spec_boolean ("gtk-can-change-accels",
1189                                                                    P_("Can change accelerators"),
1190                                                                    P_("Whether menu accelerators can be changed by pressing a key over the menu item"),
1191                                                                    FALSE,
1192                                                                    GTK_PARAM_READWRITE),
1193                                              NULL);
1194   g_assert (result == PROP_CAN_CHANGE_ACCELS);
1195
1196   result = settings_install_property_parser (class,
1197                                              g_param_spec_int ("gtk-menu-popup-delay",
1198                                                                P_("Delay before submenus appear"),
1199                                                                P_("Minimum time the pointer must stay over a menu item before the submenu appear"),
1200                                                                0, G_MAXINT,
1201                                                                225,
1202                                                                GTK_PARAM_READWRITE),
1203                                              NULL);
1204   g_assert (result == PROP_MENU_POPUP_DELAY);
1205
1206   result = settings_install_property_parser (class,
1207                                              g_param_spec_int ("gtk-menu-popdown-delay",
1208                                                                P_("Delay before hiding a submenu"),
1209                                                                P_("The time before hiding a submenu when the pointer is moving towards the submenu"),
1210                                                                0, G_MAXINT,
1211                                                                1000,
1212                                                                GTK_PARAM_READWRITE),
1213                                              NULL);
1214   g_assert (result == PROP_MENU_POPDOWN_DELAY);
1215
1216   result = settings_install_property_parser (class,
1217                                              g_param_spec_boolean ("gtk-label-select-on-focus",
1218                                                                    P_("Select on focus"),
1219                                                                    P_("Whether to select the contents of a selectable label when it is focused"),
1220                                                                    TRUE,
1221                                                                    GTK_PARAM_READWRITE),
1222                                              NULL);
1223   g_assert (result == PROP_LABEL_SELECT_ON_FOCUS);
1224
1225   result = settings_install_property_parser (class,
1226                                              g_param_spec_string ("gtk-color-palette",
1227                                                                   P_("Custom palette"),
1228                                                                   P_("Palette to use in the color selector"),
1229                                                                   default_color_palette,
1230                                                                   GTK_PARAM_READWRITE),
1231                                              NULL);
1232   g_assert (result == PROP_COLOR_PALETTE);
1233
1234   result = settings_install_property_parser (class,
1235                                              g_param_spec_enum ("gtk-im-preedit-style",
1236                                                                 P_("IM Preedit style"),
1237                                                                 P_("How to draw the input method preedit string"),
1238                                                                 GTK_TYPE_IM_PREEDIT_STYLE,
1239                                                                 GTK_IM_PREEDIT_CALLBACK,
1240                                                                 GTK_PARAM_READWRITE),
1241                                              gtk_rc_property_parse_enum);
1242   g_assert (result == PROP_IM_PREEDIT_STYLE);
1243
1244   result = settings_install_property_parser (class,
1245                                              g_param_spec_enum ("gtk-im-status-style",
1246                                                                 P_("IM Status style"),
1247                                                                 P_("How to draw the input method statusbar"),
1248                                                                 GTK_TYPE_IM_STATUS_STYLE,
1249                                                                 GTK_IM_STATUS_CALLBACK,
1250                                                                 GTK_PARAM_READWRITE),
1251                                              gtk_rc_property_parse_enum);
1252   g_assert (result == PROP_IM_STATUS_STYLE);
1253 }
1254
1255 static GtkStyleSet *
1256 gtk_settings_get_style (GtkStyleProvider *provider,
1257                         GtkWidgetPath    *path)
1258 {
1259   PangoFontDescription *font_desc;
1260   gchar *font_name, *color_scheme;
1261   GtkSettings *settings;
1262   GtkStyleSet *set;
1263   gchar **colors;
1264   guint i;
1265
1266   settings = GTK_SETTINGS (provider);
1267   set = gtk_style_set_new ();
1268
1269   g_object_get (settings,
1270                 "gtk-font-name", &font_name,
1271                 "gtk-color-scheme", &color_scheme,
1272                 NULL);
1273
1274   colors = g_strsplit_set (color_scheme, "\n;", -1);
1275
1276   for (i = 0; colors[i]; i++)
1277     {
1278       gchar *name, *pos;
1279       GdkColor col;
1280
1281       if (!*colors[i])
1282         continue;
1283
1284       name = colors[i];
1285       pos = strchr (colors[i], ':');
1286
1287       if (!pos)
1288         continue;
1289
1290       /* Set NUL after color name */
1291       *pos = '\0';
1292       pos++;
1293
1294       /* Find start of color string */
1295       while (*pos == ' ')
1296         pos++;
1297
1298       if (!*pos || !gdk_color_parse (pos, &col))
1299         continue;
1300
1301       gtk_style_set_map_color (set, name,
1302                                gtk_symbolic_color_new_literal (&col));
1303     }
1304
1305   font_desc = pango_font_description_from_string (font_name);
1306
1307   gtk_style_set_set (set, 0,
1308                      "font", font_desc,
1309                      NULL);
1310
1311   pango_font_description_free (font_desc);
1312   g_strfreev (colors);
1313   g_free (color_scheme);
1314   g_free (font_name);
1315
1316   return set;
1317 }
1318
1319 static void
1320 gtk_settings_provider_iface_init (GtkStyleProviderIface *iface)
1321 {
1322   iface->get_style = gtk_settings_get_style;
1323 }
1324
1325 static void
1326 gtk_settings_finalize (GObject *object)
1327 {
1328   GtkSettings *settings = GTK_SETTINGS (object);
1329   guint i;
1330
1331   object_list = g_slist_remove (object_list, settings);
1332
1333   _gtk_rc_context_destroy (settings);
1334
1335   for (i = 0; i < class_n_properties; i++)
1336     g_value_unset (&settings->property_values[i].value);
1337   g_free (settings->property_values);
1338   
1339   g_datalist_clear (&settings->queued_settings);
1340
1341   G_OBJECT_CLASS (gtk_settings_parent_class)->finalize (object);
1342 }
1343
1344 static void
1345 settings_init_style (GtkSettings *settings)
1346 {
1347   static GtkCssProvider *css_provider = NULL;
1348   GtkCssProvider *default_provider;
1349
1350   /* Add provider for user file */
1351   if (G_UNLIKELY (!css_provider))
1352     {
1353       GFile *home_dir, *css_file;
1354       gchar *filename;
1355
1356       css_provider = gtk_css_provider_new ();
1357       home_dir = g_file_new_for_path (g_get_home_dir ());
1358
1359       filename = g_strdup_printf (".gtk-%d.0.css", GTK_MAJOR_VERSION);
1360       css_file = g_file_get_child (home_dir, filename);
1361       g_free (filename);
1362
1363       if (g_file_query_exists (css_file, NULL))
1364         gtk_css_provider_load_from_file (css_provider, css_file, NULL);
1365
1366       g_object_unref (home_dir);
1367       g_object_unref (css_file);
1368     }
1369
1370   gtk_style_context_add_provider_for_screen (settings->screen,
1371                                              GTK_STYLE_PROVIDER (css_provider),
1372                                              GTK_STYLE_PROVIDER_PRIORITY_USER);
1373
1374   default_provider = gtk_css_provider_get_default ();
1375   gtk_style_context_add_provider_for_screen (settings->screen,
1376                                              GTK_STYLE_PROVIDER (default_provider),
1377                                              GTK_STYLE_PROVIDER_PRIORITY_FALLBACK);
1378
1379   gtk_style_context_add_provider_for_screen (settings->screen,
1380                                              GTK_STYLE_PROVIDER (settings),
1381                                              GTK_STYLE_PROVIDER_PRIORITY_SETTINGS);
1382 }
1383
1384 /**
1385  * gtk_settings_get_for_screen:
1386  * @screen: a #GdkScreen.
1387  *
1388  * Gets the #GtkSettings object for @screen, creating it if necessary.
1389  *
1390  * Return value: (transfer none): a #GtkSettings object.
1391  *
1392  * Since: 2.2
1393  */
1394 GtkSettings*
1395 gtk_settings_get_for_screen (GdkScreen *screen)
1396 {
1397   GtkSettings *settings;
1398
1399   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1400
1401   settings = g_object_get_data (G_OBJECT (screen), "gtk-settings");
1402   if (!settings)
1403     {
1404       settings = g_object_new (GTK_TYPE_SETTINGS, NULL);
1405       settings->screen = screen;
1406       g_object_set_data_full (G_OBJECT (screen), I_("gtk-settings"), 
1407                               settings, g_object_unref);
1408
1409       settings_init_style (settings);
1410       settings_update_double_click (settings);
1411 #ifdef GDK_WINDOWING_X11
1412       settings_update_cursor_theme (settings);
1413       settings_update_resolution (settings);
1414       settings_update_font_options (settings);
1415 #endif
1416       settings_update_color_scheme (settings);
1417     }
1418   
1419   return settings;
1420 }
1421
1422 /**
1423  * gtk_settings_get_default:
1424  * 
1425  * Gets the #GtkSettings object for the default GDK screen, creating
1426  * it if necessary. See gtk_settings_get_for_screen().
1427  *
1428  * Return value: (transfer none): a #GtkSettings object. If there is no default
1429  *  screen, then returns %NULL.
1430  **/
1431 GtkSettings*
1432 gtk_settings_get_default (void)
1433 {
1434   GdkScreen *screen = gdk_screen_get_default ();
1435
1436   if (screen)
1437     return gtk_settings_get_for_screen (screen);
1438   else
1439     return NULL;
1440 }
1441
1442 static void
1443 gtk_settings_set_property (GObject      *object,
1444                            guint         property_id,
1445                            const GValue *value,
1446                            GParamSpec   *pspec)
1447 {
1448   GtkSettings *settings = GTK_SETTINGS (object);
1449
1450   g_value_copy (value, &settings->property_values[property_id - 1].value);
1451   settings->property_values[property_id - 1].source = GTK_SETTINGS_SOURCE_APPLICATION;
1452   
1453   if (pspec->param_id == PROP_COLOR_SCHEME)
1454     merge_color_scheme (settings, value, GTK_SETTINGS_SOURCE_APPLICATION);
1455 }
1456
1457 static void
1458 gtk_settings_get_property (GObject     *object,
1459                            guint        property_id,
1460                            GValue      *value,
1461                            GParamSpec  *pspec)
1462 {
1463   GtkSettings *settings = GTK_SETTINGS (object);
1464   GType value_type = G_VALUE_TYPE (value);
1465   GType fundamental_type = G_TYPE_FUNDAMENTAL (value_type);
1466
1467   /* handle internal properties */
1468   switch (property_id)
1469     {
1470     case PROP_COLOR_HASH:
1471       g_value_set_boxed (value, get_color_hash (settings));
1472       return;
1473     case PROP_COLOR_SCHEME:
1474       g_value_take_string (value, get_color_scheme (settings));
1475       return;
1476     default: ;
1477     }
1478
1479   /* For enums and strings, we need to get the value as a string,
1480    * not as an int, since we support using names/nicks as the setting
1481    * value.
1482    */
1483   if ((g_value_type_transformable (G_TYPE_INT, value_type) &&
1484        !(fundamental_type == G_TYPE_ENUM || fundamental_type == G_TYPE_FLAGS)) ||
1485       g_value_type_transformable (G_TYPE_STRING, G_VALUE_TYPE (value)) ||
1486       g_value_type_transformable (GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
1487     {
1488       if (settings->property_values[property_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION ||
1489           !gdk_screen_get_setting (settings->screen, pspec->name, value))
1490         g_value_copy (&settings->property_values[property_id - 1].value, value);
1491       else 
1492         g_param_value_validate (pspec, value);
1493     }
1494   else
1495     {
1496       GValue val = { 0, };
1497
1498       /* Try to get xsetting as a string and parse it. */
1499       
1500       g_value_init (&val, G_TYPE_STRING);
1501
1502       if (settings->property_values[property_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION ||
1503           !gdk_screen_get_setting (settings->screen, pspec->name, &val))
1504         {
1505           g_value_copy (&settings->property_values[property_id - 1].value, value);
1506         }
1507       else
1508         {
1509           GValue tmp_value = { 0, };
1510           GValue gstring_value = { 0, };
1511           GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
1512           
1513           g_value_init (&gstring_value, G_TYPE_GSTRING);
1514           g_value_take_boxed (&gstring_value,
1515                               g_string_new (g_value_get_string (&val)));
1516
1517           g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1518
1519           if (parser && _gtk_settings_parse_convert (parser, &gstring_value,
1520                                                      pspec, &tmp_value))
1521             {
1522               g_value_copy (&tmp_value, value);
1523               g_param_value_validate (pspec, value);
1524             }
1525           else
1526             {
1527               g_value_copy (&settings->property_values[property_id - 1].value, value);
1528             }
1529
1530           g_value_unset (&gstring_value);
1531           g_value_unset (&tmp_value);
1532         }
1533
1534       g_value_unset (&val);
1535     }
1536 }
1537
1538 static void
1539 gtk_settings_notify (GObject    *object,
1540                      GParamSpec *pspec)
1541 {
1542   GtkSettings *settings = GTK_SETTINGS (object);
1543   guint property_id = pspec->param_id;
1544
1545   if (settings->screen == NULL) /* initialization */
1546     return;
1547
1548   switch (property_id)
1549     {
1550     case PROP_MODULES:
1551       settings_update_modules (settings);
1552       break;
1553     case PROP_DOUBLE_CLICK_TIME:
1554     case PROP_DOUBLE_CLICK_DISTANCE:
1555       settings_update_double_click (settings);
1556       break;
1557     case PROP_COLOR_SCHEME:
1558       settings_update_color_scheme (settings);
1559       break;
1560 #ifdef GDK_WINDOWING_X11
1561     case PROP_XFT_DPI:
1562       settings_update_resolution (settings);
1563       /* This is a hack because with gtk_rc_reset_styles() doesn't get
1564        * widgets with gtk_widget_style_set(), and also causes more
1565        * recomputation than necessary.
1566        */
1567       gtk_rc_reset_styles (GTK_SETTINGS (object));
1568       break;
1569     case PROP_XFT_ANTIALIAS:
1570     case PROP_XFT_HINTING:
1571     case PROP_XFT_HINTSTYLE:
1572     case PROP_XFT_RGBA:
1573       settings_update_font_options (settings);
1574       gtk_rc_reset_styles (GTK_SETTINGS (object));
1575       break;
1576     case PROP_FONTCONFIG_TIMESTAMP:
1577       if (settings_update_fontconfig (settings))
1578         gtk_rc_reset_styles (GTK_SETTINGS (object));
1579       break;
1580     case PROP_CURSOR_THEME_NAME:
1581     case PROP_CURSOR_THEME_SIZE:
1582       settings_update_cursor_theme (settings);
1583       break;
1584 #endif /* GDK_WINDOWING_X11 */
1585     }
1586 }
1587
1588 gboolean
1589 _gtk_settings_parse_convert (GtkRcPropertyParser parser,
1590                              const GValue       *src_value,
1591                              GParamSpec         *pspec,
1592                              GValue             *dest_value)
1593 {
1594   gboolean success = FALSE;
1595
1596   g_return_val_if_fail (G_VALUE_HOLDS (dest_value, G_PARAM_SPEC_VALUE_TYPE (pspec)), FALSE);
1597
1598   if (parser)
1599     {
1600       GString *gstring;
1601       gboolean free_gstring = TRUE;
1602       
1603       if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
1604         {
1605           gstring = g_value_get_boxed (src_value);
1606           free_gstring = FALSE;
1607         }
1608       else if (G_VALUE_HOLDS_LONG (src_value))
1609         {
1610           gstring = g_string_new (NULL);
1611           g_string_append_printf (gstring, "%ld", g_value_get_long (src_value));
1612         }
1613       else if (G_VALUE_HOLDS_DOUBLE (src_value))
1614         {
1615           gstring = g_string_new (NULL);
1616           g_string_append_printf (gstring, "%f", g_value_get_double (src_value));
1617         }
1618       else if (G_VALUE_HOLDS_STRING (src_value))
1619         {
1620           gchar *tstr = g_strescape (g_value_get_string (src_value), NULL);
1621           
1622           gstring = g_string_new ("\"");
1623           g_string_append (gstring, tstr);
1624           g_string_append_c (gstring, '\"');
1625           g_free (tstr);
1626         }
1627       else
1628         {
1629           g_return_val_if_fail (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING), FALSE);
1630           gstring = NULL; /* silence compiler */
1631         }
1632
1633       success = (parser (pspec, gstring, dest_value) &&
1634                  !g_param_value_validate (pspec, dest_value));
1635
1636       if (free_gstring)
1637         g_string_free (gstring, TRUE);
1638     }
1639   else if (G_VALUE_HOLDS (src_value, G_TYPE_GSTRING))
1640     {
1641       if (G_VALUE_HOLDS (dest_value, G_TYPE_STRING))
1642         {
1643           GString *gstring = g_value_get_boxed (src_value);
1644
1645           g_value_set_string (dest_value, gstring ? gstring->str : NULL);
1646           success = !g_param_value_validate (pspec, dest_value);
1647         }
1648     }
1649   else if (g_value_type_transformable (G_VALUE_TYPE (src_value), G_VALUE_TYPE (dest_value)))
1650     success = g_param_value_convert (pspec, src_value, dest_value, TRUE);
1651
1652   return success;
1653 }
1654
1655 static void
1656 apply_queued_setting (GtkSettings             *data,
1657                       GParamSpec              *pspec,
1658                       GtkSettingsValuePrivate *qvalue)
1659 {
1660   GValue tmp_value = { 0, };
1661   GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
1662
1663   g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1664   if (_gtk_settings_parse_convert (parser, &qvalue->public.value,
1665                                    pspec, &tmp_value))
1666     {
1667       if (pspec->param_id == PROP_COLOR_SCHEME) 
1668         merge_color_scheme (data, &tmp_value, qvalue->source);
1669
1670       if (data->property_values[pspec->param_id - 1].source <= qvalue->source)
1671         {
1672           g_value_copy (&tmp_value, &data->property_values[pspec->param_id - 1].value);
1673           data->property_values[pspec->param_id - 1].source = qvalue->source;
1674           g_object_notify (G_OBJECT (data), g_param_spec_get_name (pspec));
1675         }
1676
1677     }
1678   else
1679     {
1680       gchar *debug = g_strdup_value_contents (&qvalue->public.value);
1681       
1682       g_message ("%s: failed to retrieve property `%s' of type `%s' from rc file value \"%s\" of type `%s'",
1683                  qvalue->public.origin ? qvalue->public.origin : "(for origin information, set GTK_DEBUG)",
1684                  pspec->name,
1685                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
1686                  debug,
1687                  G_VALUE_TYPE_NAME (&tmp_value));
1688       g_free (debug);
1689     }
1690   g_value_unset (&tmp_value);
1691 }
1692
1693 static guint
1694 settings_install_property_parser (GtkSettingsClass   *class,
1695                                   GParamSpec         *pspec,
1696                                   GtkRcPropertyParser parser)
1697 {
1698   GSList *node, *next;
1699
1700   switch (G_TYPE_FUNDAMENTAL (G_PARAM_SPEC_VALUE_TYPE (pspec)))
1701     {
1702     case G_TYPE_BOOLEAN:
1703     case G_TYPE_UCHAR:
1704     case G_TYPE_CHAR:
1705     case G_TYPE_UINT:
1706     case G_TYPE_INT:
1707     case G_TYPE_ULONG:
1708     case G_TYPE_LONG:
1709     case G_TYPE_FLOAT:
1710     case G_TYPE_DOUBLE:
1711     case G_TYPE_STRING:
1712     case G_TYPE_ENUM:
1713       break;
1714     case G_TYPE_BOXED:
1715       if (strcmp (g_param_spec_get_name (pspec), "color-hash") == 0)
1716         {
1717           break;
1718         }
1719       /* fall through */
1720     default:
1721       if (!parser)
1722         {
1723           g_warning (G_STRLOC ": parser needs to be specified for property \"%s\" of type `%s'",
1724                      pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
1725           return 0;
1726         }
1727     }
1728   if (g_object_class_find_property (G_OBJECT_CLASS (class), pspec->name))
1729     {
1730       g_warning (G_STRLOC ": an rc-data property \"%s\" already exists",
1731                  pspec->name);
1732       return 0;
1733     }
1734   
1735   for (node = object_list; node; node = node->next)
1736     g_object_freeze_notify (node->data);
1737
1738   g_object_class_install_property (G_OBJECT_CLASS (class), ++class_n_properties, pspec);
1739   g_param_spec_set_qdata (pspec, quark_property_parser, (gpointer) parser);
1740
1741   for (node = object_list; node; node = node->next)
1742     {
1743       GtkSettings *settings = node->data;
1744       GtkSettingsValuePrivate *qvalue;
1745       
1746       settings->property_values = g_renew (GtkSettingsPropertyValue, settings->property_values, class_n_properties);
1747       settings->property_values[class_n_properties - 1].value.g_type = 0;
1748       g_value_init (&settings->property_values[class_n_properties - 1].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1749       g_param_value_set_default (pspec, &settings->property_values[class_n_properties - 1].value);
1750       settings->property_values[class_n_properties - 1].source = GTK_SETTINGS_SOURCE_DEFAULT;
1751       g_object_notify (G_OBJECT (settings), pspec->name);
1752       
1753       qvalue = g_datalist_get_data (&settings->queued_settings, pspec->name);
1754       if (qvalue)
1755         apply_queued_setting (settings, pspec, qvalue);
1756     }
1757
1758   for (node = object_list; node; node = next)
1759     {
1760       next = node->next;
1761       g_object_thaw_notify (node->data);
1762     }
1763
1764   return class_n_properties;
1765 }
1766
1767 GtkRcPropertyParser
1768 _gtk_rc_property_parser_from_type (GType type)
1769 {
1770   if (type == GDK_TYPE_COLOR)
1771     return gtk_rc_property_parse_color;
1772   else if (type == GTK_TYPE_REQUISITION)
1773     return gtk_rc_property_parse_requisition;
1774   else if (type == GTK_TYPE_BORDER)
1775     return gtk_rc_property_parse_border;
1776   else if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_ENUM && G_TYPE_IS_DERIVED (type))
1777     return gtk_rc_property_parse_enum;
1778   else if (G_TYPE_FUNDAMENTAL (type) == G_TYPE_FLAGS && G_TYPE_IS_DERIVED (type))
1779     return gtk_rc_property_parse_flags;
1780   else
1781     return NULL;
1782 }
1783
1784 void
1785 gtk_settings_install_property (GParamSpec *pspec)
1786 {
1787   static GtkSettingsClass *klass = NULL;
1788
1789   GtkRcPropertyParser parser;
1790
1791   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
1792
1793   if (! klass)
1794     klass = g_type_class_ref (GTK_TYPE_SETTINGS);
1795
1796   parser = _gtk_rc_property_parser_from_type (G_PARAM_SPEC_VALUE_TYPE (pspec));
1797
1798   settings_install_property_parser (klass, pspec, parser);
1799 }
1800
1801 void
1802 gtk_settings_install_property_parser (GParamSpec          *pspec,
1803                                       GtkRcPropertyParser  parser)
1804 {
1805   static GtkSettingsClass *klass = NULL;
1806
1807   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
1808   g_return_if_fail (parser != NULL);
1809
1810   if (! klass)
1811     klass = g_type_class_ref (GTK_TYPE_SETTINGS);
1812
1813   settings_install_property_parser (klass, pspec, parser);
1814 }
1815
1816 static void
1817 free_value (gpointer data)
1818 {
1819   GtkSettingsValuePrivate *qvalue = data;
1820   
1821   g_value_unset (&qvalue->public.value);
1822   g_free (qvalue->public.origin);
1823   g_slice_free (GtkSettingsValuePrivate, qvalue);
1824 }
1825
1826 static void
1827 gtk_settings_set_property_value_internal (GtkSettings            *settings,
1828                                           const gchar            *prop_name,
1829                                           const GtkSettingsValue *new_value,
1830                                           GtkSettingsSource       source)
1831 {
1832   GtkSettingsValuePrivate *qvalue;
1833   GParamSpec *pspec;
1834   gchar *name;
1835   GQuark name_quark;
1836
1837   if (!G_VALUE_HOLDS_LONG (&new_value->value) &&
1838       !G_VALUE_HOLDS_DOUBLE (&new_value->value) &&
1839       !G_VALUE_HOLDS_STRING (&new_value->value) &&
1840       !G_VALUE_HOLDS (&new_value->value, G_TYPE_GSTRING))
1841     {
1842       g_warning (G_STRLOC ": value type invalid");
1843       return;
1844     }
1845   
1846   name = g_strdup (prop_name);
1847   g_strcanon (name, G_CSET_DIGITS "-" G_CSET_a_2_z G_CSET_A_2_Z, '-');
1848   name_quark = g_quark_from_string (name);
1849   g_free (name);
1850
1851   qvalue = g_datalist_id_get_data (&settings->queued_settings, name_quark);
1852   if (!qvalue)
1853     {
1854       qvalue = g_slice_new0 (GtkSettingsValuePrivate);
1855       g_datalist_id_set_data_full (&settings->queued_settings, name_quark, qvalue, free_value);
1856     }
1857   else
1858     {
1859       g_free (qvalue->public.origin);
1860       g_value_unset (&qvalue->public.value);
1861     }
1862   qvalue->public.origin = g_strdup (new_value->origin);
1863   g_value_init (&qvalue->public.value, G_VALUE_TYPE (&new_value->value));
1864   g_value_copy (&new_value->value, &qvalue->public.value);
1865   qvalue->source = source;
1866   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), g_quark_to_string (name_quark));
1867   if (pspec)
1868     apply_queued_setting (settings, pspec, qvalue);
1869 }
1870
1871 void
1872 gtk_settings_set_property_value (GtkSettings            *settings,
1873                                  const gchar            *prop_name,
1874                                  const GtkSettingsValue *new_value)
1875 {
1876   g_return_if_fail (GTK_SETTINGS (settings));
1877   g_return_if_fail (prop_name != NULL);
1878   g_return_if_fail (new_value != NULL);
1879
1880   gtk_settings_set_property_value_internal (settings, prop_name, new_value,
1881                                             GTK_SETTINGS_SOURCE_APPLICATION);
1882 }
1883
1884 void
1885 _gtk_settings_set_property_value_from_rc (GtkSettings            *settings,
1886                                           const gchar            *prop_name,
1887                                           const GtkSettingsValue *new_value)
1888 {
1889   g_return_if_fail (GTK_SETTINGS (settings));
1890   g_return_if_fail (prop_name != NULL);
1891   g_return_if_fail (new_value != NULL);
1892
1893   gtk_settings_set_property_value_internal (settings, prop_name, new_value,
1894                                             GTK_SETTINGS_SOURCE_RC_FILE);
1895 }
1896
1897 void
1898 gtk_settings_set_string_property (GtkSettings *settings,
1899                                   const gchar *name,
1900                                   const gchar *v_string,
1901                                   const gchar *origin)
1902 {
1903   GtkSettingsValue svalue = { NULL, { 0, }, };
1904
1905   g_return_if_fail (GTK_SETTINGS (settings));
1906   g_return_if_fail (name != NULL);
1907   g_return_if_fail (v_string != NULL);
1908
1909   svalue.origin = (gchar*) origin;
1910   g_value_init (&svalue.value, G_TYPE_STRING);
1911   g_value_set_static_string (&svalue.value, v_string);
1912   gtk_settings_set_property_value (settings, name, &svalue);
1913   g_value_unset (&svalue.value);
1914 }
1915
1916 void
1917 gtk_settings_set_long_property (GtkSettings *settings,
1918                                 const gchar *name,
1919                                 glong        v_long,
1920                                 const gchar *origin)
1921 {
1922   GtkSettingsValue svalue = { NULL, { 0, }, };
1923   
1924   g_return_if_fail (GTK_SETTINGS (settings));
1925   g_return_if_fail (name != NULL);
1926
1927   svalue.origin = (gchar*) origin;
1928   g_value_init (&svalue.value, G_TYPE_LONG);
1929   g_value_set_long (&svalue.value, v_long);
1930   gtk_settings_set_property_value (settings, name, &svalue);
1931   g_value_unset (&svalue.value);
1932 }
1933
1934 void
1935 gtk_settings_set_double_property (GtkSettings *settings,
1936                                   const gchar *name,
1937                                   gdouble      v_double,
1938                                   const gchar *origin)
1939 {
1940   GtkSettingsValue svalue = { NULL, { 0, }, };
1941
1942   g_return_if_fail (GTK_SETTINGS (settings));
1943   g_return_if_fail (name != NULL);
1944
1945   svalue.origin = (gchar*) origin;
1946   g_value_init (&svalue.value, G_TYPE_DOUBLE);
1947   g_value_set_double (&svalue.value, v_double);
1948   gtk_settings_set_property_value (settings, name, &svalue);
1949   g_value_unset (&svalue.value);
1950 }
1951
1952 /**
1953  * gtk_rc_property_parse_color:
1954  * @pspec: a #GParamSpec
1955  * @gstring: the #GString to be parsed
1956  * @property_value: a #GValue which must hold #GdkColor values.
1957  * 
1958  * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
1959  * or gtk_widget_class_install_style_property_parser() which parses a
1960  * color given either by its name or in the form 
1961  * <literal>{ red, green, blue }</literal> where %red, %green and
1962  * %blue are integers between 0 and 65535 or floating-point numbers
1963  * between 0 and 1.
1964  * 
1965  * Return value: %TRUE if @gstring could be parsed and @property_value
1966  * has been set to the resulting #GdkColor.
1967  **/
1968 gboolean
1969 gtk_rc_property_parse_color (const GParamSpec *pspec,
1970                              const GString    *gstring,
1971                              GValue           *property_value)
1972 {
1973   GdkColor color = { 0, 0, 0, 0, };
1974   GScanner *scanner;
1975   gboolean success;
1976
1977   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
1978   g_return_val_if_fail (G_VALUE_HOLDS (property_value, GDK_TYPE_COLOR), FALSE);
1979
1980   scanner = gtk_rc_scanner_new ();
1981   g_scanner_input_text (scanner, gstring->str, gstring->len);
1982   if (gtk_rc_parse_color (scanner, &color) == G_TOKEN_NONE &&
1983       g_scanner_get_next_token (scanner) == G_TOKEN_EOF)
1984     {
1985       g_value_set_boxed (property_value, &color);
1986       success = TRUE;
1987     }
1988   else
1989     success = FALSE;
1990   g_scanner_destroy (scanner);
1991
1992   return success;
1993 }
1994
1995 /**
1996  * gtk_rc_property_parse_enum:
1997  * @pspec: a #GParamSpec
1998  * @gstring: the #GString to be parsed
1999  * @property_value: a #GValue which must hold enum values.
2000  * 
2001  * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2002  * or gtk_widget_class_install_style_property_parser() which parses a single
2003  * enumeration value.
2004  *
2005  * The enumeration value can be specified by its name, its nickname or
2006  * its numeric value. For consistency with flags parsing, the value
2007  * may be surrounded by parentheses.
2008  * 
2009  * Return value: %TRUE if @gstring could be parsed and @property_value
2010  * has been set to the resulting #GEnumValue.
2011  **/
2012 gboolean
2013 gtk_rc_property_parse_enum (const GParamSpec *pspec,
2014                             const GString    *gstring,
2015                             GValue           *property_value)
2016 {
2017   gboolean need_closing_brace = FALSE, success = FALSE;
2018   GScanner *scanner;
2019   GEnumValue *enum_value = NULL;
2020
2021   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2022   g_return_val_if_fail (G_VALUE_HOLDS_ENUM (property_value), FALSE);
2023
2024   scanner = gtk_rc_scanner_new ();
2025   g_scanner_input_text (scanner, gstring->str, gstring->len);
2026
2027   /* we just want to parse _one_ value, but for consistency with flags parsing
2028    * we support optional parenthesis
2029    */
2030   g_scanner_get_next_token (scanner);
2031   if (scanner->token == '(')
2032     {
2033       need_closing_brace = TRUE;
2034       g_scanner_get_next_token (scanner);
2035     }
2036   if (scanner->token == G_TOKEN_IDENTIFIER)
2037     {
2038       GEnumClass *class = G_PARAM_SPEC_ENUM (pspec)->enum_class;
2039       
2040       enum_value = g_enum_get_value_by_name (class, scanner->value.v_identifier);
2041       if (!enum_value)
2042         enum_value = g_enum_get_value_by_nick (class, scanner->value.v_identifier);
2043       if (enum_value)
2044         {
2045           g_value_set_enum (property_value, enum_value->value);
2046           success = TRUE;
2047         }
2048     }
2049   else if (scanner->token == G_TOKEN_INT)
2050     {
2051       g_value_set_enum (property_value, scanner->value.v_int);
2052       success = TRUE;
2053     }
2054   if (need_closing_brace && g_scanner_get_next_token (scanner) != ')')
2055     success = FALSE;
2056   if (g_scanner_get_next_token (scanner) != G_TOKEN_EOF)
2057     success = FALSE;
2058
2059   g_scanner_destroy (scanner);
2060
2061   return success;
2062 }
2063
2064 static guint
2065 parse_flags_value (GScanner    *scanner,
2066                    GFlagsClass *class,
2067                    guint       *number)
2068 {
2069   g_scanner_get_next_token (scanner);
2070   if (scanner->token == G_TOKEN_IDENTIFIER)
2071     {
2072       GFlagsValue *flags_value;
2073
2074       flags_value = g_flags_get_value_by_name (class, scanner->value.v_identifier);
2075       if (!flags_value)
2076         flags_value = g_flags_get_value_by_nick (class, scanner->value.v_identifier);
2077       if (flags_value)
2078         {
2079           *number |= flags_value->value;
2080           return G_TOKEN_NONE;
2081         }
2082     }
2083   else if (scanner->token == G_TOKEN_INT)
2084     {
2085       *number |= scanner->value.v_int;
2086       return G_TOKEN_NONE;
2087     }
2088   return G_TOKEN_IDENTIFIER;
2089 }
2090
2091 /**
2092  * gtk_rc_property_parse_flags:
2093  * @pspec: a #GParamSpec
2094  * @gstring: the #GString to be parsed
2095  * @property_value: a #GValue which must hold flags values.
2096  * 
2097  * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2098  * or gtk_widget_class_install_style_property_parser() which parses flags. 
2099  * 
2100  * Flags can be specified by their name, their nickname or
2101  * numerically. Multiple flags can be specified in the form 
2102  * <literal>"( flag1 | flag2 | ... )"</literal>.
2103  * 
2104  * Return value: %TRUE if @gstring could be parsed and @property_value
2105  * has been set to the resulting flags value.
2106  **/
2107 gboolean
2108 gtk_rc_property_parse_flags (const GParamSpec *pspec,
2109                              const GString    *gstring,
2110                              GValue           *property_value)
2111 {
2112   GFlagsClass *class;
2113    gboolean success = FALSE;
2114   GScanner *scanner;
2115
2116   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2117   g_return_val_if_fail (G_VALUE_HOLDS_FLAGS (property_value), FALSE);
2118
2119   class = G_PARAM_SPEC_FLAGS (pspec)->flags_class;
2120   scanner = gtk_rc_scanner_new ();
2121   g_scanner_input_text (scanner, gstring->str, gstring->len);
2122
2123   /* parse either a single flags value or a "\( ... [ \| ... ] \)" compound */
2124   if (g_scanner_peek_next_token (scanner) == G_TOKEN_IDENTIFIER ||
2125       scanner->next_token == G_TOKEN_INT)
2126     {
2127       guint token, flags_value = 0;
2128       
2129       token = parse_flags_value (scanner, class, &flags_value);
2130
2131       if (token == G_TOKEN_NONE && g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
2132         {
2133           success = TRUE;
2134           g_value_set_flags (property_value, flags_value);
2135         }
2136       
2137     }
2138   else if (g_scanner_get_next_token (scanner) == '(')
2139     {
2140       guint token, flags_value = 0;
2141
2142       /* parse first value */
2143       token = parse_flags_value (scanner, class, &flags_value);
2144
2145       /* parse nth values, preceeded by '|' */
2146       while (token == G_TOKEN_NONE && g_scanner_get_next_token (scanner) == '|')
2147         token = parse_flags_value (scanner, class, &flags_value);
2148
2149       /* done, last token must have closed expression */
2150       if (token == G_TOKEN_NONE && scanner->token == ')' &&
2151           g_scanner_peek_next_token (scanner) == G_TOKEN_EOF)
2152         {
2153           g_value_set_flags (property_value, flags_value);
2154           success = TRUE;
2155         }
2156     }
2157   g_scanner_destroy (scanner);
2158
2159   return success;
2160 }
2161
2162 static gboolean
2163 get_braced_int (GScanner *scanner,
2164                 gboolean  first,
2165                 gboolean  last,
2166                 gint     *value)
2167 {
2168   if (first)
2169     {
2170       g_scanner_get_next_token (scanner);
2171       if (scanner->token != '{')
2172         return FALSE;
2173     }
2174
2175   g_scanner_get_next_token (scanner);
2176   if (scanner->token != G_TOKEN_INT)
2177     return FALSE;
2178
2179   *value = scanner->value.v_int;
2180
2181   if (last)
2182     {
2183       g_scanner_get_next_token (scanner);
2184       if (scanner->token != '}')
2185         return FALSE;
2186     }
2187   else
2188     {
2189       g_scanner_get_next_token (scanner);
2190       if (scanner->token != ',')
2191         return FALSE;
2192     }
2193
2194   return TRUE;
2195 }
2196
2197 /**
2198  * gtk_rc_property_parse_requisition:
2199  * @pspec: a #GParamSpec
2200  * @gstring: the #GString to be parsed
2201  * @property_value: a #GValue which must hold boxed values.
2202  * 
2203  * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2204  * or gtk_widget_class_install_style_property_parser() which parses a
2205  * requisition in the form 
2206  * <literal>"{ width, height }"</literal> for integers %width and %height.
2207  * 
2208  * Return value: %TRUE if @gstring could be parsed and @property_value
2209  * has been set to the resulting #GtkRequisition.
2210  **/
2211 gboolean
2212 gtk_rc_property_parse_requisition  (const GParamSpec *pspec,
2213                                     const GString    *gstring,
2214                                     GValue           *property_value)
2215 {
2216   GtkRequisition requisition;
2217   GScanner *scanner;
2218   gboolean success = FALSE;
2219
2220   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2221   g_return_val_if_fail (G_VALUE_HOLDS_BOXED (property_value), FALSE);
2222
2223   scanner = gtk_rc_scanner_new ();
2224   g_scanner_input_text (scanner, gstring->str, gstring->len);
2225
2226   if (get_braced_int (scanner, TRUE, FALSE, &requisition.width) &&
2227       get_braced_int (scanner, FALSE, TRUE, &requisition.height))
2228     {
2229       g_value_set_boxed (property_value, &requisition);
2230       success = TRUE;
2231     }
2232
2233   g_scanner_destroy (scanner);
2234
2235   return success;
2236 }
2237
2238 /**
2239  * gtk_rc_property_parse_border:
2240  * @pspec: a #GParamSpec
2241  * @gstring: the #GString to be parsed
2242  * @property_value: a #GValue which must hold boxed values.
2243  * 
2244  * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
2245  * or gtk_widget_class_install_style_property_parser() which parses
2246  * borders in the form 
2247  * <literal>"{ left, right, top, bottom }"</literal> for integers 
2248  * %left, %right, %top and %bottom.
2249  * 
2250  * Return value: %TRUE if @gstring could be parsed and @property_value
2251  * has been set to the resulting #GtkBorder.
2252  **/
2253 gboolean
2254 gtk_rc_property_parse_border (const GParamSpec *pspec,
2255                               const GString    *gstring,
2256                               GValue           *property_value)
2257 {
2258   GtkBorder border;
2259   GScanner *scanner;
2260   gboolean success = FALSE;
2261   int left, right, top, bottom;
2262
2263   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
2264   g_return_val_if_fail (G_VALUE_HOLDS_BOXED (property_value), FALSE);
2265
2266   scanner = gtk_rc_scanner_new ();
2267   g_scanner_input_text (scanner, gstring->str, gstring->len);
2268
2269   if (get_braced_int (scanner, TRUE, FALSE, &left) &&
2270       get_braced_int (scanner, FALSE, FALSE, &right) &&
2271       get_braced_int (scanner, FALSE, FALSE, &top) &&
2272       get_braced_int (scanner, FALSE, TRUE, &bottom))
2273     {
2274       border.left = left;
2275       border.right = right;
2276       border.top = top;
2277       border.bottom = bottom;
2278       g_value_set_boxed (property_value, &border);
2279       success = TRUE;
2280     }
2281
2282   g_scanner_destroy (scanner);
2283
2284   return success;
2285 }
2286
2287 void
2288 _gtk_settings_handle_event (GdkEventSetting *event)
2289 {
2290   GtkSettings *settings;
2291   GParamSpec *pspec;
2292   guint property_id;
2293
2294   settings = gtk_settings_get_for_screen (gdk_window_get_screen (event->window));
2295   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), event->name);
2296  
2297   if (pspec) 
2298     {
2299       property_id = pspec->param_id;
2300
2301       if (property_id == PROP_COLOR_SCHEME)
2302         {
2303           GValue value = { 0, };
2304  
2305           g_value_init (&value, G_TYPE_STRING);
2306           if (!gdk_screen_get_setting (settings->screen, pspec->name, &value))
2307             g_value_set_static_string (&value, "");
2308           merge_color_scheme (settings, &value, GTK_SETTINGS_SOURCE_XSETTING);
2309           g_value_unset (&value);
2310         }
2311       g_object_notify (G_OBJECT (settings), pspec->name);
2312    }
2313 }
2314
2315 static void
2316 reset_rc_values_foreach (GQuark    key_id,
2317                          gpointer  data,
2318                          gpointer  user_data)
2319 {
2320   GtkSettingsValuePrivate *qvalue = data;
2321   GSList **to_reset = user_data;
2322
2323   if (qvalue->source == GTK_SETTINGS_SOURCE_RC_FILE)
2324     *to_reset = g_slist_prepend (*to_reset, GUINT_TO_POINTER (key_id));
2325 }
2326
2327 void
2328 _gtk_settings_reset_rc_values (GtkSettings *settings)
2329 {
2330   GSList *to_reset = NULL;
2331   GSList *tmp_list;
2332   GParamSpec **pspecs, **p;
2333   gint i;
2334
2335   /* Remove any queued settings
2336    */
2337   g_datalist_foreach (&settings->queued_settings,
2338                       reset_rc_values_foreach,
2339                       &to_reset);
2340
2341   for (tmp_list = to_reset; tmp_list; tmp_list = tmp_list->next)
2342     {
2343       GQuark key_id = GPOINTER_TO_UINT (tmp_list->data);
2344       g_datalist_id_remove_data (&settings->queued_settings, key_id);
2345     }
2346
2347    g_slist_free (to_reset);
2348
2349   /* Now reset the active settings
2350    */
2351   pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
2352   i = 0;
2353
2354   g_object_freeze_notify (G_OBJECT (settings));
2355   for (p = pspecs; *p; p++)
2356     {
2357       if (settings->property_values[i].source == GTK_SETTINGS_SOURCE_RC_FILE)
2358         {
2359           GParamSpec *pspec = *p;
2360
2361           g_param_value_set_default (pspec, &settings->property_values[i].value);
2362           g_object_notify (G_OBJECT (settings), pspec->name);
2363         }
2364       i++;
2365     }
2366   g_object_thaw_notify (G_OBJECT (settings));
2367   g_free (pspecs);
2368 }
2369
2370 static void
2371 settings_update_double_click (GtkSettings *settings)
2372 {
2373   if (gdk_screen_get_number (settings->screen) == 0)
2374     {
2375       GdkDisplay *display = gdk_screen_get_display (settings->screen);
2376       gint double_click_time;
2377       gint double_click_distance;
2378   
2379       g_object_get (settings, 
2380                     "gtk-double-click-time", &double_click_time, 
2381                     "gtk-double-click-distance", &double_click_distance,
2382                     NULL);
2383       
2384       gdk_display_set_double_click_time (display, double_click_time);
2385       gdk_display_set_double_click_distance (display, double_click_distance);
2386     }
2387 }
2388
2389 static void
2390 settings_update_modules (GtkSettings *settings)
2391 {
2392   gchar *modules;
2393   
2394   g_object_get (settings, 
2395                 "gtk-modules", &modules,
2396                 NULL);
2397   
2398   _gtk_modules_settings_changed (settings, modules);
2399   
2400   g_free (modules);
2401 }
2402
2403 #ifdef GDK_WINDOWING_X11
2404 static void
2405 settings_update_cursor_theme (GtkSettings *settings)
2406 {
2407   GdkDisplay *display = gdk_screen_get_display (settings->screen);
2408   gchar *theme = NULL;
2409   gint size = 0;
2410   
2411   g_object_get (settings, 
2412                 "gtk-cursor-theme-name", &theme,
2413                 "gtk-cursor-theme-size", &size,
2414                 NULL);
2415   
2416   gdk_x11_display_set_cursor_theme (display, theme, size);
2417
2418   g_free (theme);
2419 }
2420
2421 static void
2422 settings_update_font_options (GtkSettings *settings)
2423 {
2424   gint hinting;
2425   gchar *hint_style_str;
2426   cairo_hint_style_t hint_style = CAIRO_HINT_STYLE_NONE;
2427   gint antialias;
2428   cairo_antialias_t antialias_mode = CAIRO_ANTIALIAS_GRAY;
2429   gchar *rgba_str;
2430   cairo_subpixel_order_t subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
2431   cairo_font_options_t *options;
2432   
2433   g_object_get (settings,
2434                 "gtk-xft-antialias", &antialias,
2435                 "gtk-xft-hinting", &hinting,
2436                 "gtk-xft-hintstyle", &hint_style_str,
2437                 "gtk-xft-rgba", &rgba_str,
2438                 NULL);
2439
2440   options = cairo_font_options_create ();
2441
2442   cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
2443   
2444   if (hinting >= 0 && !hinting)
2445     {
2446       hint_style = CAIRO_HINT_STYLE_NONE;
2447     }
2448   else if (hint_style_str)
2449     {
2450       if (strcmp (hint_style_str, "hintnone") == 0)
2451         hint_style = CAIRO_HINT_STYLE_NONE;
2452       else if (strcmp (hint_style_str, "hintslight") == 0)
2453         hint_style = CAIRO_HINT_STYLE_SLIGHT;
2454       else if (strcmp (hint_style_str, "hintmedium") == 0)
2455         hint_style = CAIRO_HINT_STYLE_MEDIUM;
2456       else if (strcmp (hint_style_str, "hintfull") == 0)
2457         hint_style = CAIRO_HINT_STYLE_FULL;
2458     }
2459
2460   g_free (hint_style_str);
2461
2462   cairo_font_options_set_hint_style (options, hint_style);
2463
2464   if (rgba_str)
2465     {
2466       if (strcmp (rgba_str, "rgb") == 0)
2467         subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
2468       else if (strcmp (rgba_str, "bgr") == 0)
2469         subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
2470       else if (strcmp (rgba_str, "vrgb") == 0)
2471         subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
2472       else if (strcmp (rgba_str, "vbgr") == 0)
2473         subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
2474
2475       g_free (rgba_str);
2476     }
2477
2478   cairo_font_options_set_subpixel_order (options, subpixel_order);
2479   
2480   if (antialias >= 0 && !antialias)
2481     antialias_mode = CAIRO_ANTIALIAS_NONE;
2482   else if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT)
2483     antialias_mode = CAIRO_ANTIALIAS_SUBPIXEL;
2484   else if (antialias >= 0)
2485     antialias_mode = CAIRO_ANTIALIAS_GRAY;
2486   
2487   cairo_font_options_set_antialias (options, antialias_mode);
2488
2489   gdk_screen_set_font_options (settings->screen, options);
2490   
2491   cairo_font_options_destroy (options);
2492 }
2493
2494 #ifdef GDK_WINDOWING_X11
2495 static gboolean
2496 settings_update_fontconfig (GtkSettings *settings)
2497 {
2498   static guint    last_update_timestamp;
2499   static gboolean last_update_needed;
2500
2501   guint timestamp;
2502
2503   g_object_get (settings,
2504                 "gtk-fontconfig-timestamp", &timestamp,
2505                 NULL);
2506
2507   /* if timestamp is the same as last_update_timestamp, we already have
2508    * updated fontconig on this timestamp (another screen requested it perhaps?),
2509    * just return the cached result.*/
2510
2511   if (timestamp != last_update_timestamp)
2512     {
2513       PangoFontMap *fontmap = pango_cairo_font_map_get_default ();
2514       gboolean update_needed = FALSE;
2515
2516       /* bug 547680 */
2517       if (PANGO_IS_FC_FONT_MAP (fontmap) && !FcConfigUptoDate (NULL))
2518         {
2519           pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap));
2520           if (FcInitReinitialize ())
2521             update_needed = TRUE;
2522         }
2523
2524       last_update_timestamp = timestamp;
2525       last_update_needed = update_needed;
2526     }
2527
2528   return last_update_needed;
2529 }
2530 #endif /* GDK_WINDOWING_X11 */
2531
2532 static void
2533 settings_update_resolution (GtkSettings *settings)
2534 {
2535   gint dpi_int;
2536   double dpi;
2537   
2538   g_object_get (settings,
2539                 "gtk-xft-dpi", &dpi_int,
2540                 NULL);
2541
2542   if (dpi_int > 0)
2543     dpi = dpi_int / 1024.;
2544   else
2545     dpi = -1.;
2546
2547   gdk_screen_set_resolution (settings->screen, dpi);
2548 }
2549 #endif
2550
2551 typedef struct {
2552   GHashTable *color_hash;
2553   GHashTable *tables[GTK_SETTINGS_SOURCE_APPLICATION + 1];
2554   gchar *lastentry[GTK_SETTINGS_SOURCE_APPLICATION + 1];
2555 } ColorSchemeData;
2556
2557 static void
2558 color_scheme_data_free (ColorSchemeData *data)
2559 {
2560   gint i;
2561
2562   g_hash_table_unref (data->color_hash);
2563
2564   for (i = 0; i <= GTK_SETTINGS_SOURCE_APPLICATION; i++)
2565     {
2566       if (data->tables[i])
2567         g_hash_table_unref (data->tables[i]);
2568       g_free (data->lastentry[i]);
2569     }
2570
2571   g_slice_free (ColorSchemeData, data);
2572 }
2573
2574 static void
2575 settings_update_color_scheme (GtkSettings *settings)
2576 {
2577   if (!g_object_get_data (G_OBJECT (settings), "gtk-color-scheme"))
2578     {
2579       ColorSchemeData *data;
2580       GValue value = { 0, };
2581
2582       data = g_slice_new0 (ColorSchemeData);
2583       data->color_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
2584                                                 (GDestroyNotify) gdk_color_free);
2585       g_object_set_data_full (G_OBJECT (settings), "gtk-color-scheme",
2586                               data, (GDestroyNotify) color_scheme_data_free); 
2587
2588       g_value_init (&value, G_TYPE_STRING);
2589       if (gdk_screen_get_setting (settings->screen, "gtk-color-scheme", &value))
2590         {
2591           merge_color_scheme (settings, &value, GTK_SETTINGS_SOURCE_XSETTING);
2592           g_value_unset (&value);
2593         }
2594    }
2595 }
2596
2597 static gboolean
2598 add_color_to_hash (gchar      *name,
2599                    GdkColor   *color,
2600                    GHashTable *target)
2601 {
2602   GdkColor *old;
2603
2604   old = g_hash_table_lookup (target, name);
2605   if (!old || !gdk_color_equal (old, color))
2606     {
2607       g_hash_table_insert (target, g_strdup (name), gdk_color_copy (color));
2608
2609       return TRUE;
2610     }
2611
2612   return FALSE;
2613 }
2614
2615 static gboolean
2616 add_colors_to_hash_from_string (GHashTable  *hash,
2617                                 const gchar *colors)
2618 {
2619   gchar *s, *p, *name;
2620   GdkColor color;
2621   gboolean changed = FALSE;
2622   gchar *copy;
2623
2624   copy = g_strdup (colors);
2625   s = copy;
2626   while (s && *s)
2627     {
2628       name = s;
2629       p = strchr (s, ':');
2630       if (p)
2631         {
2632           *p = '\0';
2633           p++;
2634         }
2635       else
2636         break;
2637
2638       while (*p == ' ')
2639         p++;
2640
2641       s = p;
2642       while (*s) 
2643         {
2644           if (*s == '\n' || *s == ';')
2645             {
2646               *s = '\0';
2647               s++;
2648               break;
2649             }
2650           s++;
2651         }
2652
2653       if (gdk_color_parse (p, &color))
2654         changed |= add_color_to_hash (name, &color, hash);
2655     }
2656
2657   g_free (copy);
2658
2659   return changed;
2660 }
2661
2662 static gboolean
2663 update_color_hash (ColorSchemeData   *data,
2664                    const gchar       *str,
2665                    GtkSettingsSource  source)
2666 {
2667   gboolean changed = FALSE;
2668   gint i;
2669   GHashTable *old_hash;
2670   GHashTableIter iter;
2671   gpointer name;
2672   gpointer color;
2673
2674   if ((str == NULL || *str == '\0') &&
2675       (data->lastentry[source] == NULL || data->lastentry[source][0] == '\0'))
2676     return FALSE;
2677
2678   if (str && data->lastentry[source] && strcmp (str, data->lastentry[source]) == 0)
2679     return FALSE;
2680
2681   /* For the RC_FILE source we merge the values rather than over-writing
2682    * them, since multiple rc files might define independent sets of colors
2683    */
2684   if ((source != GTK_SETTINGS_SOURCE_RC_FILE) &&
2685       data->tables[source] && g_hash_table_size (data->tables[source]) > 0)
2686     {
2687       g_hash_table_unref (data->tables[source]);
2688       data->tables[source] = NULL;
2689       changed = TRUE; /* We can't rely on the code below since str might be "" */
2690     }
2691
2692   if (data->tables[source] == NULL)
2693     data->tables[source] = g_hash_table_new_full (g_str_hash, g_str_equal,
2694                                                   g_free,
2695                                                   (GDestroyNotify) gdk_color_free);
2696
2697   g_free (data->lastentry[source]);
2698   data->lastentry[source] = g_strdup (str);
2699
2700   changed |= add_colors_to_hash_from_string (data->tables[source], str);
2701
2702   if (!changed)
2703     return FALSE;
2704
2705   /* Rebuild the merged hash table. */
2706   if (data->color_hash)
2707     {
2708       old_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
2709                                         (GDestroyNotify) gdk_color_free);
2710
2711       g_hash_table_iter_init (&iter, data->color_hash);
2712       while (g_hash_table_iter_next (&iter, &name, &color))
2713         {
2714           g_hash_table_insert (old_hash, name, color);
2715           g_hash_table_iter_steal (&iter);
2716         }
2717     }
2718   else
2719     {
2720       old_hash = NULL;
2721     }
2722
2723   for (i = 0; i <= GTK_SETTINGS_SOURCE_APPLICATION; i++)
2724     {
2725       if (data->tables[i])
2726         g_hash_table_foreach (data->tables[i], (GHFunc) add_color_to_hash,
2727                               data->color_hash);
2728     }
2729
2730   if (old_hash)
2731     {
2732       /* now check if the merged hash has changed */
2733       changed = FALSE;
2734       if (g_hash_table_size (old_hash) != g_hash_table_size (data->color_hash))
2735         changed = TRUE;
2736       else
2737         {
2738           GHashTableIter iter;
2739           gpointer key, value, new_value;
2740
2741           g_hash_table_iter_init (&iter, old_hash);
2742           while (g_hash_table_iter_next (&iter, &key, &value))
2743             {
2744               new_value = g_hash_table_lookup (data->color_hash, key);
2745               if (!new_value || !gdk_color_equal (value, new_value))
2746                 {
2747                   changed = TRUE;
2748                   break;
2749                 }
2750             }
2751         }
2752
2753       g_hash_table_unref (old_hash);
2754     }
2755   else
2756     changed = TRUE;
2757
2758   return changed;
2759 }
2760
2761 static void
2762 merge_color_scheme (GtkSettings       *settings, 
2763                     const GValue      *value, 
2764                     GtkSettingsSource  source)
2765 {
2766   ColorSchemeData *data;
2767   const gchar *colors;
2768
2769   g_object_freeze_notify (G_OBJECT (settings));
2770
2771   colors = g_value_get_string (value);
2772
2773   settings_update_color_scheme (settings);
2774
2775   data = (ColorSchemeData *) g_object_get_data (G_OBJECT (settings),
2776                                                 "gtk-color-scheme");
2777   
2778   if (update_color_hash (data, colors, source))
2779     g_object_notify (G_OBJECT (settings), "color-hash");
2780
2781   g_object_thaw_notify (G_OBJECT (settings));
2782 }
2783
2784 static GHashTable *
2785 get_color_hash (GtkSettings *settings)
2786 {
2787   ColorSchemeData *data;
2788
2789   settings_update_color_scheme (settings);
2790   
2791   data = (ColorSchemeData *)g_object_get_data (G_OBJECT (settings), 
2792                                                "gtk-color-scheme");
2793
2794   return data->color_hash;
2795 }
2796
2797 static void 
2798 append_color_scheme (gpointer key,
2799                      gpointer value,
2800                      gpointer data)
2801 {
2802   gchar *name = (gchar *)key;
2803   GdkColor *color = (GdkColor *)value;
2804   GString *string = (GString *)data;
2805
2806   g_string_append_printf (string, "%s: #%04x%04x%04x\n",
2807                           name, color->red, color->green, color->blue);
2808 }
2809
2810 static gchar *
2811 get_color_scheme (GtkSettings *settings)
2812 {
2813   ColorSchemeData *data;
2814   GString *string;
2815   
2816   settings_update_color_scheme (settings);
2817
2818   data = (ColorSchemeData *) g_object_get_data (G_OBJECT (settings),
2819                                                 "gtk-color-scheme");
2820
2821   string = g_string_new ("");
2822
2823   g_hash_table_foreach (data->color_hash, append_color_scheme, string);
2824
2825   return g_string_free (string, FALSE);
2826 }