diff --git a/data/org.gnome.settings-daemon.plugins.xsettings.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.xsettings.gschema.xml.in.in
index 8cece8e..781bd33 100644
--- a/data/org.gnome.settings-daemon.plugins.xsettings.gschema.xml.in.in
+++ b/data/org.gnome.settings-daemon.plugins.xsettings.gschema.xml.in.in
@@ -35,5 +35,10 @@
       <_summary>List of explicitly enabled GTK+ modules</_summary>
       <_description>A list of strings representing the GTK+ modules that will be loaded, usually in addition to conditional and forcibly disabled ones.</_description>
     </key>
+    <key type="a{sv}" name="overrides">
+      <default>{}</default>
+      <_summary>A dictionary of XSETTINGS to override</_summary>
+      <_description>This dictionary maps XSETTINGS names to overrides values. The values must be either strings, signed int32s or (in the case of colors), 4-tuples of uint16 (red, green, blue, alpha; 65535 is fully opaque).</_description>
+    </key>
   </schema>
 </schemalist>
diff --git a/plugins/xsettings/Makefile.am b/plugins/xsettings/Makefile.am
index cc6f985..2dcdd1d 100644
--- a/plugins/xsettings/Makefile.am
+++ b/plugins/xsettings/Makefile.am
@@ -2,7 +2,7 @@ NULL =
 
 plugin_name = xsettings
 
-noinst_PROGRAMS = test-gtk-modules
+noinst_PROGRAMS = test-gtk-modules test-xsettings
 
 test_gtk_modules_SOURCES =	\
 	gsd-xsettings-gtk.c	\
@@ -24,6 +24,18 @@ test_gtk_modules_CPPFLAGS =				\
 	-DGTK_MODULES_DIRECTORY=\""$(libdir)/gnome-settings-daemon-@GSD_API_VERSION@/gtk-modules/"\" \
 	$(AM_CPPFLAGS)
 
+test_xsettings_SOURCES = \
+	gsd-xsettings-gtk.c	\
+	gsd-xsettings-manager.c	\
+	xsettings-common.c	\
+	xsettings-manager.c	\
+	fontconfig-monitor.c	\
+	test-xsettings.c
+
+test_xsettings_CFLAGS = $(test_gtk_modules_CFLAGS)
+test_xsettings_CPPFLAGS = $(test_gtk_modules_CPPFLAGS)
+test_xsettings_LDADD = $(test_gtk_modules_LDADD)
+
 plugin_LTLIBRARIES = \
 	libxsettings.la		\
 	$(NULL)
diff --git a/plugins/xsettings/gsd-xsettings-manager.c b/plugins/xsettings/gsd-xsettings-manager.c
index 868a864..19e31a1 100644
--- a/plugins/xsettings/gsd-xsettings-manager.c
+++ b/plugins/xsettings/gsd-xsettings-manager.c
@@ -52,6 +52,7 @@
 #define SOUND_SETTINGS_SCHEMA     "org.gnome.desktop.sound"
 
 #define XSETTINGS_PLUGIN_SCHEMA "org.gnome.settings-daemon.plugins.xsettings"
+#define XSETTINGS_OVERRIDE_KEY  "overrides"
 
 #define GTK_MODULES_DISABLED_KEY "disabled-gtk-modules"
 #define GTK_MODULES_ENABLED_KEY  "enabled-gtk-modules"
@@ -575,6 +576,24 @@ xft_callback (GSettings             *settings,
 }
 
 static void
+override_callback (GSettings             *settings,
+                   const gchar           *key,
+                   GnomeXSettingsManager *manager)
+{
+        GVariant *value;
+        int i;
+
+        value = g_settings_get_value (settings, XSETTINGS_OVERRIDE_KEY);
+
+        for (i = 0; manager->priv->managers[i]; i++) {
+                xsettings_manager_set_overrides (manager->priv->managers[i], value);
+                xsettings_manager_notify (manager->priv->managers [i]);
+        }
+
+        g_variant_unref (value);
+}
+
+static void
 plugin_callback (GSettings             *settings,
                  const char            *key,
                  GnomeXSettingsManager *manager)
@@ -582,6 +601,8 @@ plugin_callback (GSettings             *settings,
         if (g_str_equal (key, GTK_MODULES_DISABLED_KEY) ||
             g_str_equal (key, GTK_MODULES_ENABLED_KEY)) {
                 /* Do nothing, as GsdXsettingsGtk will handle it */
+        } else if (g_str_equal (key, XSETTINGS_OVERRIDE_KEY)) {
+                override_callback (settings, key, manager);
         } else {
                 xft_callback (settings, key, manager);
         }
@@ -820,6 +841,7 @@ gboolean
 gnome_xsettings_manager_start (GnomeXSettingsManager *manager,
                                GError               **error)
 {
+        GVariant    *overrides;
         guint        i;
         GList       *list, *l;
 
@@ -896,9 +918,12 @@ gnome_xsettings_manager_start (GnomeXSettingsManager *manager,
                                               "Net/FallbackIconTheme",
                                               "gnome");
 
+        overrides = g_settings_get_value (manager->priv->plugin_settings, XSETTINGS_OVERRIDE_KEY);
         for (i = 0; manager->priv->managers [i]; i++) {
+                xsettings_manager_set_overrides (manager->priv->managers [i], overrides);
                 xsettings_manager_notify (manager->priv->managers [i]);
         }
+        g_variant_unref (overrides);
 
 
         gnome_settings_profile_end (NULL);
diff --git a/plugins/xsettings/test-xsettings.c b/plugins/xsettings/test-xsettings.c
new file mode 100644
index 0000000..a2b9893
--- /dev/null
+++ b/plugins/xsettings/test-xsettings.c
@@ -0,0 +1,19 @@
+#include "gsd-xsettings-manager.h"
+#include <gtk/gtk.h>
+
+int
+main (void)
+{
+  GnomeXSettingsManager *manager;
+  GError *error = NULL;
+
+  gtk_init (NULL, NULL);
+
+  manager = gnome_xsettings_manager_new ();
+  gnome_xsettings_manager_start (manager, &error);
+  g_assert_no_error (error);
+
+  gtk_main ();
+
+  return 0;
+}
diff --git a/plugins/xsettings/xsettings-common.c b/plugins/xsettings/xsettings-common.c
index 992175a..e5f9fcc 100644
--- a/plugins/xsettings/xsettings-common.c
+++ b/plugins/xsettings/xsettings-common.c
@@ -20,6 +20,9 @@
  *
  * Author:  Owen Taylor, Red Hat, Inc.
  */
+
+#include <glib.h>
+
 #include "string.h"
 #include "stdlib.h"
 
@@ -29,231 +32,76 @@
 #include "xsettings-common.h"
 
 XSettingsSetting *
-xsettings_setting_copy (XSettingsSetting *setting)
+xsettings_setting_new (const gchar *name)
 {
   XSettingsSetting *result;
-  size_t str_len;
-  
-  result = malloc (sizeof *result);
-  if (!result)
-    return NULL;
-
-  str_len = strlen (setting->name);
-  result->name = malloc (str_len + 1);
-  if (!result->name)
-    goto err;
-
-  memcpy (result->name, setting->name, str_len + 1);
-
-  result->type = setting->type;
 
-  switch (setting->type)
-    {
-    case XSETTINGS_TYPE_INT:
-      result->data.v_int = setting->data.v_int;
-      break;
-    case XSETTINGS_TYPE_COLOR:
-      result->data.v_color = setting->data.v_color;
-      break;
-    case XSETTINGS_TYPE_STRING:
-      str_len = strlen (setting->data.v_string);
-      result->data.v_string = malloc (str_len + 1);
-      if (!result->data.v_string)
-	goto err;
-
-      memcpy (result->data.v_string, setting->data.v_string, str_len + 1);
-      break;
-    }
-
-  result->last_change_serial = setting->last_change_serial;
+  result = g_slice_new0 (XSettingsSetting);
+  result->name = g_strdup (name);
 
   return result;
-
- err:
-  if (result->name)
-    free (result->name);
-  free (result);
-  
-  return NULL;
 }
 
-XSettingsList *
-xsettings_list_copy (XSettingsList *list)
+static gboolean
+xsettings_variant_equal0 (GVariant *a,
+                          GVariant *b)
 {
-  XSettingsList *new = NULL;
-  XSettingsList *old_iter = list;
-  XSettingsList *new_iter = NULL;
-
-  while (old_iter)
-    {
-      XSettingsList *new_node;
+  if (a == b)
+    return TRUE;
 
-      new_node = malloc (sizeof *new_node);
-      if (!new_node)
-	goto error;
+  if (!a || !b)
+    return FALSE;
 
-      new_node->setting = xsettings_setting_copy (old_iter->setting);
-      if (!new_node->setting)
-	{
-	  free (new_node);
-	  goto error;
-	}
-
-      if (new_iter)
-	new_iter->next = new_node;
-      else
-	new = new_node;
-
-      new_iter = new_node;
-      
-      old_iter = old_iter->next;
-    }
-
-  return new;
-
- error:
-  xsettings_list_free (new);
-  return NULL;
+  return g_variant_equal (a, b);
 }
 
-int
-xsettings_setting_equal (XSettingsSetting *setting_a,
-			 XSettingsSetting *setting_b)
+GVariant *
+xsettings_setting_get (XSettingsSetting *setting)
 {
-  if (setting_a->type != setting_b->type)
-    return 0;
+  gint i;
 
-  if (strcmp (setting_a->name, setting_b->name) != 0)
-    return 0;
+  for (i = G_N_ELEMENTS (setting->value) - 1; 0 <= i; i--)
+    if (setting->value[i])
+      return setting->value[i];
 
-  switch (setting_a->type)
-    {
-    case XSETTINGS_TYPE_INT:
-      return setting_a->data.v_int == setting_b->data.v_int;
-    case XSETTINGS_TYPE_COLOR:
-      return (setting_a->data.v_color.red == setting_b->data.v_color.red &&
-	      setting_a->data.v_color.green == setting_b->data.v_color.green &&
-	      setting_a->data.v_color.blue == setting_b->data.v_color.blue &&
-	      setting_a->data.v_color.alpha == setting_b->data.v_color.alpha);
-    case XSETTINGS_TYPE_STRING:
-      return strcmp (setting_a->data.v_string, setting_b->data.v_string) == 0;
-    }
-
-  return 0;
-}
-
-void
-xsettings_setting_free (XSettingsSetting *setting)
-{
-  if (setting->type == XSETTINGS_TYPE_STRING)
-    free (setting->data.v_string);
-  
-  if (setting->name)
-    free (setting->name);
-
-  free (setting);
+  return NULL;
 }
 
 void
-xsettings_list_free (XSettingsList *list)
-{
-  while (list)
-    {
-      XSettingsList *next = list->next;
-
-      xsettings_setting_free (list->setting);
-      free (list);
-
-      list = next;
-    }
-}
-
-XSettingsResult
-xsettings_list_insert (XSettingsList    **list,
-		       XSettingsSetting  *setting)
+xsettings_setting_set (XSettingsSetting *setting,
+                       gint              tier,
+                       GVariant         *value,
+                       guint32           serial)
 {
-  XSettingsList *node;
-  XSettingsList *iter;
-  XSettingsList *last = NULL;
+  GVariant *old_value;
 
-  node = malloc (sizeof *node);
-  if (!node)
-    return XSETTINGS_NO_MEM;
-  node->setting = setting;
+  old_value = xsettings_setting_get (setting);
+  if (old_value)
+    g_variant_ref (old_value);
 
-  iter = *list;
-  while (iter)
-    {
-      int cmp = strcmp (setting->name, iter->setting->name);
+  if (setting->value[tier])
+    g_variant_unref (setting->value[tier]);
+  setting->value[tier] = value ? g_variant_ref_sink (value) : NULL;
 
-      if (cmp < 0)
-	break;
-      else if (cmp == 0)
-	{
-	  free (node);
-	  return XSETTINGS_DUPLICATE_ENTRY;
-	}
+  if (!xsettings_variant_equal0 (old_value, xsettings_setting_get (setting)))
+    setting->last_change_serial = serial;
 
-      last = iter;
-      iter = iter->next;
-    }
-  
-  if (last)
-    last->next = node;
-  else
-    *list = node;
-  
-  node->next = iter;
-  
-  return XSETTINGS_SUCCESS;
+  if (old_value)
+    g_variant_unref (old_value);
 }
 
-XSettingsResult
-xsettings_list_delete (XSettingsList **list,
-		       const char     *name)
-{
-  XSettingsList *iter;
-  XSettingsList *last = NULL;
-
-  iter = *list;
-  while (iter)
-    {
-      if (strcmp (name, iter->setting->name) == 0)
-	{
-	  if (last)
-	    last->next = iter->next;
-	  else
-	    *list = iter->next;
-  
-	  xsettings_setting_free (iter->setting);
-	  free (iter);
-
-	  return XSETTINGS_SUCCESS;
-	}
-
-      last = iter;
-      iter = iter->next;
-    }
-
-  return XSETTINGS_FAILED;
-}
-
-XSettingsSetting *
-xsettings_list_lookup (XSettingsList *list,
-		       const char    *name)
+void
+xsettings_setting_free (XSettingsSetting *setting)
 {
-  XSettingsList *iter;
+  gint i;
 
-  iter = list;
-  while (iter)
-    {
-      if (strcmp (name, iter->setting->name) == 0)
-	return iter->setting;
+  for (i = 0; i < G_N_ELEMENTS (setting->value); i++)
+    if (setting->value[i])
+      g_variant_unref (setting->value[i]);
 
-      iter = iter->next;
-    }
+  g_free (setting->name);
 
-  return NULL;
+  g_slice_free (XSettingsSetting, setting);
 }
 
 char
diff --git a/plugins/xsettings/xsettings-common.h b/plugins/xsettings/xsettings-common.h
index e3af4a6..2062f47 100644
--- a/plugins/xsettings/xsettings-common.h
+++ b/plugins/xsettings/xsettings-common.h
@@ -23,13 +23,11 @@
 #ifndef XSETTINGS_COMMON_H
 #define XSETTINGS_COMMON_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+#include <glib.h>
+
+#define XSETTINGS_N_TIERS 2
 
-typedef struct _XSettingsBuffer  XSettingsBuffer;
 typedef struct _XSettingsColor   XSettingsColor;
-typedef struct _XSettingsList    XSettingsList;
 typedef struct _XSettingsSetting XSettingsSetting;
 
 /* Types of settings possible. Enum values correspond to
@@ -42,69 +40,26 @@ typedef enum
   XSETTINGS_TYPE_COLOR   = 2
 } XSettingsType;
 
-typedef enum
-{
-  XSETTINGS_SUCCESS,
-  XSETTINGS_NO_MEM,
-  XSETTINGS_ACCESS,
-  XSETTINGS_FAILED,
-  XSETTINGS_NO_ENTRY,
-  XSETTINGS_DUPLICATE_ENTRY
-} XSettingsResult;
-
-struct _XSettingsBuffer
-{
-  char byte_order;
-  size_t len;
-  unsigned char *data;
-  unsigned char *pos;
-};
-
 struct _XSettingsColor
 {
   unsigned short red, green, blue, alpha;
 };
 
-struct _XSettingsList
-{
-  XSettingsSetting *setting;
-  XSettingsList *next;
-};
-
 struct _XSettingsSetting
 {
   char *name;
-  XSettingsType type;
-  
-  union {
-    int v_int;
-    char *v_string;
-    XSettingsColor v_color;
-  } data;
-
+  GVariant *value[XSETTINGS_N_TIERS];
   unsigned long last_change_serial;
 };
 
-XSettingsSetting *xsettings_setting_copy  (XSettingsSetting *setting);
+XSettingsSetting *xsettings_setting_new   (const gchar      *name);
+GVariant *        xsettings_setting_get   (XSettingsSetting *setting);
+void              xsettings_setting_set   (XSettingsSetting *setting,
+                                           gint              tier,
+                                           GVariant         *value,
+                                           guint32           serial);
 void              xsettings_setting_free  (XSettingsSetting *setting);
-int               xsettings_setting_equal (XSettingsSetting *setting_a,
-					   XSettingsSetting *setting_b);
-
-void              xsettings_list_free   (XSettingsList     *list);
-XSettingsList    *xsettings_list_copy   (XSettingsList     *list);
-XSettingsResult   xsettings_list_insert (XSettingsList    **list,
-					 XSettingsSetting  *setting);
-XSettingsSetting *xsettings_list_lookup (XSettingsList     *list,
-					 const char        *name);
-XSettingsResult   xsettings_list_delete (XSettingsList    **list,
-					 const char        *name);
 
 char xsettings_byte_order (void);
 
-#define XSETTINGS_PAD(n,m) ((n + m - 1) & (~(m-1)))
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
 #endif /* XSETTINGS_COMMON_H */
diff --git a/plugins/xsettings/xsettings-manager.c b/plugins/xsettings/xsettings-manager.c
index 6578ce1..231a6e4 100644
--- a/plugins/xsettings/xsettings-manager.c
+++ b/plugins/xsettings/xsettings-manager.c
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <glib.h>
 #include <X11/Xmd.h>		/* For CARD16 */
 
 #include "xsettings-manager.h"
@@ -41,11 +42,11 @@ struct _XSettingsManager
   XSettingsTerminateFunc terminate;
   void *cb_data;
 
-  XSettingsList *settings;
+  GHashTable *settings;
   unsigned long serial;
-};
 
-static XSettingsList *settings;
+  GVariant *overrides;
+};
 
 typedef struct 
 {
@@ -127,10 +128,8 @@ xsettings_manager_new (Display                *display,
   XClientMessageEvent xev;
 
   char buffer[256];
-  
-  manager = malloc (sizeof *manager);
-  if (!manager)
-    return NULL;
+
+  manager = g_slice_new (XSettingsManager);
 
   manager->display = display;
   manager->screen = screen;
@@ -143,8 +142,9 @@ xsettings_manager_new (Display                *display,
   manager->terminate = terminate;
   manager->cb_data = cb_data;
 
-  manager->settings = NULL;
+  manager->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) xsettings_setting_free);
   manager->serial = 0;
+  manager->overrides = NULL;
 
   manager->window = XCreateSimpleWindow (display,
 					 RootWindow (display, screen),
@@ -190,235 +190,194 @@ void
 xsettings_manager_destroy (XSettingsManager *manager)
 {
   XDestroyWindow (manager->display, manager->window);
-  
-  xsettings_list_free (manager->settings);
-  free (manager);
-}
-
-Window
-xsettings_manager_get_window (XSettingsManager *manager)
-{
-  return manager->window;
-}
-
-Bool
-xsettings_manager_process_event (XSettingsManager *manager,
-				 XEvent           *xev)
-{
-  if (xev->xany.window == manager->window &&
-      xev->xany.type == SelectionClear &&
-      xev->xselectionclear.selection == manager->selection_atom)
-    {
-      manager->terminate (manager->cb_data);
-      return True;
-    }
 
-  return False;
-}
+  g_hash_table_unref (manager->settings);
 
-XSettingsResult
-xsettings_manager_delete_setting (XSettingsManager *manager,
-                                  const char       *name)
-{
-  return xsettings_list_delete (&settings, name);
+  g_slice_free (XSettingsManager, manager);
 }
 
-XSettingsResult
+static void
 xsettings_manager_set_setting (XSettingsManager *manager,
-			       XSettingsSetting *setting)
+                               const gchar      *name,
+                               gint              tier,
+                               GVariant         *value)
 {
-  XSettingsSetting *old_setting = xsettings_list_lookup (settings, setting->name);
-  XSettingsSetting *new_setting;
-  XSettingsResult result;
+  XSettingsSetting *setting;
 
-  if (old_setting)
-    {
-      if (xsettings_setting_equal (old_setting, setting))
-	return XSETTINGS_SUCCESS;
+  setting = g_hash_table_lookup (manager->settings, name);
 
-      xsettings_list_delete (&settings, setting->name);
+  if (setting == NULL)
+    {
+      setting = xsettings_setting_new (name);
+      setting->last_change_serial = manager->serial;
+      g_hash_table_insert (manager->settings, setting->name, setting);
     }
 
-  new_setting = xsettings_setting_copy (setting);
-  if (!new_setting)
-    return XSETTINGS_NO_MEM;
-  
-  new_setting->last_change_serial = manager->serial;
-  
-  result = xsettings_list_insert (&settings, new_setting);
-  
-  if (result != XSETTINGS_SUCCESS)
-    xsettings_setting_free (new_setting);
+  xsettings_setting_set (setting, tier, value, manager->serial);
 
-  return result;
+  if (xsettings_setting_get (setting) == NULL)
+    g_hash_table_remove (manager->settings, name);
 }
 
-XSettingsResult
+void
 xsettings_manager_set_int (XSettingsManager *manager,
 			   const char       *name,
 			   int               value)
 {
-  XSettingsSetting setting;
-
-  setting.name = (char *)name;
-  setting.type = XSETTINGS_TYPE_INT;
-  setting.data.v_int = value;
-
-  return xsettings_manager_set_setting (manager, &setting);
+  xsettings_manager_set_setting (manager, name, 0, g_variant_new_int32 (value));
 }
 
-XSettingsResult
+void
 xsettings_manager_set_string (XSettingsManager *manager,
 			      const char       *name,
 			      const char       *value)
 {
-  XSettingsSetting setting;
-
-  setting.name = (char *)name;
-  setting.type = XSETTINGS_TYPE_STRING;
-  setting.data.v_string = (char *)value;
-
-  return xsettings_manager_set_setting (manager, &setting);
+  xsettings_manager_set_setting (manager, name, 0, g_variant_new_string (value));
 }
 
-XSettingsResult
+void
 xsettings_manager_set_color (XSettingsManager *manager,
 			     const char       *name,
 			     XSettingsColor   *value)
 {
-  XSettingsSetting setting;
-
-  setting.name = (char *)name;
-  setting.type = XSETTINGS_TYPE_COLOR;
-  setting.data.v_color = *value;
+  GVariant *tmp;
 
-  return xsettings_manager_set_setting (manager, &setting);
+  tmp = g_variant_new ("(qqqq)", value->red, value->green, value->blue, value->alpha);
+  xsettings_manager_set_setting (manager, name, 0, tmp);
 }
 
-static size_t
-setting_length (XSettingsSetting *setting)
+void
+xsettings_manager_delete_setting (XSettingsManager *manager,
+                                  const char       *name)
 {
-  size_t length = 8;	/* type + pad + name-len + last-change-serial */
-  length += XSETTINGS_PAD (strlen (setting->name), 4);
+  xsettings_manager_set_setting (manager, name, 0, NULL);
+}
 
-  switch (setting->type)
+static gchar
+xsettings_get_typecode (GVariant *value)
+{
+  switch (g_variant_classify (value))
     {
-    case XSETTINGS_TYPE_INT:
-      length += 4;
-      break;
-    case XSETTINGS_TYPE_STRING:
-      length += 4 + XSETTINGS_PAD (strlen (setting->data.v_string), 4);
-      break;
-    case XSETTINGS_TYPE_COLOR:
-      length += 8;
-      break;
+    case G_VARIANT_CLASS_INT32:
+      return XSETTINGS_TYPE_INT;
+    case G_VARIANT_CLASS_STRING:
+      return XSETTINGS_TYPE_STRING;
+    case G_VARIANT_CLASS_TUPLE:
+      return XSETTINGS_TYPE_COLOR;
+    default:
+      g_assert_not_reached ();
     }
-
-  return length;
 }
 
 static void
 setting_store (XSettingsSetting *setting,
-	       XSettingsBuffer *buffer)
+               GString          *buffer)
 {
-  size_t string_len;
-  size_t length;
+  XSettingsType type;
+  GVariant *value;
+  guint16 len16;
 
-  *(buffer->pos++) = setting->type;
-  *(buffer->pos++) = 0;
+  value = xsettings_setting_get (setting);
 
-  string_len = strlen (setting->name);
-  *(CARD16 *)(buffer->pos) = string_len;
-  buffer->pos += 2;
+  type = xsettings_get_typecode (value);
 
-  length = XSETTINGS_PAD (string_len, 4);
-  memcpy (buffer->pos, setting->name, string_len);
-  length -= string_len;
-  buffer->pos += string_len;
-  
-  while (length > 0)
-    {
-      *(buffer->pos++) = 0;
-      length--;
-    }
+  g_string_append_c (buffer, type);
+  g_string_append_c (buffer, 0);
+
+  len16 = strlen (setting->name);
+  g_string_append_len (buffer, (gchar *) &len16, 2);
+  g_string_append (buffer, setting->name);
 
-  *(CARD32 *)(buffer->pos) = setting->last_change_serial;
-  buffer->pos += 4;
+  while (buffer->len & 3)
+    g_string_append_c (buffer, '\0');
 
-  switch (setting->type)
+  g_string_append_len (buffer, (gchar *) &setting->last_change_serial, 4);
+
+  if (type == XSETTINGS_TYPE_STRING)
     {
-    case XSETTINGS_TYPE_INT:
-      *(CARD32 *)(buffer->pos) = setting->data.v_int;
-      buffer->pos += 4;
-      break;
-    case XSETTINGS_TYPE_STRING:
-      string_len = strlen (setting->data.v_string);
-      *(CARD32 *)(buffer->pos) = string_len;
-      buffer->pos += 4;
-      
-      length = XSETTINGS_PAD (string_len, 4);
-      memcpy (buffer->pos, setting->data.v_string, string_len);
-      length -= string_len;
-      buffer->pos += string_len;
-      
-      while (length > 0)
-	{
-	  *(buffer->pos++) = 0;
-	  length--;
-	}
-      break;
-    case XSETTINGS_TYPE_COLOR:
-      *(CARD16 *)(buffer->pos) = setting->data.v_color.red;
-      *(CARD16 *)(buffer->pos + 2) = setting->data.v_color.green;
-      *(CARD16 *)(buffer->pos + 4) = setting->data.v_color.blue;
-      *(CARD16 *)(buffer->pos + 6) = setting->data.v_color.alpha;
-      buffer->pos += 8;
-      break;
+      const gchar *string;
+      gsize stringlen;
+      guint32 len32;
+
+      string = g_variant_get_string (value, &stringlen);
+      len32 = stringlen;
+      g_string_append_len (buffer, (gchar *) &len32, 4);
+      g_string_append (buffer, string);
+
+      while (buffer->len & 3)
+        g_string_append_c (buffer, '\0');
     }
+  else
+    /* GVariant format is the same as XSETTINGS format for the non-string types */
+    g_string_append_len (buffer, g_variant_get_data (value), g_variant_get_size (value));
 }
 
-XSettingsResult
+void
 xsettings_manager_notify (XSettingsManager *manager)
 {
-  XSettingsBuffer buffer;
-  XSettingsList *iter;
-  int n_settings = 0;
+  GString *buffer;
+  GHashTableIter iter;
+  int n_settings;
+  gpointer value;
 
-  buffer.len = 12;		/* byte-order + pad + SERIAL + N_SETTINGS */
+  n_settings = g_hash_table_size (manager->settings);
 
-  iter = settings;
-  while (iter)
-    {
-      buffer.len += setting_length (iter->setting);
-      n_settings++;
-      iter = iter->next;
-    }
+  buffer = g_string_new (NULL);
+  g_string_append_c (buffer, xsettings_byte_order ());
+  g_string_append_c (buffer, '\0');
+  g_string_append_c (buffer, '\0');
+  g_string_append_c (buffer, '\0');
+
+  g_string_append_len (buffer, (gchar *) &manager->serial, 4);
+  g_string_append_len (buffer, (gchar *) &n_settings, 4);
+
+  g_hash_table_iter_init (&iter, manager->settings);
+  while (g_hash_table_iter_next (&iter, NULL, &value))
+    setting_store (value, buffer);
+
+  XChangeProperty (manager->display, manager->window,
+                   manager->xsettings_atom, manager->xsettings_atom,
+                   8, PropModeReplace, (guchar *) buffer->str, buffer->len);
 
-  buffer.data = buffer.pos = malloc (buffer.len);
-  if (!buffer.data)
-    return XSETTINGS_NO_MEM;
+  g_string_free (buffer, TRUE);
+  manager->serial++;
+}
 
-  *buffer.pos = xsettings_byte_order ();
+void
+xsettings_manager_set_overrides (XSettingsManager *manager,
+                                 GVariant         *overrides)
+{
+  GVariantIter iter;
+  const gchar *key;
+  GVariant *value;
 
-  buffer.pos += 4;
-  *(CARD32 *)buffer.pos = manager->serial++;
-  buffer.pos += 4;
-  *(CARD32 *)buffer.pos = n_settings;
-  buffer.pos += 4;
+  g_return_if_fail (overrides != NULL && g_variant_is_of_type (overrides, G_VARIANT_TYPE_VARDICT));
 
-  iter = settings;
-  while (iter)
+  if (manager->overrides)
     {
-      setting_store (iter->setting, &buffer);
-      iter = iter->next;
+      /* unset the existing overrides */
+
+      g_variant_iter_init (&iter, manager->overrides);
+      while (g_variant_iter_next (&iter, "{&sv}", &key, NULL))
+        /* only unset it at this point if it's not in the new list */
+        if (!g_variant_lookup (overrides, key, "*", NULL))
+          xsettings_manager_set_setting (manager, key, 1, NULL);
+      g_variant_unref (manager->overrides);
     }
 
-  XChangeProperty (manager->display, manager->window,
-		   manager->xsettings_atom, manager->xsettings_atom,
-		   8, PropModeReplace, buffer.data, buffer.len);
+  /* save this so we can do the unsets next time */
+  manager->overrides = g_variant_ref_sink (overrides);
 
-  free (buffer.data);
+  /* set the new values */
+  g_variant_iter_init (&iter, overrides);
+  while (g_variant_iter_loop (&iter, "{&sv}", &key, &value))
+    {
+      /* only accept recognised types... */
+      if (!g_variant_is_of_type (value, G_VARIANT_TYPE_STRING) &&
+          !g_variant_is_of_type (value, G_VARIANT_TYPE_INT32) &&
+          !g_variant_is_of_type (value, G_VARIANT_TYPE ("(qqqq)")))
+        continue;
 
-  return XSETTINGS_SUCCESS;
+      xsettings_manager_set_setting (manager, key, 1, value);
+    }
 }
-
diff --git a/plugins/xsettings/xsettings-manager.h b/plugins/xsettings/xsettings-manager.h
index f309768..a8cf151 100644
--- a/plugins/xsettings/xsettings-manager.h
+++ b/plugins/xsettings/xsettings-manager.h
@@ -26,10 +26,6 @@
 #include <X11/Xlib.h>
 #include "xsettings-common.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
 typedef struct _XSettingsManager XSettingsManager;
 
 typedef void (*XSettingsTerminateFunc)  (void *cb_data);
@@ -43,29 +39,20 @@ XSettingsManager *xsettings_manager_new (Display                *display,
 					 void                   *cb_data);
 
 void   xsettings_manager_destroy       (XSettingsManager *manager);
-Window xsettings_manager_get_window    (XSettingsManager *manager);
-Bool   xsettings_manager_process_event (XSettingsManager *manager,
-					XEvent           *xev);
-
-XSettingsResult xsettings_manager_delete_setting (XSettingsManager *manager,
-                                                  const char       *name);
-XSettingsResult xsettings_manager_set_setting    (XSettingsManager *manager,
-                                                  XSettingsSetting *setting);
-XSettingsResult xsettings_manager_set_int        (XSettingsManager *manager,
-                                                  const char       *name,
-                                                  int               value);
-XSettingsResult xsettings_manager_set_string     (XSettingsManager *manager,
-                                                  const char       *name,
-                                                  const char       *value);
-XSettingsResult xsettings_manager_set_color      (XSettingsManager *manager,
-                                                  const char       *name,
-                                                  XSettingsColor   *value);
-XSettingsResult xsettings_manager_notify         (XSettingsManager *manager);
-
-
 
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+void   xsettings_manager_delete_setting (XSettingsManager *manager,
+                                         const char       *name);
+void   xsettings_manager_set_int        (XSettingsManager *manager,
+                                         const char       *name,
+                                         int               value);
+void   xsettings_manager_set_string     (XSettingsManager *manager,
+                                         const char       *name,
+                                         const char       *value);
+void   xsettings_manager_set_color      (XSettingsManager *manager,
+                                         const char       *name,
+                                         XSettingsColor   *value);
+void   xsettings_manager_notify         (XSettingsManager *manager);
+void   xsettings_manager_set_overrides  (XSettingsManager *manager,
+                                         GVariant         *overrides);
 
 #endif /* XSETTINGS_MANAGER_H */
