void MonitorDesktopFileDirs (GLib.File dir) { // build a list of all the subdirectories List<GLib.File> dirs = new List<GLib.File> () {dir}; try { dirs = dirs.Union (dir.SubDirs ()).ToList (); } catch {} foreach (GLib.File d in dirs) { GLib.FileMonitor mon = d.Monitor (GLib.FileMonitorFlags.None, null); mon.RateLimit = 2500; mon.Changed += delegate(object o, GLib.ChangedArgs args) { // bug in GIO#, calling args.File or args.OtherFile crashes hard GLib.File file = GLib.FileAdapter.GetObject ((GLib.Object) args.Args [0]); GLib.File otherFile = GLib.FileAdapter.GetObject ((GLib.Object) args.Args [1]); // according to GLib documentation, the change signal runs on the same // thread that the monitor was created on. Without running this part on a thread // docky freezes up for about 500-800 ms while the .desktop files are parsed. DockServices.System.RunOnThread (() => { // if a new directory was created, make sure we watch that dir as well if (file.QueryFileType (GLib.FileQueryInfoFlags.NofollowSymlinks, null) == GLib.FileType.Directory) MonitorDesktopFileDirs (file); // we only care about .desktop files if (!file.Path.EndsWith (".desktop")) return; lock (update_lock) { UpdateDesktopItemsList (); DesktopItemsChanged (); SaveDesktopItemsCache(); } // Make sure to trigger event on main thread DockServices.System.RunOnMainThread (() => { if (DesktopFileChanged != null) DesktopFileChanged (this, new DesktopFileChangedEventArgs (args.EventType, file, otherFile)); }); }); }; } }