Index: extensions/places-menu/placeDisplay.js
===================================================================
--- extensions/places-menu/placeDisplay.js.orig	2013-07-24 17:57:44.000000000 +0800
+++ extensions/places-menu/placeDisplay.js	2014-08-22 15:18:57.002625099 +0800
@@ -192,32 +192,30 @@ const PlacesManager = new Lang.Class({
             network: [],
         };
 
-        let homePath = GLib.get_home_dir();
-
-        this._places.special.push(new PlaceInfo('special',
-                                                Gio.File.new_for_path(homePath),
-                                                _("Home")));
-
-        let specials = [];
-        for (let i = 0; i < DEFAULT_DIRECTORIES.length; i++) {
-            let specialPath = GLib.get_user_special_dir(DEFAULT_DIRECTORIES[i]);
-            if (specialPath == homePath)
-                continue;
-
-            let file = Gio.File.new_for_path(specialPath), info;
-            try {
-                info = new PlaceInfo('special', file);
-            } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
-                continue;
-            }
-
-            specials.push(info);
+        // unlike bookmark file, XDG's 'user-dirs.dirs' here only serves as a
+        // signal gnerator: when 'reload_user_special_dirs_cache' should be
+        // invoked, not a definitive source for user special dirs, which is
+        // handled by GLib as before.
+        this._userDirsFile = this._findUserDirsFile();
+        this._userDirsTimeoutId = 0;
+        this._userDirsMonitor = null;
+
+        if (this._userDirsFile) {
+            this._userDirsMonitor = this._userDirsFile.monitor_file(Gio.FileMonitorFlags.NONE, null);
+            this._userDirsMonitor.connect('changed', Lang.bind(this, function () {
+                if (this._userDirsTimeoutId > 0)
+                    return;
+                /* Defensive event compression */
+                this._userDirsTimeoutId = Mainloop.timeout_add(100, Lang.bind(this, function () {
+                    this._userDirsTimeoutId = 0;
+                    this._reloadSpecial();
+                    return false;
+                }));
+            }));
         }
-
-        specials.sort(function(a, b) {
-            return GLib.utf8_collate(a.name, b.name);
-        });
-        this._places.special = this._places.special.concat(specials);
+        // as stated above, special will always get loaded, even
+        // 'user-dirs.dirs' are not found.
+        this._reloadSpecial();
 
         /*
         * Show devices, code more or less ported from nautilus-places-sidebar.c
@@ -247,6 +245,40 @@ const PlacesManager = new Lang.Class({
         }
     },
 
+    _reloadSpecial: function() {
+        let homePath = GLib.get_home_dir();
+        this._places.special = [];
+
+        this._places.special.push(new PlaceInfo('special',
+                                                Gio.File.new_for_path(homePath),
+                                                _("Home")));
+
+        // Reload cache s.t. the changes on disk would appear here immediately
+        GLib.reload_user_special_dirs_cache();
+        let specials = [];
+        for (let i = 0; i < DEFAULT_DIRECTORIES.length; i++) {
+            let specialPath = GLib.get_user_special_dir(DEFAULT_DIRECTORIES[i]);
+            if (specialPath == homePath)
+                continue;
+
+            let file = Gio.File.new_for_path(specialPath), info;
+            try {
+                info = new PlaceInfo('special', file);
+            } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND)) {
+                continue;
+            }
+
+            specials.push(info);
+        }
+
+        specials.sort(function(a, b) {
+            return GLib.utf8_collate(a.name, b.name);
+        });
+        this._places.special = this._places.special.concat(specials);
+
+        this.emit('special-updated');
+    },
+
     _connectVolumeMonitorSignals: function() {
         const signals = ['volume-added', 'volume-removed', 'volume-changed',
                          'mount-added', 'mount-removed', 'mount-changed',
@@ -353,6 +385,19 @@ const PlacesManager = new Lang.Class({
         this.emit('network-updated');
     },
 
+    _findUserDirsFile: function() {
+        let paths = [
+            GLib.build_filenamev([GLib.get_user_config_dir(), 'user-dirs.dirs']),
+        ];
+
+        for (let i = 0; i < paths.length; i++) {
+            if (GLib.file_test(paths[i], GLib.FileTest.EXISTS))
+                return Gio.File.new_for_path(paths[i]);
+        }
+
+        return null;
+    },
+
     _findBookmarksFile: function() {
         let paths = [
             GLib.build_filenamev([GLib.get_user_config_dir(), 'gtk-3.0', 'bookmarks']),
