public IEnumerable<Window> WindowsForDesktopItem (DesktopItem item)
		{
			if (item == null)
				throw new ArgumentNullException ("DesktopItem item cannot be null.");
			

			foreach (KeyValuePair<Window, List<DesktopItem>> kvp in DesktopItemsByWindow)
				if (kvp.Value.Any (df => df == item))
					yield return kvp.Key;
		}
		public static ApplicationDockItem NewFromUri (string uri)
		{
			try {
				GLib.File file = FileFactory.NewForUri (uri);
				if (!file.Exists)
					return null;
				
				DesktopItem desktopItem = DockServices.DesktopItems.DesktopItemFromDesktopFile (file.Path);
				
				if (desktopItem == null)
					desktopItem = new DesktopItem (file.Path);

				return new ApplicationDockItem (desktopItem);
				
			} catch (Exception e) {
				Log<ApplicationDockItem>.Error (e.Message);
				Log<ApplicationDockItem>.Debug (e.StackTrace);
			}

			return null;
		}
		public ApplicationDockItem (DesktopItem item)
		{
			OwnedItem = item;
			DockServices.DesktopItems.RegisterDesktopItem (OwnedItem);
			can_manage_windows = true;
			
			UpdateInfo ();
			UpdateWindows ();
			
			OwnedItem.HasChanged += HandleOwnedItemHasChanged;
			
			Wnck.Screen.Default.WindowOpened += WnckScreenDefaultWindowOpened;
			Wnck.Screen.Default.WindowClosed += WnckScreenDefaultWindowClosed;
			
			if (CurrentDesktopOnly) {
				Wnck.Screen.Default.ViewportsChanged += WnckScreenDefaultViewportsChanged;
				Wnck.Screen.Default.ActiveWorkspaceChanged += WnckScreenDefaultActiveWorkspaceChanged;
				Wnck.Screen.Default.ActiveWindowChanged += WnckScreenDefaultWindowChanged;
				if (Wnck.Screen.Default.ActiveWindow != null)
					Wnck.Screen.Default.ActiveWindow.GeometryChanged += HandleActiveWindowGeometryChangedChanged;
			}
		}
		List<DesktopItem> LoadDesktopItemsCache (string filename)
		{
			if (!GLib.FileFactory.NewForPath (filename).Exists)
				return null;
				
			Log<DesktopItemService>.Debug ("Loading desktop item cache '{0}'.", DockyDesktopFileCacheFile);
			
			List<DesktopItem> items = new List<DesktopItem> ();
			
			try {
				using (StreamReader reader = new StreamReader (filename)) {
					DesktopItem desktopItem = null;
					string line;
					
					while ((line = reader.ReadLine ()) != null) {
						if (line.Trim ().Length <= 0)
							continue;
						
						if (line.ElementAt (0) == '[') {
							Match match = DesktopItem.sectionRegex.Match (line);
							if (match.Success) {
								string section = match.Groups ["Section"].Value;
								if (section != null) {
									GLib.File file = GLib.FileFactory.NewForPath (section);
									desktopItem = new DesktopItem (file, false);
									items.Add (desktopItem);
								}
								continue;
							}
						} else if (desktopItem != null) {
							Match match = DesktopItem.keyValueRegex.Match (line);
							if (match.Success) {
								string key = match.Groups ["Key"].Value;
								string val = match.Groups ["Value"].Value;
								if (!string.IsNullOrEmpty (key) && !string.IsNullOrEmpty (val))
									desktopItem.SetString (key, val);
								continue;
							}
						}
					}
					reader.Close ();
				}
			} catch (Exception e) {
				Log<DesktopItemService>.Error ("Error loading desktop item cache: {0}", e.Message);
				Log<DesktopItemService>.Error (e.StackTrace);
				return null;
			}

			return items;
		}
		void ProcessAndMergeSystemCacheFile (GLib.File cache)
		{
			if (!cache.Exists)
				return;
			
			Log<DesktopItemService>.Debug ("Processing {0}", cache.Path);
			
			try {
				using (StreamReader reader = new StreamReader (cache.Path)) {
					DesktopItem desktopItem = null;
					string line;
					
					while ((line = reader.ReadLine ()) != null) {
						if (line.Trim ().Length <= 0)
							continue;
						
						if (line.ElementAt (0) == '[') {
							Match match = DesktopItem.sectionRegex.Match (line);
							if (match.Success) {
								string section = match.Groups ["Section"].Value;
								if (section != null) {
									GLib.File file = cache.Parent.GetChild (string.Format ("{0}.desktop", section));
									desktopItem = RegisteredItems.First (item => item.File.Path == file.Path);
									if (desktopItem == null && file.Exists) {
										desktopItem = new DesktopItem (file);
										RegisteredItems.Add (desktopItem);
										Log<DesktopItemService>.Debug ("New application found: {0}", desktopItem.Path);
									}
									continue;
								}
							}
						} else if (desktopItem != null) {
							Match match = DesktopItem.keyValueRegex.Match (line);
							if (match.Success) {
								string key = match.Groups ["Key"].Value;
								string val = match.Groups ["Value"].Value;
								if (!string.IsNullOrEmpty (key) && !string.IsNullOrEmpty (val))
									desktopItem.SetString (key, val);
								continue;
							}
						}
					}
					reader.Close ();
				}
			} catch (Exception e) {
				Log<DesktopItemService>.Error ("Error processing desktop item cache: {0}", e.Message);
				Log<DesktopItemService>.Error (e.StackTrace);
			}
		}
		public void RegisterDesktopItem (DesktopItem item)
		{
			// check if this item is in either the registered or unregistered items
			if (DesktopItems.Contains (item))
				return;
			
			// if this item isn't in our desktop item list, we need to add it as an unregistered item
			UnregisteredItems.Add (item);
			
			// and make sure we process it
			// FIXME: do we really need to reload _every_ desktop file here? Probably only need to process the new one..
			DesktopItemsChanged ();
		}