[mutter] Port preferences to GSettings



commit d0910da036cfe7e9c86e19ccb3e765953b5dc045
Author: Florian MÃllner <fmuellner gnome org>
Date:   Fri Jun 24 18:14:15 2011 +0200

    Port preferences to GSettings
    
    Move preferences to GSettings, using mainly shared schemas from
    gsettings-desktop-schemas.
    
    Unlike GConf, GSettings support is not optional, as Gio is already
    a hard dependency of GTK+.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=635378

 .gitignore                          |    3 +-
 HACKING                             |    8 +-
 README                              |   29 +-
 configure.in                        |   33 +-
 doc/man/mutter-message.1            |    6 +-
 doc/man/mutter.1                    |    2 +-
 po/POTFILES.in                      |    2 +-
 src/Makefile.am                     |   22 +-
 src/core/all-keybindings.h          |  369 ++----
 src/core/bell.c                     |   13 +-
 src/core/core.c                     |   42 +-
 src/core/display.c                  |   12 +-
 src/core/keybindings.c              |  178 +---
 src/core/prefs.c                    | 2366 ++++++++++-------------------------
 src/core/screen.c                   |    2 +-
 src/core/window.c                   |   12 +-
 src/core/workspace.c                |   10 +-
 src/libmutter.pc.in                 |    2 +-
 src/meta/common.h                   |   33 +-
 src/meta/prefs.h                    |   74 +-
 src/mutter-schemas.convert          |    6 +
 src/mutter.schemas.in               |   89 --
 src/org.gnome.mutter.gschema.xml.in |   97 ++
 src/ui/frames.c                     |   19 +-
 test/mutter-test                    |    4 -
 25 files changed, 1011 insertions(+), 2422 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 69dbdfd..8238599 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,7 +48,8 @@ libmutter.pc
 mutter
 mutter-theme-viewer
 mutter.desktop
-mutter.schemas
+org.gnome.mutter.gschema.valid
+org.gnome.mutter.gschema.xml
 testasyncgetprop
 testboxes
 testgradient
diff --git a/HACKING b/HACKING
index a6cbdf5..763bc88 100644
--- a/HACKING
+++ b/HACKING
@@ -42,10 +42,10 @@ Minimal Building/Testing Environment
   build a development version of Metacity -- odds are, you may be able
   to build metacity from CVS without building any other modules.
 
-  As long as you have gtk+ >= 2.10 and GConf with your distro (gtk+ >=
-  2.6 if you manually revert the change from bug 348633), you should
-  be able to install your distro's development packages
-  (e.g. gtk2-devel, GConf2-devel, startup-notification-devel on
+  As long as you have gtk+ >= 3.0 and GIO >= 2.25.10 with your distro
+  (gtk+ >= 2.6 if you manually revert the change from bug 348633), you
+  should be able to install your distro's development packages
+  (e.g. gtk2-devel, glib-devel, startup-notification-devel on
   Fedora; also, remember to install the gnome-common package which is
   needed for building cvs versions of Gnome modules like Metacity) as
   well as the standard development tools (gcc, autoconf, automake,
diff --git a/README b/README
index 4ec8f2d..b0d31fa 100644
--- a/README
+++ b/README
@@ -18,8 +18,7 @@ COMPILING MUTTER
 You need GTK+ 2.2.  For startup notification to work you need
 libstartup-notification at
 http://www.freedesktop.org/software/startup-notification/ or on the
-GNOME ftp site. You also need GConf 1.2 (unless building a funky
-extra-small embedded metacity with --disable-gconf, see below).
+GNOME ftp site.
 You need Clutter 1.0. You need gobject-introspection 0.6.3.
 
 REPORTING BUGS AND SUBMITTING PATCHES
@@ -59,25 +58,24 @@ MUTTER FEATURES
    and should work with KWin, fvwm2, and other EWMH-compliant WMs.)
 
  - Has a simple theme system and a couple of extra themes come with it.
-   Change themes via gconf-editor or gconftool or GNOME themes control
-   panel:
-     gconftool-2 --type=string --set /apps/metacity/general/theme Crux
-     gconftool-2 --type=string --set /apps/metacity/general/theme Gorilla
-     gconftool-2 --type=string --set /apps/metacity/general/theme Atlanta
-     gconftool-2 --type=string --set /apps/metacity/general/theme Bright
+   Change themes via gsettings:
+     gsettings set org.gnome.desktop.wm.preferences theme Crux
+     gsettings set org.gnome.desktop.wm.preferences theme Gorilla
+     gsettings set org.gnome.desktop.wm.preferences theme Atlanta
+     gsettings set org.gnome.desktop.wm.preferences theme Bright
 
    See theme-format.txt for docs on the theme format. Use 
    metacity-theme-viewer to preview themes.
 
- - Change number of workspaces via gconf-editor or gconftool:
-     gconftool-2 --type=int --set /apps/metacity/general/num_workspaces 5
+ - Change number of workspaces via gsettings:
+     gsettings set org.gnome.desktop.wm.preferences num-workspaces 5
 
    Can also change workspaces from GNOME 2 pager.
 
  - Change focus mode:
-     gconftool-2 --type=string --set /apps/metacity/general/focus_mode mouse
-     gconftool-2 --type=string --set /apps/metacity/general/focus_mode sloppy
-     gconftool-2 --type=string --set /apps/metacity/general/focus_mode click
+     gsettings set org.gnome.desktop.wm.preferences focus-mode mouse
+     gsettings set org.gnome.desktop.wm.preferences focus-mode sloppy
+     gsettings set org.gnome.desktop.wm.preferences focus-mode click
 
  - Global keybinding defaults include:   
 
@@ -92,10 +90,9 @@ MUTTER FEATURES
 
    Change keybindings for example:
 
-     unst gconftool-2 --type=string --set /apps/metacity/global_keybindings/switch_to_workspace_1 '<Alt>F1'
+     gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 '[<Alt>F1]'
    
-   Also try the GNOME keyboard shortcuts control panel, or
-   gconf-editor.
+   Also try the GNOME keyboard shortcuts control panel.
 
  - Window keybindings:
 
diff --git a/configure.in b/configure.in
index 6e375ab..970d356 100644
--- a/configure.in
+++ b/configure.in
@@ -62,20 +62,13 @@ AC_CHECK_SIZEOF(__int64)
 AC_C_BIGENDIAN
 
 GTK_MIN_VERSION=3.3.3
+GIO_MIN_VERSION=2.25.10
 CANBERRA_GTK=libcanberra-gtk3
 CANBERRA_GTK_VERSION=0.26
 
-MUTTER_PC_MODULES="gtk+-3.0 >= $GTK_MIN_VERSION pango >= 1.2.0 cairo >= 1.10.0"
+MUTTER_PC_MODULES="gtk+-3.0 >= $GTK_MIN_VERSION gio-2.0 >= $GIO_MIN_VERSION pango >= 1.2.0 cairo >= 1.10.0 gsettings-desktop-schemas"
 
-AC_ARG_ENABLE(gconf,
-  AC_HELP_STRING([--disable-gconf],
-                 [disable gconf usage, for embedded/size-sensitive non-GNOME builds]),,
-  enable_gconf=yes)
-
-if test x$enable_gconf = xyes; then
-    AC_DEFINE(HAVE_GCONF,1,[Build with gconf support])
-    MUTTER_PC_MODULES="$MUTTER_PC_MODULES gconf-2.0 >= 1.2.0"
-fi
+GLIB_GSETTINGS
 
 AC_ARG_ENABLE(verbose-mode,
   AC_HELP_STRING([--disable-verbose-mode],
@@ -400,18 +393,6 @@ fi
 
 AC_SUBST(GDK_PIXBUF_CSOURCE)
 
-if test x$enable_gconf = xyes; then
-   AC_PATH_PROG(GCONFTOOL, gconftool-2, no)
-   if test x"$GCONFTOOL" = xno; then
-     AC_MSG_ERROR([gconftool-2 executable not found in your path - should be installed with GConf])
-   fi
-
-   AM_GCONF_SOURCE_2
-else
-  GCONF_SCHEMAS_INSTALL_TRUE='#'
-  GCONF_SCHEMAS_INSTALL_FALSE=
-fi
-
 AC_PATH_PROG(ZENITY, zenity, no)
 if test x"$ZENITY" = xno; then
   AC_MSG_ERROR([zenity not found in your path - needed for dialogs])
@@ -511,13 +492,6 @@ po/Makefile.in
 
 AC_OUTPUT
 
-if test x$enable_gconf = xno; then
-        echo "*** WARNING WARNING WARNING WARNING WARNING"
-        echo "*** Building without GConf.  This means there's no"
-        echo "*** way to change prefs except hacking source code."
-        echo "*** This is intended for embedded systems etc., not for normal use."
-fi
-
 if test x$enable_verbose_mode = xno; then
         echo "*** WARNING WARNING WARNING WARNING WARNING"
         echo "*** Building without verbose mode"
@@ -534,7 +508,6 @@ mutter-$VERSION
 	source code location:	  ${srcdir}
 	compiler:		  ${CC}
 
-	GConf:                    ${enable_gconf}
 	XFree86 Xinerama:         ${use_xfree_xinerama}
 	Solaris Xinerama:         ${use_solaris_xinerama}
 	Startup notification:     ${have_startup_notification}
diff --git a/doc/man/mutter-message.1 b/doc/man/mutter-message.1
index c301875..b309acf 100644
--- a/doc/man/mutter-message.1
+++ b/doc/man/mutter-message.1
@@ -46,13 +46,13 @@ because the original program does not have a manual page.
 Restart \fBmutter\fP(1) which is running.
 .TP
 .B reload-theme
-Reload a theme which is specified on gconf database.
+Reload a theme which is specified on gsettings database.
 .TP
 .B enable-keybindings
-Enable all of keybindings which is specified on gconf database.
+Enable all of keybindings which is specified on gsettings database.
 .TP
 .B disable-keybindings
-Disable all of keybindings which is specified on gconf database.
+Disable all of keybindings which is specified on gsettings database.
 .SH SEE ALSO
 .BR mutter (1)
 .SH AUTHOR
diff --git a/doc/man/mutter.1 b/doc/man/mutter.1
index 785d208..998d0f8 100644
--- a/doc/man/mutter.1
+++ b/doc/man/mutter.1
@@ -51,7 +51,7 @@ Print the version number.
 .B \-?, \-\-help
 Show summary of options.
 .SH CONFIGURATION
-\fBmutter\fP configuration can be found under \fIPreferences\fP->\fIWindows\fP and \fIPreferences\fP->\fIKeyboard Shortcuts\fP on the menu-panel. Advanced configuration can be achieved directly through gconf editing (gconf-editor or gconftool-2).
+\fBmutter\fP configuration can be found under \fIPreferences\fP->\fIWindows\fP and \fIPreferences\fP->\fIKeyboard Shortcuts\fP on the menu-panel. Advanced configuration can be achieved directly through gsettings.
 .SH SEE ALSO
 .BR mutter-message (1)
 .SH AUTHOR
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f3c6fea..638417b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -19,7 +19,7 @@ src/core/window-props.c
 src/core/xprops.c
 src/mutter.desktop.in
 src/mutter-wm.desktop.in
-src/mutter.schemas.in
+src/org.gnome.mutter.gschema.xml.in
 src/tools/mutter-message.c
 src/ui/frames.c
 src/ui/menu.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 227dafd..364cfd3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -226,7 +226,7 @@ typelib_DATA = Meta-$(api_version).typelib
 INTROSPECTION_GIRS = Meta-$(api_version).gir
 
 Meta-$(api_version).gir: libmutter.la
- META_GIR@_INCLUDES = GObject-2.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0
+ META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0
 @META_GIR _PACKAGES = clutter-1.0 gtk+-3.0
 @META_GIR _CFLAGS = $(INCLUDES)
 @META_GIR _LIBS = libmutter.la
@@ -262,20 +262,12 @@ wmproperties_in_files=mutter-wm.desktop.in
 wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
 wmproperties_DATA = $(wmproperties_files)
 
-schemadir   = $(GCONF_SCHEMA_FILE_DIR)
-schema_in_files = mutter.schemas.in
-schema_DATA = $(schema_in_files:.schemas.in=.schemas)
-
+gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
 @INTLTOOL_XML_NOMERGE_RULE@
+ GSETTINGS_RULES@
 
- INTLTOOL_SCHEMAS_RULE@
-
-if GCONF_SCHEMAS_INSTALL
-install-data-local:
-	GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA)
-else
-install-data-local:
-endif
+convertdir = $(datadir)/GConf/gsettings
+convert_DATA=$(srcdir)/mutter-schemas.convert
 
 IMAGES=stock_maximize.png stock_minimize.png stock_delete.png
 VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \
@@ -287,7 +279,7 @@ CLEANFILES =					\
 	inlinepixbufs.h				\
 	mutter.desktop				\
 	mutter-wm.desktop			\
-	mutter.schemas				\
+	org.gnome.mutter.gschema.xml		\
 	$(mutter_built_sources)			\
 	$(typelib_DATA)				\
 	$(gir_DATA)
@@ -304,7 +296,7 @@ EXTRA_DIST=$(desktopfiles_files) 	\
 	$(IMAGES) 			\
 	$(desktopfiles_in_files)	\
 	$(wmproperties_in_files)	\
-	$(schema_in_files)		\
+	org.gnome.mutter.gschema.xml.in \
 	libmutter.pc.in \
 	mutter-plugins.pc.in  \
 	mutter-enum-types.h.in \
diff --git a/src/core/all-keybindings.h b/src/core/all-keybindings.h
index d676f1b..7339465 100644
--- a/src/core/all-keybindings.h
+++ b/src/core/all-keybindings.h
@@ -55,12 +55,6 @@
  *                             explain this better)
  *      or 0 if no flag applies.
  *
- *   5) a string representing the default binding.
- *          If this is NULL, the action is unbound by default.
- *          Please use NULL and not "disabled".
- *   6) a short description.
- *          It must be marked translatable (i.e. inside "_(...)").
- *
  * Don't try to do XML entity escaping anywhere in the strings.
  */
 
@@ -84,30 +78,18 @@
 /* convenience, since in this file they must always be set together */
 #define REVERSES_AND_REVERSED (BINDING_REVERSES | BINDING_IS_REVERSED)
 
-keybind (switch_to_workspace_1,  handle_switch_to_workspace, 0, 0, NULL,
-        _("Switch to workspace 1"))
-keybind (switch_to_workspace_2,  handle_switch_to_workspace, 1, 0, NULL,
-        _("Switch to workspace 2"))
-keybind (switch_to_workspace_3,  handle_switch_to_workspace, 2, 0, NULL,
-        _("Switch to workspace 3"))
-keybind (switch_to_workspace_4,  handle_switch_to_workspace, 3, 0, NULL,
-        _("Switch to workspace 4"))
-keybind (switch_to_workspace_5,  handle_switch_to_workspace, 4, 0, NULL,
-        _("Switch to workspace 5"))
-keybind (switch_to_workspace_6,  handle_switch_to_workspace, 5, 0, NULL,
-        _("Switch to workspace 6"))
-keybind (switch_to_workspace_7,  handle_switch_to_workspace, 6, 0, NULL,
-        _("Switch to workspace 7"))
-keybind (switch_to_workspace_8,  handle_switch_to_workspace, 7, 0, NULL,
-        _("Switch to workspace 8"))
-keybind (switch_to_workspace_9,  handle_switch_to_workspace, 8, 0, NULL,
-        _("Switch to workspace 9"))
-keybind (switch_to_workspace_10, handle_switch_to_workspace, 9, 0, NULL,
-        _("Switch to workspace 10"))
-keybind (switch_to_workspace_11, handle_switch_to_workspace, 10, 0, NULL,
-        _("Switch to workspace 11"))
-keybind (switch_to_workspace_12, handle_switch_to_workspace, 11, 0, NULL,
-        _("Switch to workspace 12"))
+keybind (switch-to-workspace-1,  handle_switch_to_workspace, 0, 0)
+keybind (switch-to-workspace-2,  handle_switch_to_workspace, 1, 0)
+keybind (switch-to-workspace-3,  handle_switch_to_workspace, 2, 0)
+keybind (switch-to-workspace-4,  handle_switch_to_workspace, 3, 0)
+keybind (switch-to-workspace-5,  handle_switch_to_workspace, 4, 0)
+keybind (switch-to-workspace-6,  handle_switch_to_workspace, 5, 0)
+keybind (switch-to-workspace-7,  handle_switch_to_workspace, 6, 0)
+keybind (switch-to-workspace-8,  handle_switch_to_workspace, 7, 0)
+keybind (switch-to-workspace-9,  handle_switch_to_workspace, 8, 0)
+keybind (switch-to-workspace-10, handle_switch_to_workspace, 9, 0)
+keybind (switch-to-workspace-11, handle_switch_to_workspace, 10, 0)
+keybind (switch-to-workspace-12, handle_switch_to_workspace, 11, 0)
 
 /* META_MOTION_* are negative, and so distinct from workspace numbers,
  * which are always zero or positive.
@@ -117,21 +99,17 @@ keybind (switch_to_workspace_12, handle_switch_to_workspace, 11, 0, NULL,
  * workspace.h, of course.
  */
 
-keybind (switch_to_workspace_left, handle_switch_to_workspace,
-         META_MOTION_LEFT, 0, "<Control><Alt>Left",
-        _("Switch to workspace on the left of the current workspace"))
+keybind (switch-to-workspace-left, handle_switch_to_workspace,
+         META_MOTION_LEFT, 0)
 
-keybind (switch_to_workspace_right, handle_switch_to_workspace,
-         META_MOTION_RIGHT, 0, "<Control><Alt>Right",
-        _("Switch to workspace on the right of the current workspace"))
+keybind (switch-to-workspace-right, handle_switch_to_workspace,
+         META_MOTION_RIGHT, 0)
 
-keybind (switch_to_workspace_up, handle_switch_to_workspace,
-         META_MOTION_UP, 0, "<Control><Alt>Up",
-        _("Switch to workspace above the current workspace"))
+keybind (switch-to-workspace-up, handle_switch_to_workspace,
+         META_MOTION_UP, 0)
 
-keybind (switch_to_workspace_down, handle_switch_to_workspace,
-         META_MOTION_DOWN, 0, "<Control><Alt>Down",
-        _("Switch to workspace below the current workspace"))
+keybind (switch-to-workspace-down, handle_switch_to_workspace,
+         META_MOTION_DOWN, 0)
 
 /***********************************/
 
@@ -145,45 +123,25 @@ keybind (switch_to_workspace_down, handle_switch_to_workspace,
  * same function checking a bit in the parameter for difference.
  */
 
-keybind (switch_group,              handle_switch,        META_TAB_LIST_GROUP,
-         BINDING_REVERSES,       "<Alt>Above_Tab",
-        _("Move between windows of an application, using a popup window"))
-keybind (switch_group_backward,    handle_switch,        META_TAB_LIST_GROUP,
-         REVERSES_AND_REVERSED,  NULL,
-        _("Move backward between windows of an application, "
-          "using a popup window"))
-keybind (switch_windows,            handle_switch,        META_TAB_LIST_NORMAL,
-         BINDING_REVERSES,       "<Alt>Tab",
-        _("Move between windows, using a popup window"))
-keybind (switch_windows_backward,  handle_switch,        META_TAB_LIST_NORMAL,
-         REVERSES_AND_REVERSED,  NULL,
-        _("Move backward between windows, using a popup window"))
-keybind (switch_panels,             handle_switch,        META_TAB_LIST_DOCKS,
-         BINDING_REVERSES,       "<Control><Alt>Tab",
-        _("Move between panels and the desktop, using a popup window"))
-keybind (switch_panels_backward,   handle_switch,        META_TAB_LIST_DOCKS,
-         REVERSES_AND_REVERSED,  NULL,
-         _("Move backward between panels and the desktop, "
-          "using a popup window"))
-
-keybind (cycle_group,               handle_cycle,         META_TAB_LIST_GROUP,
-        BINDING_REVERSES,        "<Alt>F6",
-        _("Move between windows of an application immediately"))
-keybind (cycle_group_backward,     handle_cycle,         META_TAB_LIST_GROUP,
-        REVERSES_AND_REVERSED,   NULL,
-        _("Move backward between windows of an application immediately"))
-keybind (cycle_windows,             handle_cycle,         META_TAB_LIST_NORMAL,
-        BINDING_REVERSES,        "<Alt>Escape",
-        _("Move between windows immediately"))
-keybind (cycle_windows_backward,   handle_cycle,         META_TAB_LIST_NORMAL,
-        REVERSES_AND_REVERSED,   NULL,
-        _("Move backward between windows immediately"))
-keybind (cycle_panels,              handle_cycle,         META_TAB_LIST_DOCKS,
-        BINDING_REVERSES,        "<Control><Alt>Escape",
-        _("Move between panels and the desktop immediately"))
-keybind (cycle_panels_backward,    handle_cycle,         META_TAB_LIST_DOCKS,
-        REVERSES_AND_REVERSED,   NULL,
-        _("Move backward between panels and the desktop immediately"))
+keybind (switch-group, handle_switch, META_TAB_LIST_GROUP, BINDING_REVERSES)
+keybind (switch-group-backward, handle_switch,
+         META_TAB_LIST_GROUP, REVERSES_AND_REVERSED)
+keybind (switch-windows, handle_switch, META_TAB_LIST_NORMAL, BINDING_REVERSES)
+keybind (switch-windows-backward, handle_switch, META_TAB_LIST_NORMAL,
+         REVERSES_AND_REVERSED)
+keybind (switch-panels, handle_switch, META_TAB_LIST_DOCKS, BINDING_REVERSES)
+keybind (switch-panels-backward, handle_switch, META_TAB_LIST_DOCKS,
+         REVERSES_AND_REVERSED)
+
+keybind (cycle-group, handle_cycle, META_TAB_LIST_GROUP, BINDING_REVERSES)
+keybind (cycle-group-backward, handle_cycle, META_TAB_LIST_GROUP,
+        REVERSES_AND_REVERSED)
+keybind (cycle-windows, handle_cycle, META_TAB_LIST_NORMAL, BINDING_REVERSES)
+keybind (cycle-windows-backward, handle_cycle, META_TAB_LIST_NORMAL,
+        REVERSES_AND_REVERSED)
+keybind (cycle-panels, handle_cycle, META_TAB_LIST_DOCKS, BINDING_REVERSES)
+keybind (cycle-panels-backward, handle_cycle, META_TAB_LIST_DOCKS,
+        REVERSES_AND_REVERSED)
 
 /***********************************/
 
@@ -192,71 +150,20 @@ keybind (cycle_panels_backward,    handle_cycle,         META_TAB_LIST_DOCKS,
  * grab is in effect, they are invoked for releasing the primary modifier
  * or pressing some unbound key, respectively.
  */
-keybind (tab_popup_select,        handle_tab_popup_select, 0, 0, NULL,
-         "Select window from tab popup")
-keybind (tab_popup_cancel,        handle_tab_popup_cancel, 0, 0, NULL,
-         "Cancel tab popup")
+keybind (tab-popup-select, handle_tab_popup_select, 0, 0)
+keybind (tab-popup-cancel, handle_tab_popup_cancel, 0, 0)
 
 /***********************************/
      
-keybind (show_desktop, handle_show_desktop, 0, 0, "<Control><Alt>d",
-      _("Hide all normal windows and set focus to the desktop"))
-keybind (panel_main_menu, handle_panel,
-       META_KEYBINDING_ACTION_PANEL_MAIN_MENU, 0, "<Alt>F1",
-      _("Show the panel's main menu"))
-keybind (panel_run_dialog, handle_panel,
-       META_KEYBINDING_ACTION_PANEL_RUN_DIALOG, 0, "<Alt>F2",
-      _("Show the panel's \"Run Application\" dialog box"))
-keybind (toggle_recording, handle_toggle_recording, 0, 0, "<Control><Shift><Alt>r",
-         _("Start or stop recording the session"))
-
-/* Yes, the param is offset by one.  Historical reasons.  (Maybe worth fixing
- * at some point.)  The description is NULL here because the stanza is
- * irregularly shaped in mutter.schemas.in.  This will probably be fixed
- * as well.
- */
-keybind (run_command_1,  handle_run_command,  0, 0, NULL, NULL)
-keybind (run_command_2,  handle_run_command,  1, 0, NULL, NULL)
-keybind (run_command_3,  handle_run_command,  2, 0, NULL, NULL)
-keybind (run_command_4,  handle_run_command,  3, 0, NULL, NULL)
-keybind (run_command_5,  handle_run_command,  4, 0, NULL, NULL)
-keybind (run_command_6,  handle_run_command,  5, 0, NULL, NULL)
-keybind (run_command_7,  handle_run_command,  6, 0, NULL, NULL)
-keybind (run_command_8,  handle_run_command,  7, 0, NULL, NULL)
-keybind (run_command_9,  handle_run_command,  8, 0, NULL, NULL)
-keybind (run_command_10, handle_run_command,  9, 0, NULL, NULL)
-keybind (run_command_11, handle_run_command, 10, 0, NULL, NULL)
-keybind (run_command_12, handle_run_command, 11, 0, NULL, NULL)
-keybind (run_command_13, handle_run_command, 12, 0, NULL, NULL)
-keybind (run_command_14, handle_run_command, 13, 0, NULL, NULL)
-keybind (run_command_15, handle_run_command, 14, 0, NULL, NULL)
-keybind (run_command_16, handle_run_command, 15, 0, NULL, NULL)
-keybind (run_command_17, handle_run_command, 16, 0, NULL, NULL)
-keybind (run_command_18, handle_run_command, 17, 0, NULL, NULL)
-keybind (run_command_19, handle_run_command, 18, 0, NULL, NULL)
-keybind (run_command_20, handle_run_command, 19, 0, NULL, NULL)
-keybind (run_command_21, handle_run_command, 20, 0, NULL, NULL)
-keybind (run_command_22, handle_run_command, 21, 0, NULL, NULL)
-keybind (run_command_23, handle_run_command, 22, 0, NULL, NULL)
-keybind (run_command_24, handle_run_command, 23, 0, NULL, NULL)
-keybind (run_command_25, handle_run_command, 24, 0, NULL, NULL)
-keybind (run_command_26, handle_run_command, 25, 0, NULL, NULL)
-keybind (run_command_27, handle_run_command, 26, 0, NULL, NULL)
-keybind (run_command_28, handle_run_command, 27, 0, NULL, NULL)
-keybind (run_command_29, handle_run_command, 28, 0, NULL, NULL)
-keybind (run_command_30, handle_run_command, 29, 0, NULL, NULL)
-keybind (run_command_31, handle_run_command, 30, 0, NULL, NULL)
-keybind (run_command_32, handle_run_command, 31, 0, NULL, NULL)
-
-keybind (run_command_screenshot, handle_run_command, 32, 0, "Print",
-      _("Take a screenshot"))
-keybind (run_command_window_screenshot, handle_run_command, 33, 0,"<Alt>Print",
-      _("Take a screenshot of a window"))
-
-keybind (run_command_terminal, handle_run_terminal, 0, 0, NULL, _("Run a terminal"))
-
-/* No description because this is undocumented */
-keybind (set_spew_mark, handle_set_spew_mark, 0, 0, NULL, NULL)
+keybind (show-desktop, handle_show_desktop, 0, 0)
+keybind (panel-main-menu, handle_panel,
+       META_KEYBINDING_ACTION_PANEL_MAIN_MENU, 0)
+keybind (panel-run-dialog, handle_panel,
+       META_KEYBINDING_ACTION_PANEL_RUN_DIALOG, 0)
+keybind (toggle-recording, handle_toggle_recording, 0, 0)
+
+/* FIXME: No description because this is undocumented */
+keybind (set-spew-mark, handle_set_spew_mark, 0, 0)
 
 #undef REVERSES_AND_REVERSED
 
@@ -266,70 +173,34 @@ keybind (set_spew_mark, handle_set_spew_mark, 0, 0, NULL, NULL)
  * if no window is active.
  */
  
-keybind (activate_window_menu, handle_activate_window_menu, 0,
-        BINDING_PER_WINDOW, "<Alt>space",
-        _("Activate the window menu"))
-keybind (toggle_fullscreen, handle_toggle_fullscreen, 0, BINDING_PER_WINDOW,
-        NULL,
-        _("Toggle fullscreen mode"))
-keybind (toggle_maximized, handle_toggle_maximized, 0, BINDING_PER_WINDOW, "<Alt>F10",
-        _("Toggle maximization state"))
-keybind (toggle_above, handle_toggle_above, 0, BINDING_PER_WINDOW, NULL,
-        _("Toggle whether a window will always be visible over other windows"))
-keybind (maximize, handle_maximize, 0, BINDING_PER_WINDOW, NULL,
-        _("Maximize window"))
-keybind (unmaximize, handle_unmaximize, 0, BINDING_PER_WINDOW, "<Alt>F5",
-        _("Restore window"))
-keybind (toggle_shaded, handle_toggle_shaded, 0, BINDING_PER_WINDOW, NULL,
-        _("Toggle shaded state"))
-keybind (minimize, handle_minimize, 0, BINDING_PER_WINDOW, "<Alt>F9",
-        _("Minimize window"))
-keybind (close, handle_close, 0, BINDING_PER_WINDOW, "<Alt>F4",
-        _("Close window"))
-keybind (begin_move, handle_begin_move, 0, BINDING_PER_WINDOW, "<Alt>F7",
-        _("Move window"))
-keybind (begin_resize, handle_begin_resize, 0, BINDING_PER_WINDOW, "<Alt>F8",
-        _("Resize window"))
-keybind (toggle_on_all_workspaces, handle_toggle_on_all_workspaces, 0,
-         BINDING_PER_WINDOW, NULL,
-        _("Toggle whether window is on all workspaces or just one"))
-
-keybind (move_to_workspace_1, handle_move_to_workspace, 0, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 1"))
-keybind (move_to_workspace_2, handle_move_to_workspace, 1, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 2"))
-keybind (move_to_workspace_3, handle_move_to_workspace, 2, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 3"))
-keybind (move_to_workspace_4, handle_move_to_workspace, 3, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 4"))
-keybind (move_to_workspace_5, handle_move_to_workspace, 4, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 5"))
-keybind (move_to_workspace_6, handle_move_to_workspace, 5, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 6"))
-keybind (move_to_workspace_7, handle_move_to_workspace, 6, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 7"))
-keybind (move_to_workspace_8, handle_move_to_workspace, 7, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 8"))
-keybind (move_to_workspace_9, handle_move_to_workspace, 8, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 9"))
-keybind (move_to_workspace_10, handle_move_to_workspace, 9, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 10"))
-keybind (move_to_workspace_11, handle_move_to_workspace, 10, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 11"))
-keybind (move_to_workspace_12, handle_move_to_workspace, 11, BINDING_PER_WINDOW,
-        NULL,
-        _("Move window to workspace 12"))
+keybind (activate-window-menu, handle_activate_window_menu, 0,
+        BINDING_PER_WINDOW)
+keybind (toggle-fullscreen, handle_toggle_fullscreen, 0, BINDING_PER_WINDOW)
+keybind (toggle-maximized, handle_toggle_maximized, 0, BINDING_PER_WINDOW)
+keybind (toggle-above, handle_toggle_above, 0, BINDING_PER_WINDOW)
+keybind (maximize, handle_maximize, 0, BINDING_PER_WINDOW)
+keybind (unmaximize, handle_unmaximize, 0, BINDING_PER_WINDOW)
+keybind (toggle-shaded, handle_toggle_shaded, 0, BINDING_PER_WINDOW)
+keybind (minimize, handle_minimize, 0, BINDING_PER_WINDOW)
+keybind (close, handle_close, 0, BINDING_PER_WINDOW)
+keybind (begin-move, handle_begin_move, 0, BINDING_PER_WINDOW)
+keybind (begin-resize, handle_begin_resize, 0, BINDING_PER_WINDOW)
+keybind (toggle-on-all-workspaces, handle_toggle_on_all_workspaces, 0,
+         BINDING_PER_WINDOW)
+
+keybind (move-to-workspace-1, handle_move_to_workspace, 0, BINDING_PER_WINDOW)
+keybind (move-to-workspace-2, handle_move_to_workspace, 1, BINDING_PER_WINDOW)
+keybind (move-to-workspace-3, handle_move_to_workspace, 2, BINDING_PER_WINDOW)
+keybind (move-to-workspace-4, handle_move_to_workspace, 3, BINDING_PER_WINDOW)
+keybind (move-to-workspace-5, handle_move_to_workspace, 4, BINDING_PER_WINDOW)
+keybind (move-to-workspace-6, handle_move_to_workspace, 5, BINDING_PER_WINDOW)
+keybind (move-to-workspace-7, handle_move_to_workspace, 6, BINDING_PER_WINDOW)
+keybind (move-to-workspace-8, handle_move_to_workspace, 7, BINDING_PER_WINDOW)
+keybind (move-to-workspace-9, handle_move_to_workspace, 8, BINDING_PER_WINDOW)
+keybind (move-to-workspace-10, handle_move_to_workspace, 9, BINDING_PER_WINDOW)
+keybind (move-to-workspace-11, handle_move_to_workspace, 10, BINDING_PER_WINDOW)
+keybind (move-to-workspace-12, handle_move_to_workspace, 11, BINDING_PER_WINDOW)
+
 
 /* META_MOTION_* are negative, and so distinct from workspace numbers,
  * which are always zero or positive.
@@ -339,62 +210,34 @@ keybind (move_to_workspace_12, handle_move_to_workspace, 11, BINDING_PER_WINDOW,
  * workspace.h, of course.
  */
 
-keybind (move_to_workspace_left, handle_move_to_workspace,
-         META_MOTION_LEFT, BINDING_PER_WINDOW, "<Control><Shift><Alt>Left",
-        _("Move window one workspace to the left"))
-keybind (move_to_workspace_right, handle_move_to_workspace,
-         META_MOTION_RIGHT, BINDING_PER_WINDOW, "<Control><Shift><Alt>Right",
-        _("Move window one workspace to the right"))
-keybind (move_to_workspace_up, handle_move_to_workspace,
-         META_MOTION_UP, BINDING_PER_WINDOW, "<Control><Shift><Alt>Up",
-        _("Move window one workspace up"))
-keybind (move_to_workspace_down, handle_move_to_workspace,
-         META_MOTION_DOWN, BINDING_PER_WINDOW, "<Control><Shift><Alt>Down",
-        _("Move window one workspace down"))
-
-keybind (raise_or_lower, handle_raise_or_lower, 0, BINDING_PER_WINDOW, NULL,
-        _("Raise window if it's covered by another window, otherwise lower it"))
-keybind (raise, handle_raise, 0, BINDING_PER_WINDOW, NULL,
-        _("Raise window above other windows"))
-keybind (lower, handle_lower, 0, BINDING_PER_WINDOW, NULL,
-        _("Lower window below other windows"))
-
-keybind (maximize_vertically, handle_maximize_vertically, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Maximize window vertically"))
-
-keybind (maximize_horizontally, handle_maximize_horizontally, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Maximize window horizontally"))
-
-keybind (move_to_corner_nw, handle_move_to_corner_nw, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to north-west (top left) corner"))
-keybind (move_to_corner_ne, handle_move_to_corner_ne, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to north-east (top right) corner"))
-keybind (move_to_corner_sw, handle_move_to_corner_sw, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to south-west (bottom left) corner"))
-keybind (move_to_corner_se, handle_move_to_corner_se, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to south-east (bottom right) corner"))
-
-keybind (move_to_side_n, handle_move_to_side_n, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to north (top) side of screen"))
-keybind (move_to_side_s, handle_move_to_side_s, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to south (bottom) side of screen"))
-keybind (move_to_side_e, handle_move_to_side_e, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to east (right) side of screen"))
-keybind (move_to_side_w, handle_move_to_side_w, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to west (left) side of screen"))
-keybind (move_to_center, handle_move_to_center, 0,
-        BINDING_PER_WINDOW, NULL,
-        _("Move window to center of screen"))
+keybind (move-to-workspace-left, handle_move_to_workspace,
+         META_MOTION_LEFT, BINDING_PER_WINDOW)
+keybind (move-to-workspace-right, handle_move_to_workspace,
+         META_MOTION_RIGHT, BINDING_PER_WINDOW)
+keybind (move-to-workspace-up, handle_move_to_workspace,
+         META_MOTION_UP, BINDING_PER_WINDOW)
+keybind (move-to-workspace-down, handle_move_to_workspace,
+         META_MOTION_DOWN, BINDING_PER_WINDOW)
+
+keybind (raise-or-lower, handle_raise_or_lower, 0, BINDING_PER_WINDOW)
+keybind (raise, handle_raise, 0, BINDING_PER_WINDOW)
+keybind (lower, handle_lower, 0, BINDING_PER_WINDOW)
+
+keybind (maximize-vertically, handle_maximize_vertically, 0, BINDING_PER_WINDOW)
+
+keybind (maximize-horizontally, handle_maximize_horizontally, 0,
+        BINDING_PER_WINDOW)
+
+keybind (move-to-corner-nw, handle_move_to_corner_nw, 0, BINDING_PER_WINDOW)
+keybind (move-to-corner-ne, handle_move_to_corner_ne, 0, BINDING_PER_WINDOW)
+keybind (move-to-corner-sw, handle_move_to_corner_sw, 0, BINDING_PER_WINDOW)
+keybind (move-to-corner-se, handle_move_to_corner_se, 0, BINDING_PER_WINDOW)
+
+keybind (move-to-side-n, handle_move_to_side_n, 0, BINDING_PER_WINDOW)
+keybind (move-to-side-s, handle_move_to_side_s, 0, BINDING_PER_WINDOW)
+keybind (move-to-side-e, handle_move_to_side_e, 0, BINDING_PER_WINDOW)
+keybind (move-to-side-w, handle_move_to_side_w, 0, BINDING_PER_WINDOW)
+keybind (move-to-center, handle_move_to_center, 0, BINDING_PER_WINDOW)
 
 /* eof all-keybindings.h */
 
diff --git a/src/core/bell.c b/src/core/bell.c
index 8c7da04..07abc12 100644
--- a/src/core/bell.c
+++ b/src/core/bell.c
@@ -130,7 +130,7 @@ bell_flash_screen (MetaDisplay *display,
       XFreeGC (display->xdisplay, gc);
     }
 
-  if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK &&
+  if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK &&
       !display->mouse_mode)
     meta_display_increment_focus_sentinel (display);
   XFlush (display->xdisplay);
@@ -277,13 +277,13 @@ bell_visual_notify (MetaDisplay *display,
 {
   switch (meta_prefs_get_visual_bell_type ()) 
     {
-    case META_VISUAL_BELL_FULLSCREEN_FLASH:
+    case G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH:
       bell_flash_fullscreen (display, xkb_ev);
       break;
-    case META_VISUAL_BELL_FRAME_FLASH:
+    case G_DESKTOP_VISUAL_BELL_FRAME_FLASH:
       bell_flash_frame (display, xkb_ev); /* does nothing yet */
       break;
-    case META_VISUAL_BELL_INVALID:
+    case G_DESKTOP_VISUAL_BELL_NONE:
       /* do nothing */
       break;
     }
@@ -293,9 +293,8 @@ void
 meta_bell_notify (MetaDisplay *display, 
 		  XkbAnyEvent *xkb_ev)
 {
-  /* flash something */
-  if (meta_prefs_get_visual_bell ()) 
-    bell_visual_notify (display, xkb_ev);
+  /* flash something if appropriate */
+  bell_visual_notify (display, xkb_ev);
 
 #ifdef HAVE_LIBCANBERRA
   if (meta_prefs_bell_is_audible ())
diff --git a/src/core/core.c b/src/core/core.c
index 16f51cc..c2ec5fe 100644
--- a/src/core/core.c
+++ b/src/core/core.c
@@ -212,7 +212,7 @@ lower_window_and_transients (MetaWindow *window,
 
   meta_window_foreach_transient (window, lower_window_and_transients, NULL);
 
-  if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
+  if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
       meta_prefs_get_raise_on_click ())
     {
       /* Move window to the back of the focusing workspace's MRU list.
@@ -538,70 +538,70 @@ meta_core_get_menu_accelerator (MetaMenuOp           menu_op,
       break;
     case META_MENU_OP_UNSTICK:
     case META_MENU_OP_STICK:
-      name = "toggle_on_all_workspaces";
+      name = "toggle-on-all-workspaces";
       break;
     case META_MENU_OP_ABOVE:
     case META_MENU_OP_UNABOVE:
-      name = "toggle_above";
+      name = "toggle-above";
       break;
     case META_MENU_OP_WORKSPACES:
       switch (workspace)
         {
         case 1:
-          name = "move_to_workspace_1";
+          name = "move-to-workspace-1";
           break;
         case 2:
-          name = "move_to_workspace_2";
+          name = "move-to-workspace-2";
           break;
         case 3:
-          name = "move_to_workspace_3";
+          name = "move-to-workspace-3";
           break; 
         case 4:
-          name = "move_to_workspace_4";
+          name = "move-to-workspace-4";
           break; 
         case 5:
-          name = "move_to_workspace_5";
+          name = "move-to-workspace-5";
           break; 
         case 6:
-          name = "move_to_workspace_6";
+          name = "move-to-workspace-6";
           break; 
         case 7:
-          name = "move_to_workspace_7";
+          name = "move-to-workspace-7";
           break; 
         case 8:
-          name = "move_to_workspace_8";
+          name = "move-to-workspace-8";
           break; 
         case 9:
-          name = "move_to_workspace_9";
+          name = "move-to-workspace-9";
           break; 
         case 10:
-          name = "move_to_workspace_10";
+          name = "move-to-workspace-10";
           break;
         case 11:
-          name = "move_to_workspace_11";
+          name = "move-to-workspace-11";
           break;
         case 12:
-          name = "move_to_workspace_12";
+          name = "move-to-workspace-12";
           break;
         }
       break;
     case META_MENU_OP_MOVE:
-      name = "begin_move";
+      name = "begin-move";
       break;
     case META_MENU_OP_RESIZE:
-      name = "begin_resize";
+      name = "begin-resize";
       break;
     case META_MENU_OP_MOVE_LEFT:
-      name = "move_to_workspace_left";
+      name = "move-to-workspace-left";
       break;
     case META_MENU_OP_MOVE_RIGHT:
-      name = "move_to_workspace_right";
+      name = "move-to-workspace-right";
       break;
     case META_MENU_OP_MOVE_UP:
-      name = "move_to_workspace_up";
+      name = "move-to-workspace-up";
       break;
     case META_MENU_OP_MOVE_DOWN:
-      name = "move_to_workspace_down";
+      name = "move-to-workspace-down";
       break;
     case META_MENU_OP_RECOVER:
       /* No keybinding for this one */
diff --git a/src/core/display.c b/src/core/display.c
index 85cdd16..f2dfd20 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -1921,7 +1921,7 @@ event_callback (XEvent   *event,
                * in application-based mode, and the different
                * app is not a dock or desktop, eat the focus click.
                */
-              if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
+              if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
                   meta_prefs_get_application_based () &&
                   !window->has_focus &&
                   window->type != META_WINDOW_DOCK &&
@@ -2009,8 +2009,8 @@ event_callback (XEvent   *event,
         {
           switch (meta_prefs_get_focus_mode ())
             {
-            case META_FOCUS_MODE_SLOPPY:
-            case META_FOCUS_MODE_MOUSE:
+            case G_DESKTOP_FOCUS_MODE_SLOPPY:
+            case G_DESKTOP_FOCUS_MODE_MOUSE:
               display->mouse_mode = TRUE;
               if (window->type != META_WINDOW_DOCK &&
                   window->type != META_WINDOW_DESKTOP)
@@ -2048,7 +2048,7 @@ event_callback (XEvent   *event,
                * alternative mechanism works great.
                */
               if (window->type == META_WINDOW_DESKTOP &&
-                  meta_prefs_get_focus_mode() == META_FOCUS_MODE_MOUSE &&
+                  meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
                   display->expected_focus_window != NULL)
                 {
                   meta_topic (META_DEBUG_FOCUS,
@@ -2060,7 +2060,7 @@ event_callback (XEvent   *event,
                                                           event->xcrossing.time);
                 }
               break;
-            case META_FOCUS_MODE_CLICK:
+            case G_DESKTOP_FOCUS_MODE_CLICK:
               break;
             }
           
@@ -4003,7 +4003,7 @@ meta_display_grab_focus_window_button (MetaDisplay *display,
    * focus window may not be raised, and who wants to think about
    * mouse focus anyway.
    */
-  if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK)
+  if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK)
     {
       meta_verbose (" (well, not grabbing since not in click to focus mode)\n");
       return;
diff --git a/src/core/keybindings.c b/src/core/keybindings.c
index 8c5cb42..8869053 100644
--- a/src/core/keybindings.c
+++ b/src/core/keybindings.c
@@ -49,7 +49,7 @@
 static gboolean all_bindings_disabled = FALSE;
 
 /* Prototypes for handlers */
-#define keybind(name, handler, param, flags, stroke, description) \
+#define keybind(name, handler, param, flags) \
 static void \
 handler (MetaDisplay    *display,\
          MetaScreen     *screen,\
@@ -103,7 +103,7 @@ static gboolean process_workspace_switch_grab (MetaDisplay *display,
 static void regrab_key_bindings         (MetaDisplay *display);
 
 
-#define keybind(name, handler, param, flags, stroke, description) \
+#define keybind(name, handler, param, flags) \
   { #name, handler, handler, param, flags, NULL, NULL },
 static MetaKeyHandler key_handlers[] = {
 #include "all-keybindings.h"
@@ -2183,7 +2183,7 @@ process_tab_grab (MetaDisplay *display,
         {
           if (end_keyboard_grab (display, event->xkey.keycode))
             {
-              invoke_handler_by_name (display, screen, "tab_popup_select", NULL, event);
+              invoke_handler_by_name (display, screen, "tab-popup-select", NULL, event);
 
               /* We return FALSE to end the grab; if the handler ended the grab itself
                * that will be a noop. If the handler didn't end the grab, then it's a
@@ -2239,7 +2239,7 @@ process_tab_grab (MetaDisplay *display,
         }
 
       /* Some unhandled key press */
-      invoke_handler_by_name (display, screen, "tab_popup_cancel", NULL, event);
+      invoke_handler_by_name (display, screen, "tab-popup-cancel", NULL, event);
       return FALSE;
     }
 
@@ -2496,138 +2496,6 @@ handle_switch_to_workspace (MetaDisplay    *display,
     }
 }
 
-static void
-error_on_command (int         command_index,
-                  const char *command,
-                  const char *message,
-                  MetaScreen *screen,
-                  guint32     timestamp)
-{
-  if (command_index < 0)
-    meta_warning ("Error on terminal command \"%s\": %s\n", command, message);  
-  else
-    meta_warning ("Error on command %d \"%s\": %s\n",
-                  command_index, command, message);  
-
-  /*
-    mutter-dialog said:
-        
-    FIXME offer to change the value of the command's gconf key
-  */
-
-  if (command && strcmp(command, "")!=0)
-    {
-      char *text = g_strdup_printf (
-                                    /* Displayed when a keybinding which is
-                                     * supposed to launch a program fails.
-                                     */
-                                    _("There was an error running "
-                                      "<tt>%s</tt>:\n\n%s"),
-                                    command,
-                                    message);
-
-      meta_show_dialog ("--error",
-                        text,
-                        NULL,
-                        screen->screen_name,
-                        NULL, NULL, 0,
-                        NULL, NULL);
-
-      g_free (text);
-
-    }
-  else
-    {
-      meta_show_dialog ("--error",
-                        message,
-                        NULL,
-                        screen->screen_name,
-                        NULL, NULL, 0,
-                        NULL, NULL);
-    }
-}
-
-static void
-set_display_setup_func (void *data)
-{
-  const char *screen_name = data;
-  char *full;
-
-  full = g_strdup_printf ("DISPLAY=%s", screen_name);
-
-  putenv (full);
-
-  /* do not free full, because putenv is lame */
-} 
-
-static gboolean
-meta_spawn_command_line_async_on_screen (const gchar *command_line,
-                                         MetaScreen  *screen,
-                                         GError     **error)
-{
-  gboolean retval;
-  gchar **argv = NULL;
-
-  g_return_val_if_fail (command_line != NULL, FALSE);
-
-  if (!g_shell_parse_argv (command_line,
-                           NULL, &argv,
-                           error))
-    return FALSE;
-  
-  retval = g_spawn_async (NULL,
-                          argv,
-                          NULL,
-                          G_SPAWN_SEARCH_PATH,
-                          set_display_setup_func,
-                          screen->screen_name,
-                          NULL,
-                          error);
-  g_strfreev (argv);
-
-  return retval;
-}
-
-
-static void
-handle_run_command (MetaDisplay    *display,
-                    MetaScreen     *screen,
-                    MetaWindow     *window,
-                    XEvent         *event,
-                    MetaKeyBinding *binding,
-                    gpointer        dummy)
-{
-  gint which = binding->handler->data;
-  const char *command;
-  GError *err;
-  
-  command = meta_prefs_get_command (which);
-
-  if (command == NULL)
-    {
-      char *s;
-
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                  "No command %d to run in response to keybinding press\n",
-                  which);
-      
-      s = g_strdup_printf (_("No command %d has been defined.\n"),
-                           which + 1);
-      error_on_command (which, NULL, s, screen, event->xkey.time);
-      g_free (s);
-      
-      return;
-    }
-
-  err = NULL;
-  if (!meta_spawn_command_line_async_on_screen (command, screen, &err))
-    {
-      error_on_command (which, command, err->message, screen, event->xkey.time);
-      
-      g_error_free (err);
-    }
-}
-
 
 static void
 handle_maximize_vertically (MetaDisplay    *display,
@@ -3602,44 +3470,6 @@ meta_set_keybindings_disabled (gboolean setting)
               "Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
 }
 
-static void
-handle_run_terminal (MetaDisplay    *display,
-                     MetaScreen     *screen,
-                     MetaWindow     *window,
-                     XEvent         *event,
-                     MetaKeyBinding *binding,
-                     gpointer        dummy)
-{
-  const char *command;
-  GError *err;
-  
-  command = meta_prefs_get_terminal_command ();
-
-  if (command == NULL)
-    {
-      char *s;
-
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                  "No terminal command to run in response to "
-		  "keybinding press\n");
-      
-      s = g_strdup_printf (_("No terminal command has been defined.\n"));
-      error_on_command (-1, NULL, s, screen, event->xkey.time);
-      g_free (s);
-      
-      return;
-    }
-
-  err = NULL;
-  if (!meta_spawn_command_line_async_on_screen (command, screen, &err))
-    {
-      error_on_command (-1, command, err->message, screen,
-                        event->xkey.time);
-      
-      g_error_free (err);
-    }
-}
-
 gboolean
 meta_keybindings_set_custom_handler (const gchar        *name,
                                      MetaKeyHandlerFunc  handler,
diff --git a/src/core/prefs.c b/src/core/prefs.c
index 328c17d..8669df5 100644
--- a/src/core/prefs.c
+++ b/src/core/prefs.c
@@ -6,7 +6,8 @@
  * Copyright (C) 2001 Havoc Pennington, Copyright (C) 2002 Red Hat Inc.
  * Copyright (C) 2006 Elijah Newren
  * Copyright (C) 2008 Thomas Thurman
- * 
+ * Copyright (C) 2010 Milan Bouchet-Valat, Copyright (C) 2011 Red Hat Inc.
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -28,74 +29,65 @@
 #include "ui.h"
 #include <meta/util.h>
 #include "meta-plugin-manager.h"
-#ifdef HAVE_GCONF
-#include <gconf/gconf-client.h>
-#endif
+#include <glib.h>
+#include <gio/gio.h>
 #include <string.h>
 #include <stdlib.h>
 
-#define MAX_REASONABLE_WORKSPACES 36
-
-#define MAX_COMMANDS (32 + NUM_EXTRA_COMMANDS)
-#define NUM_EXTRA_COMMANDS 2
-#define SCREENSHOT_COMMAND_IDX (MAX_COMMANDS - 2)
-#define WIN_SCREENSHOT_COMMAND_IDX (MAX_COMMANDS - 1)
-
-/* If you add a key, it needs updating in init() and in the gconf
+/* If you add a key, it needs updating in init() and in the gsettings
  * notify listener and of course in the .schemas file.
  *
  * Keys which are handled by one of the unified handlers below are
  * not given a name here, because the purpose of the unified handlers
  * is that keys should be referred to exactly once.
  */
-#define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font"
-#define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces"
-#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
-
-#define KEY_COMMAND_DIRECTORY "/apps/metacity/keybinding_commands"
-#define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
+#define KEY_TITLEBAR_FONT "titlebar-font"
+#define KEY_NUM_WORKSPACES "num-workspaces"
+#define KEY_WORKSPACE_NAMES "workspace-names"
 
-#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
-#define KEY_TERMINAL_COMMAND KEY_TERMINAL_DIR "/exec"
+/* Keys from "foreign" schemas */
+#define KEY_GNOME_ACCESSIBILITY "toolkit-accessibility"
+#define KEY_GNOME_ANIMATIONS "enable-animations"
+#define KEY_GNOME_CURSOR_THEME "cursor-theme"
+#define KEY_GNOME_CURSOR_SIZE "cursor-size"
 
-#define KEY_OVERLAY_KEY "/apps/mutter/general/overlay_key"
-#define KEY_SCREEN_BINDINGS_PREFIX "/apps/metacity/global_keybindings"
-#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
-#define KEY_LIST_BINDINGS_SUFFIX "_list"
+#define KEY_OVERLAY_KEY "overlay-key"
+#define KEY_LIVE_HIDDEN_WINDOWS "live-hidden-windows"
+#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
+#define KEY_NO_TAB_POPUP "no-tab-popup"
 
-#define KEY_WORKSPACE_NAME_DIRECTORY "/apps/metacity/workspace_names"
-#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
+/* These are the different schemas we are keeping
+ * a GSettings instance for */
+#define SCHEMA_GENERAL         "org.gnome.desktop.wm.preferences"
+#define SCHEMA_MUTTER          "org.gnome.mutter"
+#define SCHEMA_INTERFACE       "org.gnome.desktop.interface"
 
-#define KEY_LIVE_HIDDEN_WINDOWS "/apps/mutter/general/live_hidden_windows"
-#define KEY_WORKSPACES_ONLY_ON_PRIMARY "/apps/mutter/general/workspaces_only_on_primary"
-#define KEY_DRAGGABLE_BORDER_WIDTH "/apps/mutter/general/draggable_border_width"
+#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
+#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
 
-#define KEY_NO_TAB_POPUP "/apps/metacity/general/no_tab_popup"
+#define SETTINGS(s) g_hash_table_lookup (settings_schemas, (s))
 
-#ifdef HAVE_GCONF
-static GConfClient *default_client = NULL;
 static GList *changes = NULL;
 static guint changed_idle;
 static GList *listeners = NULL;
-#endif
+static GHashTable *settings_schemas;
 
 static gboolean use_system_font = FALSE;
 static PangoFontDescription *titlebar_font = NULL;
 static MetaVirtualModifier mouse_button_mods = Mod1Mask;
-static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
-static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART;
+static GDesktopFocusMode focus_mode = G_DESKTOP_FOCUS_MODE_CLICK;
+static GDesktopFocusNewWindows focus_new_windows = G_DESKTOP_FOCUS_NEW_WINDOWS_SMART;
 static gboolean raise_on_click = TRUE;
 static gboolean attach_modal_dialogs = FALSE;
 static char* current_theme = NULL;
 static int num_workspaces = 4;
-static MetaActionTitlebar action_double_click_titlebar = META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE;
-static MetaActionTitlebar action_middle_click_titlebar = META_ACTION_TITLEBAR_LOWER;
-static MetaActionTitlebar action_right_click_titlebar = META_ACTION_TITLEBAR_MENU;
+static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE;
+static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER;
+static GDesktopTitlebarAction action_right_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_MENU;
 static gboolean application_based = FALSE;
 static gboolean disable_workarounds = FALSE;
 static gboolean auto_raise = FALSE;
 static gboolean auto_raise_delay = 500;
-static gboolean provide_visual_bell = FALSE;
 static gboolean bell_is_audible = TRUE;
 static gboolean gnome_accessibility = FALSE;
 static gboolean gnome_animations = TRUE;
@@ -106,84 +98,47 @@ static gboolean resize_with_right_button = FALSE;
 static gboolean edge_tiling = FALSE;
 static gboolean force_fullscreen = TRUE;
 
-static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
+static GDesktopVisualBellType visual_bell_type = G_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH;
 static MetaButtonLayout button_layout;
 
-/* The screenshot commands are at the end */
-static char *commands[MAX_COMMANDS] = { NULL, };
-
-static char *terminal_command = NULL;
-
-static char *workspace_names[MAX_REASONABLE_WORKSPACES] = { NULL, };
+/* NULL-terminated array */
+static char **workspace_names = NULL;
 
 static gboolean live_hidden_windows = FALSE;
 static gboolean workspaces_only_on_primary = FALSE;
 
 static gboolean no_tab_popup = FALSE;
 
-#ifdef HAVE_GCONF
-static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
 
-static char *binding_name (const char *gconf_key);
+static void handle_preference_update_enum (GSettings *settings,
+                                           gchar     *key);
+static gboolean update_binding         (MetaKeyPref *binding,
+                                        gchar      **strokes);
+static gboolean update_key_binding     (const char  *key,
+                                        gchar      **strokes);
+static gboolean update_workspace_names (void);
 
-static gboolean update_key_binding     (const char *key,
-                                        const char *value);
-typedef enum
-  {
-    META_LIST_OF_STRINGS,
-    META_LIST_OF_GCONFVALUE_STRINGS
-  } MetaStringListType;
-
-static gboolean find_and_update_list_binding (MetaKeyPref       *bindings,
-                                              const char        *key,
-                                              GSList            *value,
-                                              MetaStringListType type_of_value);
-static gboolean update_key_list_binding (const char         *key,
-                                         GSList             *value,
-                                         MetaStringListType  type_of_value);
-static gboolean update_command            (const char  *name,
-                                           const char  *value);
-static gboolean update_workspace_name     (const char  *name,
-                                           const char  *value);
-
-static void notify_new_value (const char *key,
-                              GConfValue *value);
-static void change_notify (GConfClient    *client,
-                           guint           cnxn_id,
-                           GConfEntry     *entry,
-                           gpointer        user_data);
-
-static char* gconf_key_for_workspace_name (int i);
+static void settings_changed (GSettings      *settings,
+                              gchar          *key,
+                              gpointer        data);
+static void bindings_changed (GSettings      *settings,
+                              gchar          *key,
+                              gpointer        data);
 
 static void queue_changed (MetaPreference  pref);
 
-static gboolean update_list_binding       (MetaKeyPref       *binding,
-                                           GSList            *value,
-                                           MetaStringListType type_of_value);
-
-static void     cleanup_error             (GError **error);
-static gboolean get_bool                  (const char *key, gboolean *val);
 static void maybe_give_disable_workarounds_warning (void);
 
-static void titlebar_handler (MetaPreference, const gchar*, gboolean*);
-static void theme_name_handler (MetaPreference, const gchar*, gboolean*);
-static void mouse_button_mods_handler (MetaPreference, const gchar*, gboolean*);
-static void button_layout_handler (MetaPreference, const gchar*, gboolean*);
-
-#endif /* HAVE_GCONF */
+static gboolean titlebar_handler (GVariant*, gpointer*, gpointer);
+static gboolean theme_name_handler (GVariant*, gpointer*, gpointer);
+static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer);
+static gboolean button_layout_handler (GVariant*, gpointer*, gpointer);
 
-static gboolean update_binding            (MetaKeyPref *binding,
-                                           const char  *value);
+static void     do_override               (char *key, char *schema);
 
 static void     init_bindings             (void);
-static void     init_commands             (void);
 static void     init_workspace_names      (void);
 
-#ifndef HAVE_GCONF
-static void     init_button_layout        (void);
-#endif /* !HAVE_GCONF */
-
-#ifdef HAVE_GCONF
 
 typedef struct
 {
@@ -191,102 +146,46 @@ typedef struct
   gpointer data;
 } MetaPrefsListener;
 
-static GConfEnumStringPair symtab_focus_mode[] =
-  {
-    { META_FOCUS_MODE_CLICK,  "click" },
-    { META_FOCUS_MODE_SLOPPY, "sloppy" },
-    { META_FOCUS_MODE_MOUSE,  "mouse" },
-    { 0, NULL },
-  };
-
-static GConfEnumStringPair symtab_focus_new_windows[] =
-  {
-    { META_FOCUS_NEW_WINDOWS_SMART,  "smart" },
-    { META_FOCUS_NEW_WINDOWS_STRICT, "strict" },
-    { 0, NULL },
-  };
-
-static GConfEnumStringPair symtab_visual_bell_type[] =
-  {
-    /* Note to the reader: 0 is an invalid value; these start at 1. */
-    { META_VISUAL_BELL_FULLSCREEN_FLASH, "fullscreen" },
-    { META_VISUAL_BELL_FRAME_FLASH,      "frame_flash" },
-    { 0, NULL },
-  };
-
-static GConfEnumStringPair symtab_titlebar_action[] =
-  {
-    { META_ACTION_TITLEBAR_TOGGLE_SHADE,    "toggle_shade" },
-    { META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE, "toggle_maximize" },
-    { META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_HORIZONTALLY,
-                                "toggle_maximize_horizontally" },
-    { META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_VERTICALLY,
-                                "toggle_maximize_vertically" },
-    { META_ACTION_TITLEBAR_MINIMIZE,        "minimize" },
-    { META_ACTION_TITLEBAR_NONE,            "none" },
-    { META_ACTION_TITLEBAR_LOWER,           "lower" },
-    { META_ACTION_TITLEBAR_MENU,            "menu" },
-    { META_ACTION_TITLEBAR_TOGGLE_SHADE,    "toggle_shade" },
-    { 0, NULL },
-  };
-
-/*
- * Note that 'gchar *key' is the first element of all these structures;
- * we count on that below in key_is_used and do_override.
- */
-
-/*
- * The details of one preference which is constrained to be
- * one of a small number of string values-- in other words,
- * an enumeration.
- *
- * We could have done this other ways.  One particularly attractive
- * possibility would have been to represent the entire symbol table
- * as a space-separated string literal in the list of symtabs, so
- * the focus mode enums could have been represented simply by
- * "click sloppy mouse".  However, the simplicity gained would have
- * been outweighed by the bugs caused when the ordering of the enum
- * strings got out of sync with the actual enum statement.  Also,
- * there is existing library code to use this kind of symbol tables.
- */
 typedef struct
 {
-  gchar *key;
+  char *key;
+  char *schema;
   MetaPreference pref;
-  GConfEnumStringPair *symtab;
+} MetaBasePreference;
+
+typedef struct
+{
+  MetaBasePreference base;
   gpointer target;
 } MetaEnumPreference;
 
 typedef struct
 {
-  gchar *key;
-  MetaPreference pref;
+  MetaBasePreference base;
   gboolean *target;
-  gboolean becomes_true_on_destruction;
 } MetaBoolPreference;
 
 typedef struct
 {
-  gchar *key;
-  MetaPreference pref;
+  MetaBasePreference base;
 
   /**
    * A handler.  Many of the string preferences aren't stored as
    * strings and need parsing; others of them have default values
    * which can't be solved in the general case.  If you include a
-   * function pointer here, it will be called before the string
-   * value is written out to the target variable.
+   * function pointer here, it will be called instead of writing
+   * the string value out to the target variable.
    *
-   * The function is passed two arguments: the preference, and
-   * the new string as a gchar*.  It returns a gboolean;
-   * only if this is true, the listeners will be informed that
-   * the preference has changed.
+   * The function will be passed to g_settings_get_mapped() and should
+   * return %TRUE if the mapping was successful and %FALSE otherwise.
+   * In the former case the function is expected to handle the result
+   * of the conversion itself and call queue_changed() appropriately;
+   * in particular the @result (out) parameter as returned by
+   * g_settings_get_mapped() will be ignored in all cases.
    *
    * This may be NULL.  If it is, see "target", below.
    */
-  void (*handler) (MetaPreference pref,
-                     const gchar *string_value,
-                     gboolean *inform_listeners);
+  GSettingsGetMapping handler;
 
   /**
    * Where to write the incoming string.
@@ -298,221 +197,259 @@ typedef struct
 
 } MetaStringPreference;
 
-#define METAINTPREFERENCE_NO_CHANGE_ON_DESTROY G_MININT
-
 typedef struct
 {
-  gchar *key;
-  MetaPreference pref;
+  MetaBasePreference base;
   gint *target;
-  /**
-   * Minimum and maximum values of the integer.
-   * If the new value is out of bounds, it will be discarded with a warning.
-   */
-  gint minimum, maximum;
-  /**
-   * Value to use if the key is destroyed.
-   * If this is METAINTPREFERENCE_NO_CHANGE_ON_DESTROY, it will
-   * not be changed when the key is destroyed.
-   */
-  gint value_if_destroyed;
 } MetaIntPreference;
 
+
+/* All preferences that are not keybindings must be listed here,
+ * plus in the GSettings schemas and the MetaPreference enum.
+ */
+
 /* FIXMEs: */
 /* @@@ Don't use NULL lines at the end; glib can tell you how big it is */
-/* @@@ /apps/mutter/general should be assumed if first char is not / */
-/* @@@ Will it ever be possible to merge init and update? If not, why not? */
 
 static MetaEnumPreference preferences_enum[] =
   {
-    { "/apps/metacity/general/focus_new_windows",
-      META_PREF_FOCUS_NEW_WINDOWS,
-      symtab_focus_new_windows,
+    {
+      { "focus-new-windows",
+        SCHEMA_GENERAL,
+        META_PREF_FOCUS_NEW_WINDOWS,
+      },
       &focus_new_windows,
     },
-    { "/apps/metacity/general/focus_mode",
-      META_PREF_FOCUS_MODE,
-      symtab_focus_mode,
+    {
+      { "focus-mode",
+        SCHEMA_GENERAL,
+        META_PREF_FOCUS_MODE,
+      },
       &focus_mode,
     },
-    { "/apps/metacity/general/visual_bell_type",
-      META_PREF_VISUAL_BELL_TYPE,
-      symtab_visual_bell_type,
+    {
+      { "visual-bell-type",
+        SCHEMA_GENERAL,
+        META_PREF_VISUAL_BELL_TYPE,
+      },
       &visual_bell_type,
     },
-    { "/apps/metacity/general/action_double_click_titlebar",
-      META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
-      symtab_titlebar_action,
+    {
+      { "action-double-click-titlebar",
+        SCHEMA_GENERAL,
+        META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
+      },
       &action_double_click_titlebar,
     },
-    { "/apps/metacity/general/action_middle_click_titlebar",
-      META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
-      symtab_titlebar_action,
+    {
+      { "action-middle-click-titlebar",
+        SCHEMA_GENERAL,
+        META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
+      },
       &action_middle_click_titlebar,
     },
-    { "/apps/metacity/general/action_right_click_titlebar",
-      META_PREF_ACTION_RIGHT_CLICK_TITLEBAR,
-      symtab_titlebar_action,
+    {
+      { "action-right-click-titlebar",
+        SCHEMA_GENERAL,
+        META_PREF_ACTION_RIGHT_CLICK_TITLEBAR,
+      },
       &action_right_click_titlebar,
     },
-    { NULL, 0, NULL, NULL },
+    { { NULL, 0, 0 }, NULL },
   };
 
 static MetaBoolPreference preferences_bool[] =
   {
-    { "/apps/mutter/general/attach_modal_dialogs",
-      META_PREF_ATTACH_MODAL_DIALOGS,
+    {
+      { "attach-modal-dialogs",
+        SCHEMA_MUTTER,
+        META_PREF_ATTACH_MODAL_DIALOGS,
+      },
       &attach_modal_dialogs,
-      TRUE,
     },
-    { "/apps/metacity/general/raise_on_click",
-      META_PREF_RAISE_ON_CLICK,
+    {
+      { "raise-on-click",
+        SCHEMA_GENERAL,
+        META_PREF_RAISE_ON_CLICK,
+      },
       &raise_on_click,
-      TRUE,
     },
-    { "/apps/metacity/general/titlebar_uses_system_font",
-      META_PREF_TITLEBAR_FONT, /* note! shares a pref */
+    {
+      { "titlebar-uses-system-font",
+        SCHEMA_GENERAL,
+        META_PREF_TITLEBAR_FONT, /* note! shares a pref */
+      },
       &use_system_font,
-      TRUE,
     },
-    { "/apps/metacity/general/application_based",
-      META_PREF_APPLICATION_BASED,
+    {
+      { "application-based",
+        SCHEMA_GENERAL,
+        META_PREF_APPLICATION_BASED,
+      },
       NULL, /* feature is known but disabled */
-      FALSE,
     },
-    { "/apps/metacity/general/disable_workarounds",
-      META_PREF_DISABLE_WORKAROUNDS,
+    {
+      { "disable-workarounds",
+        SCHEMA_GENERAL,
+        META_PREF_DISABLE_WORKAROUNDS,
+      },
       &disable_workarounds,
-      FALSE,
     },
-    { "/apps/metacity/general/auto_raise",
-      META_PREF_AUTO_RAISE,
+    {
+      { "auto-raise",
+        SCHEMA_GENERAL,
+        META_PREF_AUTO_RAISE,
+      },
       &auto_raise,
-      FALSE,
     },
-    { "/apps/metacity/general/visual_bell",
-      META_PREF_VISUAL_BELL,
-      &provide_visual_bell, /* FIXME: change the name: it's confusing */
-      FALSE,
-    },
-    { "/apps/metacity/general/audible_bell",
-      META_PREF_AUDIBLE_BELL,
+    {
+      { "audible-bell",
+        SCHEMA_GENERAL,
+        META_PREF_AUDIBLE_BELL,
+      },
       &bell_is_audible, /* FIXME: change the name: it's confusing */
-      FALSE,
     },
-    { "/desktop/gnome/interface/accessibility",
-      META_PREF_GNOME_ACCESSIBILITY,
+    {
+      { KEY_GNOME_ACCESSIBILITY,
+        SCHEMA_INTERFACE,
+        META_PREF_GNOME_ACCESSIBILITY,
+      },
       &gnome_accessibility,
-      FALSE,
     },
-    { "/desktop/gnome/interface/enable_animations",
-      META_PREF_GNOME_ANIMATIONS,
+    {
+      { KEY_GNOME_ANIMATIONS,
+        SCHEMA_INTERFACE,
+        META_PREF_GNOME_ANIMATIONS,
+      },
       &gnome_animations,
-      TRUE,
     },
-    { "/apps/metacity/general/resize_with_right_button",
-      META_PREF_RESIZE_WITH_RIGHT_BUTTON,
+    {
+      { "resize-with-right-button",
+        SCHEMA_GENERAL,
+        META_PREF_RESIZE_WITH_RIGHT_BUTTON,
+      },
       &resize_with_right_button,
-      FALSE,
     },
-    { "/apps/metacity/general/edge_tiling",
-      META_PREF_EDGE_TILING,
+    {
+      { "edge-tiling",
+        SCHEMA_MUTTER,
+        META_PREF_EDGE_TILING,
+      },
       &edge_tiling,
-      FALSE,
     },
-    { "/apps/mutter/general/live_hidden_windows",
-      META_PREF_LIVE_HIDDEN_WINDOWS,
+    {
+      { KEY_LIVE_HIDDEN_WINDOWS,
+        SCHEMA_MUTTER,
+        META_PREF_LIVE_HIDDEN_WINDOWS,
+      },
       &live_hidden_windows,
-      FALSE,
     },
-    { "/apps/mutter/general/workspaces_only_on_primary",
-      META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
+    {
+      { "workspaces-only-on-primary",
+        SCHEMA_MUTTER,
+        META_PREF_WORKSPACES_ONLY_ON_PRIMARY,
+      },
       &workspaces_only_on_primary,
-      FALSE,
     },
-    { "/apps/metacity/general/no_tab_popup",
-      META_PREF_NO_TAB_POPUP,
+    {
+      { KEY_NO_TAB_POPUP,
+        SCHEMA_MUTTER,
+        META_PREF_NO_TAB_POPUP,
+      },
       &no_tab_popup,
-      FALSE,
     },
-    { NULL, 0, NULL, FALSE },
+    { { NULL, 0, 0 }, NULL },
   };
 
 static MetaStringPreference preferences_string[] =
   {
-    { "/apps/metacity/general/mouse_button_modifier",
-      META_PREF_MOUSE_BUTTON_MODS,
+    {
+      { "mouse-button-modifier",
+        SCHEMA_GENERAL,
+        META_PREF_MOUSE_BUTTON_MODS,
+      },
       mouse_button_mods_handler,
       NULL,
     },
-    { "/apps/metacity/general/theme",
-      META_PREF_THEME,
+    {
+      { "theme",
+        SCHEMA_GENERAL,
+        META_PREF_THEME,
+      },
       theme_name_handler,
       NULL,
     },
-    { KEY_TITLEBAR_FONT,
-      META_PREF_TITLEBAR_FONT,
+    {
+      { KEY_TITLEBAR_FONT,
+        SCHEMA_GENERAL,
+        META_PREF_TITLEBAR_FONT,
+      },
       titlebar_handler,
       NULL,
     },
-    { KEY_TERMINAL_COMMAND,
-      META_PREF_TERMINAL_COMMAND,
-      NULL,
-      &terminal_command,
-    },
-    { "/apps/metacity/general/button_layout",
-      META_PREF_BUTTON_LAYOUT,
+    {
+      { "button-layout",
+        SCHEMA_GENERAL,
+        META_PREF_BUTTON_LAYOUT,
+      },
       button_layout_handler,
       NULL,
     },
-    { "/desktop/gnome/peripherals/mouse/cursor_theme",
-      META_PREF_CURSOR_THEME,
+    {
+      { "cursor-theme",
+        SCHEMA_INTERFACE,
+        META_PREF_CURSOR_THEME,
+      },
       NULL,
       &cursor_theme,
     },
-    { NULL, 0, NULL, NULL },
+    { { NULL, 0, 0 }, NULL },
   };
 
 static MetaIntPreference preferences_int[] =
   {
-    { "/apps/metacity/general/num_workspaces",
-      META_PREF_NUM_WORKSPACES,
-      &num_workspaces,
-      /* I would actually recommend we change the destroy value to 4
-       * and get rid of METAINTPREFERENCE_NO_CHANGE_ON_DESTROY entirely.
-       *  -- tthurman
-       */
-      1, MAX_REASONABLE_WORKSPACES, METAINTPREFERENCE_NO_CHANGE_ON_DESTROY,
+    {
+      { KEY_NUM_WORKSPACES,
+        SCHEMA_GENERAL,
+        META_PREF_NUM_WORKSPACES,
+      },
+      &num_workspaces
     },
-    { "/apps/metacity/general/auto_raise_delay",
-      META_PREF_AUTO_RAISE_DELAY,
-      &auto_raise_delay,
-      0, 10000, 0,
-      /* @@@ Get rid of MAX_REASONABLE_AUTO_RAISE_DELAY */
+    {
+      { "auto-raise-delay",
+        SCHEMA_GENERAL,
+        META_PREF_AUTO_RAISE_DELAY,
+      },
+      &auto_raise_delay
     },
-    { "/desktop/gnome/peripherals/mouse/cursor_size",
-      META_PREF_CURSOR_SIZE,
-      &cursor_size,
-      1, 128, 24,
+    {
+      { "cursor-size",
+        SCHEMA_INTERFACE,
+        META_PREF_CURSOR_SIZE,
+      },
+      &cursor_size
     },
-    { "/apps/mutter/general/draggable_border_width",
-      META_PREF_DRAGGABLE_BORDER_WIDTH,
-      &draggable_border_width,
-      0, 64, 10,
+    {
+      { "draggable-border-width",
+        SCHEMA_MUTTER,
+        META_PREF_DRAGGABLE_BORDER_WIDTH,
+      },
+      &draggable_border_width
     },
-    { NULL, 0, NULL, 0, 0, 0, },
+    { { NULL, 0, 0 }, NULL },
   };
 
 /*
- * This is used to keep track of preferences that have been
- * repointed to a different GConf key location; we modify the
- * preferences arrays directly, but we also need to remember
- * what we have done to handle subsequent overrides correctly.
+ * This is used to keep track of override schemas used to
+ * override preferences from the "normal" metacity/mutter
+ * schemas; we modify the preferences arrays directly, but
+ * we also need to remember what we have done to handle
+ * subsequent overrides correctly.
  */
 typedef struct
 {
-  gchar *original_key;
-  gchar *new_key;
+  char *key;
+  char *new_schema;
 } MetaPrefsOverriddenKey;
 
 static GSList *overridden_keys;
@@ -522,35 +459,13 @@ handle_preference_init_enum (void)
 {
   MetaEnumPreference *cursor = preferences_enum;
 
-  while (cursor->key!=NULL)
+  while (cursor->base.key != NULL)
     {
-      char *value;
-      GError *error = NULL;
-
       if (cursor->target==NULL)
-        {
-          ++cursor;
-          continue;
-        }
-
-      value = gconf_client_get_string (default_client,
-                                       cursor->key,
-                                       &error);
-      cleanup_error (&error);
-
-      if (value==NULL)
-        {
-          ++cursor;
-          continue;
-        }
+        continue;
 
-      if (!gconf_string_to_enum (cursor->symtab,
-                                 value,
-                                 (gint *) cursor->target))
-        meta_warning (_("GConf key '%s' is set to an invalid value\n"),
-                      cursor->key);
-
-      g_free (value);
+      *((gint *) cursor->target) =
+        g_settings_get_enum (SETTINGS (cursor->base.schema), cursor->base.key);
 
       ++cursor;
     }
@@ -561,10 +476,12 @@ handle_preference_init_bool (void)
 {
   MetaBoolPreference *cursor = preferences_bool;
 
-  while (cursor->key!=NULL)
+  while (cursor->base.key != NULL)
     {
       if (cursor->target!=NULL)
-        get_bool (cursor->key, cursor->target);
+        *cursor->target =
+          g_settings_get_boolean (SETTINGS (cursor->base.schema),
+                                  cursor->base.key);
 
       ++cursor;
     }
@@ -577,38 +494,30 @@ handle_preference_init_string (void)
 {
   MetaStringPreference *cursor = preferences_string;
 
-  while (cursor->key!=NULL)
+  while (cursor->base.key != NULL)
     {
       char *value;
-      GError *error = NULL;
-      gboolean dummy = TRUE;
-
-      /* the string "value" will be newly allocated */
-      value = gconf_client_get_string (default_client,
-                                       cursor->key,
-                                       &error);
-
-      if (error || !value)
-        {
-          cleanup_error (&error);
-          ++cursor;
-          continue;
-        }
 
+      /* Complex keys have a mapping function to check validity */
       if (cursor->handler)
         {
           if (cursor->target)
-            meta_bug ("%s has both a target and a handler\n", cursor->key);
+            meta_bug ("%s has both a target and a handler\n", cursor->base.key);
 
-          cursor->handler (cursor->pref, value, &dummy);
-
-          g_free (value);
+          g_settings_get_mapped (SETTINGS (cursor->base.schema),
+                                 cursor->base.key, cursor->handler, NULL);
         }
-      else if (cursor->target)
+      else
         {
+          if (!cursor->target)
+            meta_bug ("%s must have handler or target\n", cursor->base.key);
+
           if (*(cursor->target))
             g_free (*(cursor->target));
 
+          value = g_settings_get_string (SETTINGS (cursor->base.schema),
+                                         cursor->base.key);
+
           *(cursor->target) = value;
         }
 
@@ -622,277 +531,140 @@ handle_preference_init_int (void)
   MetaIntPreference *cursor = preferences_int;
 
   
-  while (cursor->key!=NULL)
+  while (cursor->base.key != NULL)
     {
-      gint value;
-      GError *error = NULL;
-
-      value = gconf_client_get_int (default_client,
-                                    cursor->key,
-                                    &error);
-      cleanup_error (&error);
-
-      if (value < cursor->minimum || value > cursor->maximum)
-        {
-          meta_warning (_("%d stored in GConf key %s is out of range %d to %d\n"),
-                        value, cursor->key,  cursor->minimum, cursor->maximum);
-          /* Former behaviour for out-of-range values was:
-           *   - number of workspaces was clamped;
-           *   - auto raise delay was always reset to zero even if too high!;
-           *   - cursor size was ignored.
-           *
-           * These seem to be meaningless variations.  If they did
-           * have meaning we could have put them into MetaIntPreference.
-           * The last of these is the closest to how we behave for
-           * other types, so I think we should standardise on that.
-           */
-        }
-      else if (cursor->target)
-        *cursor->target = value;
+      if (cursor->target)
+        *cursor->target = g_settings_get_int (SETTINGS (cursor->base.schema),
+                                              cursor->base.key);
 
       ++cursor;
     }
 }
 
-static gboolean
-handle_preference_update_enum (const gchar *key, GConfValue *value)
+static void
+handle_preference_update_enum (GSettings *settings,
+                               gchar *key)
 {
   MetaEnumPreference *cursor = preferences_enum;
   gint old_value;
 
-  while (cursor->key!=NULL && strcmp (key, cursor->key)!=0)
+  while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
     ++cursor;
 
-  if (cursor->key==NULL)
+  if (cursor->base.key == NULL)
     /* Didn't recognise that key. */
-    return FALSE;
-      
-  /* Setting it to null (that is, removing it) always means
-   * "don't change".
-   */
-
-  if (value==NULL)
-    return TRUE;
-
-  /* Check the type.  Enums are always strings. */
-
-  if (value->type != GCONF_VALUE_STRING)
-    {
-      meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                    key);
-      /* But we did recognise it. */
-      return TRUE;
-    }
+    return;
 
   /* We need to know whether the value changes, so
    * store the current value away.
    */
 
-  old_value = * ((gint *) cursor->target);
-  
-  /* Now look it up... */
-
-  if (!gconf_string_to_enum (cursor->symtab,
-                             gconf_value_get_string (value),
-                             (gint *) cursor->target))
-    {
-      /*
-       * We found it, but it was invalid.  Complain.
-       *
-       * FIXME: This replicates the original behaviour, but in the future
-       * we might consider reverting invalid keys to their original values.
-       * (We know the old value, so we can look up a suitable string in
-       * the symtab.)
-       *
-       * (Empty comment follows so the translators don't see this.)
-       */
-
-      /*  */      
-      meta_warning (_("GConf key '%s' is set to an invalid value\n"),
-                    key);
-      return TRUE;
-    }
+  old_value = * ((gint *)cursor->target);
+  *((gint *)cursor->target) =
+    g_settings_get_enum (SETTINGS (cursor->base.schema), key);
 
   /* Did it change?  If so, tell the listeners about it. */
-
-  if (old_value != *((gint *) cursor->target))
-    queue_changed (cursor->pref);
-
-  return TRUE;
+  if (old_value != *((gint *)cursor->target))
+    queue_changed (cursor->base.pref);
 }
 
-static gboolean
-handle_preference_update_bool (const gchar *key, GConfValue *value)
+static void
+handle_preference_update_bool (GSettings *settings,
+                               gchar *key)
 {
   MetaBoolPreference *cursor = preferences_bool;
   gboolean old_value;
 
-  while (cursor->key!=NULL && strcmp (key, cursor->key)!=0)
+  while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
     ++cursor;
 
-  if (cursor->key==NULL)
-    /* Didn't recognise that key. */
-    return FALSE;
-
-  if (cursor->target==NULL)
-    /* No work for us to do. */
-    return TRUE;
-      
-  if (value==NULL)
-    {
-      /* Value was destroyed; let's get out of here. */
-
-      if (cursor->becomes_true_on_destruction)
-        /* This preserves the behaviour of the old system, but
-         * for all I know that might have been an oversight.
-         */
-        *((gboolean *)cursor->target) = TRUE;
-
-      return TRUE;
-    }
-
-  /* Check the type. */
-
-  if (value->type != GCONF_VALUE_BOOL)
-    {
-      meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                    key);
-      /* But we did recognise it. */
-      return TRUE;
-    }
+  if (cursor->base.key == NULL || cursor->target == NULL)
+    /* Unknown key or no work for us to do. */
+    return;
 
   /* We need to know whether the value changes, so
    * store the current value away.
    */
-
-  old_value = * ((gboolean *) cursor->target);
+  old_value = *((gboolean *) cursor->target);
   
   /* Now look it up... */
-
-  *((gboolean *) cursor->target) = gconf_value_get_bool (value);
+  *((gboolean *) cursor->target) =
+    g_settings_get_boolean (SETTINGS (cursor->base.schema), key);
 
   /* Did it change?  If so, tell the listeners about it. */
+  if (old_value != *((gboolean *)cursor->target))
+    queue_changed (cursor->base.pref);
 
-  if (old_value != *((gboolean *) cursor->target))
-    queue_changed (cursor->pref);
-
-  if (cursor->pref==META_PREF_DISABLE_WORKAROUNDS)
+  if (cursor->base.pref==META_PREF_DISABLE_WORKAROUNDS)
     maybe_give_disable_workarounds_warning ();
-
-  return TRUE;
 }
 
-static gboolean
-handle_preference_update_string (const gchar *key, GConfValue *value)
+static void
+handle_preference_update_string (GSettings *settings,
+                                 gchar *key)
 {
   MetaStringPreference *cursor = preferences_string;
-  const gchar *value_as_string;
-  gboolean inform_listeners = TRUE;
+  char *value;
+  gboolean inform_listeners = FALSE;
 
-  while (cursor->key!=NULL && strcmp (key, cursor->key)!=0)
+  while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
     ++cursor;
 
-  if (cursor->key==NULL)
+  if (cursor->base.key==NULL)
     /* Didn't recognise that key. */
-    return FALSE;
-
-  if (value==NULL)
-    return TRUE;
-
-  /* Check the type. */
+    return;
 
-  if (value->type != GCONF_VALUE_STRING)
+  /* Complex keys have a mapping function to check validity */
+  if (cursor->handler)
     {
-      meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                    key);
-      /* But we did recognise it. */
-      return TRUE;
+      if (cursor->target)
+        meta_bug ("%s has both a target and a handler\n", cursor->base.key);
+
+      g_settings_get_mapped (SETTINGS (cursor->base.schema),
+                             cursor->base.key, cursor->handler, NULL);
     }
+  else
+    {
+      if (!cursor->target)
+        meta_bug ("%s must have handler or target\n", cursor->base.key);
 
-  /* Docs: "The returned string is not a copy, don't try to free it." */
-  value_as_string = gconf_value_get_string (value);
+      value = g_settings_get_string (SETTINGS (cursor->base.schema),
+                                     cursor->base.key);
+
+      inform_listeners = (g_strcmp0 (value, *(cursor->target)) != 0);
 
-  if (cursor->handler)
-    cursor->handler (cursor->pref, value_as_string, &inform_listeners);
-  else if (cursor->target)
-    {
       if (*(cursor->target))
         g_free(*(cursor->target));
 
-      if (value_as_string!=NULL)
-        *(cursor->target) = g_strdup (value_as_string);
-      else
-        *(cursor->target) = NULL;
-
-      inform_listeners =
-        (value_as_string==NULL && *(cursor->target)==NULL) ||
-        (value_as_string!=NULL && *(cursor->target)!=NULL &&
-         strcmp (value_as_string, *(cursor->target))==0);
+      *(cursor->target) = value;
     }
 
   if (inform_listeners)
-    queue_changed (cursor->pref);
-
-  return TRUE;
+    queue_changed (cursor->base.pref);
 }
 
-static gboolean
-handle_preference_update_int (const gchar *key, GConfValue *value)
+static void
+handle_preference_update_int (GSettings *settings,
+                              gchar *key)
 {
   MetaIntPreference *cursor = preferences_int;
   gint new_value;
 
-  while (cursor->key!=NULL && strcmp (key, cursor->key)!=0)
+  while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
     ++cursor;
 
-  if (cursor->key==NULL)
-    /* Didn't recognise that key. */
-    return FALSE;
-
-  if (cursor->target==NULL)
-    /* No work for us to do. */
-    return TRUE;
-      
-  if (value==NULL)
-    {
-      /* Value was destroyed. */
-
-      if (cursor->value_if_destroyed != METAINTPREFERENCE_NO_CHANGE_ON_DESTROY)
-        *((gint *)cursor->target) = cursor->value_if_destroyed;
-
-      return TRUE;
-    }
-
-  /* Check the type. */
-
-  if (value->type != GCONF_VALUE_INT)
-    {
-      meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                    key);
-      /* But we did recognise it. */
-      return TRUE;
-    }
-
-  new_value = gconf_value_get_int (value);
+  if (cursor->base.key == NULL || cursor->target == NULL)
+    /* Unknown key or no work for us to do. */
+    return;
 
-  if (new_value < cursor->minimum || new_value > cursor->maximum)
-    {
-      meta_warning (_("%d stored in GConf key %s is out of range %d to %d\n"),
-                    new_value, cursor->key,
-                    cursor->minimum, cursor->maximum);
-      return TRUE;
-    }
+  new_value = g_settings_get_int (SETTINGS (cursor->base.schema), key);
 
   /* Did it change?  If so, tell the listeners about it. */
-
   if (*cursor->target != new_value)
     {
       *cursor->target = new_value;
-      queue_changed (cursor->pref);
+      queue_changed (cursor->base.pref);
     }
-
-  return TRUE;
-  
 }
 
 
@@ -1012,70 +784,61 @@ queue_changed (MetaPreference pref)
     meta_topic (META_DEBUG_PREFS, "Change of pref %s was already pending\n",
                 meta_preference_to_string (pref));
 
-  /* add idle at priority below the gconf notify idle */
   if (changed_idle == 0)
     changed_idle = g_idle_add_full (META_PRIORITY_PREFS_NOTIFY,
                                     changed_idle_handler, NULL, NULL);
 }
 
-#else /* HAVE_GCONF */
-
-void
-meta_prefs_add_listener (MetaPrefsChangedFunc func,
-                         gpointer             data)
-{
-  /* Nothing, because they have gconf turned off */
-}
-
-void
-meta_prefs_remove_listener (MetaPrefsChangedFunc func,
-                            gpointer             data)
-{
-  /* Nothing, because they have gconf turned off */
-}
-
-#endif /* HAVE_GCONF */
-
 
 /****************************************************************************/
 /* Initialisation.                                                          */
 /****************************************************************************/
 
-#ifdef HAVE_GCONF
-/* @@@ again, use glib's ability to tell you the size of the array */
-static gchar *gconf_dirs_we_are_interested_in[] = {
-  "/apps/metacity",
-  "/apps/mutter",
-  KEY_TERMINAL_DIR,
-  KEY_GNOME_ACCESSIBILITY,
-  "/desktop/gnome/peripherals/mouse",
-  "/desktop/gnome/interface",
-  NULL,
-};
-#endif
-
 void
 meta_prefs_init (void)
 {
-#ifdef HAVE_GCONF
-  GError *err = NULL;
-  gchar **gconf_dir_cursor;
-  
-  if (default_client != NULL)
-    return;
-  
-  /* returns a reference which we hold forever */
-  default_client = gconf_client_get_default ();
-
-  for (gconf_dir_cursor=gconf_dirs_we_are_interested_in;
-       *gconf_dir_cursor!=NULL;
-       gconf_dir_cursor++)
-    {
-      gconf_client_add_dir (default_client,
-                            *gconf_dir_cursor,
-                            GCONF_CLIENT_PRELOAD_RECURSIVE,
-                            &err);
-      cleanup_error (&err);
+  GSettings *settings;
+  GSList *tmp;
+
+  settings_schemas = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                            g_free, g_object_unref);
+
+  settings = g_settings_new (SCHEMA_GENERAL);
+  g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
+  g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_GENERAL), settings);
+
+  settings = g_settings_new (SCHEMA_MUTTER);
+  g_signal_connect (settings, "changed", G_CALLBACK (settings_changed), NULL);
+  g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_MUTTER), settings);
+
+  /* Individual keys we watch outside of our schemas */
+  settings = g_settings_new (SCHEMA_INTERFACE);
+  g_signal_connect (settings, "changed::" KEY_GNOME_ACCESSIBILITY,
+                    G_CALLBACK (settings_changed), NULL);
+  g_signal_connect (settings, "changed::" KEY_GNOME_ANIMATIONS,
+                    G_CALLBACK (settings_changed), NULL);
+  g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_THEME,
+                    G_CALLBACK (settings_changed), NULL);
+  g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_SIZE,
+                    G_CALLBACK (settings_changed), NULL);
+  g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INTERFACE), settings);
+
+  /* Bindings have a separate handler, since they are in separate schemas
+   * and work differently */
+  settings = g_settings_new (SCHEMA_COMMON_KEYBINDINGS);
+  g_signal_connect (settings, "changed", G_CALLBACK (bindings_changed), NULL);
+  g_hash_table_insert (settings_schemas,
+                       g_strdup (SCHEMA_COMMON_KEYBINDINGS), settings);
+
+  settings = g_settings_new (SCHEMA_MUTTER_KEYBINDINGS);
+  g_signal_connect (settings, "changed", G_CALLBACK (bindings_changed), NULL);
+  g_hash_table_insert (settings_schemas,
+                       g_strdup (SCHEMA_MUTTER_KEYBINDINGS), settings);
+
+  for (tmp = overridden_keys; tmp; tmp = tmp->next)
+    {
+      MetaPrefsOverriddenKey *override = tmp->data;
+      do_override (override->key, override->new_schema);
     }
 
   /* Pick up initial values. */
@@ -1085,44 +848,15 @@ meta_prefs_init (void)
   handle_preference_init_string ();
   handle_preference_init_int ();
 
-  /* @@@ Is there any reason we don't do the add_dir here? */
-  for (gconf_dir_cursor=gconf_dirs_we_are_interested_in;
-       *gconf_dir_cursor!=NULL;
-       gconf_dir_cursor++)
-    {
-      gconf_client_notify_add (default_client,
-                               *gconf_dir_cursor,
-                               change_notify,
-                               NULL,
-                               NULL,
-                               &err);
-      cleanup_error (&err);
-    }
-
-#else  /* HAVE_GCONF */
-
-  /* Set defaults for some values that can't be set at initialization time of
-   * the static globals.  In the case of the theme, note that there is code
-   * elsewhere that will do everything possible to fallback to an existing theme
-   * if the one here does not exist.
-   */
-  titlebar_font = pango_font_description_from_string ("Sans Bold 10");
-  current_theme = g_strdup ("Atlanta");
-  
-  init_button_layout();
-#endif /* HAVE_GCONF */
-  
   init_bindings ();
-  init_commands ();
   init_workspace_names ();
 }
 
-/* This count on the key being the first element of the
- * preference structure */
 static gboolean
-key_is_used (void       *prefs,
-             size_t      pref_size,
-             const char *new_key)
+find_pref (void                *prefs,
+           size_t               pref_size,
+           const char          *search_key,
+           MetaBasePreference **pref)
 {
   void *p = prefs;
 
@@ -1132,8 +866,11 @@ key_is_used (void       *prefs,
       if (*key == NULL)
         break;
 
-      if (strcmp (*key, new_key) == 0)
-        return TRUE;
+      if (strcmp (*key, search_key) == 0)
+        {
+          *pref = p;
+          return TRUE;
+        }
 
       p = (guchar *)p + pref_size;
     }
@@ -1141,52 +878,68 @@ key_is_used (void       *prefs,
   return FALSE;
 }
 
-static gboolean
-do_override (void       *prefs,
-             size_t      pref_size,
-             const char *search_key,
-             char       *new_key)
+
+static void
+do_override (char *key,
+             char *schema)
 {
-  void *p = prefs;
+  MetaBasePreference *pref;
+  GSettings *settings;
+  char *detailed_signal;
+  gpointer data;
+  guint handler_id;
 
-  while (TRUE)
+  g_return_if_fail (settings_schemas != NULL);
+
+  if (!find_pref (preferences_enum, sizeof(MetaEnumPreference), key, &pref) &&
+      !find_pref (preferences_bool, sizeof(MetaBoolPreference), key, &pref) &&
+      !find_pref (preferences_string, sizeof(MetaStringPreference), key, &pref) &&
+      !find_pref (preferences_int, sizeof(MetaIntPreference), key, &pref))
     {
-      char **key = p;
-      if (*key == NULL)
-        break;
+      meta_warning ("Can't override preference key, \"%s\" not found\n", key);
+      return;
+    }
 
-      if (strcmp (*key, search_key) == 0)
-        {
-          *key = new_key;
-          return TRUE;
-        }
+  settings = SETTINGS (pref->schema);
+  data = g_object_get_data (G_OBJECT (settings), key);
+  if (data)
+    {
+      handler_id = GPOINTER_TO_UINT (data);
+      g_signal_handler_disconnect (settings, handler_id);
+    }
 
-      p = (guchar *)p + pref_size;
+  pref->schema = schema;
+  settings = SETTINGS (pref->schema);
+  if (!settings)
+    {
+      settings = g_settings_new (pref->schema);
+      g_hash_table_insert (settings_schemas, g_strdup (pref->schema), settings);
     }
 
-  return FALSE;
+  detailed_signal = g_strdup_printf ("changed::%s", key);
+  handler_id = g_signal_connect (settings, detailed_signal,
+                                 G_CALLBACK (settings_changed), NULL);
+  g_object_set_data (G_OBJECT (settings), key, GUINT_TO_POINTER (handler_id));
+
+  settings_changed (settings, key, NULL);
 }
 
+
 /**
- * meta_prefs_override_preference_location
- * @original_key: the normal Metacity preference location
- * @new_key: the Metacity preference location to use instead.
+ * meta_prefs_override_preference_schema
+ * @key: the preference name
+ * @schema: new schema for preference %key
  *
- * Substitute a different location to use instead of a standard Metacity
- * GConf key location. This might be used if a plugin expected a different
- * value for some preference than the Metacity default. While this function
- * can be called at any point, this function should generally be called
- * in a plugin's constructor, rather than in its start() method so the
- * preference isn't first loaded with one value then changed to another
- * value.
+ * Specify a schema whose keys are used to override the standard Metacity
+ * keys. This might be used if a plugin expected a different value for
+ * some preference than the Metacity default. While this function can be
+ * called at any point, this function should generally be called in a
+ * plugin's constructor, rather than in its start() method so the preference
+ * isn't first loaded with one value then changed to another value.
  */
 void
-meta_prefs_override_preference_location (const char *original_key,
-                                         const char *new_key)
+meta_prefs_override_preference_schema (const char *key, const char *schema)
 {
-  const char *search_key;
-  char *new_key_copy;
-  gboolean found;
   MetaPrefsOverriddenKey *overridden;
   GSList *tmp;
 
@@ -1194,81 +947,36 @@ meta_prefs_override_preference_location (const char *original_key,
   for (tmp = overridden_keys; tmp; tmp = tmp->next)
     {
       MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
-      if (strcmp (tmp_overridden->original_key, original_key) == 0 &&
-          strcmp (tmp_overridden->new_key, new_key) == 0)
+      if (strcmp (tmp_overridden->key, key) == 0 &&
+          strcmp (tmp_overridden->new_schema, schema) == 0)
         return;
     }
 
-  /* We depend on a unique mapping from GConf key to preference, so
-   * enforce this */
-
-  if (key_is_used (preferences_enum, sizeof(MetaEnumPreference), new_key) ||
-      key_is_used (preferences_bool, sizeof(MetaBoolPreference), new_key) ||
-      key_is_used (preferences_string, sizeof(MetaStringPreference), new_key) ||
-      key_is_used (preferences_int, sizeof(MetaIntPreference), new_key))
-    {
-      meta_warning (_("GConf key %s is already in use and can't be used to override %s\n"),
-                    new_key, original_key);
-
-    }
-
-  new_key_copy = g_strdup (new_key);
-
-  search_key = original_key;
   overridden = NULL;
 
   for (tmp = overridden_keys; tmp; tmp = tmp->next)
     {
       MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
-      if (strcmp (overridden->original_key, original_key) == 0)
-        {
-          overridden = tmp_overridden;
-          search_key = tmp_overridden->new_key;
-        }
+      if (strcmp (tmp_overridden->key, key) == 0)
+        overridden = tmp_overridden;
     }
 
-  found =
-    do_override (preferences_enum, sizeof(MetaEnumPreference), search_key, new_key_copy) ||
-    do_override (preferences_bool, sizeof(MetaBoolPreference), search_key, new_key_copy) ||
-    do_override (preferences_string, sizeof(MetaStringPreference), search_key, new_key_copy) ||
-    do_override (preferences_int, sizeof(MetaIntPreference), search_key, new_key_copy);
-  if (found)
+  if (overridden)
     {
-      if (overridden)
-        {
-          g_free (overridden->new_key);
-          overridden->new_key = new_key_copy;
-        }
-      else
-        {
-          overridden = g_slice_new (MetaPrefsOverriddenKey);
-          overridden->original_key = g_strdup (original_key);
-          overridden->new_key = new_key_copy;
-        }
-
-#ifdef HAVE_GCONF
-      if (default_client != NULL)
-        {
-          /* We're already initialized, so notify of a change */
-
-          GConfValue *value;
-          GError *err = NULL;
-
-          value = gconf_client_get (default_client, new_key, &err);
-          cleanup_error (&err);
-
-          notify_new_value (new_key, value);
-
-          if (value)
-            gconf_value_free (value);
-        }
-#endif /* HAVE_GCONF */
+      g_free (overridden->new_schema);
+      overridden->new_schema = g_strdup (schema);
     }
   else
     {
-      meta_warning (_("Can't override GConf key, %s not found\n"), original_key);
-      g_free (new_key_copy);
+      overridden = g_slice_new (MetaPrefsOverriddenKey);
+      overridden->key = g_strdup (key);
+      overridden->new_schema = g_strdup (schema);
+
+      overridden_keys = g_slist_prepend (overridden_keys, overridden);
     }
+
+  if (settings_schemas != NULL)
+    do_override (overridden->key, overridden->new_schema);
 }
 
 
@@ -1276,116 +984,50 @@ meta_prefs_override_preference_location (const char *original_key,
 /* Updates.                                                                 */
 /****************************************************************************/
 
-#ifdef HAVE_GCONF
-
-gboolean (*preference_update_handler[]) (const gchar*, GConfValue*) = {
-  handle_preference_update_enum,
-  handle_preference_update_bool,
-  handle_preference_update_string,
-  handle_preference_update_int,
-  NULL
-};
 
 static void
-notify_new_value (const char *key,
-                  GConfValue *value)
+settings_changed (GSettings *settings,
+                  gchar *key,
+                  gpointer data)
 {
-  int i = 0;
+  GVariant *value;
+  const GVariantType *type;
+  MetaEnumPreference *cursor;
+  gboolean found_enum;
 
-  /* FIXME: Use MetaGenericPreference and save a bit of code duplication */
-
-  while (preference_update_handler[i] != NULL)
+  /* String array, handled separately */
+  if (strcmp (key, KEY_WORKSPACE_NAMES) == 0)
     {
-      if (preference_update_handler[i] (key, value))
-        return;
-
-      i++;
+      if (update_workspace_names ());
+        queue_changed (META_PREF_WORKSPACE_NAMES);
+      return;
     }
-}
 
-static void
-change_notify (GConfClient    *client,
-               guint           cnxn_id,
-               GConfEntry     *entry,
-               gpointer        user_data)
-{
-  const char *key;
-  GConfValue *value;
-  
-  key = gconf_entry_get_key (entry);
-  value = gconf_entry_get_value (entry);
+  value = g_settings_get_value (settings, key);
+  type = g_variant_get_type (value);
 
-  /* First, search for a handler that might know what to do. */
-
-  notify_new_value (key, value);
-  
-  if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX) ||
-      g_str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
+  if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
+    handle_preference_update_bool (settings, key);
+  else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
+    handle_preference_update_int (settings, key);
+  else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
     {
-      if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
-        {
-          GSList *list;
+      cursor = preferences_enum;
+      found_enum = FALSE;
 
-          if (value && value->type != GCONF_VALUE_LIST)
-            {
-              meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                            key);
-              goto out;
-            }
-
-          list = value ? gconf_value_get_list (value) : NULL;
-
-          if (update_key_list_binding (key, list, META_LIST_OF_GCONFVALUE_STRINGS))
-            queue_changed (META_PREF_KEYBINDINGS);
-        }
-      else
+      while (cursor->base.key != NULL)
         {
-          const char *str;
 
-          if (value && value->type != GCONF_VALUE_STRING)
-            {
-              meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                            key);
-              goto out;
-            }
-
-          str = value ? gconf_value_get_string (value) : NULL;
-
-          if (update_key_binding (key, str))
-            queue_changed (META_PREF_KEYBINDINGS);
-        }
-    }
-  else if (g_str_has_prefix (key, KEY_COMMAND_PREFIX))
-    {
-      const char *str;
-
-      if (value && value->type != GCONF_VALUE_STRING)
-        {
-          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                        key);
-          goto out;
-        }
-
-      str = value ? gconf_value_get_string (value) : NULL;
-
-      if (update_command (key, str))
-        queue_changed (META_PREF_COMMANDS);
-    }
-  else if (g_str_has_prefix (key, KEY_WORKSPACE_NAME_PREFIX))
-    {
-      const char *str;
+          if (strcmp (key, cursor->base.key) == 0)
+            found_enum = TRUE;
 
-      if (value && value->type != GCONF_VALUE_STRING)
-        {
-          meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
-                        key);
-          goto out;
+          cursor++;
         }
 
-      str = value ? gconf_value_get_string (value) : NULL;
-
-      if (update_workspace_name (key, str))
-        queue_changed (META_PREF_WORKSPACE_NAMES);
+      if (found_enum)
+        handle_preference_update_enum (settings, key);
+      else
+        handle_preference_update_string (settings, key);
     }
   else if (g_str_equal (key, KEY_OVERLAY_KEY))
     {
@@ -1393,49 +1035,25 @@ change_notify (GConfClient    *client,
     }
   else
     {
-      meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Mutter\n",
-                  key);
+      /* Someone added a preference of an unhandled type */
+      g_assert_not_reached ();
     }
-  
- out:
-  /* nothing */
-  return; /* AIX compiler wants something after a label like out: */
-}
 
-static void
-cleanup_error (GError **error)
-{
-  if (*error)
-    {
-      meta_warning ("%s\n", (*error)->message);
-      
-      g_error_free (*error);
-      *error = NULL;
-    }
+  g_variant_unref (value);
 }
 
-/* get_bool returns TRUE if *val is filled in, FALSE otherwise */
-/* @@@ probably worth moving this inline; only used once */
-static gboolean
-get_bool (const char *key, gboolean *val)
+static void
+bindings_changed (GSettings *settings,
+                  gchar *key,
+                  gpointer data)
 {
-  GError     *err = NULL;
-  GConfValue *value;
-  gboolean    filled_in = FALSE;
+  gchar **strokes;
+  strokes = g_settings_get_strv (settings, key);
 
-  value = gconf_client_get (default_client, key, &err);
-  cleanup_error (&err);
-  if (value)
-    {
-      if (value->type == GCONF_VALUE_BOOL)
-        {
-          *val = gconf_value_get_bool (value);
-          filled_in = TRUE;
-        }
-      gconf_value_free (value);
-    }
+  if (update_key_binding (key, strokes))
+    queue_changed (META_PREF_KEYBINDINGS);
 
-  return filled_in;
+  g_strfreev (strokes);
 }
 
 /**
@@ -1456,21 +1074,19 @@ maybe_give_disable_workarounds_warning (void)
     }
 }
 
-#endif /* HAVE_GCONF */
-
 MetaVirtualModifier
 meta_prefs_get_mouse_button_mods  (void)
 {
   return mouse_button_mods;
 }
 
-MetaFocusMode
+GDesktopFocusMode
 meta_prefs_get_focus_mode (void)
 {
   return focus_mode;
 }
 
-MetaFocusNewWindows
+GDesktopFocusNewWindows
 meta_prefs_get_focus_new_windows (void)
 {
   return focus_new_windows;
@@ -1488,7 +1104,7 @@ meta_prefs_get_raise_on_click (void)
   /* Force raise_on_click on for click-to-focus, as requested by Havoc
    * in #326156.
    */
-  return raise_on_click || focus_mode == META_FOCUS_MODE_CLICK;
+  return raise_on_click || focus_mode == G_DESKTOP_FOCUS_MODE_CLICK;
 }
 
 const char*
@@ -1514,88 +1130,104 @@ meta_prefs_get_cursor_size (void)
 /* Handlers for string preferences.                                         */
 /****************************************************************************/
 
-#ifdef HAVE_GCONF
-
-static void
-titlebar_handler (MetaPreference pref,
-                  const gchar    *string_value,
-                  gboolean       *inform_listeners)
+static gboolean
+titlebar_handler (GVariant *value,
+                  gpointer *result,
+                  gpointer data)
 {
-  PangoFontDescription *new_desc = NULL;
+  PangoFontDescription *desc;
+  const gchar *string_value;
 
-  if (string_value)
-    new_desc = pango_font_description_from_string (string_value);
+  *result = NULL; /* ignored */
+  string_value = g_variant_get_string (value, NULL);
+  desc = pango_font_description_from_string (string_value);
 
-  if (new_desc == NULL)
+  if (desc == NULL)
     {
       meta_warning (_("Could not parse font description "
-                      "\"%s\" from GConf key %s\n"),
+                      "\"%s\" from GSettings key %s\n"),
                     string_value ? string_value : "(null)",
                     KEY_TITLEBAR_FONT);
-
-      *inform_listeners = FALSE;
-
-      return;
+      return FALSE;
     }
 
   /* Is the new description the same as the old? */
-
   if (titlebar_font &&
-      pango_font_description_equal (new_desc, titlebar_font))
+      pango_font_description_equal (desc, titlebar_font))
     {
-      pango_font_description_free (new_desc);
-      *inform_listeners = FALSE;
-      return;
+      pango_font_description_free (desc);
     }
+  else
+    {
+      if (titlebar_font)
+        pango_font_description_free (titlebar_font);
 
-  /* No, so free the old one and put ours in instead. */
-
-  if (titlebar_font)
-    pango_font_description_free (titlebar_font);
-
-  titlebar_font = new_desc;
+      titlebar_font = desc;
+      queue_changed (META_PREF_TITLEBAR_FONT);
+    }
 
+  return TRUE;
 }
 
-static void
-theme_name_handler (MetaPreference pref,
-                    const gchar *string_value,
-                    gboolean *inform_listeners)
+static gboolean
+theme_name_handler (GVariant *value,
+                    gpointer *result,
+                    gpointer  data)
 {
-  g_free (current_theme);
+  const gchar *string_value;
 
-  /* Fallback crackrock */
-  if (string_value == NULL)
-    current_theme = g_strdup ("Atlanta");
-  else
-    current_theme = g_strdup (string_value);
+  *result = NULL; /* ignored */
+  string_value = g_variant_get_string (value, NULL);
+
+  if (!string_value || !*string_value)
+    return FALSE;
+
+  if (g_strcmp0 (current_theme, string_value) != 0)
+    {
+      if (current_theme)
+        g_free (current_theme);
+
+      current_theme = g_strdup (string_value);
+      queue_changed (META_PREF_THEME);
+    }
+
+  return TRUE;
 }
 
-static void
-mouse_button_mods_handler (MetaPreference pref,
-                           const gchar *string_value,
-                           gboolean *inform_listeners)
+static gboolean
+mouse_button_mods_handler (GVariant *value,
+                           gpointer *result,
+                           gpointer  data)
 {
   MetaVirtualModifier mods;
+  const gchar *string_value;
 
-  meta_topic (META_DEBUG_KEYBINDINGS,
-              "Mouse button modifier has new gconf value \"%s\"\n",
-              string_value);
-  if (string_value && meta_ui_parse_modifier (string_value, &mods))
-    {
-      mouse_button_mods = mods;
-    }
-  else
+  *result = NULL; /* ignored */
+  string_value = g_variant_get_string (value, NULL);
+
+  if (!string_value || !meta_ui_parse_modifier (string_value, &mods))
     {
       meta_topic (META_DEBUG_KEYBINDINGS,
-                  "Failed to parse new gconf value\n");
+                  "Failed to parse new GSettings value\n");
           
       meta_warning (_("\"%s\" found in configuration database is "
                       "not a valid value for mouse button modifier\n"),
                     string_value);
 
-      *inform_listeners = FALSE;
+      return FALSE;
     }
+
+  meta_topic (META_DEBUG_KEYBINDINGS,
+              "Mouse button modifier has new GSettings value \"%s\"\n",
+              string_value);
+
+  if (mods != mouse_button_mods)
+    {
+      mouse_button_mods = mods;
+      queue_changed (META_PREF_MOUSE_BUTTON_MODS);
+    }
+
+  return TRUE;
 }
 
 static gboolean
@@ -1621,11 +1253,13 @@ button_layout_equal (const MetaButtonLayout *a,
   return TRUE;
 }
 
+/*
+ * This conversion cannot be handled by GSettings since
+ * several values are stored in the same key (as a string).
+ */
 static MetaButtonFunction
 button_function_from_string (const char *str)
 {
-  /* FIXME: gconf_string_to_enum is the obvious way to do this */
-
   if (strcmp (str, "menu") == 0)
     return META_BUTTON_FUNCTION_MENU;
   else if (strcmp (str, "minimize") == 0)
@@ -1670,19 +1304,23 @@ button_opposite_function (MetaButtonFunction ofwhat)
     }
 }
 
-static void
-button_layout_handler (MetaPreference pref,
-                         const gchar *string_value,
-                         gboolean *inform_listeners)
+static gboolean
+button_layout_handler (GVariant *value,
+                       gpointer *result,
+                       gpointer  data)
 {
   MetaButtonLayout new_layout;
+  const gchar *string_value;
   char **sides = NULL;
   int i;
-  
+
   /* We need to ignore unknown button functions, for
    * compat with future versions
    */
-  
+
+  *result = NULL; /* ignored */
+  string_value = g_variant_get_string (value, NULL);
+
   if (string_value)
     sides = g_strsplit (string_value, ":", 2);
 
@@ -1693,14 +1331,13 @@ button_layout_handler (MetaPreference pref,
       int b;
       gboolean used[META_BUTTON_FUNCTION_LAST];
 
-      i = 0;
       while (i < META_BUTTON_FUNCTION_LAST)
         {
           used[i] = FALSE;
           new_layout.left_buttons_has_spacer[i] = FALSE;
           ++i;
         }
-      
+
       buttons = g_strsplit (sides[0], ",", -1);
       i = 0;
       b = 0;
@@ -1729,7 +1366,6 @@ button_layout_handler (MetaPreference pref,
 
                   if (f != META_BUTTON_FUNCTION_LAST)
                       new_layout.left_buttons[i++] = f;
-
                 }
               else
                 {
@@ -1737,7 +1373,7 @@ button_layout_handler (MetaPreference pref,
                               buttons[b]);
                 }
             }
-          
+
           ++b;
         }
 
@@ -1754,7 +1390,6 @@ button_layout_handler (MetaPreference pref,
       int b;
       gboolean used[META_BUTTON_FUNCTION_LAST];
 
-      i = 0;
       while (i < META_BUTTON_FUNCTION_LAST)
         {
           used[i] = FALSE;
@@ -1841,19 +1476,15 @@ button_layout_handler (MetaPreference pref,
 
     new_layout = rtl_layout;
   }
-  
-  if (button_layout_equal (&button_layout, &new_layout))
-    {
-      /* Same as before, so duck out */
-      *inform_listeners = FALSE;
-    }
-  else
+
+  if (!button_layout_equal (&button_layout, &new_layout))
     {
       button_layout = new_layout;
+      emit_changed (META_PREF_BUTTON_LAYOUT);
     }
-}
 
-#endif /* HAVE_GCONF */
+  return TRUE;
+}
 
 const PangoFontDescription*
 meta_prefs_get_titlebar_font (void)
@@ -1884,16 +1515,11 @@ meta_prefs_get_disable_workarounds (void)
   return disable_workarounds;
 }
 
-#ifdef HAVE_GCONF
-#define MAX_REASONABLE_AUTO_RAISE_DELAY 10000
-  
-#endif /* HAVE_GCONF */
-
 #ifdef WITH_VERBOSE_MODE
 const char*
 meta_preference_to_string (MetaPreference pref)
 {
-  /* FIXME: another case for gconf_string_to_enum */
+  /* TODO: better handled via GLib enum nicknames */
   switch (pref)
     {
     case META_PREF_MOUSE_BUTTON_MODS:
@@ -1944,12 +1570,6 @@ meta_preference_to_string (MetaPreference pref)
     case META_PREF_AUTO_RAISE_DELAY:
       return "AUTO_RAISE_DELAY";
 
-    case META_PREF_COMMANDS:
-      return "COMMANDS";
-
-    case META_PREF_TERMINAL_COMMAND:
-      return "TERMINAL_COMMAND";
-
     case META_PREF_BUTTON_LAYOUT:
       return "BUTTON_LAYOUT";
 
@@ -2006,38 +1626,21 @@ meta_preference_to_string (MetaPreference pref)
 void
 meta_prefs_set_num_workspaces (int n_workspaces)
 {
-#ifdef HAVE_GCONF
-  GError *err;
-  
-  if (default_client == NULL)
-    return;
+  MetaBasePreference *pref;
 
-  if (n_workspaces < 1)
-    n_workspaces = 1;
-  if (n_workspaces > MAX_REASONABLE_WORKSPACES)
-    n_workspaces = MAX_REASONABLE_WORKSPACES;
-  
-  err = NULL;
-  gconf_client_set_int (default_client,
-                        KEY_NUM_WORKSPACES,
-                        n_workspaces,
-                        &err);
-
-  if (err)
-    {
-      meta_warning (_("Error setting number of workspaces to %d: %s\n"),
-                    num_workspaces,
-                    err->message);
-      g_error_free (err);
-    }
-#endif /* HAVE_GCONF */
+  find_pref (preferences_int, sizeof(MetaIntPreference),
+             KEY_NUM_WORKSPACES, &pref);
+
+  g_settings_set_int (SETTINGS (pref->schema),
+                      KEY_NUM_WORKSPACES,
+                      n_workspaces);
 }
 
-#define keybind(name, handler, param, flags, stroke, description) \
-  { #name, stroke, NULL, !!(flags & BINDING_REVERSES), !!(flags & BINDING_PER_WINDOW) },
+#define keybind(name, handler, param, flags) \
+  { #name, NULL, !!(flags & BINDING_REVERSES), !!(flags & BINDING_PER_WINDOW) },
 static MetaKeyPref key_bindings[] = {
 #include "all-keybindings.h"
-  { NULL, NULL, NULL, FALSE }
+  { NULL, NULL, FALSE }
 };
 #undef keybind
 
@@ -2047,19 +1650,14 @@ static MetaKeyCombo overlay_key_combo = { 0, 0, 0 };
 static void
 init_special_bindings (void)
 {
-#ifdef HAVE_GCONF
   char *val;
-  GError *err = NULL;
-#endif
   
   /* Default values for bindings which are global, but take special handling */
   meta_ui_parse_accelerator ("Super_L", &overlay_key_combo.keysym, 
                              &overlay_key_combo.keycode, 
                              &overlay_key_combo.modifiers);
 
-#ifdef HAVE_GCONF
-  val = gconf_client_get_string (default_client, KEY_OVERLAY_KEY, &err);
-  cleanup_error (&err);
+  val = g_settings_get_string (SETTINGS (SCHEMA_MUTTER), KEY_OVERLAY_KEY);
     
   if (val && meta_ui_parse_accelerator (val, &overlay_key_combo.keysym, 
                                         &overlay_key_combo.keycode, 
@@ -2071,359 +1669,85 @@ init_special_bindings (void)
                   "Failed to parse value for overlay_key\n");
     }
   g_free (val);
-#endif
 }
 
 static void
 init_bindings (void)
 {
-#ifdef HAVE_GCONF
-  const char *prefix[] = {
-    KEY_WINDOW_BINDINGS_PREFIX,
-    KEY_SCREEN_BINDINGS_PREFIX,
-    NULL
-  };
   int i;
-  GSList *list, *l, *list_val;
-  const char *str_val;
-  const char *key;
-  GConfEntry *entry;
-  GConfValue *value;
-  GHashTable *to_update;
+  gchar **keys;
+  gchar **strokes;
 
   g_assert (G_N_ELEMENTS (key_bindings) == META_KEYBINDING_ACTION_LAST + 1);
 
-  to_update = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-
-  for (i = 0; prefix[i]; i++)
-    {
-      list = gconf_client_all_entries (default_client, prefix[i], NULL);
-      for (l = list; l; l = l->next)
-        {
-          entry = l->data;
-          key = gconf_entry_get_key (entry);
-          value = gconf_entry_get_value (entry);
-          if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
-            {
-              /* List bindings are used in addition to the normal bindings and never
-               * have defaults, so we just go ahead and set them immediately; there
-               * will be only a few of them, so don't worry about the linear scan
-               * in find_and_update_list_binding.
-               */
-              list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, NULL);
- 
-              update_key_list_binding (key, list_val, META_LIST_OF_STRINGS);
-              g_slist_foreach (list_val, (GFunc)g_free, NULL);
-              g_slist_free (list_val);
-            }
-          else
-            {
-              str_val = gconf_value_get_string (value);
-              g_hash_table_insert (to_update, binding_name (key), g_strdup (str_val));
-            }
-          gconf_entry_free (entry);
-        }
-      g_slist_free (list);
-    }
-
-  i = 0;
-  while (key_bindings[i].name)
+  keys = g_settings_list_keys (SETTINGS (SCHEMA_COMMON_KEYBINDINGS));
+  for (i = 0; (guint)i < g_strv_length (keys); i++)
     {
-      update_binding (&key_bindings[i],
-                      g_hash_table_lookup (to_update, key_bindings[i].name));
+      strokes = g_settings_get_strv (SETTINGS (SCHEMA_COMMON_KEYBINDINGS),
+                                     keys[i]);
+      update_key_binding (keys[i], strokes);
 
-      ++i;
+      g_strfreev (strokes);
     }
+  g_strfreev (keys);
 
-  g_hash_table_destroy (to_update);
-
-#else /* HAVE_GCONF */
-  int i = 0;
-  while (key_bindings[i].name)
+  keys = g_settings_list_keys (SETTINGS (SCHEMA_MUTTER_KEYBINDINGS));
+  for (i = 0; (guint)i < g_strv_length (keys); i++)
     {
-      if (key_bindings[i].default_keybinding)
-        {
-          /* Set the binding */
-          update_binding (&key_bindings[i], NULL);
-        }
+      strokes = g_settings_get_strv (SETTINGS (SCHEMA_MUTTER_KEYBINDINGS),
+                                               keys[i]);
+      update_key_binding (keys[i], strokes);
 
-      ++i;
+      g_strfreev (strokes);
     }
-#endif /* HAVE_GCONF */
-  
-  init_special_bindings ();  
-}
+  g_strfreev (keys);
 
-static void
-init_commands (void)
-{
-#ifdef HAVE_GCONF
-  GSList *list, *l;
-  const char *str_val;
-  const char *key;
-  GConfEntry *entry;
-  GConfValue *value;
-
-  list = gconf_client_all_entries (default_client, KEY_COMMAND_DIRECTORY, NULL);
-  for (l = list; l; l = l->next)
-    {
-      entry = l->data;
-      key = gconf_entry_get_key (entry);
-      value = gconf_entry_get_value (entry);
-      str_val = gconf_value_get_string (value);
-      update_command (key, str_val);
-      gconf_entry_free (entry);
-    }
-  g_slist_free (list);
-#else
-  int i;
-  for (i = 0; i < MAX_COMMANDS; i++)
-    commands[i] = NULL;
-#endif /* HAVE_GCONF */
+  init_special_bindings ();  
 }
 
 static void
 init_workspace_names (void)
 {
-  int i;
-
-#ifdef HAVE_GCONF
-  GSList *list, *l;
-  const char *str_val;
-  const char *key;
-  GConfEntry *entry;
-  GConfValue *value;
-
-  list = gconf_client_all_entries (default_client, KEY_WORKSPACE_NAME_DIRECTORY, NULL);
-  for (l = list; l; l = l->next)
-    {
-      entry = l->data;
-      key = gconf_entry_get_key (entry);
-      value = gconf_entry_get_value (entry);
-      str_val = gconf_value_get_string (value);
-      update_workspace_name (key, str_val);
-      gconf_entry_free (entry);
-    }
-  g_slist_free (list);
-#endif /* HAVE_GCONF */
-
-  for (i = 0; i < MAX_REASONABLE_WORKSPACES; i++)
-    if (workspace_names[i] == NULL)
-      workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1);
-
-  meta_topic (META_DEBUG_PREFS,
-              "Initialized workspace names\n");
+  update_workspace_names ();
 }
 
 static gboolean
 update_binding (MetaKeyPref *binding,
-                const char  *value)
-{
-  unsigned int keysym;
-  unsigned int keycode;
-  MetaVirtualModifier mods;
-  MetaKeyCombo *combo;
-  gboolean changed;
-
-  if (value == NULL)
-    value = binding->default_keybinding;
-
-  meta_topic (META_DEBUG_KEYBINDINGS,
-              "Binding \"%s\" has new gconf value \"%s\"\n",
-              binding->name, value ? value : "none");
-  
-  keysym = 0;
-  keycode = 0;
-  mods = 0;
-  if (value)
-    {
-      if (!meta_ui_parse_accelerator (value, &keysym, &keycode, &mods))
-        {
-          meta_topic (META_DEBUG_KEYBINDINGS,
-                      "Failed to parse new gconf value\n");
-          meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"),
-                        value, binding->name);
-
-          return FALSE;
-        }
-    }
-
-  /* If there isn't already a first element, make one. */
-  if (!binding->bindings)
-    {
-      MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo));
-      binding->bindings = g_slist_alloc();
-      binding->bindings->data = blank;
-    }
-  
-   combo = binding->bindings->data;
-
-#ifdef HAVE_GCONF
-   /* Bug 329676: Bindings which can be shifted must not have no modifiers,
-    * nor only SHIFT as a modifier.
-    */
-
-  if (binding->add_shift &&
-      0 != keysym &&
-      (META_VIRTUAL_SHIFT_MASK == mods || 0 == mods))
-    {
-      gchar *old_setting;
-      gchar *key;
-      GError *err = NULL;
-      
-      meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
-                    "such as Ctrl or Alt.\n",
-                    binding->name,
-                    value);
-
-      old_setting = meta_ui_accelerator_name (combo->keysym,
-                                              combo->modifiers);
-
-      if (!strcmp(old_setting, value))
-        {
-          /* We were about to set it to the same value
-           * that it had originally! This must be caused
-           * by getting an invalid string back from
-           * meta_ui_accelerator_name. Bail out now
-           * so we don't get into an infinite loop.
-           */
-           g_free (old_setting);
-           return TRUE;
-        }
-
-      meta_warning ("Reverting \"%s\" to %s.\n",
-                    binding->name,
-                    old_setting);
-
-      /* FIXME: add_shift is currently screen_bindings only, but
-       * there's no really good reason it should always be.
-       * So we shouldn't blindly add KEY_SCREEN_BINDINGS_PREFIX
-       * onto here.
-       */
-      key = g_strconcat (KEY_SCREEN_BINDINGS_PREFIX, "/",
-                         binding->name, NULL);
-      
-      gconf_client_set_string (gconf_client_get_default (),
-                               key, old_setting, &err);
-
-      if (err)
-        {
-          meta_warning ("Error while reverting keybinding: %s\n",
-                        err->message);
-          g_error_free (err);
-          err = NULL;
-        }
-      
-      g_free (old_setting);
-      g_free (key);
-
-      /* The call to gconf_client_set_string() will cause this function
-       * to be called again with the new value, so there's no need to
-       * carry on.
-       */
-      return TRUE;
-    }
-#endif
-  
-  changed = FALSE;
-  if (keysym != combo->keysym ||
-      keycode != combo->keycode ||
-      mods != combo->modifiers)
-    {
-      changed = TRUE;
-      
-      combo->keysym = keysym;
-      combo->keycode = keycode;
-      combo->modifiers = mods;
-      
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                  "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
-                  binding->name, combo->keysym, combo->keycode,
-                  combo->modifiers);
-    }
-  else
-    {
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                  "Keybinding for \"%s\" is unchanged\n", binding->name);
-    }
-  
-  return changed;
-}
-
-#ifdef HAVE_GCONF
-static gboolean
-update_list_binding (MetaKeyPref *binding,
-                     GSList      *value,
-                     MetaStringListType type_of_value)
+                gchar      **strokes)
 {
   unsigned int keysym;
   unsigned int keycode;
   MetaVirtualModifier mods;
   gboolean changed = FALSE;
-  const gchar *pref_string;
-  GSList *pref_iterator = value, *tmp;
   MetaKeyCombo *combo;
+  int i;
 
   meta_topic (META_DEBUG_KEYBINDINGS,
-              "Binding \"%s\" has new gconf value\n",
+              "Binding \"%s\" has new GSettings value\n",
               binding->name);
-  
-  if (binding->bindings == NULL)
-    {
-      /* We need to insert a dummy element into the list, because the first
-       * element is the one governed by update_binding. We only handle the
-       * subsequent elements.
-       */
-      MetaKeyCombo *blank = g_malloc0 (sizeof (MetaKeyCombo));
-      binding->bindings = g_slist_alloc();
-      binding->bindings->data = blank;
-    }
-       
+
   /* Okay, so, we're about to provide a new list of key combos for this
    * action. Delete any pre-existing list.
    */
-  tmp = binding->bindings->next;
-  while (tmp)
-    {
-      g_free (tmp->data);
-      tmp = tmp->next;
-    }
-  g_slist_free (binding->bindings->next);
-  binding->bindings->next = NULL;
+  g_slist_foreach (binding->bindings, (GFunc) g_free, NULL);
+  g_slist_free (binding->bindings);
+  binding->bindings = NULL;
   
-  while (pref_iterator)
+  for (i = 0; strokes && strokes[i]; i++)
     {
       keysym = 0;
       keycode = 0;
       mods = 0;
 
-      if (!pref_iterator->data)
-        {
-          pref_iterator = pref_iterator->next;
-          continue;
-        }
-
-      switch (type_of_value)
-        {
-        case META_LIST_OF_STRINGS:
-          pref_string = pref_iterator->data;
-          break;
-        case META_LIST_OF_GCONFVALUE_STRINGS:
-          pref_string = gconf_value_get_string (pref_iterator->data);
-          break;
-        default:
-          g_assert_not_reached ();
-        }
-      
-      if (!meta_ui_parse_accelerator (pref_string, &keysym, &keycode, &mods))
+      if (!meta_ui_parse_accelerator (strokes[i], &keysym, &keycode, &mods))
         {
           meta_topic (META_DEBUG_KEYBINDINGS,
-                      "Failed to parse new gconf value\n");
+                      "Failed to parse new GSettings value\n");
           meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"),
-                        pref_string, binding->name);
+                        strokes[i], binding->name);
 
-          /* Should we remove this value from the list in gconf? */
-          pref_iterator = pref_iterator->next;
+          /* Value is kept and will thus be removed next time we save the key.
+           * Changing the key in response to a modification could lead to cyclic calls. */
           continue;
         }
 
@@ -2437,12 +1761,10 @@ update_list_binding (MetaKeyPref *binding,
         {
           meta_warning ("Cannot bind \"%s\" to %s: it needs a modifier "
                         "such as Ctrl or Alt.\n",
-                        binding->name,
-                        pref_string);
-
-          /* Should we remove this value from the list in gconf? */
+                        binding->name, strokes[i]);
 
-          pref_iterator = pref_iterator->next;
+          /* Value is kept and will thus be removed next time we save the key.
+           * Changing the key in response to a modification could lead to cyclic calls. */
           continue;
         }
   
@@ -2452,370 +1774,137 @@ update_list_binding (MetaKeyPref *binding,
       combo->keysym = keysym;
       combo->keycode = keycode;
       combo->modifiers = mods;
-      binding->bindings->next = g_slist_prepend (binding->bindings->next, combo);
+      binding->bindings = g_slist_prepend (binding->bindings, combo);
 
       meta_topic (META_DEBUG_KEYBINDINGS,
                       "New keybinding for \"%s\" is keysym = 0x%x keycode = 0x%x mods = 0x%x\n",
                       binding->name, keysym, keycode, mods);
+    }
 
-      pref_iterator = pref_iterator->next;
-    }  
   return changed;
 }
 
-static char *
-binding_name (const char *gconf_key)
-{
-  const char *start, *end;
-
-  if (*gconf_key == '/')
-    start = strrchr (gconf_key, '/') + 1;
-  else
-    start = gconf_key;
-
-  if (g_str_has_suffix (gconf_key, KEY_LIST_BINDINGS_SUFFIX))
-    end = gconf_key + strlen(gconf_key) - strlen (KEY_LIST_BINDINGS_SUFFIX);
-  else
-    end = gconf_key + strlen(gconf_key);
-
-  return g_strndup (start, end - start);
-}
-
-/* Return value is TRUE if a preference changed and we need to
- * notify
- */
-static gboolean
-find_and_update_binding (MetaKeyPref *bindings, 
-                         const char  *key,
-                         const char  *value)
-{
-  char *name = binding_name (key);
-  int i;
-
-  i = 0;
-  while (bindings[i].name &&
-         strcmp (name, bindings[i].name) != 0)
-    ++i;
-
-  g_free (name);
-
-  if (bindings[i].name)
-    return update_binding (&bindings[i], value);
-  else
-    return FALSE;
-}
-
 static gboolean
 update_key_binding (const char *key,
-                    const char *value)
-{
-  return find_and_update_binding (key_bindings, key, value);
-}
-
-static gboolean
-find_and_update_list_binding (MetaKeyPref       *bindings,
-                              const char        *key,
-                              GSList            *value,
-                              MetaStringListType type_of_value)
+                    gchar     **strokes)
 {
-  char *name = binding_name (key);
   int i;
 
   i = 0;
-  while (bindings[i].name &&
-         strcmp (name, bindings[i].name) != 0)
+  while (key_bindings[i].name &&
+         strcmp (key, key_bindings[i].name) != 0)
     ++i;
 
-  g_free (name);
-
-  if (bindings[i].name)
-    return update_list_binding (&bindings[i], value, type_of_value);
+  if (key_bindings[i].name)
+    return update_binding (&key_bindings[i], strokes);
   else
     return FALSE;
 }
 
 static gboolean
-update_key_list_binding (const char        *key,
-                         GSList            *value,
-                         MetaStringListType type_of_value)
+update_workspace_names (void)
 {
-  return find_and_update_list_binding (key_bindings, key, value, type_of_value);
-}
-
-static gboolean
-update_command (const char  *name,
-                const char  *value)
-{
-  char *p;
   int i;
-  
-  p = strrchr (name, '_');
-  if (p == NULL)
-    {
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                  "Command %s has no underscore?\n", name);
-      return FALSE;
-    }
-  
-  ++p;
-
-  if (g_ascii_isdigit (*p))
-    {
-      i = atoi (p);
-      i -= 1; /* count from 0 not 1 */
-    }
-  else
-    {
-      p = strrchr (name, '/');
-      ++p;
-
-      if (strcmp (p, "command_screenshot") == 0)
-        {
-          i = SCREENSHOT_COMMAND_IDX;
-        }
-      else if (strcmp (p, "command_window_screenshot") == 0)
-        {
-          i = WIN_SCREENSHOT_COMMAND_IDX;
-        }
-      else
-        {
-          meta_topic (META_DEBUG_KEYBINDINGS,
-                      "Command %s doesn't end in number?\n", name);
-          return FALSE;
-        }
-    }
-  
-  if (i >= MAX_COMMANDS)
-    {
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                  "Command %d is too highly numbered, ignoring\n", i);
-      return FALSE;
-    }
-
-  if ((commands[i] == NULL && value == NULL) ||
-      (commands[i] && value && strcmp (commands[i], value) == 0))
-    {
-      meta_topic (META_DEBUG_KEYBINDINGS,
-                  "Command %d is unchanged\n", i);
-      return FALSE;
-    }
-  
-  g_free (commands[i]);
-  commands[i] = g_strdup (value);
-
-  meta_topic (META_DEBUG_KEYBINDINGS,
-              "Updated command %d to \"%s\"\n",
-              i, commands[i] ? commands[i] : "none");
-  
-  return TRUE;
-}
+  char **names;
+  int n_workspace_names, n_names;
+  gboolean changed = FALSE;
 
-#endif /* HAVE_GCONF */
+  names = g_settings_get_strv (SETTINGS (SCHEMA_GENERAL), KEY_WORKSPACE_NAMES);
+  n_names = g_strv_length (names);
+  n_workspace_names = workspace_names ? g_strv_length (workspace_names) : 0;
 
-const char*
-meta_prefs_get_command (int i)
-{
-  g_return_val_if_fail (i >= 0 && i < MAX_COMMANDS, NULL);
-  
-  return commands[i];
-}
+  for (i = 0; i < n_names; i++)
+    if (n_workspace_names < i + 1 || !workspace_names[i] ||
+        g_strcmp0 (names[i], workspace_names[i]) != 0)
+      {
+        changed = TRUE;
+        break;
+      }
 
-char*
-meta_prefs_get_gconf_key_for_command (int i)
-{
-  char *key;
+  if (n_workspace_names != n_names)
+    changed = TRUE;
 
-  switch (i)
+  if (changed)
     {
-    case SCREENSHOT_COMMAND_IDX:
-      key = g_strdup (KEY_COMMAND_PREFIX "screenshot");
-      break;
-    case WIN_SCREENSHOT_COMMAND_IDX:
-      key = g_strdup (KEY_COMMAND_PREFIX "window_screenshot");
-      break;
-    default:
-      key = g_strdup_printf (KEY_COMMAND_PREFIX"%d", i + 1);
-      break;
+      if (workspace_names)
+        g_strfreev (workspace_names);
+      workspace_names = names;
     }
-  
-  return key;
-}
+  else
+    g_strfreev (names);
 
-const char*
-meta_prefs_get_terminal_command (void)
-{
-  return terminal_command;
+  return changed;
 }
 
 const char*
-meta_prefs_get_gconf_key_for_terminal_command (void)
+meta_prefs_get_workspace_name (int i)
 {
-  return KEY_TERMINAL_COMMAND;
-}
+  const char *name;
 
-#ifdef HAVE_GCONF
-static gboolean
-update_workspace_name (const char  *name,
-                       const char  *value)
-{
-  char *p;
-  int i;
-  
-  p = strrchr (name, '_');
-  if (p == NULL)
+  if (!workspace_names ||
+      g_strv_length (workspace_names) < (guint)i + 1 ||
+      !*workspace_names[i])
     {
-      meta_topic (META_DEBUG_PREFS,
-                  "Workspace name %s has no underscore?\n", name);
-      return FALSE;
-    }
-  
-  ++p;
-
-  if (!g_ascii_isdigit (*p))
-    {
-      meta_topic (META_DEBUG_PREFS,
-                  "Workspace name %s doesn't end in number?\n", name);
-      return FALSE;
-    }
-  
-  i = atoi (p);
-  i -= 1; /* count from 0 not 1 */
-  
-  if (i >= MAX_REASONABLE_WORKSPACES)
-    {
-      meta_topic (META_DEBUG_PREFS,
-                  "Workspace name %d is too highly numbered, ignoring\n", i);
-      return FALSE;
-    }
-
-  if (workspace_names[i] && value && strcmp (workspace_names[i], value) == 0)
-    {
-      meta_topic (META_DEBUG_PREFS,
-                  "Workspace name %d is unchanged\n", i);
-      return FALSE;
-    }  
-
-  /* This is a bad hack. We have to treat empty string as
-   * "unset" because the root window property can't contain
-   * null. So it gets empty string instead and we don't want
-   * that to result in setting the empty string as a value that
-   * overrides "unset".
-   */
-  if (value != NULL && *value != '\0')
-    {
-      g_free (workspace_names[i]);
-      workspace_names[i] = g_strdup (value);
+      char *generated_name = g_strdup_printf (_("Workspace %d"), i + 1);
+      name = g_intern_string (generated_name);
+      g_free (generated_name);
     }
   else
-    {
-      /* use a default name */
-      char *d;
+    name = workspace_names[i];
 
-      d = g_strdup_printf (_("Workspace %d"), i + 1);
-      if (workspace_names[i] && strcmp (workspace_names[i], d) == 0)
-        {
-          g_free (d);
-          return FALSE;
-        }
-      else
-        {
-          g_free (workspace_names[i]);
-          workspace_names[i] = d;
-        }
-    }
-  
   meta_topic (META_DEBUG_PREFS,
-              "Updated workspace name %d to \"%s\"\n",
-              i, workspace_names[i] ? workspace_names[i] : "none");
-  
-  return TRUE;
-}
-#endif /* HAVE_GCONF */
+              "Getting name of workspace %d: \"%s\"\n", i, name);
 
-const char*
-meta_prefs_get_workspace_name (int i)
-{
-  g_return_val_if_fail (i >= 0 && i < MAX_REASONABLE_WORKSPACES, NULL);
-
-  g_assert (workspace_names[i] != NULL);
-
-  meta_topic (META_DEBUG_PREFS,
-              "Getting workspace name for %d: \"%s\"\n",
-              i, workspace_names[i]);
-  
-  return workspace_names[i];
+  return name;
 }
 
 void
-meta_prefs_change_workspace_name (int         i,
+meta_prefs_change_workspace_name (int         num,
                                   const char *name)
 {
-#ifdef HAVE_GCONF
-  char *key;
-  GError *err;
+  GVariantBuilder builder;
+  int n_workspace_names, i;
   
-  g_return_if_fail (i >= 0 && i < MAX_REASONABLE_WORKSPACES);
+  g_return_if_fail (num >= 0);
 
   meta_topic (META_DEBUG_PREFS,
               "Changing name of workspace %d to %s\n",
-              i, name ? name : "none");
+              num, name ? name : "none");
 
-  /* This is a bad hack. We have to treat empty string as
-   * "unset" because the root window property can't contain
-   * null. So it gets empty string instead and we don't want
-   * that to result in setting the empty string as a value that
-   * overrides "unset".
-   */
-  if (name && *name == '\0')
-    name = NULL;
-  
-  if ((name == NULL && workspace_names[i] == NULL) ||
-      (name && workspace_names[i] && strcmp (name, workspace_names[i]) == 0))
+  /* NULL and empty string both mean "default" here,
+   * and we also need to match the name against its default value
+   * to avoid saving it literally. */
+  if (g_strcmp0 (name, meta_prefs_get_workspace_name (num)) == 0)
     {
-      meta_topic (META_DEBUG_PREFS,
-                  "Workspace %d already has name %s\n",
-                  i, name ? name : "none");
+      if (!name || !*name)
+        meta_topic (META_DEBUG_PREFS,
+                    "Workspace %d already uses default name\n", num);
+      else
+        meta_topic (META_DEBUG_PREFS,
+                    "Workspace %d already has name %s\n", num, name);
       return;
     }
-  
-  key = gconf_key_for_workspace_name (i);
 
-  err = NULL;
-  if (name != NULL)
-    gconf_client_set_string (default_client,
-                             key, name,
-                             &err);
-  else
-    gconf_client_unset (default_client,
-                        key, &err);
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_STRING_ARRAY);
+  n_workspace_names = workspace_names ? g_strv_length (workspace_names) : 0;
 
-  
-  if (err)
+  for (i = 0; i < MAX (num + 1, n_workspace_names); i++)
     {
-      meta_warning (_("Error setting name for workspace %d to \"%s\": %s\n"),
-                    i, name ? name : "none",
-                    err->message);
-      g_error_free (err);
+      const char *value;
+
+      if (i == num)
+        value = name ? name : "";
+      else if (i < n_workspace_names)
+        value = workspace_names[i] ? workspace_names[i] : "";
+      else
+        value = "";
+
+      g_variant_builder_add (&builder, "s", value);
     }
-  
-  g_free (key);
-#else
-  g_free (workspace_names[i]);
-  workspace_names[i] = g_strdup (name);
-#endif /* HAVE_GCONF */
-}
 
-#ifdef HAVE_GCONF
-static char*
-gconf_key_for_workspace_name (int i)
-{
-  char *key;
-  
-  key = g_strdup_printf (KEY_WORKSPACE_NAME_PREFIX"%d", i + 1);
-  
-  return key;
+  g_settings_set_value (SETTINGS (SCHEMA_GENERAL), KEY_WORKSPACE_NAMES,
+                        g_variant_builder_end (&builder));
 }
-#endif /* HAVE_GCONF */
 
 void
 meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p)
@@ -2824,18 +1913,12 @@ meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p)
 }
 
 gboolean
-meta_prefs_get_visual_bell (void)
-{
-  return provide_visual_bell;
-}
-
-gboolean
 meta_prefs_bell_is_audible (void)
 {
   return bell_is_audible;
 }
 
-MetaVisualBellType
+GDesktopVisualBellType
 meta_prefs_get_visual_bell_type (void)
 {
   return visual_bell_type;
@@ -2856,19 +1939,19 @@ meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
   *combo = overlay_key_combo;
 }
 
-MetaActionTitlebar
+GDesktopTitlebarAction
 meta_prefs_get_action_double_click_titlebar (void)
 {
   return action_double_click_titlebar;
 }
 
-MetaActionTitlebar
+GDesktopTitlebarAction
 meta_prefs_get_action_middle_click_titlebar (void)
 {
   return action_middle_click_titlebar;
 }
 
-MetaActionTitlebar
+GDesktopTitlebarAction
 meta_prefs_get_action_right_click_titlebar (void)
 {
   return action_right_click_titlebar;
@@ -2996,23 +2079,12 @@ meta_prefs_get_live_hidden_windows (void)
 void
 meta_prefs_set_live_hidden_windows (gboolean whether)
 {
-#ifdef HAVE_GCONF
-  GError *err = NULL;
+  MetaBasePreference *pref;
 
-  gconf_client_set_bool (default_client,
-                         KEY_LIVE_HIDDEN_WINDOWS,
-                         whether,
-                         &err);
-
-  if (err)
-    {
-      meta_warning (_("Error setting live hidden windows status status: %s\n"),
-                    err->message);
-      g_error_free (err);
-    }
-#else
-  live_hidden_windows = whether;
-#endif
+  find_pref (preferences_bool, sizeof(MetaBoolPreference),
+             KEY_LIVE_HIDDEN_WINDOWS, &pref);
+  g_settings_set_boolean (SETTINGS (pref->schema), KEY_LIVE_HIDDEN_WINDOWS,
+                          whether);
 }
 
 gboolean
@@ -3031,23 +2103,11 @@ meta_prefs_get_no_tab_popup (void)
 void
 meta_prefs_set_no_tab_popup (gboolean whether)
 {
-#ifdef HAVE_GCONF
-  GError *err = NULL;
-
-  gconf_client_set_bool (default_client,
-                         KEY_NO_TAB_POPUP,
-                         whether,
-                         &err);
+  MetaBasePreference *pref;
 
-  if (err)
-    {
-      meta_warning (_("Error setting no tab popup status: %s\n"),
-                    err->message);
-      g_error_free (err);
-    }
-#else
-  no_tab_popup = whether;
-#endif
+  find_pref (preferences_bool, sizeof(MetaBoolPreference),
+             KEY_NO_TAB_POPUP, &pref);
+  g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
 }
 
 int
@@ -3056,48 +2116,8 @@ meta_prefs_get_draggable_border_width (void)
   return draggable_border_width;
 }
 
-#ifndef HAVE_GCONF
-static void
-init_button_layout(void)
-{
-  MetaButtonLayout button_layout_ltr = {
-    {    
-      /* buttons in the group on the left side */
-      META_BUTTON_FUNCTION_MENU,
-      META_BUTTON_FUNCTION_LAST
-    },
-    {
-      /* buttons in the group on the right side */
-      META_BUTTON_FUNCTION_MINIMIZE,
-      META_BUTTON_FUNCTION_MAXIMIZE,
-      META_BUTTON_FUNCTION_CLOSE,
-      META_BUTTON_FUNCTION_LAST
-    }
-  };
-  MetaButtonLayout button_layout_rtl = {
-    {    
-      /* buttons in the group on the left side */
-      META_BUTTON_FUNCTION_CLOSE,
-      META_BUTTON_FUNCTION_MAXIMIZE,
-      META_BUTTON_FUNCTION_MINIMIZE,
-      META_BUTTON_FUNCTION_LAST
-    },
-    {
-      /* buttons in the group on the right side */
-      META_BUTTON_FUNCTION_MENU,
-      META_BUTTON_FUNCTION_LAST
-    }
-  };
-
-  button_layout = meta_ui_get_direction() == META_UI_DIRECTION_LTR ?
-    button_layout_ltr : button_layout_rtl;
-};
-
-#endif
-
 void
 meta_prefs_set_force_fullscreen (gboolean whether)
 {
   force_fullscreen = whether;
 }
-
diff --git a/src/core/screen.c b/src/core/screen.c
index ee28666..bb5815a 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -1186,7 +1186,7 @@ prefs_changed_callback (MetaPreference pref,
   
   if (pref == META_PREF_NUM_WORKSPACES)
     {
-      /* GConf doesn't provide timestamps, but luckily update_num_workspaces
+      /* GSettings doesn't provide timestamps, but luckily update_num_workspaces
        * often doesn't need it...
        */
       guint32 timestamp = 
diff --git a/src/core/window.c b/src/core/window.c
index 95ae2bb..d9c1c13 100644
--- a/src/core/window.c
+++ b/src/core/window.c
@@ -2277,7 +2277,7 @@ idle_calc_showing (gpointer data)
       tmp = tmp->next;
     }
 
-  if (meta_prefs_get_focus_mode () != META_FOCUS_MODE_CLICK)
+  if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK)
     {
       /* When display->mouse_mode is false, we want to ignore
        * EnterNotify events unless they come from mouse motion.  To do
@@ -2617,7 +2617,7 @@ window_state_on_map (MetaWindow *window,
    * approximation to enforce so we do that.
    */
   if (*takes_focus &&
-      meta_prefs_get_focus_new_windows () == META_FOCUS_NEW_WINDOWS_STRICT &&
+      meta_prefs_get_focus_new_windows () == G_DESKTOP_FOCUS_NEW_WINDOWS_STRICT &&
       !window->display->allow_terminal_deactivation &&
       __window_is_terminal (window->display->focus_window) &&
       !meta_window_is_ancestor_of_transient (window->display->focus_window,
@@ -2952,7 +2952,7 @@ meta_window_show (MetaWindow *window)
        * that new window below a lot of other windows.
        */
       if (overlap ||
-          (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
+          (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
            meta_prefs_get_raise_on_click ()))
         meta_window_stack_just_below (window, focus_window);
 
@@ -6836,7 +6836,7 @@ meta_window_notify_focus (MetaWindow *window,
            *
            * There is dicussion in bugs 102209, 115072, and 461577
            */
-          if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK ||
+          if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
               !meta_prefs_get_raise_on_click())
             meta_display_ungrab_focus_window_button (window->display, window);
 
@@ -6889,7 +6889,7 @@ meta_window_notify_focus (MetaWindow *window,
           meta_window_update_layer (window);
 
           /* Re-grab for click to focus and raise-on-click, if necessary */
-          if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK ||
+          if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
               !meta_prefs_get_raise_on_click ())
             meta_display_grab_focus_window_button (window->display, window);
        }
@@ -9867,7 +9867,7 @@ meta_window_set_user_time (MetaWindow *window,
        * doesn't want to have focus transferred for now due to new windows.
        */
       if (meta_prefs_get_focus_new_windows () ==
-               META_FOCUS_NEW_WINDOWS_STRICT &&
+               G_DESKTOP_FOCUS_NEW_WINDOWS_STRICT &&
           __window_is_terminal (window))
         window->display->allow_terminal_deactivation = FALSE;
     }
diff --git a/src/core/workspace.c b/src/core/workspace.c
index 66f9dd0..ffadd39 100644
--- a/src/core/workspace.c
+++ b/src/core/workspace.c
@@ -1201,7 +1201,7 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
     }
 
 
-  if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK ||
+  if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
       !workspace->screen->display->mouse_mode)
     focus_ancestor_or_mru_window (workspace, not_this_one, timestamp);
   else
@@ -1239,9 +1239,9 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
                                                      window);
             }
         }
-      else if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_SLOPPY)
+      else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_SLOPPY)
         focus_ancestor_or_mru_window (workspace, not_this_one, timestamp);
-      else if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_MOUSE)
+      else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_MOUSE)
         {
           meta_topic (META_DEBUG_FOCUS,
                       "Setting focus to no_focus_window, since no valid "
@@ -1300,7 +1300,7 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
           meta_window_focus (ancestor, timestamp);
 
           /* Also raise the window if in click-to-focus */
-          if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
+          if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
             meta_window_raise (ancestor);
 
           return;
@@ -1346,7 +1346,7 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
       meta_window_focus (window, timestamp);
 
       /* Also raise the window if in click-to-focus */
-      if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK)
+      if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
         meta_window_raise (window);
     }
   else
diff --git a/src/libmutter.pc.in b/src/libmutter.pc.in
index aced2f5..1f819af 100644
--- a/src/libmutter.pc.in
+++ b/src/libmutter.pc.in
@@ -12,7 +12,7 @@ mutter_plugin_api_version= MUTTER_PLUGIN_API_VERSION@
 
 Name: libmutter
 Description: Mutter window manager library
-Requires: gtk+-3.0 @CLUTTER_PACKAGE@ x11
+Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11
 Version: @VERSION@
 Libs: -L${libdir} -lmutter
 Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}
diff --git a/src/meta/common.h b/src/meta/common.h
index 3f31267..40d63db 100644
--- a/src/meta/common.h
+++ b/src/meta/common.h
@@ -1,6 +1,9 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 
-/* Mutter common types shared by core.h and ui.h */
+/* Mutter common types shared by core.h and ui.h
+ *
+ * PLEASE KEEP IN SYNC WITH GSETTINGS SCHEMAS!
+ */
 
 /* 
  * Copyright (C) 2001 Havoc Pennington
@@ -166,32 +169,6 @@ typedef enum
 
 typedef enum
 {
-  META_FOCUS_MODE_CLICK,
-  META_FOCUS_MODE_SLOPPY,
-  META_FOCUS_MODE_MOUSE
-} MetaFocusMode;
-
-typedef enum
-{
-  META_FOCUS_NEW_WINDOWS_SMART,
-  META_FOCUS_NEW_WINDOWS_STRICT
-} MetaFocusNewWindows;
-
-typedef enum
-{
-  META_ACTION_TITLEBAR_TOGGLE_SHADE,
-  META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE,
-  META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_HORIZONTALLY,
-  META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_VERTICALLY,
-  META_ACTION_TITLEBAR_MINIMIZE,
-  META_ACTION_TITLEBAR_NONE,
-  META_ACTION_TITLEBAR_LOWER,
-  META_ACTION_TITLEBAR_MENU,
-  META_ACTION_TITLEBAR_LAST
-} MetaActionTitlebar;
-
-typedef enum
-{
   META_FRAME_TYPE_NORMAL,
   META_FRAME_TYPE_DIALOG,
   META_FRAME_TYPE_MODAL_DIALOG,
@@ -374,10 +351,8 @@ void meta_frame_borders_clear (MetaFrameBorders *self);
 
 /* G_PRIORITY_DEFAULT_IDLE:
  *  Mutter plugin unloading
- *  GConf notify idle
  */
 
-/* Chosen to be below the GConf notify idle */
 #define META_PRIORITY_PREFS_NOTIFY   (G_PRIORITY_DEFAULT_IDLE + 10)
 
 /************************************************************/
diff --git a/src/meta/prefs.h b/src/meta/prefs.h
index 31256d4..099aef7 100644
--- a/src/meta/prefs.h
+++ b/src/meta/prefs.h
@@ -28,7 +28,9 @@
 /* This header is a "common" one between the UI and core side */
 #include <meta/common.h>
 #include <pango/pango-font.h>
+#include <gdesktop-enums.h>
 
+/* Keep in sync with GSettings schemas! */
 typedef enum
 {
   META_PREF_MOUSE_BUTTON_MODS,
@@ -47,8 +49,6 @@ typedef enum
   META_PREF_APPLICATION_BASED,
   META_PREF_KEYBINDINGS,
   META_PREF_DISABLE_WORKAROUNDS,
-  META_PREF_COMMANDS,
-  META_PREF_TERMINAL_COMMAND,
   META_PREF_BUTTON_LAYOUT,
   META_PREF_WORKSPACE_NAMES,
   META_PREF_VISUAL_BELL,
@@ -77,16 +77,16 @@ void meta_prefs_remove_listener (MetaPrefsChangedFunc func,
 
 void meta_prefs_init (void);
 
-void meta_prefs_override_preference_location (const char *original_key,
-                                              const char *new_key);
+void meta_prefs_override_preference_schema (const char *key,
+                                            const char *schema);
 
 const char* meta_preference_to_string (MetaPreference pref);
 
 MetaVirtualModifier         meta_prefs_get_mouse_button_mods  (void);
 guint                       meta_prefs_get_mouse_button_resize (void);
 guint                       meta_prefs_get_mouse_button_menu  (void);
-MetaFocusMode               meta_prefs_get_focus_mode         (void);
-MetaFocusNewWindows         meta_prefs_get_focus_new_windows  (void);
+GDesktopFocusMode           meta_prefs_get_focus_mode         (void);
+GDesktopFocusNewWindows     meta_prefs_get_focus_new_windows  (void);
 gboolean                    meta_prefs_get_attach_modal_dialogs (void);
 gboolean                    meta_prefs_get_raise_on_click     (void);
 const char*                 meta_prefs_get_theme              (void);
@@ -101,19 +101,18 @@ gboolean                    meta_prefs_get_gnome_accessibility (void);
 gboolean                    meta_prefs_get_gnome_animations   (void);
 gboolean                    meta_prefs_get_edge_tiling        (void);
 
-const char*                 meta_prefs_get_command            (int i);
+const char*                 meta_prefs_get_screenshot_command (void);
 
-char*                       meta_prefs_get_gconf_key_for_command (int i);
+const char*                 meta_prefs_get_window_screenshot_command (void);
 
 const char*                 meta_prefs_get_terminal_command   (void);
-const char*                 meta_prefs_get_gconf_key_for_terminal_command (void);
 
 void                        meta_prefs_get_button_layout (MetaButtonLayout *button_layout);
 
 /* Double, right, middle click can be configured to any titlebar meta-action */
-MetaActionTitlebar          meta_prefs_get_action_double_click_titlebar (void);
-MetaActionTitlebar          meta_prefs_get_action_middle_click_titlebar (void);
-MetaActionTitlebar          meta_prefs_get_action_right_click_titlebar (void);
+GDesktopTitlebarAction      meta_prefs_get_action_double_click_titlebar (void);
+GDesktopTitlebarAction      meta_prefs_get_action_middle_click_titlebar (void);
+GDesktopTitlebarAction      meta_prefs_get_action_right_click_titlebar (void);
 
 void meta_prefs_set_num_workspaces (int n_workspaces);
 
@@ -187,41 +186,6 @@ typedef enum _MetaKeyBindingAction
   META_KEYBINDING_ACTION_PANEL_MAIN_MENU,
   META_KEYBINDING_ACTION_PANEL_RUN_DIALOG,
   META_KEYBINDING_ACTION_TOGGLE_RECORDING,
-  META_KEYBINDING_ACTION_COMMAND_1,
-  META_KEYBINDING_ACTION_COMMAND_2,
-  META_KEYBINDING_ACTION_COMMAND_3,
-  META_KEYBINDING_ACTION_COMMAND_4,
-  META_KEYBINDING_ACTION_COMMAND_5,
-  META_KEYBINDING_ACTION_COMMAND_6,
-  META_KEYBINDING_ACTION_COMMAND_7,
-  META_KEYBINDING_ACTION_COMMAND_8,
-  META_KEYBINDING_ACTION_COMMAND_9,
-  META_KEYBINDING_ACTION_COMMAND_10,
-  META_KEYBINDING_ACTION_COMMAND_11,
-  META_KEYBINDING_ACTION_COMMAND_12,
-  META_KEYBINDING_ACTION_COMMAND_13,
-  META_KEYBINDING_ACTION_COMMAND_14,
-  META_KEYBINDING_ACTION_COMMAND_15,
-  META_KEYBINDING_ACTION_COMMAND_16,
-  META_KEYBINDING_ACTION_COMMAND_17,
-  META_KEYBINDING_ACTION_COMMAND_18,
-  META_KEYBINDING_ACTION_COMMAND_19,
-  META_KEYBINDING_ACTION_COMMAND_20,
-  META_KEYBINDING_ACTION_COMMAND_21,
-  META_KEYBINDING_ACTION_COMMAND_22,
-  META_KEYBINDING_ACTION_COMMAND_23,
-  META_KEYBINDING_ACTION_COMMAND_24,
-  META_KEYBINDING_ACTION_COMMAND_25,
-  META_KEYBINDING_ACTION_COMMAND_26,
-  META_KEYBINDING_ACTION_COMMAND_27,
-  META_KEYBINDING_ACTION_COMMAND_28,
-  META_KEYBINDING_ACTION_COMMAND_29,
-  META_KEYBINDING_ACTION_COMMAND_30,
-  META_KEYBINDING_ACTION_COMMAND_31,
-  META_KEYBINDING_ACTION_COMMAND_32,
-  META_KEYBINDING_ACTION_COMMAND_SCREENSHOT,
-  META_KEYBINDING_ACTION_COMMAND_WINDOW_SCREENSHOT,
-  META_KEYBINDING_ACTION_COMMAND_TERMINAL,
   META_KEYBINDING_ACTION_SET_SPEW_MARK,
   META_KEYBINDING_ACTION_ACTIVATE_WINDOW_MENU,
   META_KEYBINDING_ACTION_TOGGLE_FULLSCREEN,
@@ -279,13 +243,10 @@ typedef struct
 typedef struct
 {
   const char   *name;
-  const char   *default_keybinding;
   /**
    * A list of MetaKeyCombos. Each of them is bound to
    * this keypref. If one has keysym==modifiers==0, it is
-   * ignored. For historical reasons, the first entry is
-   * governed by the pref FOO and the remainder are
-   * governed by the pref FOO_list.
+   * ignored.
    */
   GSList *bindings;
 
@@ -307,17 +268,8 @@ void meta_prefs_get_window_binding (const char          *name,
 
 void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
 
-typedef enum
-{
-  META_VISUAL_BELL_INVALID = 0,
-  META_VISUAL_BELL_FULLSCREEN_FLASH,
-  META_VISUAL_BELL_FRAME_FLASH
-
-} MetaVisualBellType;
-
-gboolean           meta_prefs_get_visual_bell      (void);
 gboolean           meta_prefs_bell_is_audible      (void);
-MetaVisualBellType meta_prefs_get_visual_bell_type (void);
+GDesktopVisualBellType meta_prefs_get_visual_bell_type (void);
 
 #endif
 
diff --git a/src/mutter-schemas.convert b/src/mutter-schemas.convert
new file mode 100644
index 0000000..92bea5a
--- /dev/null
+++ b/src/mutter-schemas.convert
@@ -0,0 +1,6 @@
+[org.gnome.mutter]
+overlay-key = /apps/mutter/general/overlay_key
+attach-modal-dialogs = /apps/mutter/general/attach_modal_dialogs
+live-hidden-windows = /apps/mutter/general/live_hidden_windows
+workspaces-only-on-primary = /apps/mutter/general/workspaces_only_on_primary
+draggable-border-width = /apps/mutter/general/draggable_border_width
diff --git a/src/org.gnome.mutter.gschema.xml.in b/src/org.gnome.mutter.gschema.xml.in
new file mode 100644
index 0000000..76f13d6
--- /dev/null
+++ b/src/org.gnome.mutter.gschema.xml.in
@@ -0,0 +1,97 @@
+<schemalist>
+  <schema id="org.gnome.mutter" path="/org/gnome/mutter/"
+          gettext-domain="@GETTEXT_DOMAIN">
+
+    <key name="overlay-key" type="s">
+      <default>'Super_L'</default>
+      <_summary>Modifier to use for extended window management operations</_summary>
+      <_description>
+        This key will initiate the "overlay", which is a combination window
+        overview and application launching system.  The default is intended
+        to be the "Windows key" on PC hardware.
+
+        It's expected that this binding either the default or set to
+        the empty string.
+      </_description>
+    </key>
+
+    <key name="attach-modal-dialogs" type="b">
+      <default>false</default>
+      <_summary>Attach modal dialogs</_summary>
+      <_description>
+        When true, instead of having independent titlebars, modal dialogs
+        appear attached to the titlebar of the parent window and are moved
+        together with the parent window.
+      </_description>
+    </key>
+
+    <key name="live-hidden-windows" type="b">
+      <default>false</default>
+      <_summary>Live Hidden Windows</_summary>
+      <_description>
+        Determines whether hidden windows (i.e., minimized windows and
+        windows on other workspaces than the current one) should be kept
+        alive.
+      </_description>
+    </key>
+
+    <key name="edge-tiling" type="b">
+      <default>false</default>
+      <_summary>Enable edge tiling when dropping windows on screen edges</_summary>
+      <_description>
+        If enabled, dropping windows on vertical screen edges maximizes them
+        vertically and resizes them horizontally to cover half of the available
+        area. Dropping windows on the top screen edge maximizes them completely.
+      </_description>
+    </key>
+
+    <key name="workspaces-only-on-primary" type="b">
+      <default>false</default>
+      <_summary>Workspaces only on primary</_summary>
+      <_description>
+        Determines whether workspace switching should happen for windows
+        on all monitors or only for windows on the primary monitor.
+      </_description>
+    </key>
+
+    <key name="no-tab-popup" type="b">
+      <default>false</default>
+      <_summary>No tab popup</_summary>
+      <_description>
+        Determines whether the use of popup and highlight frame should
+        be disabled for window cycling.
+      </_description>
+    </key>
+
+    <key name="draggable-border-width" type="i">
+      <default>10</default>
+      <range min="0" max="64"/>
+      <_summary>Draggable border width</_summary>
+      <_description>
+          The amount of total draggable borders. If the theme's visible
+          borders are not enough, invisible borders will be added to meet
+          this value.
+      </_description>
+    </key>
+
+    <child name="keybindings" schema="org.gnome.mutter.keybindings"/>
+
+  </schema>
+  <schema id="org.gnome.mutter.keybindings" path="/org/gnome/mutter/keybindings/">
+
+    <key name="toggle-recording" type="as">
+      <default><![CDATA[['<Control><Shift><Alt>r']]]></default>
+    </key>
+
+    <key name="tab-popup-select" type="as">
+      <default>[]</default>
+      <_summary>Select window from tab popup</_summary>
+    </key>
+
+    <key name="tab-popup-cancel" type="as">
+      <default>[]</default>
+      <_summary>Cancel tab popup</_summary>
+    </key>
+
+  </schema>
+</schemalist>
diff --git a/src/ui/frames.c b/src/ui/frames.c
index 83003ee..0204f1a 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -1299,7 +1299,7 @@ meta_frame_titlebar_event (MetaUIFrame    *frame,
   
   switch (action)
     {
-    case META_ACTION_TITLEBAR_TOGGLE_SHADE:
+    case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_SHADE:
       {
         meta_core_get (display, frame->xwindow,
                        META_CORE_GET_FRAME_FLAGS, &flags,
@@ -1319,7 +1319,7 @@ meta_frame_titlebar_event (MetaUIFrame    *frame,
       }
       break;          
       
-    case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE:
+    case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE:
       {
         meta_core_get (display, frame->xwindow,
                        META_CORE_GET_FRAME_FLAGS, &flags,
@@ -1332,7 +1332,7 @@ meta_frame_titlebar_event (MetaUIFrame    *frame,
       }
       break;
 
-    case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_HORIZONTALLY:
+    case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE_HORIZONTALLY:
       {
         meta_core_get (display, frame->xwindow,
                        META_CORE_GET_FRAME_FLAGS, &flags,
@@ -1345,7 +1345,7 @@ meta_frame_titlebar_event (MetaUIFrame    *frame,
       }
       break;
 
-    case META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE_VERTICALLY:
+    case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_MAXIMIZE_VERTICALLY:
       {
         meta_core_get (display, frame->xwindow,
                        META_CORE_GET_FRAME_FLAGS, &flags,
@@ -1358,7 +1358,7 @@ meta_frame_titlebar_event (MetaUIFrame    *frame,
       }
       break;
 
-    case META_ACTION_TITLEBAR_MINIMIZE:
+    case G_DESKTOP_TITLEBAR_ACTION_MINIMIZE:
       {
         meta_core_get (display, frame->xwindow,
                        META_CORE_GET_FRAME_FLAGS, &flags,
@@ -1371,17 +1371,17 @@ meta_frame_titlebar_event (MetaUIFrame    *frame,
       }
       break;
 
-    case META_ACTION_TITLEBAR_NONE:
+    case G_DESKTOP_TITLEBAR_ACTION_NONE:
       /* Yaay, a sane user that doesn't use that other weird crap! */
       break;
     
-    case META_ACTION_TITLEBAR_LOWER:
+    case G_DESKTOP_TITLEBAR_ACTION_LOWER:
       meta_core_user_lower_and_unfocus (display,
                                         frame->xwindow,
                                         event->time);
       break;
 
-    case META_ACTION_TITLEBAR_MENU:
+    case G_DESKTOP_TITLEBAR_ACTION_MENU:
       meta_core_show_window_menu (display,
                                   frame->xwindow,
                                   event->x_root,
@@ -1389,9 +1389,6 @@ meta_frame_titlebar_event (MetaUIFrame    *frame,
                                   event->button,
                                   event->time);
       break;
-
-    case META_ACTION_TITLEBAR_LAST:
-      break;
     }
   
   return TRUE;
diff --git a/test/mutter-test b/test/mutter-test
index 3f22b67..463e0ba 100644
--- a/test/mutter-test
+++ b/test/mutter-test
@@ -195,10 +195,6 @@ class test_ansi(BuildTest):
     def run(self):
         return self.run_build(c='ansi')
 
-class test_gconfoff(BuildTest):
-    def run(self):
-        return self.run_build(autogen='--disable-gconf')
-
 class test_compositoroff(BuildTest):
     def run(self):
         return self.run_build(autogen='--disable-compositor')



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]