]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtksettings.c
Rename the default theme to "Raleigh". (#312254, Thomas Wood)
[~andy/gtk] / gtk / gtksettings.c
index 28f7ed8f1b3743b693e06a8976f25f22620345fb..0cb964cf58f2cdda8b91c38b725b9135ee897f4b 100644 (file)
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <config.h>
+#include "gtkmodules.h"
 #include "gtksettings.h"
 #include "gtkrc.h"
 #include "gtkintl.h"
 #include "gtkwidget.h"
+#include "gtkprivate.h"
+#include "gtkalias.h"
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"
+#endif
+
+#if 0
+#include <pango/pangoxft.h>
+#endif
+
+typedef struct _GtkSettingsValuePrivate GtkSettingsValuePrivate;
+
+typedef enum
+{
+  GTK_SETTINGS_SOURCE_DEFAULT,
+  GTK_SETTINGS_SOURCE_RC_FILE,
+  GTK_SETTINGS_SOURCE_APPLICATION
+} GtkSettingsSource;
+
+struct _GtkSettingsValuePrivate
+{
+  GtkSettingsValue public;
+  GtkSettingsSource source;
+};
+
+struct _GtkSettingsPropertyValue
+{
+  GValue value;
+  GtkSettingsSource source;
+};
 
 enum {
   PROP_0,
   PROP_DOUBLE_CLICK_TIME,
+  PROP_DOUBLE_CLICK_DISTANCE,
   PROP_CURSOR_BLINK,
   PROP_CURSOR_BLINK_TIME,
   PROP_SPLIT_CURSOR,
   PROP_THEME_NAME,
+  PROP_ICON_THEME_NAME,
   PROP_KEY_THEME_NAME,
-  PROP_MENU_BAR_ACCEL
+  PROP_MENU_BAR_ACCEL,
+  PROP_DND_DRAG_THRESHOLD,
+  PROP_FONT_NAME,
+  PROP_ICON_SIZES,
+  PROP_MODULES,
+#ifdef GDK_WINDOWING_X11
+  PROP_XFT_ANTIALIAS,
+  PROP_XFT_HINTING,
+  PROP_XFT_HINTSTYLE,
+  PROP_XFT_RGBA,
+  PROP_XFT_DPI,
+  PROP_CURSOR_THEME_NAME,
+  PROP_CURSOR_THEME_SIZE,
+#endif
+  PROP_ALTERNATIVE_BUTTON_ORDER
 };
 
 
@@ -37,9 +86,6 @@ enum {
 static void    gtk_settings_init                (GtkSettings           *settings);
 static void    gtk_settings_class_init          (GtkSettingsClass      *class);
 static void    gtk_settings_finalize            (GObject               *object);
-static GObject*        gtk_settings_constructor         (GType                  type,
-                                                 guint                  n_construct_properties,
-                                                 GObjectConstructParam *construct_properties);
 static void    gtk_settings_get_property        (GObject               *object,
                                                  guint                  property_id,
                                                  GValue                *value,
@@ -53,11 +99,17 @@ static void gtk_settings_notify              (GObject               *object,
 static guint   settings_install_property_parser (GtkSettingsClass      *class,
                                                  GParamSpec            *pspec,
                                                  GtkRcPropertyParser    parser);
+static void    settings_update_double_click      (GtkSettings           *settings);
+static void    settings_update_modules           (GtkSettings           *settings);
+
+#ifdef GDK_WINDOWING_X11
+static void    settings_update_cursor_theme      (GtkSettings           *settings);
+#endif
+
 
 
 /* --- variables --- */
 static gpointer                 parent_class = NULL;
-static GtkSettings     *the_singleton = NULL;
 static GQuark           quark_property_parser = 0;
 static GSList           *object_list = NULL;
 static guint            class_n_properties = 0;
@@ -84,7 +136,8 @@ gtk_settings_get_type (void)
        (GInstanceInitFunc) gtk_settings_init,
       };
       
-      settings_type = g_type_register_static (G_TYPE_OBJECT, "GtkSettings", &settings_info, 0);
+      settings_type = g_type_register_static (G_TYPE_OBJECT, "GtkSettings",
+                                             &settings_info, 0);
     }
   
   return settings_type;
@@ -107,7 +160,7 @@ gtk_settings_init (GtkSettings *settings)
   for (p = pspecs; *p; p++)
     if ((*p)->owner_type == G_OBJECT_TYPE (settings))
       i++;
-  settings->property_values = g_new0 (GValue, i);
+  settings->property_values = g_new0 (GtkSettingsPropertyValue, i);
   i = 0;
   g_object_freeze_notify (G_OBJECT (settings));
   for (p = pspecs; *p; p++)
@@ -116,9 +169,10 @@ gtk_settings_init (GtkSettings *settings)
 
       if (pspec->owner_type != G_OBJECT_TYPE (settings))
        continue;
-      g_value_init (settings->property_values + i, G_PARAM_SPEC_VALUE_TYPE (pspec));
-      g_param_value_set_default (pspec, settings->property_values + i);
+      g_value_init (&settings->property_values[i].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+      g_param_value_set_default (pspec, &settings->property_values[i].value);
       g_object_notify (G_OBJECT (settings), pspec->name);
+      settings->property_values[i].source = GTK_SETTINGS_SOURCE_DEFAULT;
       i++;
     }
   g_object_thaw_notify (G_OBJECT (settings));
@@ -133,7 +187,6 @@ gtk_settings_class_init (GtkSettingsClass *class)
   
   parent_class = g_type_class_peek_parent (class);
 
-  gobject_class->constructor = gtk_settings_constructor;
   gobject_class->finalize = gtk_settings_finalize;
   gobject_class->get_property = gtk_settings_get_property;
   gobject_class->set_property = gtk_settings_set_property;
@@ -143,62 +196,194 @@ gtk_settings_class_init (GtkSettingsClass *class)
 
   result = settings_install_property_parser (class,
                                              g_param_spec_int ("gtk-double-click-time",
-                                                               _("Double Click Time"),
-                                                               _("Maximum time allowed between two clicks for them to be considered a double click (in milliseconds)"),
+                                                               P_("Double Click Time"),
+                                                               P_("Maximum time allowed between two clicks for them to be considered a double click (in milliseconds)"),
                                                                0, G_MAXINT, 250,
-                                                               G_PARAM_READWRITE),
+                                                               GTK_PARAM_READWRITE),
                                              NULL);
   g_assert (result == PROP_DOUBLE_CLICK_TIME);
+  result = settings_install_property_parser (class,
+                                             g_param_spec_int ("gtk-double-click-distance",
+                                                               P_("Double Click Distance"),
+                                                               P_("Maximum distance allowed between two clicks for them to be considered a double click (in pixels)"),
+                                                               0, G_MAXINT, 5,
+                                                               GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_DOUBLE_CLICK_DISTANCE);
   result = settings_install_property_parser (class,
                                              g_param_spec_boolean ("gtk-cursor-blink",
-                                                                  _("Cursor Blink"),
-                                                                  _("Whether the cursor should blink"),
+                                                                  P_("Cursor Blink"),
+                                                                  P_("Whether the cursor should blink"),
                                                                   TRUE,
-                                                                  G_PARAM_READWRITE),
+                                                                  GTK_PARAM_READWRITE),
                                             NULL);
   g_assert (result == PROP_CURSOR_BLINK);
   result = settings_install_property_parser (class,
                                              g_param_spec_int ("gtk-cursor-blink-time",
-                                                               _("Cursor Blink Time"),
-                                                               _("Length of the cursor blink cycle, in milleseconds"),
+                                                               P_("Cursor Blink Time"),
+                                                               P_("Length of the cursor blink cycle, in milleseconds"),
                                                                100, G_MAXINT, 1200,
-                                                               G_PARAM_READWRITE),
+                                                               GTK_PARAM_READWRITE),
                                              NULL);
   g_assert (result == PROP_CURSOR_BLINK_TIME);
   result = settings_install_property_parser (class,
                                              g_param_spec_boolean ("gtk-split-cursor",
-                                                                  _("Split Cursor"),
-                                                                  _("Whether two cursors should be displayed for mixed left-to-right and right-to-left text"),
+                                                                  P_("Split Cursor"),
+                                                                  P_("Whether two cursors should be displayed for mixed left-to-right and right-to-left text"),
                                                                   TRUE,
-                                                                  G_PARAM_READWRITE),
+                                                                  GTK_PARAM_READWRITE),
                                              NULL);
   g_assert (result == PROP_SPLIT_CURSOR);
   result = settings_install_property_parser (class,
                                              g_param_spec_string ("gtk-theme-name",
-                                                                  _("Theme Name"),
-                                                                  _("Name of theme RC file to load"),
-                                                                 NULL,
-                                                                 G_PARAM_READWRITE),
+                                                                  P_("Theme Name"),
+                                                                  P_("Name of theme RC file to load"),
+                                                                 "Raleigh",
+                                                                 GTK_PARAM_READWRITE),
                                              NULL);
   g_assert (result == PROP_THEME_NAME);
+  result = settings_install_property_parser (class,
+                                             g_param_spec_string ("gtk-icon-theme-name",
+                                                                 P_("Icon Theme Name"),
+                                                                 P_("Name of icon theme to use"),
+                                                                 "hicolor",
+                                                                 GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_ICON_THEME_NAME);
+  
   result = settings_install_property_parser (class,
                                              g_param_spec_string ("gtk-key-theme-name",
-                                                                 _("Key Theme Name"),
-                                                                 _("Name of key theme RC file to load"),
+                                                                 P_("Key Theme Name"),
+                                                                 P_("Name of key theme RC file to load"),
                                                                  NULL,
-                                                                 G_PARAM_READWRITE),
+                                                                 GTK_PARAM_READWRITE),
                                              NULL);
   g_assert (result == PROP_KEY_THEME_NAME);    
 
   result = settings_install_property_parser (class,
                                              g_param_spec_string ("gtk-menu-bar-accel",
-                                                                  _("Menu bar accelerator"),
-                                                                  _("Keybinding to activate the menu bar"),
+                                                                  P_("Menu bar accelerator"),
+                                                                  P_("Keybinding to activate the menu bar"),
                                                                   "F10",
-                                                                  G_PARAM_READWRITE),
+                                                                  GTK_PARAM_READWRITE),
                                              NULL);
-
   g_assert (result == PROP_MENU_BAR_ACCEL);
+
+  result = settings_install_property_parser (class,
+                                            g_param_spec_int ("gtk-dnd-drag-threshold",
+                                                              P_("Drag threshold"),
+                                                              P_("Number of pixels the cursor can move before dragging"),
+                                                              1, G_MAXINT, 8,
+                                                               GTK_PARAM_READWRITE),
+                                            NULL);
+  g_assert (result == PROP_DND_DRAG_THRESHOLD);
+
+  result = settings_install_property_parser (class,
+                                             g_param_spec_string ("gtk-font-name",
+                                                                  P_("Font Name"),
+                                                                  P_("Name of default font to use"),
+                                                                 "Sans 10",
+                                                                 GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_FONT_NAME);
+
+  result = settings_install_property_parser (class,
+                                             g_param_spec_string ("gtk-icon-sizes",
+                                                                  P_("Icon Sizes"),
+                                                                  P_("List of icon sizes (gtk-menu=16,16:gtk-button=20,20..."),
+                                                                 NULL,
+                                                                 GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_ICON_SIZES);
+
+  result = settings_install_property_parser (class,
+                                             g_param_spec_string ("gtk-modules",
+                                                                 P_("GTK Modules"),
+                                                                 P_("List of currently active GTK modules"),
+                                                                 NULL,
+                                                                 GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_MODULES);
+
+#ifdef GDK_WINDOWING_X11
+  result = settings_install_property_parser (class,
+                                            g_param_spec_int ("gtk-xft-antialias",
+                                                              P_("Xft Antialias"),
+                                                              P_("Whether to antialias Xft fonts; 0=no, 1=yes, -1=default"),
+                                                              -1, 1, -1,
+                                                              GTK_PARAM_READWRITE),
+                                            NULL);
+  g_assert (result == PROP_XFT_ANTIALIAS);
+  
+  result = settings_install_property_parser (class,
+                                            g_param_spec_int ("gtk-xft-hinting",
+                                                              P_("Xft Hinting"),
+                                                              P_("Whether to hint Xft fonts; 0=no, 1=yes, -1=default"),
+                                                              -1, 1, -1,
+                                                              GTK_PARAM_READWRITE),
+                                            NULL);
+  
+  g_assert (result == PROP_XFT_HINTING);
+  
+  result = settings_install_property_parser (class,
+                                            g_param_spec_string ("gtk-xft-hintstyle",
+                                                                 P_("Xft Hint Style"),
+                                                                 P_("What degree of hinting to use; hintnone, hintslight, hintmedium, or hintfull"),
+                                                                 NULL,
+                                                                 GTK_PARAM_READWRITE),
+                                              NULL);
+  
+  g_assert (result == PROP_XFT_HINTSTYLE);
+  
+  result = settings_install_property_parser (class,
+                                            g_param_spec_string ("gtk-xft-rgba",
+                                                                 P_("Xft RGBA"),
+                                                                 P_("Type of subpixel antialiasing; none, rgb, bgr, vrgb, vbgr"),
+                                                                 NULL,
+                                                                 GTK_PARAM_READWRITE),
+                                            NULL);
+  
+  g_assert (result == PROP_XFT_RGBA);
+  
+  result = settings_install_property_parser (class,
+                                            g_param_spec_int ("gtk-xft-dpi",
+                                                              P_("Xft DPI"),
+                                                              P_("Resolution for Xft, in 1024 * dots/inch. -1 to use default value"),
+                                                              -1, 1024*1024, -1,
+                                                              GTK_PARAM_READWRITE),
+                                            NULL);
+  
+  g_assert (result == PROP_XFT_DPI);
+
+  result = settings_install_property_parser (class,
+                                             g_param_spec_string ("gtk-cursor-theme-name",
+                                                                 P_("Cursor theme name"),
+                                                                 P_("Name of the cursor theme to use"),
+                                                                 NULL,
+                                                                 GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_CURSOR_THEME_NAME);
+
+  result = settings_install_property_parser (class,
+                                            g_param_spec_int ("gtk-cursor-theme-size",
+                                                              P_("Cursor theme size"),
+                                                              P_("Size to use for cursors"),
+                                                              0, 128, 24,
+                                                              GTK_PARAM_READWRITE),
+                                            NULL);
+  
+  g_assert (result == PROP_CURSOR_THEME_SIZE);
+
+#endif  /* GDK_WINDOWING_X11 */
+  result = settings_install_property_parser (class,
+                                             g_param_spec_boolean ("gtk-alternative-button-order",
+                                                                  P_("Alternative button order"),
+                                                                  P_("Whether buttons in dialogs should use the alternative button order"),
+                                                                  FALSE,
+                                                                  GTK_PARAM_READWRITE),
+                                             NULL);
+  g_assert (result == PROP_ALTERNATIVE_BUTTON_ORDER);
 }
 
 static void
@@ -210,7 +395,7 @@ gtk_settings_finalize (GObject *object)
   object_list = g_slist_remove (object_list, settings);
 
   for (i = 0; i < class_n_properties; i++)
-    g_value_unset (settings->property_values + i);
+    g_value_unset (&settings->property_values[i].value);
   g_free (settings->property_values);
 
   g_datalist_clear (&settings->queued_settings);
@@ -218,34 +403,55 @@ gtk_settings_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static GObject*
-gtk_settings_constructor (GType                         type,
-                         guint                  n_construct_properties,
-                         GObjectConstructParam *construct_properties)
+/**
+ * gtk_settings_get_for_screen:
+ * @screen : a #GdkScreen.
+ * 
+ * Gets the #GtkSettings object for @screen, creating it if necessary.
+ *
+ * Return value: a #GtkSettings object.
+ *
+ * Since: 2.2
+ */
+GtkSettings*
+gtk_settings_get_for_screen (GdkScreen *screen)
 {
-  GObject *object;
-
-  /* currently we're a singleton, that might change with multiple display support though */
-  if (!the_singleton)
+  GtkSettings *settings;
+  
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+  
+  settings = g_object_get_data (G_OBJECT (screen), "gtk-settings");
+  if (!settings)
     {
-      object = G_OBJECT_CLASS (parent_class)->constructor (type,
-                                                          n_construct_properties,
-                                                          construct_properties);
-      the_singleton = GTK_SETTINGS (g_object_ref (object));
-    }
-  else
-    object = g_object_ref (G_OBJECT (the_singleton));
+      settings = g_object_new (GTK_TYPE_SETTINGS, NULL);
+      settings->screen = screen;
+      g_object_set_data (G_OBJECT (screen), "gtk-settings", settings);
 
-  return object;
+      gtk_rc_reparse_all_for_settings (settings, TRUE);
+      settings_update_double_click (settings);
+    }
+  
+  return settings;
 }
 
+/**
+ * gtk_settings_get_default:
+ * 
+ * Gets the #GtkSettings object for the default GDK screen, creating
+ * it if necessary. See gtk_settings_get_for_screen().
+ * 
+ * Return value: a #GtkSettings object. If there is no default
+ *  screen, then returns %NULL.
+ **/
 GtkSettings*
 gtk_settings_get_default (void)
 {
-  if (!the_singleton)
-    g_object_new (GTK_TYPE_SETTINGS, NULL);
-  
-  return the_singleton;        /* we don't add a reference count here, we'd be settings_ref_global() if we did */
+  GdkScreen *screen = gdk_screen_get_default ();
+
+  if (screen)
+    return gtk_settings_get_for_screen (screen);
+  else
+    return NULL;
 }
 
 static void
@@ -255,8 +461,9 @@ gtk_settings_set_property (GObject      *object,
                           GParamSpec   *pspec)
 {
   GtkSettings *settings = GTK_SETTINGS (object);
-  
-  g_value_copy (value, settings->property_values + property_id - 1);
+
+  g_value_copy (value, &settings->property_values[property_id - 1].value);
+  settings->property_values[property_id - 1].source = GTK_SETTINGS_SOURCE_APPLICATION;
 }
 
 static void
@@ -266,15 +473,23 @@ gtk_settings_get_property (GObject     *object,
                           GParamSpec  *pspec)
 {
   GtkSettings *settings = GTK_SETTINGS (object);
+  GType value_type = G_VALUE_TYPE (value);
+  GType fundamental_type = G_TYPE_FUNDAMENTAL (value_type);
 
-  if (g_value_type_transformable (G_TYPE_INT, G_VALUE_TYPE (value)) ||
+  /* For enums and strings, we need to get the value as a string,
+   * not as an int, since we support using names/nicks as the setting
+   * value.
+   */
+  if ((g_value_type_transformable (G_TYPE_INT, value_type) &&
+       !(fundamental_type == G_TYPE_ENUM || fundamental_type == G_TYPE_FLAGS)) ||
       g_value_type_transformable (G_TYPE_STRING, G_VALUE_TYPE (value)) ||
       g_value_type_transformable (GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
     {
-      if (gdk_setting_get (pspec->name, value))
-        g_param_value_validate (pspec, value);
+      if (settings->property_values[property_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION ||
+         !gdk_screen_get_setting (settings->screen, pspec->name, value))
+        g_value_copy (&settings->property_values[property_id - 1].value, value);
       else
-        g_value_copy (settings->property_values + property_id - 1, value);
+        g_param_value_validate (pspec, value);
     }
   else
     {
@@ -284,21 +499,21 @@ gtk_settings_get_property (GObject     *object,
       
       g_value_init (&val, G_TYPE_STRING);
 
-      if (!gdk_setting_get (pspec->name, &val))
+      if (settings->property_values[property_id - 1].source == GTK_SETTINGS_SOURCE_APPLICATION ||
+         !gdk_screen_get_setting (settings->screen, pspec->name, &val))
         {
-          g_value_copy (settings->property_values + property_id - 1, value);
+          g_value_copy (&settings->property_values[property_id - 1].value, value);
         }
       else
         {
           GValue tmp_value = { 0, };
           GValue gstring_value = { 0, };
-          GtkRcPropertyParser parser = g_param_spec_get_qdata (pspec,
-                                                               quark_property_parser);
+          GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
           
           g_value_init (&gstring_value, G_TYPE_GSTRING);
 
-          g_value_set_boxed (&gstring_value,
-                             g_string_new (g_value_get_string (&val)));
+          g_value_take_boxed (&gstring_value,
+                              g_string_new (g_value_get_string (&val)));
 
           g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
 
@@ -310,7 +525,7 @@ gtk_settings_get_property (GObject     *object,
             }
           else
             {
-              g_value_copy (settings->property_values + property_id - 1, value);
+              g_value_copy (&settings->property_values[property_id - 1].value, value);
             }
 
           g_value_unset (&gstring_value);
@@ -325,27 +540,39 @@ static void
 gtk_settings_notify (GObject    *object,
                     GParamSpec *pspec)
 {
+  GtkSettings *settings = GTK_SETTINGS (object);
   guint property_id = pspec->param_id;
-  gint double_click_time;
-  
-#if 1
-  GValue tmp_value = { 0, };
-  gchar *contents;
-  g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
-  g_object_get_property (object, pspec->name, &tmp_value);
-  contents = g_strdup_value_contents (&tmp_value);
+
+  if (settings->screen == NULL) /* initialization */
+    return;
 
   switch (property_id)
     {
+    case PROP_MODULES:
+      settings_update_modules (settings);
+      break;
     case PROP_DOUBLE_CLICK_TIME:
-      g_object_get (object, pspec->name, &double_click_time, NULL);
-      gdk_set_double_click_time (double_click_time);
+    case PROP_DOUBLE_CLICK_DISTANCE:
+      settings_update_double_click (settings);
+      break;
+#ifdef GDK_WINDOWING_X11
+    case PROP_XFT_DPI:
+    case PROP_XFT_ANTIALIAS:
+    case PROP_XFT_HINTING:
+    case PROP_XFT_HINTSTYLE:
+    case PROP_XFT_RGBA:
+      /* This is a hack because with gtk_rc_reset_styles() doesn't get
+       * widgets with gtk_widget_style_set(), and also causes more
+       * recomputation than necessary.
+       */
+      gtk_rc_reset_styles (GTK_SETTINGS (object));
+      break;
+    case PROP_CURSOR_THEME_NAME:
+    case PROP_CURSOR_THEME_SIZE:
+      settings_update_cursor_theme (settings);
       break;
+#endif /* GDK_WINDOWING_X11 */
     }
-
-  g_free (contents);
-  g_value_unset (&tmp_value);
-#endif
 }
 
 gboolean
@@ -370,12 +597,12 @@ _gtk_settings_parse_convert (GtkRcPropertyParser parser,
        }
       else if (G_VALUE_HOLDS_LONG (src_value))
        {
-         gstring = g_string_new ("");
+         gstring = g_string_new (NULL);
          g_string_append_printf (gstring, "%ld", g_value_get_long (src_value));
        }
       else if (G_VALUE_HOLDS_DOUBLE (src_value))
        {
-         gstring = g_string_new ("");
+         gstring = g_string_new (NULL);
          g_string_append_printf (gstring, "%f", g_value_get_double (src_value));
        }
       else if (G_VALUE_HOLDS_STRING (src_value))
@@ -416,23 +643,29 @@ _gtk_settings_parse_convert (GtkRcPropertyParser parser,
 }
 
 static void
-apply_queued_setting (GtkSettings      *data,
-                     GParamSpec       *pspec,
-                     GtkSettingsValue *qvalue)
+apply_queued_setting (GtkSettings             *data,
+                     GParamSpec              *pspec,
+                     GtkSettingsValuePrivate *qvalue)
 {
   GValue tmp_value = { 0, };
-  GtkRcPropertyParser parser = g_param_spec_get_qdata (pspec, quark_property_parser);
+  GtkRcPropertyParser parser = (GtkRcPropertyParser) g_param_spec_get_qdata (pspec, quark_property_parser);
 
   g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
-  if (_gtk_settings_parse_convert (parser, &qvalue->value,
+  if (_gtk_settings_parse_convert (parser, &qvalue->public.value,
                                   pspec, &tmp_value))
-    g_object_set_property (G_OBJECT (data), pspec->name, &tmp_value);
+    {
+      if (data->property_values[pspec->param_id - 1].source <= qvalue->source)
+       {
+         g_object_set_property (G_OBJECT (data), pspec->name, &tmp_value);
+         data->property_values[pspec->param_id - 1].source = qvalue->source;
+       }
+    }
   else
     {
-      gchar *debug = g_strdup_value_contents (&qvalue->value);
+      gchar *debug = g_strdup_value_contents (&qvalue->public.value);
       
       g_message ("%s: failed to retrieve property `%s' of type `%s' from rc file value \"%s\" of type `%s'",
-                qvalue->origin,
+                qvalue->public.origin,
                 pspec->name,
                 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
                 debug,
@@ -481,17 +714,18 @@ settings_install_property_parser (GtkSettingsClass   *class,
     g_object_freeze_notify (node->data);
 
   g_object_class_install_property (G_OBJECT_CLASS (class), ++class_n_properties, pspec);
-  g_param_spec_set_qdata (pspec, quark_property_parser, parser);
+  g_param_spec_set_qdata (pspec, quark_property_parser, (gpointer) parser);
 
   for (node = object_list; node; node = node->next)
     {
       GtkSettings *settings = node->data;
-      GtkSettingsValue *qvalue;
+      GtkSettingsValuePrivate *qvalue;
       
-      settings->property_values = g_renew (GValue, settings->property_values, class_n_properties);
-      settings->property_values[class_n_properties - 1].g_type = 0;
-      g_value_init (settings->property_values + class_n_properties - 1, G_PARAM_SPEC_VALUE_TYPE (pspec));
-      g_param_value_set_default (pspec, settings->property_values + class_n_properties - 1);
+      settings->property_values = g_renew (GtkSettingsPropertyValue, settings->property_values, class_n_properties);
+      settings->property_values[class_n_properties - 1].value.g_type = 0;
+      g_value_init (&settings->property_values[class_n_properties - 1].value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+      g_param_value_set_default (pspec, &settings->property_values[class_n_properties - 1].value);
+      settings->property_values[class_n_properties - 1].source = GTK_SETTINGS_SOURCE_DEFAULT;
       g_object_notify (G_OBJECT (settings), pspec->name);
       
       qvalue = g_datalist_get_data (&settings->queued_settings, pspec->name);
@@ -526,7 +760,7 @@ _gtk_rc_property_parser_from_type (GType type)
 }
 
 void
-gtk_settings_install_property (GParamSpec  *pspec)
+gtk_settings_install_property (GParamSpec *pspec)
 {
   GtkRcPropertyParser parser;
 
@@ -538,8 +772,8 @@ gtk_settings_install_property (GParamSpec  *pspec)
 }
 
 void
-gtk_settings_install_property_parser (GParamSpec         *pspec,
-                                     GtkRcPropertyParser parser)
+gtk_settings_install_property_parser (GParamSpec          *pspec,
+                                     GtkRcPropertyParser  parser)
 {
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
   g_return_if_fail (parser != NULL);
@@ -550,28 +784,24 @@ gtk_settings_install_property_parser (GParamSpec         *pspec,
 static void
 free_value (gpointer data)
 {
-  GtkSettingsValue *qvalue = data;
+  GtkSettingsValuePrivate *qvalue = data;
   
-  g_value_unset (&qvalue->value);
-  g_free (qvalue->origin);
+  g_value_unset (&qvalue->public.value);
+  g_free (qvalue->public.origin);
   g_free (qvalue);
 }
 
-void
-gtk_settings_set_property_value (GtkSettings            *settings,
-                                const gchar            *prop_name,
-                                const GtkSettingsValue *new_value)
+static void
+gtk_settings_set_property_value_internal (GtkSettings            *settings,
+                                         const gchar            *prop_name,
+                                         const GtkSettingsValue *new_value,
+                                         GtkSettingsSource       source)
 {
-  GtkSettingsValue *qvalue;
+  GtkSettingsValuePrivate *qvalue;
   GParamSpec *pspec;
   gchar *name;
   GQuark name_quark;
 
-  g_return_if_fail (GTK_SETTINGS (settings));
-  g_return_if_fail (prop_name != NULL);
-  g_return_if_fail (new_value != NULL);
-  g_return_if_fail (new_value->origin != NULL);
-
   if (!G_VALUE_HOLDS_LONG (&new_value->value) &&
       !G_VALUE_HOLDS_DOUBLE (&new_value->value) &&
       !G_VALUE_HOLDS_STRING (&new_value->value) &&
@@ -583,31 +813,57 @@ gtk_settings_set_property_value (GtkSettings            *settings,
   
   name = g_strdup (prop_name);
   g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
-  name_quark = g_quark_try_string (name);
-  if (name_quark)
-    g_free (name);
-  else
-    name_quark = g_quark_from_string (name);
+  name_quark = g_quark_from_string (name);
+  g_free (name);
 
   qvalue = g_datalist_id_get_data (&settings->queued_settings, name_quark);
   if (!qvalue)
     {
-      qvalue = g_new0 (GtkSettingsValue, 1);
+      qvalue = g_new0 (GtkSettingsValuePrivate, 1);
       g_datalist_id_set_data_full (&settings->queued_settings, name_quark, qvalue, free_value);
     }
   else
     {
-      g_free (qvalue->origin);
-      g_value_unset (&qvalue->value);
+      g_free (qvalue->public.origin);
+      g_value_unset (&qvalue->public.value);
     }
-  qvalue->origin = g_strdup (new_value->origin);
-  g_value_init (&qvalue->value, G_VALUE_TYPE (&new_value->value));
-  g_value_copy (&new_value->value, &qvalue->value);
+  qvalue->public.origin = g_strdup (new_value->origin);
+  g_value_init (&qvalue->public.value, G_VALUE_TYPE (&new_value->value));
+  g_value_copy (&new_value->value, &qvalue->public.value);
+  qvalue->source = source;
   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (settings), g_quark_to_string (name_quark));
   if (pspec)
     apply_queued_setting (settings, pspec, qvalue);
 }
 
+void
+gtk_settings_set_property_value (GtkSettings            *settings,
+                                const gchar            *prop_name,
+                                const GtkSettingsValue *new_value)
+{
+  g_return_if_fail (GTK_SETTINGS (settings));
+  g_return_if_fail (prop_name != NULL);
+  g_return_if_fail (new_value != NULL);
+  g_return_if_fail (new_value->origin != NULL);
+
+  gtk_settings_set_property_value_internal (settings, prop_name, new_value,
+                                           GTK_SETTINGS_SOURCE_APPLICATION);
+}
+
+void
+_gtk_settings_set_property_value_from_rc (GtkSettings            *settings,
+                                         const gchar            *prop_name,
+                                         const GtkSettingsValue *new_value)
+{
+  g_return_if_fail (GTK_SETTINGS (settings));
+  g_return_if_fail (prop_name != NULL);
+  g_return_if_fail (new_value != NULL);
+  g_return_if_fail (new_value->origin != NULL);
+
+  gtk_settings_set_property_value_internal (settings, prop_name, new_value,
+                                           GTK_SETTINGS_SOURCE_RC_FILE);
+}
+
 void
 gtk_settings_set_string_property (GtkSettings *settings,
                                  const gchar *name,
@@ -666,6 +922,22 @@ gtk_settings_set_double_property (GtkSettings *settings,
   g_value_unset (&svalue.value);
 }
 
+/**
+ * gtk_rc_property_parse_color:
+ * @pspec: a #GParamSpec
+ * @gstring: the #GString to be parsed
+ * @property_value: a #GValue which must hold #GdkColor values.
+ * 
+ * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
+ * or gtk_widget_class_install_style_property_parser() which parses a
+ * color given either by its name or in the form 
+ * <literal>{ red, green, blue }</literal> where %red, %green and
+ * %blue are integers between 0 and 65535 or floating-point numbers
+ * between 0 and 1.
+ * 
+ * Return value: %TRUE if @gstring could be parsed and @property_value
+ * has been set to the resulting #GdkColor.
+ **/
 gboolean
 gtk_rc_property_parse_color (const GParamSpec *pspec,
                             const GString    *gstring,
@@ -693,6 +965,23 @@ gtk_rc_property_parse_color (const GParamSpec *pspec,
   return success;
 }
 
+/**
+ * gtk_rc_property_parse_enum:
+ * @pspec: a #GParamSpec
+ * @gstring: the #GString to be parsed
+ * @property_value: a #GValue which must hold enum values.
+ * 
+ * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
+ * or gtk_widget_class_install_style_property_parser() which parses a single
+ * enumeration value.
+ *
+ * The enumeration value can be specified by its name, its nickname or
+ * its numeric value. For consistency with flags parsing, the value
+ * may be surrounded by parentheses.
+ * 
+ * Return value: %TRUE if @gstring could be parsed and @property_value
+ * has been set to the resulting #GEnumValue.
+ **/
 gboolean
 gtk_rc_property_parse_enum (const GParamSpec *pspec,
                            const GString    *gstring,
@@ -709,7 +998,7 @@ gtk_rc_property_parse_enum (const GParamSpec *pspec,
   g_scanner_input_text (scanner, gstring->str, gstring->len);
 
   /* we just want to parse _one_ value, but for consistency with flags parsing
-   * we support optional paranthesis
+   * we support optional parenthesis
    */
   g_scanner_get_next_token (scanner);
   if (scanner->token == '(')
@@ -772,13 +1061,29 @@ parse_flags_value (GScanner    *scanner,
   return G_TOKEN_IDENTIFIER;
 }
 
+/**
+ * gtk_rc_property_parse_flags:
+ * @pspec: a #GParamSpec
+ * @gstring: the #GString to be parsed
+ * @property_value: a #GValue which must hold flags values.
+ * 
+ * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
+ * or gtk_widget_class_install_style_property_parser() which parses flags. 
+ * 
+ * Flags can be specified by their name, their nickname or
+ * numerically. Multiple flags can be specified in the form 
+ * <literal>"( flag1 | flag2 | ... )"</literal>.
+ * 
+ * Return value: %TRUE if @gstring could be parsed and @property_value
+ * has been set to the resulting flags value.
+ **/
 gboolean
 gtk_rc_property_parse_flags (const GParamSpec *pspec,
                             const GString    *gstring,
                             GValue           *property_value)
 {
   GFlagsClass *class;
-  gboolean success = FALSE;
+   gboolean success = FALSE;
   GScanner *scanner;
 
   g_return_val_if_fail (G_IS_PARAM_SPEC (pspec), FALSE);
@@ -862,6 +1167,20 @@ get_braced_int (GScanner *scanner,
   return TRUE;
 }
 
+/**
+ * gtk_rc_property_parse_requisition:
+ * @pspec: a #GParamSpec
+ * @gstring: the #GString to be parsed
+ * @property_value: a #GValue which must hold boxed values.
+ * 
+ * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
+ * or gtk_widget_class_install_style_property_parser() which parses a
+ * requisition in the form 
+ * <literal>"{ width, height }"</literal> for integers %width and %height.
+ * 
+ * Return value: %TRUE if @gstring could be parsed and @property_value
+ * has been set to the resulting #GtkRequisition.
+ **/
 gboolean
 gtk_rc_property_parse_requisition  (const GParamSpec *pspec,
                                    const GString    *gstring,
@@ -889,6 +1208,21 @@ gtk_rc_property_parse_requisition  (const GParamSpec *pspec,
   return success;
 }
 
+/**
+ * gtk_rc_property_parse_border:
+ * @pspec: a #GParamSpec
+ * @gstring: the #GString to be parsed
+ * @property_value: a #GValue which must hold boxed values.
+ * 
+ * A #GtkRcPropertyParser for use with gtk_settings_install_property_parser()
+ * or gtk_widget_class_install_style_property_parser() which parses
+ * borders in the form 
+ * <literal>"{ left, right, top, bottom }"</literal> for integers 
+ * %left, %right, %top and %bottom.
+ * 
+ * Return value: %TRUE if @gstring could be parsed and @property_value
+ * has been set to the resulting #GtkBorder.
+ **/
 gboolean
 gtk_rc_property_parse_border (const GParamSpec *pspec,
                              const GString    *gstring,
@@ -921,8 +1255,114 @@ gtk_rc_property_parse_border (const GParamSpec *pspec,
 void
 _gtk_settings_handle_event (GdkEventSetting *event)
 {
-  GtkSettings *settings = gtk_settings_get_default ();
+  GtkSettings *settings = gtk_settings_get_for_screen (gdk_drawable_get_screen (event->window));
   
   if (g_object_class_find_property (G_OBJECT_GET_CLASS (settings), event->name))
     g_object_notify (G_OBJECT (settings), event->name);
 }
+
+static void
+reset_rc_values_foreach (GQuark    key_id,
+                        gpointer  data,
+                        gpointer  user_data)
+{
+  GtkSettingsValuePrivate *qvalue = data;
+  GSList **to_reset = user_data;
+
+  if (qvalue->source == GTK_SETTINGS_SOURCE_RC_FILE)
+    *to_reset = g_slist_prepend (*to_reset, GUINT_TO_POINTER (key_id));
+}
+
+void
+_gtk_settings_reset_rc_values (GtkSettings *settings)
+{
+  GSList *to_reset = NULL;
+  GSList *tmp_list;
+  GParamSpec **pspecs, **p;
+  gint i;
+
+  /* Remove any queued settings
+   */
+  g_datalist_foreach (&settings->queued_settings,
+                     reset_rc_values_foreach,
+                     &to_reset);
+
+  for (tmp_list = to_reset; tmp_list; tmp_list = tmp_list->next)
+    {
+      GQuark key_id = GPOINTER_TO_UINT (tmp_list->data);
+      g_datalist_id_remove_data (&settings->queued_settings, key_id);
+    }
+
+  /* Now reset the active settings
+   */
+  pspecs = g_object_class_list_properties (G_OBJECT_GET_CLASS (settings), NULL);
+  i = 0;
+
+  g_object_freeze_notify (G_OBJECT (settings));
+  for (p = pspecs; *p; p++)
+    {
+      if (settings->property_values[i].source == GTK_SETTINGS_SOURCE_RC_FILE)
+       {
+         GParamSpec *pspec = *p;
+
+         g_param_value_set_default (pspec, &settings->property_values[i].value);
+         g_object_notify (G_OBJECT (settings), pspec->name);
+       }
+      i++;
+    }
+  g_object_thaw_notify (G_OBJECT (settings));
+  g_free (pspecs);
+}
+
+static void
+settings_update_double_click (GtkSettings *settings)
+{
+  if (gdk_screen_get_number (settings->screen) == 0)
+    {
+      GdkDisplay *display = gdk_screen_get_display (settings->screen);
+      gint double_click_time;
+      gint double_click_distance;
+  
+      g_object_get (settings, 
+                   "gtk-double-click-time", &double_click_time, 
+                   "gtk-double-click-distance", &double_click_distance,
+                   NULL);
+      
+      gdk_display_set_double_click_time (display, double_click_time);
+      gdk_display_set_double_click_distance (display, double_click_distance);
+    }
+}
+
+static void
+settings_update_modules (GtkSettings *settings)
+{
+  gchar *modules;
+  
+  g_object_get (settings, 
+               "gtk-modules", &modules,
+               NULL);
+  
+  _gtk_modules_settings_changed (settings, modules);
+  
+  g_free (modules);
+}
+
+#ifdef GDK_WINDOWING_X11
+static void
+settings_update_cursor_theme (GtkSettings *settings)
+{
+  GdkDisplay *display = gdk_screen_get_display (settings->screen);
+  gchar *theme = NULL;
+  gint size = 0;
+  
+  g_object_get (settings, 
+               "gtk-cursor-theme-name", &theme,
+               "gtk-cursor-theme-size", &size,
+               NULL);
+  
+  gdk_x11_display_set_cursor_theme (display, theme, size);
+}
+#endif
+
+#define __GTK_SETTINGS_C__
+#include "gtkaliasdef.c"