diff -uNr a/configure.ac b/configure.ac
--- a/configure.ac	2013-05-22 17:35:08.000000000 +0100
+++ b/configure.ac	2013-05-22 21:36:04.000000000 +0100
@@ -68,6 +68,7 @@
 GIO_MIN_VERSION=2.29.10
 POLKIT_MIN_VERSION=0.100
 STARTUP_NOTIFICATION_MIN_VERSION=0.11
+GNOME_DESKTOP_MIN_VERSION=3.0.0
 
 # Collect more than 20 libraries for a prize!
 PKG_CHECK_MODULES(CINNAMON, gio-2.0 >= $GIO_MIN_VERSION
@@ -82,7 +83,8 @@
                                gobject-introspection-1.0 >= $GOBJECT_INTROSPECTION_MIN_VERSION
 			       libcanberra
                                polkit-agent-1 >= $POLKIT_MIN_VERSION xfixes
-                               libnm-glib libnm-util gnome-keyring-1)
+                               libnm-glib libnm-util gnome-keyring-1
+                               gnome-desktop-3.0 >= GNOME_DESKTOP_MIN_VERSION)
 
 PKG_CHECK_MODULES(CINNAMON_PERF_HELPER, gtk+-3.0 gio-2.0)
 
@@ -106,7 +108,8 @@
 CFLAGS=$saved_CFLAGS
 LIBS=$saved_LIBS
 
-PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.2 gnome-desktop-3.0 >= 2.90.0 x11)
+PKG_CHECK_MODULES(ST, clutter-1.0 gtk+-3.0 libcroco-0.6 >= 0.6.2 
+                      gnome-desktop-3.0 >= GNOME_DESKTOP_MIN_VERSION x11)
 PKG_CHECK_MODULES(GDMUSER, dbus-glib-1 gtk+-3.0)
 PKG_CHECK_MODULES(TRAY, gtk+-3.0)
 PKG_CHECK_MODULES(GVC, libpulse libpulse-mainloop-glib gobject-2.0)
diff -uNr a/data/org.cinnamon.gschema.xml.in b/data/org.cinnamon.gschema.xml.in
--- a/data/org.cinnamon.gschema.xml.in	2013-05-22 17:35:08.000000000 +0100
+++ b/data/org.cinnamon.gschema.xml.in	2013-05-22 21:36:04.000000000 +0100
@@ -754,6 +754,23 @@
     </key>
   </schema>
 
+
+  <enum id="bg_style">
+    <value nick="none" value="0"/>
+    <value nick="wallpaper" value="1"/>
+    <value nick="centered" value="2"/>
+    <value nick="scaled" value="3"/>
+    <value nick="stretched" value="4"/>
+    <value nick="zoom" value="5"/>
+    <value nick="spanned" value="6"/>
+  </enum>
+
+  <enum id="bg_shading">
+    <value nick="solid" value="0"/>
+    <value nick="vertical" value="1"/>
+    <value nick="horizontal" value="2"/>
+  </enum>
+
   <schema id="org.cinnamon.background" path="/org/cinnamon/background/">
     <key name="mode" type="s">
       <default>"wallpaper"</default>
@@ -784,8 +801,60 @@
         This key defines the delay for the slideshow.
       </description>
     </key>
+    <key name="draw-background" type="b">
+      <default>true</default>
+      <_summary>Draw Desktop Background</_summary>
+      <_description>Have GNOME draw the desktop background.</_description>
+    </key>
+    <key name="picture-options" enum="bg_style">
+      <default>'zoom'</default>
+      <_summary>Picture Options</_summary>
+      <_description>
+        Determines how the image set by wallpaper_filename is rendered.
+        Possible values are "none", "wallpaper", "centered", "scaled",
+        "stretched", "zoom", "spanned".
+      </_description>
+    </key>
+    <key name="picture-uri" type="s">
+      <default>'file:///usr/share/themes/Adwaita/backgrounds/adwaita-timed.xml'</default>
+      <_summary>Picture URI</_summary>
+      <_description>
+        URI to use for the background image. Not that the backend only supports
+        local (file://) URIs.
+      </_description>
+    </key>
+    <key name="picture-opacity" type="i">
+      <range min="0" max="100"/>
+      <default>100</default>
+      <_summary>Picture Opacity</_summary>
+      <_description>
+        Opacity with which to draw the background picture.
+      </_description>
+    </key>
+    <key name="primary-color" type="s">
+      <default>'#023c88'</default>
+      <_summary>Primary Color</_summary>
+      <_description>
+        Left or Top color when drawing gradients, or the solid color.
+      </_description>
+    </key>
+    <key name="secondary-color" type="s">
+      <default>'#5789ca'</default>
+      <_summary>Secondary Color</_summary>
+      <_description>
+        Right or Bottom color when drawing gradients, not used for solid color.
+      </_description>
+    </key>
+    <key name="color-shading-type" enum="bg_shading">
+      <default>'solid'</default>
+      <_summary>Color Shading Type</_summary>
+      <_description>
+        How to shade the background color. Possible values are "horizontal",
+        "vertical", and "solid".
+      </_description>
+    </key>
   </schema>
-  
+
   <schema id="org.cinnamon.screensaver" path="/org/cinnamon/screensaver/">
     <key name="default-message" type="s">
       <default>""</default>
diff -uNr a/files/usr/bin/cinnamon2d b/files/usr/bin/cinnamon2d
--- a/files/usr/bin/cinnamon2d	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/bin/cinnamon2d	2013-05-22 21:36:04.000000000 +0100
@@ -1,2 +1,2 @@
 #!/bin/bash
-CLUTTER_PAINT=disable-clipped-redraws:disable-culling LIBGL_ALWAYS_SOFTWARE=1 CINNAMON_SOFTWARE_RENDERING=1 CINNAMON_SLOWDOWN_FACTOR=0.0001 MUFFIN_NO_SHADOWS=1 CLUTTER_DEFAULT_FPS=15 cinnamon $@
+CLUTTER_DISABLE_XINPUT=1 CLUTTER_PAINT=disable-clipped-redraws:disable-culling LIBGL_ALWAYS_SOFTWARE=1 CINNAMON_SOFTWARE_RENDERING=1 CINNAMON_SLOWDOWN_FACTOR=0.0001 MUFFIN_NO_SHADOWS=1 CLUTTER_DEFAULT_FPS=15 cinnamon $@
diff -uNr a/files/usr/bin/cinnamon3d b/files/usr/bin/cinnamon3d
--- a/files/usr/bin/cinnamon3d	1970-01-01 01:00:00.000000000 +0100
+++ b/files/usr/bin/cinnamon3d	2013-05-22 21:36:04.000000000 +0100
@@ -0,0 +1,2 @@
+#!/bin/bash
+CLUTTER_DISABLE_XINPUT=1 cinnamon $@
diff -uNr a/files/usr/bin/gnome-session-cinnamon b/files/usr/bin/gnome-session-cinnamon
--- a/files/usr/bin/gnome-session-cinnamon	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/bin/gnome-session-cinnamon	2013-05-22 21:36:04.000000000 +0100
@@ -1,3 +1,3 @@
 #! /bin/sh
-exec gnome-session --session cinnamon "$@"
+CLUTTER_DISABLE_XINPUT=1 exec gnome-session --session cinnamon "$@"
 
diff -uNr a/files/usr/lib/cinnamon-settings/modules/cs_backgrounds.py b/files/usr/lib/cinnamon-settings/modules/cs_backgrounds.py
--- a/files/usr/lib/cinnamon-settings/modules/cs_backgrounds.py	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/lib/cinnamon-settings/modules/cs_backgrounds.py	2013-05-22 21:36:04.000000000 +0100
@@ -232,11 +232,11 @@
     
 
 class BackgroundWallpaperPane (Gtk.VBox):
-    def __init__(self, sidepage, gnome_background_schema):
+    def __init__(self, sidepage, cinnamon_background_schema):
         Gtk.VBox.__init__(self)
         self.set_spacing(5)
         
-        self._gnome_background_schema = gnome_background_schema
+        self._cinnamon_background_schema = cinnamon_background_schema
         self._sidepage = sidepage
         
         scw = Gtk.ScrolledWindow()
@@ -263,15 +263,15 @@
         if wallpaper:
             for key in wallpaper:
                 if key == "filename":
-                    self._gnome_background_schema.set_string("picture-uri", "file://" + wallpaper[key])
+                    self._cinnamon_background_schema.set_string("picture-uri", "file://" + wallpaper[key])
                 elif key == "pcolor":
-                    self._gnome_background_schema.set_string("primary-color", wallpaper[key])
+                    self._cinnamon_background_schema.set_string("primary-color", wallpaper[key])
                 elif key == "scolor":
-                    self._gnome_background_schema.set_string("secondary-color", wallpaper[key])
+                    self._cinnamon_background_schema.set_string("secondary-color", wallpaper[key])
                 elif key == "shade_type":
-                    self._gnome_background_schema.set_string("color-shading-type", wallpaper[key])
+                    self._cinnamon_background_schema.set_string("color-shading-type", wallpaper[key])
                 elif key == "options":
-                    self._gnome_background_schema.set_string("picture-options", wallpaper[key])
+                    self._cinnamon_background_schema.set_string("picture-options", wallpaper[key])
             if (not "metadataFile" in wallpaper) or (wallpaper["metadataFile"] == ""):
                 self._sidepage.remove_wallpaper_button.set_sensitive(True)
     
@@ -365,7 +365,7 @@
         return res
 
 class BackgroundSlideshowPane(Gtk.Table):
-    def __init__(self, sidepage, gnome_background_schema, cinnamon_background_schema):
+    def __init__(self, sidepage, cinnamon_background_schema):
         Gtk.Table.__init__(self)
         self.set_col_spacings(5)
         self.set_row_spacings(5)
@@ -446,12 +446,11 @@
             f = open(filename, "w")
             f.write(xml_data)
             f.close()
-            Gio.Settings("org.gnome.desktop.background").set_string("picture-uri", "file://" + filename)
+            Gio.Settings("org.cinnamon.background").set_string("picture-uri", "file://" + filename)
 
 class BackgroundSidePage (SidePage):
     def __init__(self, name, icon, keywords, advanced, content_box):
         SidePage.__init__(self, name, icon, keywords, advanced, content_box, -1)
-        self._gnome_background_schema = Gio.Settings("org.gnome.desktop.background")
         self._cinnamon_background_schema = Gio.Settings("org.cinnamon.background")
         self._add_wallpapers_dialog = AddWallpapersDialog()
         
@@ -516,8 +515,8 @@
         self.mainbox.set_visible_window(False)
         self.content_box.pack_start(self.mainbox, True, True, 3)
         
-        self.wallpaper_pane = BackgroundWallpaperPane(self, self._gnome_background_schema)
-        self.slideshow_pane = BackgroundSlideshowPane(self, self._gnome_background_schema, self._cinnamon_background_schema)
+        self.wallpaper_pane = BackgroundWallpaperPane(self, self._cinnamon_background_schema)
+        self.slideshow_pane = BackgroundSlideshowPane(self, self._cinnamon_background_schema)
         if self._cinnamon_background_schema["mode"] == "slideshow":
             self.mainbox.add(self.slideshow_pane)
         else:
@@ -537,21 +536,21 @@
         l = Gtk.Label(_("Picture aspect"))
         l.set_alignment(0, 0.5)
         advanced_options_box.pack_start(l, False, False, 0)
-        self.picture_options = GSettingsComboBox("", "org.gnome.desktop.background", "picture-options", None, BACKGROUND_PICTURE_OPTIONS)
+        self.picture_options = GSettingsComboBox("", "org.cinnamon.background", "picture-options", None, BACKGROUND_PICTURE_OPTIONS)
         advanced_options_box.pack_start(self.picture_options, False, False, 0)
         
         l = Gtk.Label(_("Gradient"))
         l.set_alignment(0, 0.5)
         advanced_options_box.pack_start(l, False, False, 0)
-        self.color_shading_type = GSettingsComboBox("", "org.gnome.desktop.background", "color-shading-type", None, BACKGROUND_COLOR_SHADING_TYPES)
+        self.color_shading_type = GSettingsComboBox("", "org.cinnamon.background", "color-shading-type", None, BACKGROUND_COLOR_SHADING_TYPES)
         advanced_options_box.pack_start(self.color_shading_type, False, False, 0)
         
         hbox = Gtk.HBox()
         l = Gtk.Label(_("Colors"))
         hbox.pack_start(l, False, False, 2)
-        self.primary_color = GSettingsColorChooser("org.gnome.desktop.background", "primary-color", None)
+        self.primary_color = GSettingsColorChooser("org.cinnamon.background", "primary-color", None)
         hbox.pack_start(self.primary_color, False, False, 2)
-        self.secondary_color = GSettingsColorChooser("org.gnome.desktop.background", "secondary-color", None)
+        self.secondary_color = GSettingsColorChooser("org.cinnamon.background", "secondary-color", None)
         hbox.pack_start(self.secondary_color, False, False, 2)
         advanced_options_box.pack_start(hbox, False, False, 0)
         self.content_box.show_all()
diff -uNr a/files/usr/lib/cinnamon-settings/modules/cs_keyboard.py b/files/usr/lib/cinnamon-settings/modules/cs_keyboard.py
--- a/files/usr/lib/cinnamon-settings/modules/cs_keyboard.py	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/lib/cinnamon-settings/modules/cs_keyboard.py	2013-05-22 21:36:04.000000000 +0100
@@ -42,8 +42,8 @@
     # Cinnamon stuff
     [_("Toggle Scale"), "org.gnome.desktop.wm.keybindings", "switch-to-workspace-down", True, "cinnamon"],
     [_("Toggle Expo"), "org.gnome.desktop.wm.keybindings", "switch-to-workspace-up", True, "cinnamon"],
-    [_("Cycle through open windows"), "org.gnome.desktop.wm.keybindings", "switch-windows", True, "cinnamon"],
-    [_("Cycle backwards though open windows"), "org.gnome.desktop.wm.keybindings", "switch-windows-backward", True, "cinnamon"],
+    [_("Cycle through open windows"), "org.gnome.desktop.wm.keybindings", "switch-applications", True, "cinnamon"],
+    [_("Cycle backwards though open windows"), "org.gnome.desktop.wm.keybindings", "switch-applications-backward", True, "cinnamon"],
     [_("Run dialog (must restart Cinnamon)"), "org.gnome.desktop.wm.keybindings", "panel-run-dialog", True, "cinnamon"],
     [_("Menu button (must restart Cinnamon)"), "org.cinnamon.muffin", "overlay-key", False, "cinnamon"],
 
diff -uNr a/files/usr/share/cinnamon/applets/brightness@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/brightness@cinnamon.org/applet.js
--- a/files/usr/share/cinnamon/applets/brightness@cinnamon.org/applet.js	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/share/cinnamon/applets/brightness@cinnamon.org/applet.js	2013-05-22 21:36:04.000000000 +0100
@@ -5,7 +5,6 @@
 const PopupMenu = imports.ui.popupMenu;
 const GLib = imports.gi.GLib;
 const Gio = imports.gi.Gio;
-const DBus = imports.dbus;
 
 /* constants */
 const DimSettingsSchema = "org.gnome.settings-daemon.plugins.power";
@@ -14,24 +13,25 @@
 const PowerBusName = 'org.gnome.SettingsDaemon';
 const PowerObjectPath = '/org/gnome/SettingsDaemon/Power';
 
-/* DBus interface */
-const PowerManagerInterface = {
-    name: 'org.gnome.SettingsDaemon.Power.Screen',
-    methods:
-        [
-            { name: 'GetPercentage', inSignature: '', outSignature: 'u' },
-            { name: 'SetPercentage', inSignature: 'u', outSignature: 'u' },
-            { name: 'StepUp', inSignature: '', outSignature: 'u' },
-            { name: 'StepDown', inSignature: '', outSignature: 'u' },
-        ],
-    signals:
-        [
-            { name: 'Changed', inSignature: '', outSignature: '' },
-        ]
-};
+const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power.Screen">
+<method name="GetPercentage">
+    <arg type="u" direction="out"/>
+</method>
+<method name="SetPercentage">
+    <arg type="u" direction="in"/>
+    <arg type="u" direction="out"/>
+</method>
+<method name="StepUp">
+    <arg type="u" direction="out"/>
+</method>
+<method name="StepDown">
+    <arg type="u" direction="out"/>
+</method>
+<signal name="Changed" />
+</interface>;
 
 /* DBus magic */
-let PowerManagerProxy = DBus.makeProxyClass(PowerManagerInterface);
+const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
 
 /* TextImageMenuItem taken from sound@cinnamon.org applet */
 let icon_path = "/usr/share/cinnamon/theme/";
@@ -100,7 +100,7 @@
         Applet.IconApplet.prototype._init.call(this, orientation, panel_height);
         
         try {
-            this._proxy = new PowerManagerProxy(DBus.session, PowerBusName, PowerObjectPath);
+            this._proxy = new PowerManagerProxy(Gio.DBus.session, PowerBusName, PowerObjectPath);
             
             this.menuManager = new PopupMenu.PopupMenuManager(this);
             this.menu = new Applet.AppletPopupMenu(this, orientation);
@@ -137,7 +137,8 @@
                     this.menu.addMenuItem(this._settingsMenu);
                 
                     //get notified
-                    this._proxy.connect('Changed', Lang.bind(this, this._getBrightness));
+                    this._proxy.connectSignal('Changed', Lang.bind(this, this._getBrightness));
+                    
                     this.actor.connect('scroll-event', Lang.bind(this, this._onScrollEvent));
                 } else {
                     this.set_applet_tooltip(_("Brightness"));
diff -uNr a/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js
--- a/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/share/cinnamon/applets/power@cinnamon.org/applet.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,6 +1,5 @@
 const Applet = imports.ui.applet;
 const Gio = imports.gi.Gio;
-const DBus = imports.dbus;
 const Lang = imports.lang;
 const St = imports.gi.St;
 const PopupMenu = imports.ui.popupMenu;
@@ -42,34 +41,17 @@
     TIME: 'time'
 };
 
-const PowerManagerInterface = {
-    name: 'org.gnome.SettingsDaemon.Power',
-    methods: [
-        { name: 'GetDevices', inSignature: '', outSignature: 'a(susdut)' },
-        { name: 'GetPrimaryDevice', inSignature: '', outSignature: '(susdut)' },
-        ],
-    signals: [
-        { name: 'PropertiesChanged', inSignature: 's,a{sv},a[s]' },
-        ],
-    properties: [
-        { name: 'Icon', signature: 's', access: 'read' },
-        ]
-};
-let PowerManagerProxy = DBus.makeProxyClass(PowerManagerInterface);
-
-const SettingsManagerInterface = {
-	name: 'org.freedesktop.DBus.Properties',
-	methods: [
-		{ name: 'Get', inSignature: 's,s', outSignature: 'v' },
-		{ name: 'GetAll', inSignature: 's', outSignature: 'a{sv}' },
-		{ name: 'Set', inSignature: 's,s,v', outSignature: '' }
-	],
-	signals: [
-	{name: 'PropertiesChanged', inSignature:'s,a{sv},a[s]', outSignature:''}
-	]
-};
+const PowerManagerInterface = <interface name="org.gnome.SettingsDaemon.Power">
+<method name="GetDevices">
+    <arg type="a(susdut)" direction="out"/>
+</method>
+<method name="GetPrimaryDevice">
+    <arg type="(susdut)" direction="out"/>
+</method>
+<property name="Icon" type="s" access="read" />
+</interface>;
 
-let SettingsManagerProxy = DBus.makeProxyClass(SettingsManagerInterface);
+const PowerManagerProxy = Gio.DBusProxy.makeProxyWrapper(PowerManagerInterface);
 
 function DeviceItem() {
     this._init.apply(this, arguments);
@@ -143,11 +125,19 @@
             this.menuManager = new PopupMenu.PopupMenuManager(this);
             this.menu = new Applet.AppletPopupMenu(this, orientation);
             this.menuManager.addMenu(this.menu);            
-            
+
             //this.set_applet_icon_symbolic_name('battery-missing');            
-            this._proxy = new PowerManagerProxy(DBus.session, BUS_NAME, OBJECT_PATH);
-            this._smProxy = new SettingsManagerProxy(DBus.session, BUS_NAME, OBJECT_PATH);
-            
+            this._proxy = new PowerManagerProxy(Gio.DBus.session, BUS_NAME, OBJECT_PATH,
+                                               Lang.bind(this, function(proxy, error) {
+                                                             if (error) {
+                                                                 global.log(error.message);
+
+                                                                 return;
+                                                             }
+                                                             this._proxy.connect('g-properties-changed', Lang.bind(this, this._devicesChanged));
+                                                             this._devicesChanged();
+                                               }));
+
             let icon = this.actor.get_children()[0];
             this.actor.remove_actor(icon);
             let box = new St.BoxLayout({ name: 'batteryBox' });
@@ -200,9 +190,6 @@
 
             this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
             this.menu.addSettingsAction(_("Power Settings"), 'power');
-
-            this._smProxy.connect('PropertiesChanged', Lang.bind(this, this._devicesChanged));
-            this._devicesChanged();            
         }
         catch (e) {
             global.logError(e);
@@ -234,14 +221,14 @@
     },
     
     _readPrimaryDevice: function() {
-        this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(device, error) {
+        this._proxy.GetPrimaryDeviceRemote(Lang.bind(this, function(result, error) {
             if (error) {
                 this._hasPrimary = false;
                 this._primaryDeviceId = null;
                 this._batteryItem.actor.hide();                
                 return;
             }
-            let [device_id, device_type, icon, percentage, state, seconds] = device;
+            let [[device_id, device_type, icon, percentage, state, seconds]] = result;
             if (device_type == UPDeviceType.BATTERY) {
                 this._hasPrimary = true;
                 let time = Math.round(seconds / 60);
@@ -279,7 +266,7 @@
     },
 
     _readOtherDevices: function() {
-        this._proxy.GetDevicesRemote(Lang.bind(this, function(devices, error) {
+        this._proxy.GetDevicesRemote(Lang.bind(this, function([devices], error) {
             this._deviceItems.forEach(function(i) { i.destroy(); });
             this._deviceItems = [];
 
@@ -306,25 +293,26 @@
         this._devicesChanged();
     },
 
-    _devicesChanged: function() {        
-        this._proxy.GetRemote('Icon', Lang.bind(this, function(icon, error) {
-            if (icon) {    
-                this.set_applet_icon_symbolic_name('battery-missing');
-                let gicon = Gio.icon_new_for_string(icon);
-                this._applet_icon.gicon = gicon;
-                this.actor.show();
-            } else {
-                this.menu.close();
-                this.actor.hide();
-            }
-        }));
+
+    _devicesChanged: function() {
+        this.set_applet_icon_symbolic_name('battery-missing');
+        let icon = this._proxy.Icon;
+        if (icon) {
+            let gicon = Gio.icon_new_for_string(icon);
+            this._applet_icon.gicon = gicon
+            this.actor.show();
+        } else {
+            this.menu.close();
+            this.actor.hide();
+        }
+
         this._readPrimaryDevice();
         this._readOtherDevices();
         this._updateLabel();
     },
     
     _updateLabel: function() {
-        this._proxy.GetDevicesRemote(Lang.bind(this, function(devices, error) {
+        this._proxy.GetDevicesRemote(Lang.bind(this, function([devices], error) {
             if (error) {
                 this._mainLabel.set_text("");
                 return;
diff -uNr a/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js
--- a/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/share/cinnamon/applets/sound@cinnamon.org/applet.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,7 +1,6 @@
 const Applet = imports.ui.applet;
 const Mainloop = imports.mainloop;
 const Gio = imports.gi.Gio;
-const DBus = imports.dbus;
 const Lang = imports.lang;
 const Cinnamon = imports.gi.Cinnamon;
 const Clutter = imports.gi.Clutter;
@@ -12,94 +11,49 @@
 const Pango = imports.gi.Pango;
 const Tooltips = imports.ui.tooltips;
 
-const PropIFace = {
-    name: 'org.freedesktop.DBus.Properties',
-    signals: [{ name: 'PropertiesChanged',
-                inSignature: 'a{sv}'}]
-};
-
-const MediaServer2IFace = {
-    name: 'org.mpris.MediaPlayer2',
-    methods: [{ name: 'Raise',
-                inSignature: '',
-                outSignature: '' },
-              { name: 'Quit',
-                inSignature: '',
-                outSignature: '' }],
-    properties: [{ name: 'CanRaise',
-                   signature: 'b',
-                   access: 'read'},
-                 { name: 'CanQuit',
-                   signature: 'b',
-                   access: 'read'}],
-};
-
-const MediaServer2PlayerIFace = {
-    name: 'org.mpris.MediaPlayer2.Player',
-    methods: [{ name: 'PlayPause',
-                inSignature: '',
-                outSignature: '' },
-              { name: 'Pause',
-                inSignature: '',
-                outSignature: '' },
-              { name: 'Play',
-                inSignature: '',
-                outSignature: '' },
-              { name: 'Stop',
-                inSignature: '',
-                outSignature: '' },
-              { name: 'Next',
-                inSignature: '',
-                outSignature: '' },
-              { name: 'Previous',
-                inSignature: '',
-                outSignature: '' },
-              { name: 'SetPosition',
-                inSignature: 'ox',
-                outSignature: '' }],
-    properties: [{ name: 'Metadata',
-                   signature: 'a{sv}',
-                   access: 'read'},
-                 { name: 'Shuffle',
-                   signature: 'b',
-                   access: 'readwrite'},
-                 { name: 'Rate',
-                   signature: 'd',
-                   access: 'readwrite'},
-                 { name: 'LoopStatus',
-                   signature: 'b',
-                   access: 'readwrite'},
-                 { name: 'Volume',
-                   signature: 'd',
-                   access: 'readwrite'},
-                 { name: 'PlaybackStatus',
-                   signature: 's',
-                   access: 'read'},
-                 { name: 'Position',
-                   signature: 'x',
-                   access: 'read'},
-                 { name: 'CanGoNext',
-                   signature: 'b',
-                   access: 'read'},
-                 { name: 'CanGoPrevious',
-                   signature: 'b',
-                   access: 'read'},
-                 { name: 'CanPlay',
-                   signature: 'b',
-                   access: 'read'},
-                 { name: 'CanPause',
-                   signature: 'b',
-                   access: 'read'},
-                 { name: 'CanSeek',
-                   signature: 'b',
-                   access: 'read'}],
-    signals: [{ name: 'Seeked',
-                inSignature: 'x' }]
-};
+const PropIFace = <interface name="org.freedesktop.DBus.Properties">
+<signal name="PropertiesChanged">
+    <arg type="a{sv}"/>
+</signal>
+</interface>;
+
+const MediaServer2IFace = <interface name="org.mpris.MediaPlayer2">
+<method name="Raise" />
+<method name="Quit" />
+<property name="CanRaise" type="b" access="read" />
+<property name="CanQuit" type="b" access="read" />
+</interface>;
+
+const MediaServer2PlayerIFace = <interface name="org.mpris.MediaPlayer2.Player">
+<method name="PlayPause" />
+<method name="Pause" />
+<method name="Play" />
+<method name="Stop" />
+<method name="Next" />
+<method name="Previous" />
+<method name="SetPosition">
+    <arg type="a{ov}" direction="in"/>
+</method>
+<property name='Metadata' access='read' type='a{sv}' />
+<property name='Shuffle' access='readwrite' type='b' />
+<property name='Rate' access='readwrite' type='d' />
+<property name='LoopStatus' access='readwrite' type='s' />
+<property name='Volume' access='readwrite' type='d' />
+<property name='PlaybackStatus' access='read' type='s' />
+<property name='Position' access='read' type='x' />
+<property name="CanGoNext" type="b" access="read" />
+<property name="CanGoPrevious" type="b" access="read" />
+<property name="CanPlay" type="b" access="read" />
+<property name="CanPause" type="b" access="read" />
+<property name="CanSeek" type="b" access="read" />
+<signal name="Seeked">
+    <arg type="x"/>
+</signal>
+</interface>;
 
 /* global values */
 let icon_path = "/usr/share/cinnamon/theme/";
-let compatible_players = [ "clementine", "mpd", "exaile", "banshee", "rhythmbox", "rhythmbox3", "pragha", "quodlibet", "guayadeque", "amarok", "googlemusicframe", "xbmc", "noise", "xnoise", "gmusicbrowser", "spotify", "audacious", "vlc", "beatbox", "songbird", "pithos", "gnome-mplayer", "nuvolaplayer", "qmmp" ];
+let compatible_players = [ "clementine", "mpd", "exaile", "banshee", "rhythmbox", "rhythmbox3", "pragha", "quodlibet", "guayadeque", "amarok", "googlemusicframe", "xbmc", "noise", "xnoise", "gmusicbrowser", "spotify", "audacious", "vlc", "beatbox", "songbird", "pithos", "gnome-mplayer", "nuvolaplayer", "qmmp"];
 let support_seek = [ "clementine", "banshee", "rhythmbox", "rhythmbox3", "pragha", "quodlibet", "amarok", "noise", "xnoise", "gmusicbrowser", "spotify", "vlc", "beatbox", "gnome-mplayer", "qmmp" ];
 /* dummy vars for translation */
 let x = _("Playing");
@@ -112,131 +66,20 @@
 const ICON_SIZE = 28;
 
 
-function Prop() {
-    this._init.apply(this, arguments);
+var PropProxy = Gio.DBusProxy.makeProxyWrapper(PropIFace);
+function Prop(owner, initCallback, cancellable) {
+    return new PropProxy(Gio.DBus.session, owner, '/org/mpris/MediaPlayer2', initCallback, cancellable);
 }
 
-Prop.prototype = {
-    _init: function(owner) {
-        DBus.session.proxifyObject(this, owner, '/org/mpris/MediaPlayer2', this);
-    }
+var MediaServer2Proxy = Gio.DBusProxy.makeProxyWrapper(MediaServer2IFace);
+function MediaServer2(owner, initCallback, cancellable) {
+    return new MediaServer2Proxy(Gio.DBus.session, owner, '/org/mpris/MediaPlayer2', initCallback, cancellable);
 }
-DBus.proxifyPrototype(Prop.prototype, PropIFace)
 
-function MediaServer2() {
-    this._init.apply(this, arguments);
-}
-
-MediaServer2.prototype = {
-    _init: function(owner) {
-        DBus.session.proxifyObject(this, owner, '/org/mpris/MediaPlayer2', this);
-    },
-    getRaise: function(callback) {
-        this.GetRemote('CanRaise', Lang.bind(this,
-            function(raise, ex) {
-                if (!ex)
-                    callback(this, raise);
-            }));
-    },
-    getQuit: function(callback) {
-        this.GetRemote('CanQuit', Lang.bind(this,
-            function(quit, ex) {
-                if (!ex)
-                    callback(this, quit);
-            }));
-    }
-}
-DBus.proxifyPrototype(MediaServer2.prototype, MediaServer2IFace)
-
-function MediaServer2Player() {
-    this._init.apply(this, arguments);
-}
-
-MediaServer2Player.prototype = {
-    _init: function(owner) {
-        this._owner = owner;
-        DBus.session.proxifyObject(this, owner, '/org/mpris/MediaPlayer2', this);
-    },
-    getMetadata: function(callback) {
-        this.GetRemote('Metadata', Lang.bind(this,
-            function(metadata, ex) {
-                if (!ex)
-                    callback(this, metadata);
-            }));
-    },
-    getPlaybackStatus: function(callback) {
-        this.GetRemote('PlaybackStatus', Lang.bind(this,
-            function(status, ex) {
-                if (!ex)
-                    callback(this, status);
-            }));
-    },
-    getRate: function(callback) {
-        this.GetRemote('Rate', Lang.bind(this,
-            function(rate, ex) {
-                if (!ex)
-                    callback(this, rate);
-            }));
-    },
-    getPosition: function(callback) {
-        this.GetRemote('Position', Lang.bind(this,
-            function(position, ex) {
-                if (!ex)
-                    callback(this, position);
-            }));
-    },
-    setPosition: function(value) {
-        this.SetRemote('Position', value);
-    },
-    getShuffle: function(callback) {
-        this.GetRemote('Shuffle', Lang.bind(this,
-            function(shuffle, ex) {
-                if (!ex)
-                    callback(this, shuffle);
-            }));
-    },
-    setShuffle: function(value) {
-        this.SetRemote('Shuffle', value);
-    },
-    getVolume: function(callback) {
-        this.GetRemote('Volume', Lang.bind(this,
-            function(volume, ex) {
-                if (!ex)
-                    callback(this, volume);
-            }));
-    },
-    setVolume: function(value) {
-        this.SetRemote('Volume', parseFloat(value));
-    },
-    getRepeat: function(callback) {
-        this.GetRemote('LoopStatus', Lang.bind(this,
-            function(repeat, ex) {
-                if (!ex) {
-                    if (repeat == "None")
-                        repeat = false
-                    else
-                        repeat = true
-                    callback(this, repeat);
-                }
-            }));
-    },
-    setRepeat: function(value) {
-        if (value)
-            value = "Playlist"
-        else
-            value = "None"
-        this.SetRemote('LoopStatus', value);
-    },
-    getCanSeek: function(callback) {
-        this.GetRemote('CanSeek', Lang.bind(this,
-            function(canSeek, err) {
-                if (!err) {
-                    callback(this, canSeek);
-                }
-            }));
-    }
+var MediaServer2PlayerProxy = Gio.DBusProxy.makeProxyWrapper(MediaServer2PlayerIFace);
+function MediaServer2Player(owner, initCallback, cancellable) {
+    return new MediaServer2PlayerProxy(Gio.DBus.session, owner, '/org/mpris/MediaPlayer2', initCallback, cancellable);
 }
-DBus.proxifyPrototype(MediaServer2Player.prototype, MediaServer2PlayerIFace)
 
 function TrackInfo() {
     this._init.apply(this, arguments);
@@ -355,7 +198,6 @@
     _init: function(system_status_button, owner) {
         PopupMenu.PopupMenuSection.prototype._init.call(this);
 
-        this.showPosition = true; // @todo: Get from settings
         this._owner = owner;
         this._system_status_button = system_status_button;
         this._name = this._owner.split('.')[3];
@@ -389,7 +231,7 @@
         this.infos_top.add_actor(this._artist.getActor());
         this.infos_bottom.add_actor(this._album.getActor());
         this.infos_top.add_actor(this._title.getActor());
-
+        this.infos_bottom.add_actor(this._time.getActor());
         this._trackInfosTop.set_child(this.infos_top);
         this._trackInfosBottom.set_child(this.infos_bottom);
 
@@ -414,45 +256,20 @@
         this._trackControls.set_child(this.controls);
         this.addActor(this._trackControls);
 
-        this._seekControls = new St.Bin({style_class: 'sound-seek', x_align: St.Align.START});
-        this.seekControls = new St.BoxLayout({style_class: 'sound-seek-box'});
-        this.seekControls.add_actor(this._time.getActor());
-
-        this._positionSlider = new PopupMenu.PopupSliderMenuItem(0);
-        this._positionSlider.connect('value-changed', Lang.bind(this, function(item) {
-            let time = item._value * this._songLength;
-            this._time.setLabel(this._formatTime(time) + " / " + this._formatTime(this._songLength));
-        }));
-        this._positionSlider.connect('drag-end', Lang.bind(this, function(item) {
-            let time = item._value * this._songLength;
-            this._time.setLabel(this._formatTime(time) + " / " + this._formatTime(this._songLength));
-            this._wantedSeekValue = Math.round(time * 1000000);
-            this._mediaServerPlayer.SetPositionRemote(this._trackObj, time * 1000000);
-        }));
-
-        this.sliderBin = new St.Bin({style_class: 'sound-seek-slider'});
-        this.sliderBin.set_child(this._positionSlider.actor);
-        this.seekControls.add_actor(this.sliderBin);
-        this._seekControls.set_child(this.seekControls);
-        this.addActor(this._seekControls);
-
-        this._mediaServer.getRaise(Lang.bind(this, function(sender, raise) {
-            if (raise) {
-                this._raiseButton = new ControlButton('go-up',
-                    Lang.bind(this, function () { this._mediaServer.RaiseRemote(); this._system_status_button.menu.actor.hide(); }));
-                this._raiseButtonTooltip = new Tooltips.Tooltip(this._raiseButton.button, _("Open Player"));
-                this.controls.add_actor(this._raiseButton.getActor());
-            }
-        }));
-
-        this._mediaServer.getQuit(Lang.bind(this, function(sender, quit) {
-            if (quit) {
-                this._quitButton = new ControlButton('window-close',
-                    Lang.bind(this, function () { this._mediaServer.QuitRemote(); }));
-                this.controls.add_actor(this._quitButton.getActor());
-                this._quitButtonTooltip = new Tooltips.Tooltip(this._quitButton.button, _("Quit Player"));
-            }
-        }));
+    let CanRaise = this._mediaServer.CanRaise;
+    let CanQuit = this._mediaServer.CanQuit;
+    if (CanRaise) {
+            this._raiseButton = new ControlButton('go-up',
+                          Lang.bind(this, function () { this._mediaServer.RaiseRemote(); this._system_status_button.menu.actor.hide(); }));
+            this._raiseButtonTooltip = new Tooltips.Tooltip(this._raiseButton.button, _("Open Player"));
+            this.controls.add_actor(this._raiseButton.getActor());
+    }
+    if (CanQuit) {
+            this._quitButton = new ControlButton('window-close',
+                         Lang.bind(this, function () { this._mediaServer.QuitRemote(); }));
+            this.controls.add_actor(this._quitButton.getActor());
+            this._quitButtonTooltip = new Tooltips.Tooltip(this._quitButton.button, _("Quit Player"));
+    }
 
         /* this players don't support seek */
         if (support_seek.indexOf(this._name) == -1) {
@@ -460,44 +277,29 @@
             this.showPosition = false;
             this._positionSlider.actor.hide();
         }
+
         this._getStatus();
         this._trackId = {};
         this._getMetadata();
         this._currentTime = 0;
         this._getPosition();
-        this._wantedSeekValue = 0;
-        this._updatePositionSlider();
 
-        this._prop.connect('PropertiesChanged', Lang.bind(this, function(sender, iface, value) {
+        this._prop.connectSignal('PropertiesChanged', Lang.bind(this, function(sender, iface, value) {
             if (value["PlaybackStatus"])
-                this._setStatus(iface, value["PlaybackStatus"]);
+                this._setStatus(value["PlaybackStatus"]);
             if (value["Metadata"])
-                this._setMetadata(iface, value["Metadata"]);
-            //qmmp
-            if(sender._dbusBusName == 'org.mpris.MediaPlayer2.qmmp') {
+                this._setMetadata(value["Metadata"]);
+            // qmmp
+            if (sender._dbusBusName == 'org.mpris.MediaPlayer2.qmmp') {
                 if (value["playbackStatus"])
-                    this._setStatus(iface, value["playbackStatus"]);
+                    this._setStatus(value["playbackStatus"]);
                 if (value["metadata"])
-                    this._setMetadata(sender, value["metadata"]);
-            } 
-        }));
-
-        this._mediaServerPlayer.connect('Seeked', Lang.bind(this, function(sender, value) {
-            if (value > 0) {
-                this._setPosition(value);
-            }
-            // Seek initiated by the position slider
-            else if (this._wantedSeekValue > 0) {
-                // Some broken gstreamer players (Banshee) reports always 0
-                // when the track is seeked so we set the position at the
-                // value we set on the slider
-                this._setPosition(this._wantedSeekValue);
+                    this._setMetadata(value["metadata"]);
             }
-            // Seek value send by the player
-            else
-                this._setPosition(value);
+        }));
 
-            this._wantedSeekValue = 0;
+        this._mediaServerPlayer.connectSignal('Seeked', Lang.bind(this, function(sender, iface, [value]) {
+            this._setPosition(sender, value);
         }));
 
         Mainloop.timeout_add(1000, Lang.bind(this, this._getPosition));
@@ -528,29 +330,26 @@
         }));
     },
 
-    _setPosition: function(value) {
-        if (value == null && this._playerStatus != 'Stopped') {
-            this._updatePositionSlider(false);
-        }
-        else {
-            this._currentTime = value / 1000000;
-            this._updateTimer();
-        }
+    _setPosition: function(sender, value) {
+        this._stopTimer();
+        this._currentTime = value / 1000000;
+        this._updateTimer();
+        if (this._playerStatus == "Playing")
+            this._runTimer();
     },
 
     _getPosition: function() {
-        this._mediaServerPlayer.getPosition(Lang.bind(this, function(sender, value) {
-            this._setPosition(value);
-        }));
+    this._setPosition(this._mediaServerPlayer.Position);
+        Mainloop.timeout_add(1000, Lang.bind(this, this._getPosition));
     },
 
-    _setMetadata: function(sender, metadata) {
+    _setMetadata: function(metadata) {
         if (metadata["mpris:length"]) {
             // song length in secs
-            this._songLength = metadata["mpris:length"] / 1000000;
+            this._songLength = metadata["mpris:length"].unpack() / 1000000;
             // FIXME upstream
             if (this._name == "quodlibet")
-                this._songLength = metadata["mpris:length"] / 1000;
+                this._songLength = metadata["mpris:length"].unpack() / 1000;
             // reset timer
             this._stopTimer();
             if (this._playerStatus == "Playing")
@@ -561,26 +360,29 @@
             this._stopTimer();
         }
         if (metadata["xesam:artist"])
-            this._artist.setLabel(metadata["xesam:artist"].toString());
+            this._artist.setLabel(metadata["xesam:artist"].unpack());
         else
             this._artist.setLabel(_("Unknown Artist"));
         if (metadata["xesam:album"])
-            this._album.setLabel(metadata["xesam:album"].toString());
+            this._album.setLabel(metadata["xesam:album"].unpack());
         else
             this._album.setLabel(_("Unknown Album"));
         if (metadata["xesam:title"])
-            this._title.setLabel(metadata["xesam:title"].toString());
+            this._title.setLabel(metadata["xesam:title"].unpack());
         else
             this._title.setLabel(_("Unknown Title"));
-        
-        if (metadata["mpris:trackid"]) {
-            this._trackObj = metadata["mpris:trackid"];
-        }
+        /*if (metadata["mpris:trackid"]) {
+            this._trackId = {
+                _init: function() {
+                    DBus.session.proxifyObject(this, this._owner, metadata["mpris:trackid"]);
+                }
+            }
+        }*/
 
         let change = false;
         if (metadata["mpris:artUrl"]) {
-            if (this._trackCoverFile != metadata["mpris:artUrl"].toString()) {
-                this._trackCoverFile = metadata["mpris:artUrl"].toString();
+            if (this._trackCoverFile != metadata["mpris:artUrl"].unpack()) {
+                this._trackCoverFile = metadata["mpris:artUrl"].unpack();
                 change = true;
             }
         }
@@ -613,13 +415,10 @@
     },
 
     _getMetadata: function() {
-        this._mediaServerPlayer.getMetadata(Lang.bind(this,
-            this._setMetadata
-        ));
+    this._setMetadata(this._mediaServerPlayer.Metadata);
     },
 
-    _setStatus: function(sender, status) {
-        this._updatePositionSlider();
+    _setStatus: function(status) {
         this._playerStatus = status;
         if (status == "Playing") {
             this._playButton.setIcon("media-playback-pause");
@@ -633,53 +432,39 @@
             this._playButton.setIcon("media-playback-start");
             this._stopTimer();
         }
-
         this._playerInfo.setImage("player-" + status.toLowerCase());
         this._setName(status);
     },
 
     _getStatus: function() {
-        this._mediaServerPlayer.getPlaybackStatus(Lang.bind(this,
-            this._setStatus
-        ));
+    this._setStatus(this._mediaServerPlayer.PlaybackStatus);
     },
 
     _updateRate: function() {
-        this._mediaServerPlayer.getRate(Lang.bind(this, function(sender, rate) {
-            this._rate = rate;
-        }));
+    this._rate = this._mediaServerPlayer.Rate;
     },
 
     _updateTimer: function() {
-        if (this.showPosition && this._canSeek) {
-            if (!isNaN(this._currentTime) && !isNaN(this._songLength) && this._currentTime > 0)
-                this._positionSlider.setValue(this._currentTime / this._songLength);
-            else
-                this._positionSlider.setValue(0);
-        }
         this._time.setLabel(this._formatTime(this._currentTime) + " / " + this._formatTime(this._songLength));
     },
 
     _runTimer: function() {
-        if (this._playerStatus == 'Playing') {
-            this._timeoutId = Mainloop.timeout_add_seconds(1, Lang.bind(this, this._runTimer));
-            this._currentTime += 1;
-            this._updateTimer();
-        }
+        /*if (!Tweener.resumeTweens(this)) {
+            Tweener.addTween(this,
+                { time: this._songLength - this._currentTime,
+                  transition: 'linear',
+                  onUpdate: Lang.bind(this, this._updateTimer) });
+        }*/
     },
 
     _pauseTimer: function() {
-        if (this._timeoutId != 0) {
-            Mainloop.source_remove(this._timeoutId);
-            this._timeoutId = 0;
-        }
-        this._updateTimer();
+        //Tweener.pauseTweens(this);
     },
 
     _stopTimer: function() {
+        /*Tweener.removeTweens(this);
         this._currentTime = 0;
-        this._pauseTimer();
-        this._updateTimer();
+        this._updateTimer();*/
     },
 
     _formatTime: function(s) {
@@ -773,7 +558,7 @@
     },
 
     activate: function (event) {
-    	this._menu.actor.hide();
+        this._menu.actor.hide();
         this._app.activate_full(-1, event.get_time());
         return true;
     }
@@ -801,7 +586,7 @@
             this._players = {};
             // watch players
             for (var p=0; p<compatible_players.length; p++) {
-                DBus.session.watch_name('org.mpris.MediaPlayer2.'+compatible_players[p], false,
+                Gio.DBus.session.watch_name('org.mpris.MediaPlayer2.'+compatible_players[p], Gio.BusNameWatcherFlags.NONE,
                     Lang.bind(this, this._addPlayer),
                     Lang.bind(this, this._removePlayer)
                 );
@@ -932,7 +717,7 @@
         return Object.keys(this._players).length;
     },
 
-    _addPlayer: function(owner) {
+    _addPlayer: function(connection, owner) {
         // ensure menu is empty
         this._cleanup();
         this._volumeControlShown = false;
@@ -947,12 +732,12 @@
         this._readOutput();
     },
 
-    _removePlayer: function(owner) {
+    _removePlayer: function(connection, owner) {
         delete this._players[owner];
         this._cleanup();
         this._volumeControlShown = false;
         for (owner in this._players) {
-            this._addPlayer(owner);
+            this._addPlayer(connection, owner);
         }
         this.menu.emit('players-loaded', true);
 
@@ -976,21 +761,21 @@
         this._volumeControlShown = true;
 
         if (this._nbPlayers()==0){
-        	this._availablePlayers = new Array();
+            this._availablePlayers = new Array();
             let appsys = Cinnamon.AppSystem.get_default();
             let allApps = appsys.get_all();
             let listedDesktopFiles = new Array();
             for (let y=0; y<allApps.length; y++) {
-            	let app = allApps[y];
-            	let entry = app.get_tree_entry();
-            	let path = entry.get_desktop_file_path();
-            	for (var p=0; p<compatible_players.length; p++) {
+                let app = allApps[y];
+                let entry = app.get_tree_entry();
+                let path = entry.get_desktop_file_path();
+                for (var p=0; p<compatible_players.length; p++) {
                     let desktopFile = compatible_players[p]+".desktop";
-            		if (path.indexOf(desktopFile) != -1 && listedDesktopFiles.indexOf(desktopFile) == -1) {
-                		this._availablePlayers.push(app);
+                    if (path.indexOf(desktopFile) != -1 && listedDesktopFiles.indexOf(desktopFile) == -1) {
+                        this._availablePlayers.push(app);
                         listedDesktopFiles.push(desktopFile);
-            		}
-           		}
+                    }
+                }
             }
 
             if (this._availablePlayers.length > 0){
@@ -1139,19 +924,19 @@
             this._mutedChanged (null, null, '_output');
             this._volumeChanged (null, null, '_output');
             let sinks = this._control.get_sinks();
-	        this._selectDeviceItem.menu.removeAll();
-	        for (let i = 0; i < sinks.length; i++) {
-	        	let sink = sinks[i];
-	        	let menuItem = new PopupMenu.PopupMenuItem(sink.get_description());
-	        	if (sinks[i].get_id() == this._output.get_id()) {
-	        		menuItem.setShowDot(true);
-	        	}
-	        	menuItem.connect('activate', Lang.bind(this, function() {
-	        		log('Changing default sink to ' + sink.get_description());
-	                this._control.set_default_sink(sink);
-	            }));
-	            this._selectDeviceItem.menu.addMenuItem(menuItem);
-	        }
+            this._selectDeviceItem.menu.removeAll();
+            for (let i = 0; i < sinks.length; i++) {
+                let sink = sinks[i];
+                let menuItem = new PopupMenu.PopupMenuItem(sink.get_description());
+                if (sinks[i].get_id() == this._output.get_id()) {
+                    menuItem.setShowDot(true);
+                }
+                menuItem.connect('activate', Lang.bind(this, function() {
+                    log('Changing default sink to ' + sink.get_description());
+                    this._control.set_default_sink(sink);
+                }));
+                this._selectDeviceItem.menu.addMenuItem(menuItem);
+            }
         } else {
             this._outputSlider.setValue(0);
             this.setIconName('audio-volume-muted-symbolic');
diff -uNr a/files/usr/share/cinnamon/applets/xrandr@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/xrandr@cinnamon.org/applet.js
--- a/files/usr/share/cinnamon/applets/xrandr@cinnamon.org/applet.js	2013-05-22 17:35:08.000000000 +0100
+++ b/files/usr/share/cinnamon/applets/xrandr@cinnamon.org/applet.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,6 +1,6 @@
 /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
 
-const DBus = imports.dbus;
+const Gio = imports.gi.Gio;
 const Gdk = imports.gi.Gdk;
 const GLib = imports.gi.GLib;
 const GnomeDesktop = imports.gi.GnomeDesktop;
@@ -22,13 +22,14 @@
 		  [ GnomeDesktop.RRRotation.ROTATION_180, N_("Upside-down") ]
 		];
 
-const XRandr2Iface = {
-    name: 'org.gnome.SettingsDaemon.XRANDR_2',
-    methods: [
-	{ name: 'ApplyConfiguration', inSignature: 'xx', outSignature: '' },
-    ]
-};
-let XRandr2 = DBus.makeProxyClass(XRandr2Iface);
+const XRandr2Iface = <interface name="org.gnome.SettingsDaemon.XRANDR_2">
+<method name="ApplyConfiguration">
+    <arg type="x" direction="in"/>
+    <arg type="x" direction="in"/>
+</method>
+</interface>;
+
+const XRandr2 = Gio.DBusProxy.makeProxyWrapper(XRandr2Iface);
 
 function MyApplet(orientation, panel_height) {
     this._init(orientation, panel_height);
@@ -48,7 +49,7 @@
             this.menu = new Applet.AppletPopupMenu(this, orientation);
             this.menuManager.addMenu(this.menu);            
                                 
-            this._proxy = new XRandr2(DBus.session, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/XRANDR');
+            this._proxy = new XRandr2(Gio.DBus.session, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/XRANDR');
 
             try {
                 this._screen = new GnomeDesktop.RRScreen({ gdk_screen: Gdk.Screen.get_default() });
diff -uNr a/js/misc/gnomeSession.js b/js/misc/gnomeSession.js
--- a/js/misc/gnomeSession.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/misc/gnomeSession.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,20 +1,18 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const DBus = imports.dbus;
+const Gio = imports.gi.Gio;
 const Lang = imports.lang;
 const Signals = imports.signals;
 
-const PresenceIface = {
-    name: 'org.gnome.SessionManager.Presence',
-    methods: [{ name: 'SetStatus',
-                inSignature: 'u',
-                outSignature: '' }],
-    properties: [{ name: 'status',
-                   signature: 'u',
-                   access: 'readwrite' }],
-    signals: [{ name: 'StatusChanged',
-                inSignature: 'u' }]
-};
+const PresenceIface = <interface name="org.gnome.SessionManager.Presence">
+<method name="SetStatus">
+    <arg type="u" direction="in"/>
+</method>
+<property name="status" type="u" access="readwrite"/>
+<signal name="StatusChanged">
+    <arg type="u" direction="out"/>
+</signal>
+</interface>;
 
 const PresenceStatus = {
     AVAILABLE: 0,
@@ -23,104 +21,37 @@
     IDLE: 3
 };
 
-function Presence() {
-    this._init();
+var PresenceProxy = Gio.DBusProxy.makeProxyWrapper(PresenceIface);
+function Presence(initCallback, cancellable) {
+    return new PresenceProxy(Gio.DBus.session, 'org.gnome.SessionManager',
+                             '/org/gnome/SessionManager/Presence', initCallback, cancellable);
 }
 
-Presence.prototype = {
-    _init: function() {
-        DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager/Presence', this);
-    },
-
-    getStatus: function(callback) {
-        this.GetRemote('status', Lang.bind(this,
-            function(status, ex) {
-                if (!ex)
-                    callback(this, status);
-            }));
-    },
-
-    setStatus: function(status) {
-        this.SetStatusRemote(status);
-    }
-};
-DBus.proxifyPrototype(Presence.prototype, PresenceIface);
-
-// Note inhibitors are immutable objects, so they don't
-// change at runtime (changes always come in the form
-// of new inhibitors)
-const InhibitorIface = {
-    name: 'org.gnome.SessionManager.Inhibitor',
-    properties: [{ name: 'app_id',
-                   signature: 's',
-                   access: 'readonly' },
-                 { name: 'client_id',
-                   signature: 's',
-                   access: 'readonly' },
-                 { name: 'reason',
-                   signature: 's',
-                   access: 'readonly' },
-                 { name: 'flags',
-                   signature: 'u',
-                   access: 'readonly' },
-                 { name: 'toplevel_xid',
-                   signature: 'u',
-                   access: 'readonly' },
-                 { name: 'cookie',
-                   signature: 'u',
-                   access: 'readonly' }],
-};
-
-function Inhibitor(objectPath) {
-    this._init(objectPath);
+const InhibitorIface = <interface name="org.gnome.SessionManager.Inhibitor">
+<property name="app_id" type="s" access="read" />
+<property name="client_id" type="s" access="read" />
+<property name="reason" type="s" access="read" />
+<property name="flags" type="u" access="read" />
+<property name="toplevel_xid" type="u" access="read" />
+<property name="cookie" type="u" access="read" />
+</interface>;
+
+var InhibitorProxy = Gio.DBusProxy.makeProxyWrapper(InhibitorIface);
+function Inhibitor(objectPath, initCallback, cancellable) {
+    return new InhibitorProxy(Gio.DBus.session, 'org.gnome.SessionManager', objectPath, initCallback, cancellable);
 }
 
-Inhibitor.prototype = {
-    _init: function(objectPath) {
-        DBus.session.proxifyObject(this,
-                                   'org.gnome.SessionManager',
-                                   objectPath);
-        this.isLoaded = false;
-        this._loadingPropertiesCount = InhibitorIface.properties.length;
-        for (let i = 0; i < InhibitorIface.properties.length; i++) {
-            let propertyName = InhibitorIface.properties[i].name;
-            this.GetRemote(propertyName, Lang.bind(this,
-                function(value, exception) {
-                    if (exception)
-                        return;
-
-                    this[propertyName] = value;
-                    this._loadingPropertiesCount--;
-
-                    if (this._loadingPropertiesCount == 0) {
-                        this.isLoaded = true;
-                        this.emit('is-loaded');
-                    }
-                }));
-        }
-    },
-};
-DBus.proxifyPrototype(Inhibitor.prototype, InhibitorIface);
-Signals.addSignalMethods(Inhibitor.prototype);
-
-
-// Not the full interface, only the methods we use
-const SessionManagerIface = {
-    name: 'org.gnome.SessionManager',
-    methods: [
-        { name: 'Logout', inSignature: 'u', outSignature: '' },
-        { name: 'Shutdown', inSignature: '', outSignature: '' },
-        { name: 'CanShutdown', inSignature: '', outSignature: 'b' }
-    ]
-};
-
-function SessionManager() {
-    this._init();
+const SessionManagerIface = <interface name="org.gnome.SessionManager">
+<method name="Logout">
+    <arg type="u" direction="in" />
+</method>
+<method name="Shutdown" />
+<method name="CanShutdown">
+    <arg type="b" direction="out" />
+</method>
+</interface>;
+
+var SessionManagerProxy = Gio.DBusProxy.makeProxyWrapper(SessionManagerIface);
+function SessionManager(initCallback, cancellable) {
+    return new SessionManagerProxy(Gio.DBus.session, 'org.gnome.SessionManager', '/org/gnome/SessionManager', initCallback, cancellable);
 }
-
-SessionManager.prototype = {
-    _init: function() {
-        DBus.session.proxifyObject(this, 'org.gnome.SessionManager', '/org/gnome/SessionManager');
-    }
-};
-DBus.proxifyPrototype(SessionManager.prototype, SessionManagerIface);
\ No newline at end of file
diff -uNr a/js/misc/modemManager.js b/js/misc/modemManager.js
--- a/js/misc/modemManager.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/misc/modemManager.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,6 +1,6 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const DBus = imports.dbus;
+const Gio = imports.gi.Gio;
 const Lang = imports.lang;
 const Cinnamon = imports.gi.Cinnamon;
 const Signals = imports.signals;
@@ -8,33 +8,43 @@
 // The following are not the complete interfaces, just the methods we need
 // (or may need in the future)
 
-const ModemGsmNetworkInterface = {
-    name: 'org.freedesktop.ModemManager.Modem.Gsm.Network',
-    methods: [
-        { name: 'GetRegistrationInfo', inSignature: '', outSignature: 'uss' },
-        { name: 'GetSignalQuality', inSignature: '', outSignature: 'u' }
-    ],
-    properties: [
-        { name: 'AccessTechnology', signature: 'u', access: 'read' }
-    ],
-    signals: [
-        { name: 'SignalQuality', inSignature: 'u' },
-        { name: 'RegistrationInfo', inSignature: 'uss' }
-    ]
-};
-const ModemGsmNetworkProxy = DBus.makeProxyClass(ModemGsmNetworkInterface);
-
-const ModemCdmaInterface = {
-    name: 'org.freedesktop.ModemManager.Modem.Cdma',
-    methods: [
-        { name: 'GetSignalQuality', inSignature: '', outSignature: 'u' },
-        { name: 'GetServingSystem', inSignature: '', outSignature: 'usu' }
-    ],
-    signals: [
-        { name: 'SignalQuality', inSignature: 'u' }
-    ]
-};
-const ModemCdmaProxy = DBus.makeProxyClass(ModemCdmaInterface);
+const ModemGsmNetworkInterface = <interface name="org.freedesktop.ModemManager.Modem.Gsm.Network">
+<method name="GetRegistrationInfo">
+    <arg type="u" direction="out" />
+    <arg type="s" direction="out" />
+    <arg type="s" direction="out" />
+</method>
+<method name="GetSignalQuality">
+    <arg type="u" direction="out" />
+</method>
+<property name="AccessTechnology" type="u" access="read" />
+<signal name="SignalQuality">
+    <arg type="u" direction="out" />
+</signal>
+<signal name="RegistrationInfo">
+    <arg type="u" direction="out" />
+    <arg type="s" direction="out" />
+    <arg type="s" direction="out" />
+</signal>
+</interface>;
+
+const ModemGsmNetworkProxy = Gio.DBusProxy.makeProxyWrapper(ModemGsmNetworkInterface);
+
+const ModemCdmaInterface = <interface name="org.freedesktop.ModemManager.Modem.Cdma">
+<method name="GetSignalQuality">
+    <arg type="u" direction="out" />
+</method>
+<method name="GetServingSystem">
+    <arg type="u" direction="out" />
+    <arg type="s" direction="out" />
+    <arg type="u" direction="out" />
+</method>
+<signal name="SignalQuality">
+    <arg type="u" direction="out" />
+</signal>
+</interface>;
+
+const ModemCdmaProxy = Gio.DBusProxy.makeProxyWrapper(ModemCdmaInterface);
 
 let _providersTable;
 function _getProvidersTable() {
@@ -50,17 +60,17 @@
 
 ModemGsm.prototype = {
     _init: function(path) {
-        this._proxy = new ModemGsmNetworkProxy(DBus.system, 'org.freedesktop.ModemManager', path);
+        this._proxy = new ModemGsmNetworkProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
 
         this.signal_quality = 0;
         this.operator_name = null;
 
         // Code is duplicated because the function have different signatures
-        this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
+        this._proxy.connectSignal('SignalQuality', Lang.bind(this, function(proxy, sender, [quality]) {
             this.signal_quality = quality;
             this.emit('notify::signal-quality');
         }));
-        this._proxy.connect('RegistrationInfo', Lang.bind(this, function(proxy, status, code, name) {
+        this._proxy.connectSignal('RegistrationInfo', Lang.bind(this, function(proxy, sender, [status, code, name]) {
             this.operator_name = this._findOperatorName(name, code);
             this.emit('notify::operator-name');
         }));
@@ -154,12 +164,13 @@
 }
 
 ModemCdma.prototype = {
-    _init: function(path) {
-        this._proxy = new ModemCdmaProxy(DBus.system, 'org.freedesktop.ModemManager', path);
+    _init: function(path) {        
+        this._proxy = new ModemCdmaProxy(Gio.DBus.system, 'org.freedesktop.ModemManager', path);
 
         this.signal_quality = 0;
         this.operator_name = null;
-        this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, quality) {
+        this._proxy.connect('SignalQuality', Lang.bind(this, function(proxy, sender, params) {
+            this.signal_quality = params[0];
             this.signal_quality = quality;
             this.emit('notify::signal-quality');
 
diff -uNr a/js/misc/screenSaver.js b/js/misc/screenSaver.js
--- a/js/misc/screenSaver.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/misc/screenSaver.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,53 +1,48 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const DBus = imports.dbus;
 const Lang = imports.lang;
+const Gio = imports.gi.Gio;
 
-const ScreenSaverIface = {
-    name: 'org.gnome.ScreenSaver',
-    methods: [{ name: 'GetActive',
-                inSignature: '',
-                outSignature: 'b' },
-              { name: 'Lock',
-                inSignature: '' },
-              { name: 'SetActive',
-                inSignature: 'b' }],
-    signals: [{ name: 'ActiveChanged',
-                inSignature: 'b' }]
-};
+const ScreenSaverIface = <interface name="org.gnome.ScreenSaver">
+<method name="GetActive">
+    <arg type="b" direction="out" />
+</method>
+<method name="Lock" />
+<method name="SetActive">
+    <arg type="b" direction="in" />
+</method>
+<signal name="ActiveChanged">
+    <arg type="b" direction="out" />
+</signal>
+</interface>;
+
+const ScreenSaverInfo = Gio.DBusInterfaceInfo.new_for_xml(ScreenSaverIface);
 
 function ScreenSaverProxy() {
-    this._init();
-}
+    var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
+                                  g_interface_name: ScreenSaverInfo.name,
+                                  g_interface_info: ScreenSaverInfo,
+                                  g_name: 'org.gnome.ScreenSaver',
+                                  g_object_path: '/org/gnome/ScreenSaver',
+                                   g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
+                                             Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
+    self.init(null);
+    self.screenSaverActive = false;
+
+    self.connectSignal('ActiveChanged', function(proxy, senderName, [isActive]) {
+        self.screenSaverActive = isActive;
+    });
+    self.connect('notify::g-name-owner', function() {
+        if (self.g_name_owner) {
+            self.GetActiveRemote(function(result, excp) {
+                if (result) {
+                    let [isActive] = result;
+                    self.screenSaverActive = isActive;
+                }
+            });
+        } else
+            self.screenSaverActive = false;
+    });
 
-ScreenSaverProxy.prototype = {
-    _init: function() {
-        DBus.session.proxifyObject(this,
-                                   'org.gnome.ScreenSaver',
-                                   '/org/gnome/ScreenSaver');
-
-        DBus.session.watch_name('org.gnome.ScreenSaver',
-                                false, // do not launch a name-owner if none exists
-                                Lang.bind(this, this._onSSAppeared),
-                                Lang.bind(this, this._onSSVanished));
-
-        this.screenSaverActive = false;
-        this.connect('ActiveChanged',
-                     Lang.bind(this, this._onActiveChanged));
-    },
-
-    _onSSAppeared: function(owner) {
-        this.GetActiveRemote(Lang.bind(this, function(isActive) {
-            this.screenSaverActive = isActive;
-        }))
-    },
-
-    _onSSVanished: function(oldOwner) {
-        this.screenSaverActive = false;
-    },
-
-    _onActiveChanged: function(object, isActive) {
-        this.screenSaverActive = isActive;
-    }
-};
-DBus.proxifyPrototype(ScreenSaverProxy.prototype, ScreenSaverIface);
+    return self;
+}
diff -uNr a/js/ui/appletManager.js b/js/ui/appletManager.js
--- a/js/ui/appletManager.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/appletManager.js	2013-05-22 21:36:04.000000000 +0100
@@ -7,7 +7,6 @@
 const Main = imports.ui.main;
 const Applet = imports.ui.applet;
 const Extension = imports.ui.extension;
-const DBus = imports.dbus;
 
 // Maps uuid -> metadata object
 var appletMeta;
diff -uNr a/js/ui/automountManager.js b/js/ui/automountManager.js
--- a/js/ui/automountManager.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/automountManager.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,7 +1,6 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Lang = imports.lang;
-const DBus = imports.dbus;
 const Mainloop = imports.mainloop;
 const Gio = imports.gi.Gio;
 const Params = imports.misc.params;
@@ -15,63 +14,57 @@
 
 const AUTORUN_EXPIRE_TIMEOUT_SECS = 10;
 
-const ConsoleKitSessionIface = {
-    name: 'org.freedesktop.ConsoleKit.Session',
-    methods: [{ name: 'IsActive',
-                inSignature: '',
-                outSignature: 'b' }],
-    signals: [{ name: 'ActiveChanged',
-                inSignature: 'b' }]
-};
-
-const ConsoleKitSessionProxy = DBus.makeProxyClass(ConsoleKitSessionIface);
-
-const ConsoleKitManagerIface = {
-    name: 'org.freedesktop.ConsoleKit.Manager',
-    methods: [{ name: 'GetCurrentSession',
-                inSignature: '',
-                outSignature: 'o' }]
-};
+const ConsoleKitSessionIface = <interface name="org.freedesktop.ConsoleKit.Session">
+<method name="isActive">
+    <arg type="b" direction="out" />
+</method>
+<method name="ActiveChanged">
+    <arg type="b" direction="in" />
+</method>
+</interface>;
+
+const ConsoleKitSessionProxy = Gio.DBusProxy.makeProxyWrapper(ConsoleKitSessionIface);
+
+const ConsoleKitManagerIface = <interface name="org.freedesktop.ConsoleKit.Manager">
+<method name="GetCurrentSession">
+    <arg type="o" direction="out" />
+</method>
+</interface>;
 
-function ConsoleKitManager() {
-    this._init();
-};
-
-ConsoleKitManager.prototype = {
-    _init: function() {
-        this.sessionActive = true;
+const ConsoleKitManagerInfo = Gio.DBusInterfaceInfo.new_for_xml(ConsoleKitManagerIface);
 
-        DBus.system.proxifyObject(this,
-                                  'org.freedesktop.ConsoleKit',
-                                  '/org/freedesktop/ConsoleKit/Manager');
-
-        DBus.system.watch_name('org.freedesktop.ConsoleKit',
-                               false, // do not launch a name-owner if none exists
-                               Lang.bind(this, this._onManagerAppeared),
-                               Lang.bind(this, this._onManagerVanished));
-    },
-
-    _onManagerAppeared: function(owner) {
-        this.GetCurrentSessionRemote(Lang.bind(this, this._onCurrentSession));
-    },
-
-    _onManagerVanished: function(oldOwner) {
-        this.sessionActive = true;
-    },
-
-    _onCurrentSession: function(session) {
-        this._ckSession = new ConsoleKitSessionProxy(DBus.system, 'org.freedesktop.ConsoleKit', session);
-
-        this._ckSession.connect
-            ('ActiveChanged', Lang.bind(this, function(object, isActive) {
-                this.sessionActive = isActive;            
-            }));
-        this._ckSession.IsActiveRemote(Lang.bind(this, function(isActive) {
-            this.sessionActive = isActive;            
-        }));
+function ConsoleKitManager() {
+    var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system,
+                                  g_interface_name: ConsoleKitManagerInfo.name,
+                                  g_interface_info: ConsoleKitManagerInfo,
+                                  g_name: 'org.freedesktop.ConsoleKit',
+                                  g_object_path: '/org/freedesktop/ConsoleKit/Manager',
+                                   g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
+                                             Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
+    
+    self._updateSessionActive = function() {
+        if (self.g_name_owner) {
+            self.GetCurrentSessionRemote(function([session]) {
+                self._ckSession = new ConsoleKitSessionProxy(Gio.DBus.system, 'org.freedesktop.ConsoleKit', session);
+
+                self._ckSession.connectSignal('ActiveChanged', function(object, senderName, [isActive]) {
+                    self.sessionActive = isActive;
+                });
+                self._ckSession.IsActiveRemote(function([isActive]) {
+                    self.sessionActive = isActive;
+                });
+            });
+        } else {
+            self.sessionActive = true;
+        }
     }
-};
-DBus.proxifyPrototype(ConsoleKitManager.prototype, ConsoleKitManagerIface);
+    self.connect('notify::g-name-owner',
+                 Lang.bind(self, self._updateSessionActive));
+ 
+    self._updateSessionActive();
+    self.init(null);
+    return self;
+}
 
 function AutomountManager() {
     this._init();
@@ -85,9 +78,8 @@
         this.ckListener = new ConsoleKitManager();
 
         this._ssProxy = new ScreenSaver.ScreenSaverProxy();
-        this._ssProxy.connect('ActiveChanged',
-                              Lang.bind(this,
-                                        this._screenSaverActiveChanged));
+        this._ssProxy.connectSignal('ActiveChanged',
+                                    Lang.bind(this, this._screenSaverActiveChanged));
 
         this._volumeMonitor = Gio.VolumeMonitor.get();
 
@@ -110,7 +102,7 @@
         Mainloop.idle_add(Lang.bind(this, this._startupMountAll));
     },
 
-    _screenSaverActiveChanged: function(object, isActive) {
+    _screenSaverActiveChanged: function(object, senderName, [isActive]) {
         if (!isActive) {
             this._volumeQueue.forEach(Lang.bind(this, function(volume) {
                 this._checkAndMountVolume(volume);
diff -uNr a/js/ui/autorunManager.js b/js/ui/autorunManager.js
--- a/js/ui/autorunManager.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/autorunManager.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,7 +1,6 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Lang = imports.lang;
-const DBus = imports.dbus;
 const Gio = imports.gi.Gio;
 const St = imports.gi.St;
 
@@ -61,25 +60,19 @@
 
 /******************************************/
 
-const HotplugSnifferIface = {
-    name: 'org.Cinnamon.HotplugSniffer',
-    methods: [{ name: 'SniffURI',
-                inSignature: 's',
-                outSignature: 'as' }]
-};
-
-const HotplugSniffer = function() {
-    this._init();
-};
-
-HotplugSniffer.prototype = {
-    _init: function() {
-        DBus.session.proxifyObject(this,
+const HotplugSnifferIface = <interface name="org.Cinnamon.HotplugSniffer">
+<method name="SniffURI">
+    <arg type="s" direction="in" />
+    <arg type="as" direction="out" />
+</method>
+</interface>;
+
+const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
+function HotplugSniffer() {
+    return new HotplugSnifferProxy(Gio.DBus.session,
                                    'org.Cinnamon.HotplugSniffer',
                                    '/org/Cinnamon/HotplugSniffer');
-    },
-};
-DBus.proxifyPrototype(HotplugSniffer.prototype, HotplugSnifferIface);
+}
 
 function ContentTypeDiscoverer(callback) {
     this._init(callback);
diff -uNr a/js/ui/calendar.js b/js/ui/calendar.js
--- a/js/ui/calendar.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/calendar.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,6 +1,5 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const DBus = imports.dbus;
 const Clutter = imports.gi.Clutter;
 const Gio = imports.gi.Gio;
 const Lang = imports.lang;
@@ -194,30 +193,34 @@
 };
 Signals.addSignalMethods(EmptyEventSource.prototype);
 
-const CalendarServerIface = {
-    name: 'org.Cinnamon.CalendarServer',
-    methods: [{ name: 'GetEvents',
-                inSignature: 'xxb',
-                outSignature: 'a(sssbxxa{sv})' }],
-    signals: [{ name: 'Changed',
-                inSignature: '' }]
-};
+const CalendarServerIface = <interface name="org.Cinnamon.CalendarServer">
+<method name="GetEvents">
+    <arg type="x" direction="in" />
+    <arg type="x" direction="in" />
+    <arg type="b" direction="in" />
+    <arg type="a(sssbxxa{sv})" direction="out" />
+</method>
+<signal name="Changed" />
+</interface>;
+
+const CalendarServerInfo  = Gio.DBusInterfaceInfo.new_for_xml(CalendarServerIface);
+
+function CalendarServer() {
+    var self = new Gio.DBusProxy({ g_connection: Gio.DBus.session,
+				   g_interface_name: CalendarServerInfo.name,
+				   g_interface_info: CalendarServerInfo,
+				   g_name: 'org.Cinnamon.CalendarServer',
+				   g_object_path: '/org/Cinnamon/CalendarServer',
+                                   g_flags: (Gio.DBusProxyFlags.DO_NOT_AUTO_START |
+                                             Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) });
 
-const CalendarServer = function () {
-    this._init();
-};
-
-CalendarServer.prototype = {
-     _init: function() {
-         DBus.session.proxifyObject(this, 'org.Cinnamon.CalendarServer', '/org/Cinnamon/CalendarServer');
-     }
-};
-
-DBus.proxifyPrototype(CalendarServer.prototype, CalendarServerIface);
+    self.init(null);
+    return self;
+}
 
 // an implementation that reads data from a session bus service
-function DBusEventSource(owner) {
-    this._init(owner);
+function DBusEventSource() {
+    this._init();
 }
 
 function _datesEqual(a, b) {
@@ -240,16 +243,18 @@
 
 
 DBusEventSource.prototype = {
-    _init: function(owner) {
+    _init: function() {
         this._resetCache();
 
-        this._dbusProxy = new CalendarServer(owner);
-        this._dbusProxy.connect('Changed', Lang.bind(this, this._onChanged));
+        this._dbusProxy = new CalendarServer();
+        this._dbusProxy.connectSignal('Changed', Lang.bind(this, this._onChanged));
 
-        DBus.session.watch_name('org.Cinnamon.CalendarServer',
-                                false, // do not launch a name-owner if none exists
-                                Lang.bind(this, this._onNameAppeared),
-                                Lang.bind(this, this._onNameVanished));
+        this._dbusProxy.connect('notify::g-name-owner', Lang.bind(this, function() {
+            if (this._dbusProxy.g_name_owner)
+                this._onNameAppeared();
+            else
+                this._onNameVanished();
+        }));
     },
 
     _resetCache: function() {
@@ -272,7 +277,7 @@
         this._loadEvents(false);
     },
 
-    _onEventsReceived: function(appointments) {
+    _onEventsReceived: function([appointments]) {
         let newEvents = [];
         if (appointments != null) {
             for (let n = 0; n < appointments.length; n++) {
@@ -295,9 +300,9 @@
 
     _loadEvents: function(forceReload) {
         if (this._curRequestBegin && this._curRequestEnd){
-            let callFlags = 0;
+            let callFlags = Gio.DBusCallFlags.NO_AUTO_START;
             if (forceReload)
-                callFlags |= DBus.CALL_FLAG_START;
+                callFlags = Gio.DBusCallFlags.NONE;
             this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
                                             this._curRequestEnd.getTime() / 1000,
                                             forceReload,
diff -uNr a/js/ui/cinnamonDBus.js b/js/ui/cinnamonDBus.js
--- a/js/ui/cinnamonDBus.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/cinnamonDBus.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,7 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const DBus = imports.dbus;
 const Lang = imports.lang;
+const Gio = imports.gi.Gio;
 
 const Config = imports.misc.config;
 const Flashspot = imports.ui.flashspot;
@@ -9,48 +9,53 @@
 const AppletManager = imports.ui.appletManager;
 const DeskletManager = imports.ui.deskletManager;
 
-const CinnamonIface = {
-    name: 'org.Cinnamon',
-    methods: [{ name: 'Eval',
-                inSignature: 's',
-                outSignature: 'bs'
-              },
-              { name: 'ScreenshotArea',
-                inSignature: 'biiiibs',
-                outSignature: ''
-              },
-              { name: 'ScreenshotWindow',
-                inSignature: 'bbbs',
-                outSignature: ''
-              },
-              { name: 'Screenshot',
-                inSignature: 'bbs',
-                outSignature: ''
-              },
-              {
-                name: 'FlashArea',
-                inSignature: 'iiii',
-                outSignature: ''
-              },
-              {
-                name: 'highlightApplet',
-                inSignature: 'sb',
-                outSignature: ''
-              },
-              {
-                name: 'activateCallback',
-                inSignature: 'ssb',
-                outSignature: ''
-              }
-             ],
-    signals: [],
-    properties: [{ name: 'OverviewActive',
-                   signature: 'b',
-                   access: 'readwrite' },
-                 { name: 'CinnamonVersion',
-                   signature: 's',
-                   access: 'read' }]
-};
+
+const CinnamonIface = <interface name="org.Cinnamon">
+<method name="Eval">
+    <arg type="s" direction="in" name="script" />
+    <arg type="b" direction="out" name="success" />
+    <arg type="s" direction="out" name="result" />
+</method>
+<method name="ScreenshotArea">
+include_cursor
+    <arg type="b" direction="in" name="include_cursor"/>
+    <arg type="i" direction="in" name="x"/>
+    <arg type="i" direction="in" name="y"/>
+    <arg type="i" direction="in" name="width"/>
+    <arg type="i" direction="in" name="height"/>
+    <arg type="b" direction="in" name="flash"/>
+    <arg type="s" direction="in" name="filename"/>
+</method>
+<method name="ScreenshotWindow">
+    <arg type="b" direction="in" name="include_frame"/>
+    <arg type="b" direction="in" name="include_cursor"/>
+    <arg type="b" direction="in" name="flash"/>
+    <arg type="s" direction="in" name="filename"/>
+</method>
+<method name="Screenshot">
+    <arg type="b" direction="in" name="include_frame"/>
+    <arg type="b" direction="in" name="flash"/>
+    <arg type="s" direction="in" name="filename"/>
+</method>
+<method name="FlashArea">
+include_cursor
+    <arg type="i" direction="in" name="x"/>
+    <arg type="i" direction="in" name="y"/>
+    <arg type="i" direction="in" name="width"/>
+    <arg type="i" direction="in" name="height"/>
+</method>
+<method name="highlightApplet">
+    <arg type="s" direction="in" />
+    <arg type="b" direction="in" />
+</method>
+<method name="activateCallback">
+    <arg type="s" direction="in" />
+    <arg type="s" direction="in" />
+    <arg type="b" direction="in" />
+</method>
+<property name="OverviewActive" type="b" access="readwrite" />
+<property name="CinnamonVersion" type="s" access="read" />
+</interface>;
 
 function Cinnamon() {
     this._init();
@@ -58,7 +63,8 @@
 
 Cinnamon.prototype = {
     _init: function() {
-        DBus.session.exportObject('/org/Cinnamon', this);
+        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(CinnamonIface, this);
+        this._dbusImpl.export(Gio.DBus.session, '/org/Cinnamon');
     },
 
     /**
@@ -215,5 +221,3 @@
     CinnamonVersion: Config.PACKAGE_VERSION
 };
 
-DBus.conformExport(Cinnamon.prototype, CinnamonIface);
-
diff -uNr a/js/ui/endSessionDialog.js b/js/ui/endSessionDialog.js
--- a/js/ui/endSessionDialog.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/endSessionDialog.js	2013-05-22 21:36:04.000000000 +0100
@@ -18,19 +18,19 @@
  * 02110-1335, USA.
  */
 
-const DBus = imports.dbus;
 const Lang = imports.lang;
 const Signals = imports.signals;
 
 const AccountsService = imports.gi.AccountsService;
 const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
 const Pango = imports.gi.Pango;
 const St = imports.gi.St;
 const Cinnamon = imports.gi.Cinnamon;
 
-const GnomeSession = imports.misc.gnomeSession
+const GnomeSession = imports.misc.gnomeSession;
 const ModalDialog = imports.ui.modalDialog;
 const Tweener = imports.ui.tweener;
 
@@ -40,20 +40,20 @@
 const _DIALOG_ICON_SIZE = 32;
 
 const GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
-
-const EndSessionDialogIface = {
-    name: 'org.gnome.SessionManager.EndSessionDialog',
-    methods: [{ name: 'Open',
-                inSignature: 'uuuao',
-                outSignature: ''
-              }
-             ],
-    signals: [{ name: 'Canceled',
-                inSignature: '',
-              }],
-    properties: []
-};
-
+const EndSessionDialogIface = <interface name="org.gnome.SessionManager.EndSessionDialog">
+<method name="Open">
+    <arg type="u" direction="in" />
+    <arg type="u" direction="in" />
+    <arg type="u" direction="in" />
+    <arg type="ao" direction="in" />
+</method>
+<signal name="ConfirmedLogout" />
+<signal name="ConfirmedReboot" />
+<signal name="ConfirmedShutdown" />
+<signal name="Canceled" />
+<signal name="Closed" />
+</interface>;
+ 
 const logoutDialogContent = {
     subjectWithUser: _("Log Out %s"),
     subject: _("Log Out"),
@@ -230,8 +230,6 @@
 function EndSessionDialog() {
     if (_endSessionDialog == null) {
         this._init();
-        DBus.session.exportObject('/org/gnome/SessionManager/EndSessionDialog',
-                                  this);
         _endSessionDialog = this;
     }
 
@@ -328,6 +326,9 @@
                                           if (this._applicationList.get_children().length == 0)
                                               scrollView.hide();
                                       }));
+
+        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
+        this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
     },
 
     _onDestroy: function() {
@@ -442,25 +443,19 @@
 
     close: function() {
         ModalDialog.ModalDialog.prototype.close.call(this);
-        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
-                                 'org.gnome.SessionManager.EndSessionDialog',
-                                 'Closed', '', []);
+        this._dbusImpl.emit_signal('Closed', null);
     },
 
     cancel: function() {
         this._stopTimer();
-        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
-                                 'org.gnome.SessionManager.EndSessionDialog',
-                                 'Canceled', '', []);
+        this._dbusImpl.emit_signal('Canceled', null);
         this.close(global.get_current_time());
     },
 
     _confirm: function(signal) {
         this._fadeOutDialog();
         this._stopTimer();
-        DBus.session.emit_signal('/org/gnome/SessionManager/EndSessionDialog',
-                                 'org.gnome.SessionManager.EndSessionDialog',
-                                 signal, '', []);
+        this._dbusImpl.emit_signal(signal, null);
     },
 
     _onOpened: function() {
@@ -512,39 +507,41 @@
         this._updateContent();
     },
 
-    OpenAsync: function(type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths, callback) {
+    OpenAsync: function(parameters, invocation) {
+        let [type, timestamp, totalSecondsToStayOpen, inhibitorObjectPaths] = parameters;
         this._totalSecondsToStayOpen = totalSecondsToStayOpen;
         this._inhibitors = [];
         this._applicationList.destroy_children();
         this._type = type;
 
-        if (!(this._type in DialogContent))
-            throw new DBus.DBusError('org.Cinnamon.ModalDialog.TypeError',
-                                     "Unknown dialog type requested");
+        if (!(this._type in DialogContent)) {
+            invocation.report_dbus_error('org.Cinnamon.ModalDialog.TypeError',
+                                         "Unknown dialog type requested");
+            return;
+        }
 
         for (let i = 0; i < inhibitorObjectPaths.length; i++) {
-            let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i]);
+            let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], Lang.bind(this, function(proxy, error) {
+                this._onInhibitorLoaded(proxy);
+            }));
 
-            inhibitor.connect('is-loaded',
-                              Lang.bind(this, function() {
-                                  this._onInhibitorLoaded(inhibitor);
-                              }));
             this._inhibitors.push(inhibitor);
         }
 
         this._updateButtons();
 
-        if (!this.open(timestamp))
-            throw new DBus.DBusError('org.Cinnamon.ModalDialog.GrabError',
-                                     "Cannot grab pointer and keyboard");
+        if (!this.open(timestamp)) {
+            invocation.report_dbus_error('org.Cinnamon.ModalDialog.GrabError',
+                                         "Cannot grab pointer and keyboard");
+            return;
+        }
 
         this._updateContent();
 
         let signalId = this.connect('opened',
                                     Lang.bind(this, function() {
-                                        callback();
+                                        invocation.return_value(null);
                                         this.disconnect(signalId);
                                     }));
     }
 };
-DBus.conformExport(EndSessionDialog.prototype, EndSessionDialogIface);
diff -uNr a/js/ui/keyboard.js b/js/ui/keyboard.js
--- a/js/ui/keyboard.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/keyboard.js	2013-05-22 21:36:04.000000000 +0100
@@ -2,7 +2,6 @@
 
 const Caribou = imports.gi.Caribou;
 const Clutter = imports.gi.Clutter;
-const DBus = imports.dbus;
 const Gdk = imports.gi.Gdk;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
@@ -38,28 +37,27 @@
     'Alt_L': 'Alt'
 };
 
-const CaribouKeyboardIface = {
-    name: 'org.gnome.Caribou.Keyboard',
-    methods:    [ { name: 'Show',
-                    inSignature: 'u',
-                    outSignature: ''
-                  },
-                  { name: 'Hide',
-                    inSignature: 'u',
-                    outSignature: ''
-                  },
-                  { name: 'SetCursorLocation',
-                    inSignature: 'iiii',
-                    outSignature: ''
-                  },
-                  { name: 'SetEntryLocation',
-                    inSignature: 'iiii',
-                    outSignature: ''
-                  } ],
-    properties: [ { name: 'Name',
-                    signature: 's',
-                    access: 'read' } ]
-};
+const CaribouKeyboardIface = <interface name='org.gnome.Caribou.Keyboard'>
+<method name='Show'>
+    <arg type='u' direction='in' />
+</method>
+<method name='Hide'>
+    <arg type='u' direction='in' />
+</method>
+<method name='SetCursorLocation'>
+    <arg type='i' direction='in' />
+    <arg type='i' direction='in' />
+    <arg type='i' direction='in' />
+    <arg type='i' direction='in' />
+</method>
+<method name='SetEntryLocation'>
+    <arg type='i' direction='in' />
+    <arg type='i' direction='in' />
+    <arg type='i' direction='in' />
+    <arg type='i' direction='in' />
+</method>
+<property name='Name' access='read' type='s' />
+</interface>;
 
 function Key() {
     this._init.apply(this, arguments);
@@ -199,7 +197,8 @@
 
 Keyboard.prototype = {
     _init: function () {
-        DBus.session.exportObject('/org/gnome/Caribou/Keyboard', this);
+        this._impl = Gio.DBusExportedObject.wrapJSObject(CaribouKeyboardIface, this);
+        this._impl.export(Gio.DBus.session, '/org/gnome/Caribou/Keyboard');
 
         this.actor = null;
 
@@ -541,7 +540,6 @@
         return 'cinnamon';
     }
 };
-DBus.conformExport(Keyboard.prototype, CaribouKeyboardIface);
 
 function KeyboardSource() {
     this._init.apply(this, arguments);
diff -uNr a/js/ui/layout.js b/js/ui/layout.js
--- a/js/ui/layout.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/layout.js	2013-05-22 21:36:04.000000000 +0100
@@ -492,12 +492,14 @@
 
         this._screenSaverActive = false;
         this._screenSaverProxy = new ScreenSaver.ScreenSaverProxy();
-        this._screenSaverProxy.connect('ActiveChanged', Lang.bind(this, this._onScreenSaverActiveChanged));
-        this._screenSaverProxy.GetActiveRemote(Lang.bind(this,
-            function(result, err) {
-                if (!err)
-                    this._onScreenSaverActiveChanged(this._screenSaverProxy, result);
-            }));
+        this._screenSaverProxy.connectSignal('ActiveChanged', Lang.bind(this, function(proxy, senderName, [isActive]) {
+            this._onScreenSaverActiveChanged(isActive);
+        }));
+        this._screenSaverProxy.GetActiveRemote(Lang.bind(this, function(result, err) {
+            if (!err)
+                this._onScreenSaverActiveChanged(result[0]);
+        }));
+
 
         this._relayout();
     },
diff -uNr a/js/ui/magnifierDBus.js b/js/ui/magnifierDBus.js
--- a/js/ui/magnifierDBus.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/magnifierDBus.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,6 +1,6 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const DBus = imports.dbus;
+const Gio = imports.gi.Gio;
 const Main = imports.ui.main;
 
 const MAG_SERVICE_NAME = 'org.gnome.Magnifier';
@@ -10,47 +10,85 @@
 
 // Subset of gnome-mag's Magnifier dbus interface -- to be expanded.  See:
 // http://git.gnome.org/browse/gnome-mag/tree/xml/...Magnifier.xml
-const MagnifierIface = {
-    name: MAG_SERVICE_NAME,
-    methods: [
-                { name: 'setActive', inSignature: 'b', outSignature: '' },
-                { name: 'isActive', inSignature: '', outSignature: 'b' },
-                { name: 'showCursor', inSignature: '', outSignature: '' },
-                { name: 'hideCursor', inSignature: '', outSignature: ''  },
-                { name: 'createZoomRegion', inSignature: 'ddaiai', outSignature: 'o' },
-                { name: 'addZoomRegion', inSignature: 'o', outSignature: 'b' },
-                { name: 'getZoomRegions', inSignature: '', outSignature: 'ao' },
-                { name: 'clearAllZoomRegions', inSignature: '', outSignature: '' },
-                { name: 'fullScreenCapable', inSignature: '', outSignature: 'b' },
-
-                { name: 'setCrosswireSize', inSignature: 'i', outSignature: '' },
-                { name: 'getCrosswireSize', inSignature: '', outSignature: 'i' },
-                { name: 'setCrosswireLength', inSignature: 'i', outSignature: '' },
-                { name: 'getCrosswireLength', inSignature: '', outSignature: 'i' },
-                { name: 'setCrosswireClip', inSignature: 'b', outSignature: '' },
-                { name: 'getCrosswireClip', inSignature: '', outSignature: 'b' },
-                { name: 'setCrosswireColor', inSignature: 'u', outSignature: '' },
-                { name: 'getCrosswireColor', inSignature: '', outSignature: 'u' }
-             ],
-    signals: [],
-    properties: []
-};
+const MagnifierIface = <interface name={MAG_SERVICE_NAME}>
+<method name="setActive">
+    <arg type="b" direction="in" />
+</method>
+<method name="isActive">
+    <arg type="b" direction="out" />
+</method>
+<method name="showCursor" />
+<method name="hideCursor" />
+<method name="createZoomRegion">
+    <arg type="d" direction="in" />
+    <arg type="d" direction="in" />
+    <arg type="ai" direction="in" />
+    <arg type="ai" direction="in" />
+    <arg type="o" direction="out" />
+</method>
+<method name="addZoomRegion">
+    <arg type="o" direction="in" />
+    <arg type="b" direction="out" />
+</method>
+<method name="getZoomRegions">
+    <arg type="ao" direction="out" />
+</method>
+<method name="clearAllZoomRegions" />
+<method name="fullScreenCapable">
+    <arg type="b" direction="out" />
+</method>
+<method name="setCrosswireSize">
+    <arg type="i" direction="in" />
+</method>
+<method name="getCrosswireSize">
+    <arg type="i" direction="out" />
+</method>
+<method name="setCrosswireLength">
+    <arg type="i" direction="in" />
+</method>
+<method name="getCrosswireLength">
+    <arg type="i" direction="out" />
+</method>
+<method name="setCrosswireClip">
+    <arg type="b" direction="in" />
+</method>
+<method name="getCrosswireClip">
+    <arg type="b" direction="out" />
+</method>
+<method name="setCrosswireColor">
+    <arg type="u" direction="in" />
+</method>
+<method name="getCrosswireColor">
+    <arg type="u" direction="out" />
+</method>
+</interface>;
 
 // Subset of gnome-mag's ZoomRegion dbus interface -- to be expanded.  See:
 // http://git.gnome.org/browse/gnome-mag/tree/xml/...ZoomRegion.xml
-const ZoomRegionIface = {
-    name: ZOOM_SERVICE_NAME,
-    methods: [
-                { name: 'setMagFactor', inSignature: 'dd', outSignature: ''},
-                { name: 'getMagFactor', inSignature: '', outSignature: 'dd' },
-                { name: 'setRoi', inSignature: 'ai', outSignature: '' },
-                { name: 'getRoi', inSignature: '', outSignature: 'ai' },
-                { name: 'shiftContentsTo', inSignature: 'ii', outSignature: 'b' },
-                { name: 'moveResize', inSignature: 'ai', outSignature: '' }
-             ],
-    signals: [],
-    properties: []
-};
+const ZoomRegionIface = <interface name={ZOOM_SERVICE_NAME}>
+<method name="setMagFactor">
+    <arg type="d" direction="in" />
+    <arg type="d" direction="in" />
+</method>
+<method name="getMagFactor">
+    <arg type="d" direction="out" />
+    <arg type="d" direction="out" />
+</method>
+<method name="setRoi">
+    <arg type="ai" direction="in" />
+</method>
+<method name="getRoi">
+    <arg type="ai" direction="out" />
+</method>
+<method name="shiftContentsTo">
+    <arg type="i" direction="in" />
+    <arg type="i" direction="in" />
+    <arg type="b" direction="out" />
+</method>
+<method name="moveResize">
+    <arg type="ai" direction="in" />
+</method>
+</interface>;
 
 // For making unique ZoomRegion DBus proxy object paths of the form:
 // '/org/gnome/Magnifier/ZoomRegion/zoomer0',
@@ -64,7 +102,9 @@
 CinnamonMagnifier.prototype = {
     _init: function() {
         this._zoomers = {};
-        DBus.session.exportObject(MAG_SERVICE_PATH, this);
+
+        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(MagnifierIface, this);
+        this._dbusImpl.export(Gio.DBus.session, MAG_SERVICE_PATH);
     },
 
     /**
@@ -195,10 +235,10 @@
         Main.magnifier.clearAllZoomRegions();
         for (let objectPath in this._zoomers) {
             let proxyAndZoomer = this._zoomers[objectPath];
+            proxyAndZoomer.proxy.destroy();
             proxyAndZoomer.proxy = null;
             proxyAndZoomer.zoomRegion = null;
             delete this._zoomers[objectPath];
-            DBus.session.unexportObject(proxyAndZoomer);
         }
         this._zoomers = {};
     },
@@ -300,8 +340,9 @@
 CinnamonMagnifierZoomRegion.prototype = {
     _init: function(zoomerObjectPath, zoomRegion) {
         this._zoomRegion = zoomRegion;
-        DBus.session.proxifyObject(this, ZOOM_SERVICE_NAME, zoomerObjectPath);
-        DBus.session.exportObject(zoomerObjectPath, this);
+
+        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(ZoomRegionIface, this);
+        this._dbusImpl.export(Gio.DBus.session, zoomerObjectPath);
     },
 
     /**
@@ -376,8 +417,9 @@
     moveResize: function(viewPort) {
         let viewRect = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
         this._zoomRegion.setViewPort(viewRect);
+    },
+
+    destroy: function() {
+        this._dbusImpl.unexport();
     }
 };
-
-DBus.conformExport(CinnamonMagnifier.prototype, MagnifierIface);
-DBus.conformExport(CinnamonMagnifierZoomRegion.prototype, ZoomRegionIface);
diff -uNr a/js/ui/main.js b/js/ui/main.js
--- a/js/ui/main.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/main.js	2013-05-22 21:36:04.000000000 +0100
@@ -44,7 +44,7 @@
  */
 
 const Clutter = imports.gi.Clutter;
-const DBus= imports.dbus;
+
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
@@ -129,6 +129,7 @@
 let dynamicWorkspaces = null;
 let nWorks = null;
 let tracker = null;
+let backgroundManager = null;
 let desktopShown;
 
 let workspace_names = [];
@@ -246,11 +247,6 @@
 
     cinnamonDBusService = new CinnamonDBus.Cinnamon();
     lookingGlassDBusService = new LookingGlassDBus.CinnamonLookingGlass();
-    // Force a connection now; dbus.js will do this internally
-    // if we use its name acquisition stuff but we aren't right
-    // now; to do so we'd need to convert from its async calls
-    // back into sync ones.
-    DBus.session.flush();
 
     // Ensure CinnamonWindowTracker and CinnamonAppUsage are initialized; this will
     // also initialize CinnamonAppSystem first.  CinnamonAppSystem
@@ -262,7 +258,7 @@
     // be predictable anyways.
     tracker = Cinnamon.WindowTracker.get_default();
     Cinnamon.AppUsage.get_default();
-
+    backgroundManager = Cinnamon.BackgroundManager.get_default();
     // The stage is always covered so Clutter doesn't need to clear it; however
     // the color is used as the default contents for the Muffin root background
     // actor so set it anyways.
diff -uNr a/js/ui/messageTray.js b/js/ui/messageTray.js
--- a/js/ui/messageTray.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/messageTray.js	2013-05-22 21:36:04.000000000 +0100
@@ -1388,12 +1388,17 @@
 
 MessageTray.prototype = {
     _init: function() {
-        this._presence = new GnomeSession.Presence();
+        this._presence = new GnomeSession.Presence(Lang.bind(this, function(proxy, error) {
+            this._onStatusChanged(proxy.status);
+        }));
+
         this._userStatus = GnomeSession.PresenceStatus.AVAILABLE;
         this._busy = false;
         this._backFromAway = false;
-        this._presence.connect('StatusChanged', Lang.bind(this, this._onStatusChanged));
-        this._presence.getStatus(Lang.bind(this, this._onStatusChanged));
+        this._presence.connectSignal('StatusChanged', Lang.bind(this, function(proxy, senderName, [status]) {
+            this._onStatusChanged(status);
+        }));
+
 
         this._notificationBin = new St.Bin();
         this._notificationBin.hide();
@@ -1548,7 +1553,7 @@
         this._updateState();
     },
 
-    _onStatusChanged: function(presence, status) {
+    _onStatusChanged: function(status) {
         this._backFromAway = (this._userStatus == GnomeSession.PresenceStatus.IDLE && this._userStatus != status);
         this._userStatus = status;
 
diff -uNr a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js
--- a/js/ui/notificationDaemon.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/notificationDaemon.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,7 +1,7 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 const Clutter = imports.gi.Clutter;
-const DBus = imports.dbus;
+const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Lang = imports.lang;
 const Cinnamon = imports.gi.Cinnamon;
@@ -14,49 +14,52 @@
 
 let nextNotificationId = 1;
 
-// Should really be defined in dbus.js
-const BusIface = {
-    name: 'org.freedesktop.DBus',
-    methods: [{ name: 'GetConnectionUnixProcessID',
-                inSignature: 's',
-                outSignature: 'i' }]
-};
-
-const Bus = function () {
-    this._init();
-};
-
-Bus.prototype = {
-     _init: function() {
-         DBus.session.proxifyObject(this, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
-     }
-};
-
-DBus.proxifyPrototype(Bus.prototype, BusIface);
+// Should really be defined in Gio.js
+const BusIface = <interface name="org.freedesktop.DBus">
+<method name="GetConnectionUnixProcessID">
+    <arg type="s" direction="in" />
+    <arg type="u" direction="out" />
+</method>
+</interface>;
+
+var BusProxy = Gio.DBusProxy.makeProxyWrapper(BusIface);
+function Bus() {
+    return new BusProxy(Gio.DBus.session, 'org.freedesktop.DBus', '/org/freedesktop/DBus');
+}
 
-const NotificationDaemonIface = {
-    name: 'org.freedesktop.Notifications',
-    methods: [{ name: 'Notify',
-                inSignature: 'susssasa{sv}i',
-                outSignature: 'u'
-              },
-              { name: 'CloseNotification',
-                inSignature: 'u',
-                outSignature: ''
-              },
-              { name: 'GetCapabilities',
-                inSignature: '',
-                outSignature: 'as'
-              },
-              { name: 'GetServerInformation',
-                inSignature: '',
-                outSignature: 'ssss'
-              }],
-    signals: [{ name: 'NotificationClosed',
-                inSignature: 'uu' },
-              { name: 'ActionInvoked',
-                inSignature: 'us' }]
-};
+const NotificationDaemonIface = <interface name="org.freedesktop.Notifications">
+<method name="Notify">
+    <arg type="s" direction="in"/>
+    <arg type="u" direction="in"/>
+    <arg type="s" direction="in"/>
+    <arg type="s" direction="in"/>
+    <arg type="s" direction="in"/>
+    <arg type="as" direction="in"/>
+    <arg type="a{sv}" direction="in"/>
+    <arg type="i" direction="in"/>
+    <arg type="u" direction="out"/>
+</method>
+<method name="CloseNotification">
+    <arg type="u" direction="in"/>
+</method>
+<method name="GetCapabilities">
+    <arg type="as" direction="out"/>
+</method>
+<method name="GetServerInformation">
+    <arg type="s" direction="out"/>
+    <arg type="s" direction="out"/>
+    <arg type="s" direction="out"/>
+    <arg type="s" direction="out"/>
+</method>
+<signal name="NotificationClosed">
+    <arg type="u"/>
+    <arg type="u"/>
+</signal>
+<signal name="ActionInvoked">
+    <arg type="u"/>
+    <arg type="s"/>
+</signal>
+</interface>;
 
 const NotificationClosedReason = {
     EXPIRED: 1,
@@ -88,7 +91,8 @@
 
 NotificationDaemon.prototype = {
     _init: function() {
-        DBus.session.exportObject('/org/freedesktop/Notifications', this);
+        this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(NotificationDaemonIface, this);
+        this._dbusImpl.export(Gio.DBus.session, '/org/freedesktop/Notifications');
 
         this._sources = [];
         this._senderToPid = {};
@@ -213,10 +217,15 @@
         return source;
     },
 
-    Notify: function(appName, replacesId, icon, summary, body,
-                     actions, hints, timeout) {
+    NotifyAsync: function(params, invocation) {
+        let [appName, replacesId, icon, summary, body, actions, hints, timeout] = params;
         let id;
-        
+
+        for (let hint in hints) {
+            // unpack the variants
+            hints[hint] = hints[hint].deep_unpack();
+        }
+
         let rewrites = rewriteRules[appName];
         if (rewrites) {
             for (let i = 0; i < rewrites.length; i++) {
@@ -257,51 +266,55 @@
         }
         this._notifications[id] = ndata;
 
-        let sender = DBus.getCurrentMessageContext().sender;
+        let sender = invocation.get_sender();
         let pid = this._senderToPid[sender];
 
         let source = this._getSource(appName, pid, ndata, sender, null);
 
         if (source) {
             this._notifyForSource(source, ndata);
-            return id;
+            return invocation.return_value(GLib.Variant.new('(u)', [id]));
         }
 
         if (replacesId) {
             // There's already a pending call to GetConnectionUnixProcessID,
             // which will see the new notification data when it finishes,
             // so we don't have to do anything.
-            return id;
+            return invocation.return_value(GLib.Variant.new('(u)', [id]));
         }
 
-        this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this,
-            function (pid, ex) {
-                // The app may have updated or removed the notification
-                ndata = this._notifications[id];
-                if (!ndata)
-                    return;
-
-                source = this._getSource(appName, pid, ndata, sender, null);
-
-                // We only store sender-pid entries for persistent sources.
-                // Removing the entries once the source is destroyed
-                // would result in the entries associated with transient
-                // sources removed once the notification is shown anyway.
-                // However, keeping these pairs would mean that we would
-                // possibly remove an entry associated with a persistent
-                // source when a transient source for the same sender is
-                // distroyed.
-                if (!source.isTransient) {
-                    this._senderToPid[sender] = pid;
-                    source.connect('destroy', Lang.bind(this,
-                        function() {
-                            delete this._senderToPid[sender];
-                        }));
-                }
-                this._notifyForSource(source, ndata);
-            }));
+        this._busProxy.GetConnectionUnixProcessIDRemote(sender, Lang.bind(this, function (result, excp) {
+            // The app may have updated or removed the notification
+            ndata = this._notifications[id];
+            if (!ndata)
+                return;
 
-        return id;
+            if (excp) {
+                logError(excp, 'Call to GetConnectionUnixProcessID failed');
+                return;
+            }
+
+            let [pid] = result;
+            source = this._getSource(appName, pid, ndata, sender);
+
+            // We only store sender-pid entries for persistent sources.
+            // Removing the entries once the source is destroyed
+            // would result in the entries associated with transient
+            // sources removed once the notification is shown anyway.
+            // However, keeping these pairs would mean that we would
+            // possibly remove an entry associated with a persistent
+            // source when a transient source for the same sender is
+            // distroyed.
+            if (!source.isTransient) {
+                this._senderToPid[sender] = pid;
+                source.connect('destroy', Lang.bind(this, function() {
+                    delete this._senderToPid[sender];
+                }));
+            }
+            this._notifyForSource(source, ndata);
+        }));
+
+        return invocation.return_value(GLib.Variant.new('(u)', [id]));
     },
 
     _notifyForSource: function(source, ndata) {
@@ -441,17 +454,13 @@
     },
 
     _emitNotificationClosed: function(id, reason) {
-        DBus.session.emit_signal('/org/freedesktop/Notifications',
-                                 'org.freedesktop.Notifications',
-                                 'NotificationClosed', 'uu',
-                                 [id, reason]);
+        this._dbusImpl.emit_signal('NotificationClosed',
+                                   GLib.Variant.new('(uu)', [id, reason]));
     },
 
     _emitActionInvoked: function(id, action) {
-        DBus.session.emit_signal('/org/freedesktop/Notifications',
-                                 'org.freedesktop.Notifications',
-                                 'ActionInvoked', 'us',
-                                 [id, action]);
+        this._dbusImpl.emit_signal('ActionInvoked',
+                                   GLib.Variant.new('(us)', [id, action]));
     },
 
     _onTrayIconAdded: function(o, icon) {
@@ -465,8 +474,6 @@
     }
 };
 
-DBus.conformExport(NotificationDaemon.prototype, NotificationDaemonIface);
-
 function Source(title, pid, sender, trayIcon) {
     this._init(title, pid, sender, trayIcon);
 }
@@ -481,15 +488,12 @@
 
         this.pid = pid;
         if (sender)
-            // TODO: dbus-glib implementation of watch_name() doesn’t return an id to be used for
-            // unwatch_name() or implement unwatch_name(), however when we move to using GDBus implementation,
-            // we should save the id here and call unwatch_name() with it in destroy().
-            // Moving to GDBus is the work in progress: https://bugzilla.gnome.org/show_bug.cgi?id=648651
-            // and https://bugzilla.gnome.org/show_bug.cgi?id=622921 .
-            DBus.session.watch_name(sender,
-                                    false,
-                                    null,
-                                    Lang.bind(this, this._onNameVanished));
+            this._nameWatcherId = Gio.DBus.session.watch_name(sender,
+                                                              Gio.BusNameWatcherFlags.NONE,
+                                                              null,
+                                                              Lang.bind(this, this._onNameVanished));
+        else
+            this._nameWatcherId = 0;
 
         this._setApp();
         if (this.app)
@@ -596,6 +600,10 @@
     },
 
     destroy: function() {
+        if (this._nameWatcherId) {
+            Gio.DBus.session.unwatch_name(this._nameWatcherId);
+            this._nameWatcherId = 0;
+        }
         MessageTray.Source.prototype.destroy.call(this);
     }
 };
diff -uNr a/js/ui/scripting.js b/js/ui/scripting.js
--- a/js/ui/scripting.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/scripting.js	2013-05-22 21:36:04.000000000 +0100
@@ -1,6 +1,5 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const DBus = imports.dbus;
 const Gio = imports.gi.Gio;
 const Mainloop = imports.mainloop;
 const Meta = imports.gi.Meta;
@@ -70,24 +69,21 @@
     };
 }
 
-const PerfHelperIface = {
-    name: 'org.Cinnamon.PerfHelper',
-    methods: [{ name: 'CreateWindow', inSignature: 'iibb', outSignature: '' },
-              { name: 'WaitWindows', inSignature: '', outSignature: '' },
-              { name: 'DestroyWindows', inSignature: '', outSignature: ''}]
-};
-
-const PerfHelper = function () {
-    this._init();
-};
-
-PerfHelper.prototype = {
-     _init: function() {
-         DBus.session.proxifyObject(this, 'org.Cinnamon.PerfHelper', '/org/Cinnamon/PerfHelper');
-     }
-};
-
-DBus.proxifyPrototype(PerfHelper.prototype, PerfHelperIface);
+const PerfHelperIface = <interface name="org.gnome.Shell.PerfHelper">
+<method name="CreateWindow">
+    <arg type="i" direction="in" />
+    <arg type="i" direction="in" />
+    <arg type="b" direction="in" />
+    <arg type="b" direction="in" />
+</method>
+<method name="WaitWindows" />
+<method name="DestroyWindows" />
+</interface>;
+
+var PerfHelperProxy = Gio.DBusProxy.makeProxyWrapper(PerfHelperIface);
+function PerfHelper() {
+    return new PerfHelperProxy(Gio.DBus.session, 'org.gnome.Shell.PerfHelper', '/org/gnome/Shell/PerfHelper');
+}
 
 let _perfHelper = null;
 function _getPerfHelper() {
diff -uNr a/js/ui/windowManager.js b/js/ui/windowManager.js
--- a/js/ui/windowManager.js	2013-05-22 17:35:08.000000000 +0100
+++ b/js/ui/windowManager.js	2013-05-22 21:36:04.000000000 +0100
@@ -134,11 +134,11 @@
                                             Lang.bind(this, this._showWorkspaceSwitcher));
         Meta.keybindings_set_custom_handler('switch-to-workspace-down',
                                             Lang.bind(this, this._showWorkspaceSwitcher));
-        Meta.keybindings_set_custom_handler('switch-windows',
+        Meta.keybindings_set_custom_handler('switch-applications',
                                             Lang.bind(this, this._startAppSwitcher));
         Meta.keybindings_set_custom_handler('switch-group',
                                             Lang.bind(this, this._startAppSwitcher));
-        Meta.keybindings_set_custom_handler('switch-windows-backward',
+        Meta.keybindings_set_custom_handler('switch-applications-backward',
                                             Lang.bind(this, this._startAppSwitcher));
         Meta.keybindings_set_custom_handler('switch-group-backward',
                                             Lang.bind(this, this._startAppSwitcher));
diff -uNr a/src/cinnamon-background-manager.c b/src/cinnamon-background-manager.c
--- a/src/cinnamon-background-manager.c	1970-01-01 01:00:00.000000000 +0100
+++ b/src/cinnamon-background-manager.c	2013-05-22 21:36:04.000000000 +0100
@@ -0,0 +1,377 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright © 2001 Ximian, Inc.
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ * Copyright 2007 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 License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#include <libgnome-desktop/gnome-bg.h>
+#include <X11/Xatom.h>
+
+#include "cinnamon-background-manager.h"
+
+#define CINNAMON_BACKGROUND_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CINNAMON_TYPE_BACKGROUND_MANAGER, CinnamonBackgroundManagerPrivate))
+
+struct CinnamonBackgroundManagerPrivate
+{
+        GSettings   *settings;
+        GnomeBG     *bg;
+
+        GnomeBGCrossfade *fade;
+
+        GDBusProxy  *proxy;
+        guint        proxy_signal_id;
+};
+
+static void     cinnamon_background_manager_class_init  (CinnamonBackgroundManagerClass *klass);
+static void     cinnamon_background_manager_init        (CinnamonBackgroundManager      *background_manager);
+static void     cinnamon_background_manager_finalize    (GObject             *object);
+
+static void setup_bg (CinnamonBackgroundManager *manager);
+static void connect_screen_signals (CinnamonBackgroundManager *manager);
+
+G_DEFINE_TYPE (CinnamonBackgroundManager, cinnamon_background_manager, G_TYPE_OBJECT)
+
+static gboolean
+dont_draw_background (CinnamonBackgroundManager *manager)
+{
+        return !g_settings_get_boolean (manager->priv->settings,
+                                        "draw-background");
+}
+
+static void
+on_crossfade_finished (CinnamonBackgroundManager *manager)
+{
+        g_object_unref (manager->priv->fade);
+        manager->priv->fade = NULL;
+}
+
+static void
+draw_background (CinnamonBackgroundManager *manager,
+                 gboolean              use_crossfade)
+{
+        GdkDisplay *display;
+        int         n_screens;
+        int         i;
+
+        display = gdk_display_get_default ();
+        n_screens = gdk_display_get_n_screens (display);
+
+        for (i = 0; i < n_screens; ++i) {
+                GdkScreen *screen;
+                GdkWindow *root_window;
+                cairo_surface_t *surface;
+
+                screen = gdk_display_get_screen (display, i);
+
+                root_window = gdk_screen_get_root_window (screen);
+
+                surface = gnome_bg_create_surface (manager->priv->bg,
+                                                   root_window,
+                                                   gdk_screen_get_width (screen),
+                                                   gdk_screen_get_height (screen),
+                                                   TRUE);
+
+                if (use_crossfade) {
+
+                        if (manager->priv->fade != NULL) {
+                                g_object_unref (manager->priv->fade);
+                        }
+
+                        manager->priv->fade = gnome_bg_set_surface_as_root_with_crossfade (screen, surface);
+                        g_signal_connect_swapped (manager->priv->fade, "finished",
+                                                  G_CALLBACK (on_crossfade_finished),
+                                                  manager);
+                } else {
+                        gnome_bg_set_surface_as_root (screen, surface);
+                }
+
+                cairo_surface_destroy (surface);
+        }
+}
+
+static void
+on_bg_transitioned (GnomeBG              *bg,
+                    CinnamonBackgroundManager *manager)
+{
+        draw_background (manager, FALSE);
+}
+
+static gboolean
+settings_change_event_cb (GSettings            *settings,
+                          gpointer              keys,
+                          gint                  n_keys,
+                          CinnamonBackgroundManager *manager)
+{
+        gnome_bg_load_from_preferences (manager->priv->bg,
+                                        manager->priv->settings);
+        return FALSE;
+}
+
+static void
+on_screen_size_changed (GdkScreen            *screen,
+                        CinnamonBackgroundManager *manager)
+{
+        draw_background (manager, FALSE);
+}
+
+static void
+watch_bg_preferences (CinnamonBackgroundManager *manager)
+{
+        g_signal_connect (manager->priv->settings,
+                          "change-event",
+                          G_CALLBACK (settings_change_event_cb),
+                          manager);
+}
+
+static void
+on_bg_changed (GnomeBG              *bg,
+               CinnamonBackgroundManager *manager)
+{
+        draw_background (manager, TRUE);
+}
+
+static void
+setup_bg (CinnamonBackgroundManager *manager)
+{
+        g_return_if_fail (manager->priv->bg == NULL);
+
+        manager->priv->bg = gnome_bg_new ();
+
+        g_signal_connect (manager->priv->bg,
+                          "changed",
+                          G_CALLBACK (on_bg_changed),
+                          manager);
+
+        g_signal_connect (manager->priv->bg,
+                          "transitioned",
+                          G_CALLBACK (on_bg_transitioned),
+                          manager);
+
+        connect_screen_signals (manager);
+        watch_bg_preferences (manager);
+        gnome_bg_load_from_preferences (manager->priv->bg,
+                                        manager->priv->settings);
+}
+
+static void
+setup_bg_and_draw_background (CinnamonBackgroundManager *manager)
+{
+        setup_bg (manager);
+        draw_background (manager, FALSE);
+}
+
+static void
+disconnect_session_manager_listener (CinnamonBackgroundManager *manager)
+{
+        if (manager->priv->proxy && manager->priv->proxy_signal_id) {
+                g_signal_handler_disconnect (manager->priv->proxy,
+                                             manager->priv->proxy_signal_id);
+                manager->priv->proxy_signal_id = 0;
+        }
+}
+
+static void
+on_session_manager_signal (GDBusProxy   *proxy,
+                           const gchar  *sender_name,
+                           const gchar  *signal_name,
+                           GVariant     *parameters,
+                           gpointer      user_data)
+{
+        CinnamonBackgroundManager *manager = CINNAMON_BACKGROUND_MANAGER (user_data);
+
+        if (g_strcmp0 (signal_name, "SessionRunning") == 0) {
+                setup_bg_and_draw_background (manager);
+                disconnect_session_manager_listener (manager);
+        }
+}
+
+static void
+disconnect_screen_signals (CinnamonBackgroundManager *manager)
+{
+        GdkDisplay *display;
+        int         i;
+        int         n_screens;
+
+        display = gdk_display_get_default ();
+        n_screens = gdk_display_get_n_screens (display);
+
+        for (i = 0; i < n_screens; ++i) {
+                GdkScreen *screen;
+                screen = gdk_display_get_screen (display, i);
+                g_signal_handlers_disconnect_by_func (screen,
+                                                      G_CALLBACK (on_screen_size_changed),
+                                                      manager);
+        }
+}
+
+static void
+connect_screen_signals (CinnamonBackgroundManager *manager)
+{
+        GdkDisplay *display;
+        int         i;
+        int         n_screens;
+
+        display = gdk_display_get_default ();
+        n_screens = gdk_display_get_n_screens (display);
+
+        for (i = 0; i < n_screens; ++i) {
+                GdkScreen *screen;
+                screen = gdk_display_get_screen (display, i);
+                g_signal_connect (screen,
+                                  "monitors-changed",
+                                  G_CALLBACK (on_screen_size_changed),
+                                  manager);
+                g_signal_connect (screen,
+                                  "size-changed",
+                                  G_CALLBACK (on_screen_size_changed),
+                                  manager);
+        }
+}
+
+static void
+draw_background_changed (GSettings            *settings,
+                         const char           *key,
+                         CinnamonBackgroundManager *manager)
+{
+        if (dont_draw_background (manager) == FALSE)
+                setup_bg_and_draw_background (manager);
+}
+
+gboolean
+cinnamon_background_manager_start (CinnamonBackgroundManager *manager)
+{
+        manager->priv->settings = g_settings_new ("org.cinnamon.background");
+        g_signal_connect (manager->priv->settings, "changed::draw-background",
+                          G_CALLBACK (draw_background_changed), manager);
+
+        setup_bg_and_draw_background (manager);
+
+        return TRUE;
+}
+
+void
+cinnamon_background_manager_stop (CinnamonBackgroundManager *manager)
+{
+        CinnamonBackgroundManagerPrivate *p = manager->priv;
+
+        g_debug ("Stopping background manager");
+
+        disconnect_screen_signals (manager);
+
+        if (manager->priv->proxy) {
+                disconnect_session_manager_listener (manager);
+                g_object_unref (manager->priv->proxy);
+        }
+
+        g_signal_handlers_disconnect_by_func (manager->priv->settings,
+                                              settings_change_event_cb,
+                                              manager);
+
+        if (p->settings != NULL) {
+                g_object_unref (p->settings);
+                p->settings = NULL;
+        }
+
+        if (p->bg != NULL) {
+                g_object_unref (p->bg);
+                p->bg = NULL;
+        }
+}
+
+/**
+ * cinnamon_background_manager_get_default:
+ *
+ * Return Value: (transfer none): The global #CinnamonBackgroundManager singleton
+ */
+CinnamonBackgroundManager *
+cinnamon_background_manager_get_default ()
+{
+  static CinnamonBackgroundManager *instance = NULL;
+
+  if (instance == NULL)
+    instance = g_object_new (CINNAMON_TYPE_BACKGROUND_MANAGER, NULL);
+
+  return instance;
+}
+
+static GObject *
+cinnamon_background_manager_constructor (GType                  type,
+                                    guint                  n_construct_properties,
+                                    GObjectConstructParam *construct_properties)
+{
+        CinnamonBackgroundManager      *background_manager;
+
+        background_manager = CINNAMON_BACKGROUND_MANAGER (G_OBJECT_CLASS (cinnamon_background_manager_parent_class)->constructor (type,
+                                                                                                                        n_construct_properties,
+                                                                                                                        construct_properties));
+
+        return G_OBJECT (background_manager);
+}
+
+static void
+cinnamon_background_manager_class_init (CinnamonBackgroundManagerClass *klass)
+{
+        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+
+        object_class->constructor = cinnamon_background_manager_constructor;
+        object_class->finalize = cinnamon_background_manager_finalize;
+
+        g_type_class_add_private (klass, sizeof (CinnamonBackgroundManagerPrivate));
+}
+
+static void
+cinnamon_background_manager_init (CinnamonBackgroundManager *manager)
+{
+        manager->priv = CINNAMON_BACKGROUND_MANAGER_GET_PRIVATE (manager);
+        cinnamon_background_manager_start (manager);
+}
+
+static void
+cinnamon_background_manager_finalize (GObject *object)
+{
+        CinnamonBackgroundManager *background_manager;
+
+        g_return_if_fail (object != NULL);
+        g_return_if_fail (CINNAMON_IS_BACKGROUND_MANAGER (object));
+
+        background_manager = CINNAMON_BACKGROUND_MANAGER (object);
+
+        g_return_if_fail (background_manager->priv != NULL);
+
+        G_OBJECT_CLASS (cinnamon_background_manager_parent_class)->finalize (object);
+}
diff -uNr a/src/cinnamon-background-manager.h b/src/cinnamon-background-manager.h
--- a/src/cinnamon-background-manager.h	1970-01-01 01:00:00.000000000 +0100
+++ b/src/cinnamon-background-manager.h	2013-05-22 21:36:04.000000000 +0100
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __CINNAMON_BACKGROUND_MANAGER_H
+#define __CINNAMON_BACKGROUND_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CINNAMON_TYPE_BACKGROUND_MANAGER         (cinnamon_background_manager_get_type ())
+#define CINNAMON_BACKGROUND_MANAGER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), CINNAMON_TYPE_BACKGROUND_MANAGER, CinnamonBackgroundManager))
+#define CINNAMON_BACKGROUND_MANAGER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), CINNAMON_TYPE_BACKGROUND_MANAGER, CinnamonBackgroundManagerClass))
+#define CINNAMON_IS_BACKGROUND_MANAGER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), CINNAMON_TYPE_BACKGROUND_MANAGER))
+#define CINNAMON_IS_BACKGROUND_MANAGER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), CINNAMON_TYPE_BACKGROUND_MANAGER))
+#define CINNAMON_BACKGROUND_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CINNAMON_TYPE_BACKGROUND_MANAGER, CinnamonBackgroundManagerClass))
+
+typedef struct CinnamonBackgroundManagerPrivate CinnamonBackgroundManagerPrivate;
+
+typedef struct
+{
+        GObject                     parent;
+        CinnamonBackgroundManagerPrivate *priv;
+} CinnamonBackgroundManager;
+
+typedef struct
+{
+        GObjectClass   parent_class;
+} CinnamonBackgroundManagerClass;
+
+GType                   cinnamon_background_manager_get_type            (void);
+
+CinnamonBackgroundManager *cinnamon_background_manager_get_default (void);
+
+gboolean                cinnamon_background_manager_start               (CinnamonBackgroundManager *manager);
+void                    cinnamon_background_manager_stop                (CinnamonBackgroundManager *manager);
+
+G_END_DECLS
+
+#endif /* __CINNAMON_BACKGROUND_MANAGER_H */
diff -uNr a/src/main.c b/src/main.c
--- a/src/main.c	2013-05-22 17:35:08.000000000 +0100
+++ b/src/main.c	2013-05-22 21:36:04.000000000 +0100
@@ -34,99 +34,122 @@
 #define OVERRIDES_SCHEMA "org.cinnamon.overrides"
 
 static void
+cinnamon_dbus_acquire_name (GDBusProxy *bus,
+                         guint32     request_name_flags,
+                         guint32    *request_name_result,
+                         gchar      *name,
+                         gboolean    fatal)
+{
+  GError *error = NULL;
+  GVariant *request_name_variant;
+
+  if (!(request_name_variant = g_dbus_proxy_call_sync (bus,
+                                                       "RequestName",
+                                                       g_variant_new ("(su)", name, request_name_flags),
+                                                       0, /* call flags */
+                                                       -1, /* timeout */
+                                                       NULL, /* cancellable */
+                                                       &error)))
+    {
+      g_printerr ("failed to acquire %s: %s\n", name, error->message);
+      if (!fatal)
+        return;
+      exit (1);
+    }
+  g_variant_get (request_name_variant, "(u)", request_name_result);
+}
+
+static void
+cinnamon_dbus_acquire_names (GDBusProxy *bus,
+                          guint32     request_name_flags,
+                          gchar      *name,
+                          gboolean    fatal, ...) G_GNUC_NULL_TERMINATED;
+
+static void
+cinnamon_dbus_acquire_names (GDBusProxy *bus,
+                          guint32     request_name_flags,
+                          gchar      *name,
+                          gboolean    fatal, ...)
+{
+  va_list al;
+  guint32 request_name_result;
+  va_start (al, fatal);
+  for (;;)
+  {
+    cinnamon_dbus_acquire_name (bus,
+                             request_name_flags,
+                             &request_name_result,
+                             name, fatal);
+    name = va_arg (al, gchar *);
+    if (!name)
+      break;
+    fatal = va_arg (al, gboolean);
+  }
+  va_end (al);
+}
+
+static void
 cinnamon_dbus_init (gboolean replace)
 {
+  GDBusConnection *session;
+  GDBusProxy *bus;
   GError *error = NULL;
-  DBusGConnection *session;
-  DBusGProxy *bus;
   guint32 request_name_flags;
   guint32 request_name_result;
 
-  /** TODO:
-   * In the future we should use GDBus for this.  However, in
-   * order to do that, we need to port all of the JavaScript
-   * code.  Otherwise, the name will be claimed on the wrong
-   * connection.
-   */
-  session = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
+  session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
 
-  bus = dbus_g_proxy_new_for_name (session,
-                                   DBUS_SERVICE_DBUS,
-                                   DBUS_PATH_DBUS,
-                                   DBUS_INTERFACE_DBUS);
+  if (error) {
+    g_printerr ("Failed to connect to session bus: %s", error->message);
+    exit (1);
+  }
+
+  bus = g_dbus_proxy_new_sync (session,
+                               G_DBUS_PROXY_FLAGS_NONE,
+                               NULL, /* interface info */
+                               "org.freedesktop.DBus",
+                               "/org/freedesktop/DBus",
+                               "org.freedesktop.DBus",
+                               NULL, /* cancellable */
+                               &error);
 
-  request_name_flags = DBUS_NAME_FLAG_DO_NOT_QUEUE | DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
+  request_name_flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
   if (replace)
     request_name_flags |= DBUS_NAME_FLAG_REPLACE_EXISTING;
-  if (!dbus_g_proxy_call (bus, "RequestName", &error,
-                          G_TYPE_STRING, CINNAMON_DBUS_SERVICE,
-                          G_TYPE_UINT, request_name_flags,
-                          G_TYPE_INVALID,
-                          G_TYPE_UINT, &request_name_result,
-                          G_TYPE_INVALID))
-    {
-      g_printerr ("failed to acquire org.Cinnamon: %s\n", error->message);
-      exit (1);
-    }
+
+  cinnamon_dbus_acquire_name (bus,
+                           request_name_flags,
+                           &request_name_result,
+                           CINNAMON_DBUS_SERVICE, TRUE);
   if (!(request_name_result == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
         || request_name_result == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER))
     {
-      g_printerr ("%s already exists on bus and --replace not specified\n",
-                  CINNAMON_DBUS_SERVICE);
+      g_printerr (CINNAMON_DBUS_SERVICE " already exists on bus and --replace not specified\n");
       exit (1);
     }
 
-  /* Also grab org.gnome.Panel to replace any existing panel process */
-  if (!dbus_g_proxy_call (bus, "RequestName", &error, G_TYPE_STRING,
-                          "org.gnome.Panel", G_TYPE_UINT,
-                          DBUS_NAME_FLAG_REPLACE_EXISTING | request_name_flags,
-                          G_TYPE_INVALID, G_TYPE_UINT,
-                          &request_name_result, G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire org.gnome.Panel: %s\n", error->message);
-      exit (1);
-    }
-
-  /* ...and the org.gnome.Magnifier service.
+  /*
+   * We always specify REPLACE_EXISTING to ensure we kill off
+   * the existing service if it was running.
    */
-  if (!dbus_g_proxy_call (bus, "RequestName", &error,
-                          G_TYPE_STRING, MAGNIFIER_DBUS_SERVICE,
-                          G_TYPE_UINT, DBUS_NAME_FLAG_REPLACE_EXISTING | request_name_flags,
-                          G_TYPE_INVALID,
-                          G_TYPE_UINT, &request_name_result,
-                          G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire %s: %s\n", MAGNIFIER_DBUS_SERVICE, error->message);
-      /* Failing to acquire the magnifer service is not fatal.  Log the error,
-       * but keep going. */
-    }
-
-  /* ...and the org.freedesktop.Notifications service; we always
-   * specify REPLACE_EXISTING to ensure we kill off
-   * notification-daemon if it was running.
-   */
-  if (!dbus_g_proxy_call (bus, "RequestName", &error,
-                          G_TYPE_STRING, "org.freedesktop.Notifications",
-                          G_TYPE_UINT, DBUS_NAME_FLAG_REPLACE_EXISTING | request_name_flags,
-                          G_TYPE_INVALID,
-                          G_TYPE_UINT, &request_name_result,
-                          G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire org.freedesktop.Notifications: %s\n", error->message);
-    }
+  request_name_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
 
+  cinnamon_dbus_acquire_names (bus,
+                            request_name_flags,
+  /* Also grab org.gnome.Panel to replace any existing panel process */
+                            "org.gnome.Panel", TRUE,
+  /* ...and the org.gnome.Magnifier service. */
+                            MAGNIFIER_DBUS_SERVICE, FALSE,
+  /* ...and the org.freedesktop.Notifications service. */
+                            "org.freedesktop.Notifications", FALSE,
+                            NULL);
   /* ...and the on-screen keyboard service */
-  if (!dbus_g_proxy_call (bus, "RequestName", &error,
-                          G_TYPE_STRING, "org.gnome.Caribou.Keyboard",
-                          G_TYPE_UINT, DBUS_NAME_FLAG_REPLACE_EXISTING,
-                          G_TYPE_INVALID,
-                          G_TYPE_UINT, &request_name_result,
-                          G_TYPE_INVALID))
-    {
-      g_print ("failed to acquire org.gnome.Caribou.Keyboard: %s\n", error->message);
-    }
-
+  cinnamon_dbus_acquire_name (bus,
+                           DBUS_NAME_FLAG_REPLACE_EXISTING,
+                           &request_name_result,
+                           "org.gnome.Caribou.Keyboard", FALSE);
   g_object_unref (bus);
+  g_object_unref (session);
 }
 
 static void
diff -uNr a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am	2013-05-22 17:35:08.000000000 +0100
+++ b/src/Makefile.am	2013-05-22 21:36:04.000000000 +0100
@@ -105,6 +105,7 @@
 	cinnamon-app-system.h		\
 	cinnamon-app-usage.h		\
 	cinnamon-arrow.h			\
+	cinnamon-background-manager.h	\
 	cinnamon-doc-system.h		\
 	cinnamon-embedded-window.h		\
 	cinnamon-generic-container.h	\
@@ -142,6 +143,7 @@
 	cinnamon-app-system.c		\
 	cinnamon-app-usage.c		\
 	cinnamon-arrow.c			\
+	cinnamon-background-manager.c	\
 	cinnamon-doc-system.c		\
 	cinnamon-embedded-window.c		\
 	cinnamon-generic-container.c	\

