39 | 39 |
|
40 | 40 |
guint entry_type : 2;
|
41 | 41 |
guint is_legacy : 1;
|
42 | |
volatile gint refcount;
|
|
42 |
guint refcount : 24;
|
43 | 43 |
};
|
44 | 44 |
|
45 | 45 |
struct EntryDirectoryList
|
46 | 46 |
{
|
47 | |
volatile int refcount;
|
|
47 |
int refcount;
|
48 | 48 |
int length;
|
49 | 49 |
GList *dirs;
|
50 | 50 |
};
|
|
64 | 64 |
guint have_read_entries : 1;
|
65 | 65 |
guint deleted : 1;
|
66 | 66 |
|
67 | |
GFunc notify;
|
68 | |
gpointer notify_data;
|
69 | |
|
70 | |
volatile gint references;
|
|
67 |
guint references : 28;
|
71 | 68 |
};
|
72 | 69 |
|
73 | 70 |
struct CachedDirMonitor
|
|
82 | 79 |
static void cached_dir_free (CachedDir *dir);
|
83 | 80 |
static gboolean cached_dir_load_entries_recursive (CachedDir *dir,
|
84 | 81 |
const char *dirname);
|
85 | |
static void cached_dir_unref (CachedDir *dir);
|
86 | |
static CachedDir * cached_dir_add_subdir (CachedDir *dir,
|
87 | |
const char *basename,
|
88 | |
const char *path);
|
89 | |
static gboolean cached_dir_remove_subdir (CachedDir *dir,
|
90 | |
const char *basename);
|
91 | 82 |
|
92 | 83 |
static void handle_cached_dir_changed (MenuMonitor *monitor,
|
93 | 84 |
MenuMonitorEvent event,
|
|
100 | 91 |
|
101 | 92 |
static CachedDir *dir_cache = NULL;
|
102 | 93 |
|
103 | |
static void
|
104 | |
clear_cache (CachedDir *dir,
|
105 | |
gpointer *cache)
|
106 | |
{
|
107 | |
*cache = NULL;
|
108 | |
}
|
109 | |
|
110 | 94 |
static CachedDir *
|
111 | 95 |
cached_dir_new (const char *name)
|
112 | 96 |
{
|
113 | 97 |
CachedDir *dir;
|
114 | 98 |
|
115 | 99 |
dir = g_new0 (CachedDir, 1);
|
|
100 |
|
116 | 101 |
dir->name = g_strdup (name);
|
117 | |
|
118 | |
return dir;
|
119 | |
}
|
120 | |
|
121 | |
static CachedDir *
|
122 | |
cached_dir_new_full (const char *name,
|
123 | |
GFunc notify,
|
124 | |
gpointer notify_data)
|
125 | |
{
|
126 | |
CachedDir *dir;
|
127 | |
|
128 | |
dir = cached_dir_new (name);
|
129 | |
|
130 | |
dir->notify = notify;
|
131 | |
dir->notify_data = notify_data;
|
132 | 102 |
|
133 | 103 |
return dir;
|
134 | 104 |
}
|
|
156 | 126 |
dir->entries = NULL;
|
157 | 127 |
|
158 | 128 |
g_slist_foreach (dir->subdirs,
|
159 | |
(GFunc) cached_dir_unref,
|
|
129 |
(GFunc) cached_dir_free,
|
160 | 130 |
NULL);
|
161 | 131 |
g_slist_free (dir->subdirs);
|
162 | 132 |
dir->subdirs = NULL;
|
|
168 | 138 |
g_free (dir);
|
169 | 139 |
}
|
170 | 140 |
|
171 | |
static CachedDir *
|
172 | |
cached_dir_ref (CachedDir *dir)
|
173 | |
{
|
174 | |
g_atomic_int_inc (&dir->references);
|
175 | |
|
176 | |
return dir;
|
177 | |
}
|
178 | |
|
179 | |
static void
|
180 | |
cached_dir_unref (CachedDir *dir)
|
181 | |
{
|
182 | |
gboolean is_zero;
|
183 | |
|
184 | |
is_zero = g_atomic_int_dec_and_test (&dir->references);
|
185 | |
if (is_zero)
|
186 | |
{
|
187 | |
CachedDir *parent;
|
188 | |
|
189 | |
parent = dir->parent;
|
190 | |
|
191 | |
if (parent != NULL)
|
192 | |
cached_dir_remove_subdir (parent, dir->name);
|
193 | |
|
194 | |
if (dir->notify)
|
195 | |
dir->notify (dir, dir->notify_data);
|
196 | |
|
197 | |
cached_dir_free (dir);
|
198 | |
}
|
199 | |
}
|
200 | |
|
201 | 141 |
static inline CachedDir *
|
202 | 142 |
find_subdir (CachedDir *dir,
|
203 | 143 |
const char *subdir)
|
|
227 | 167 |
tmp = dir->entries;
|
228 | 168 |
while (tmp != NULL)
|
229 | 169 |
{
|
230 | |
const char *entry_basename;
|
231 | |
|
232 | |
entry_basename = desktop_entry_get_basename (tmp->data);
|
233 | |
if (strcmp (entry_basename, basename) == 0)
|
234 | |
{
|
235 | |
return tmp->data;
|
236 | |
}
|
|
170 |
if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
|
|
171 |
return tmp->data;
|
237 | 172 |
|
238 | 173 |
tmp = tmp->next;
|
239 | 174 |
}
|
|
281 | 216 |
int i;
|
282 | 217 |
|
283 | 218 |
if (dir_cache == NULL)
|
284 | |
dir_cache = cached_dir_new_full ("/",
|
285 | |
(GFunc) clear_cache,
|
286 | |
&dir_cache);
|
|
219 |
dir_cache = cached_dir_new ("/");
|
287 | 220 |
dir = dir_cache;
|
288 | 221 |
|
289 | 222 |
g_assert (canonical != NULL && canonical[0] == G_DIR_SEPARATOR);
|
|
297 | 230 |
{
|
298 | 231 |
CachedDir *subdir;
|
299 | 232 |
|
300 | |
subdir = cached_dir_add_subdir (dir, split[i], NULL);
|
|
233 |
if ((subdir = find_subdir (dir, split[i])) == NULL)
|
|
234 |
{
|
|
235 |
subdir = cached_dir_new (split[i]);
|
|
236 |
dir->subdirs = g_slist_prepend (dir->subdirs, subdir);
|
|
237 |
subdir->parent = dir;
|
|
238 |
}
|
301 | 239 |
|
302 | 240 |
dir = subdir;
|
303 | 241 |
|
|
347 | 285 |
tmp = dir->entries;
|
348 | 286 |
while (tmp != NULL)
|
349 | 287 |
{
|
350 | |
const char *entry_basename;
|
351 | |
entry_basename = desktop_entry_get_basename (tmp->data);
|
352 | |
if (strcmp (entry_basename, basename) == 0)
|
|
288 |
if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
|
353 | 289 |
{
|
354 | 290 |
if (!desktop_entry_reload (tmp->data))
|
355 | 291 |
{
|
|
374 | 310 |
tmp = dir->entries;
|
375 | 311 |
while (tmp != NULL)
|
376 | 312 |
{
|
377 | |
const char *entry_basename;
|
378 | |
entry_basename = desktop_entry_get_basename (tmp->data);
|
379 | |
|
380 | |
if (strcmp (entry_basename, basename) == 0)
|
|
313 |
if (strcmp (desktop_entry_get_basename (tmp->data), basename) == 0)
|
381 | 314 |
{
|
382 | 315 |
desktop_entry_unref (tmp->data);
|
383 | 316 |
dir->entries = g_slist_delete_link (dir->entries, tmp);
|
|
390 | 323 |
return FALSE;
|
391 | 324 |
}
|
392 | 325 |
|
393 | |
static CachedDir *
|
|
326 |
static gboolean
|
394 | 327 |
cached_dir_add_subdir (CachedDir *dir,
|
395 | 328 |
const char *basename,
|
396 | 329 |
const char *path)
|
|
402 | 335 |
if (subdir != NULL)
|
403 | 336 |
{
|
404 | 337 |
subdir->deleted = FALSE;
|
405 | |
return subdir;
|
|
338 |
return TRUE;
|
406 | 339 |
}
|
407 | 340 |
|
408 | 341 |
subdir = cached_dir_new (basename);
|
409 | 342 |
|
410 | |
if (path != NULL && !cached_dir_load_entries_recursive (subdir, path))
|
|
343 |
if (!cached_dir_load_entries_recursive (subdir, path))
|
411 | 344 |
{
|
412 | 345 |
cached_dir_free (subdir);
|
413 | |
return NULL;
|
|
346 |
return FALSE;
|
414 | 347 |
}
|
415 | 348 |
|
416 | 349 |
menu_verbose ("Caching dir \"%s\"\n", basename);
|
417 | 350 |
|
418 | 351 |
subdir->parent = dir;
|
419 | |
dir->subdirs = g_slist_prepend (dir->subdirs, cached_dir_ref (subdir));
|
420 | |
|
421 | |
return subdir;
|
|
352 |
dir->subdirs = g_slist_prepend (dir->subdirs, subdir);
|
|
353 |
|
|
354 |
return TRUE;
|
422 | 355 |
}
|
423 | 356 |
|
424 | 357 |
static gboolean
|
|
435 | 368 |
|
436 | 369 |
if (subdir->references == 0)
|
437 | 370 |
{
|
438 | |
cached_dir_unref (subdir);
|
|
371 |
cached_dir_free (subdir);
|
439 | 372 |
dir->subdirs = g_slist_remove (dir->subdirs, subdir);
|
440 | 373 |
}
|
441 | 374 |
|
|
630 | 563 |
switch (event)
|
631 | 564 |
{
|
632 | 565 |
case MENU_MONITOR_EVENT_CREATED:
|
633 | |
handled = cached_dir_add_subdir (dir, basename, path) != NULL;
|
|
566 |
handled = cached_dir_add_subdir (dir, basename, path);
|
634 | 567 |
break;
|
635 | 568 |
|
636 | 569 |
case MENU_MONITOR_EVENT_CHANGED:
|
|
802 | 735 |
static void
|
803 | 736 |
cached_dir_add_reference (CachedDir *dir)
|
804 | 737 |
{
|
805 | |
cached_dir_ref (dir);
|
|
738 |
dir->references++;
|
806 | 739 |
|
807 | 740 |
if (dir->parent != NULL)
|
808 | 741 |
{
|
|
817 | 750 |
|
818 | 751 |
parent = dir->parent;
|
819 | 752 |
|
820 | |
cached_dir_unref (dir);
|
|
753 |
if (--dir->references == 0 && dir->deleted)
|
|
754 |
{
|
|
755 |
if (dir->parent != NULL)
|
|
756 |
{
|
|
757 |
GSList *tmp;
|
|
758 |
|
|
759 |
tmp = parent->subdirs;
|
|
760 |
while (tmp != NULL)
|
|
761 |
{
|
|
762 |
CachedDir *subdir = tmp->data;
|
|
763 |
|
|
764 |
if (!strcmp (subdir->name, dir->name))
|
|
765 |
{
|
|
766 |
parent->subdirs = g_slist_delete_link (parent->subdirs, tmp);
|
|
767 |
break;
|
|
768 |
}
|
|
769 |
|
|
770 |
tmp = tmp->next;
|
|
771 |
}
|
|
772 |
}
|
|
773 |
|
|
774 |
cached_dir_free (dir);
|
|
775 |
}
|
821 | 776 |
|
822 | 777 |
if (parent != NULL)
|
823 | 778 |
{
|
|
889 | 844 |
g_return_val_if_fail (ed != NULL, NULL);
|
890 | 845 |
g_return_val_if_fail (ed->refcount > 0, NULL);
|
891 | 846 |
|
892 | |
g_atomic_int_inc (&ed->refcount);
|
|
847 |
ed->refcount++;
|
893 | 848 |
|
894 | 849 |
return ed;
|
895 | 850 |
}
|
|
897 | 852 |
void
|
898 | 853 |
entry_directory_unref (EntryDirectory *ed)
|
899 | 854 |
{
|
900 | |
gboolean is_zero;
|
901 | |
|
902 | 855 |
g_return_if_fail (ed != NULL);
|
903 | 856 |
g_return_if_fail (ed->refcount > 0);
|
904 | 857 |
|
905 | |
is_zero = g_atomic_int_dec_and_test (&ed->refcount);
|
906 | |
if (is_zero)
|
|
858 |
if (--ed->refcount == 0)
|
907 | 859 |
{
|
908 | 860 |
cached_dir_remove_reference (ed->dir);
|
909 | 861 |
|
|
1019 | 971 |
|
1020 | 972 |
if (desktop_entry_get_type (entry) == ed->entry_type)
|
1021 | 973 |
{
|
1022 | |
gboolean ret;
|
1023 | |
char *file_id;
|
1024 | |
const char *basename;
|
1025 | |
|
1026 | |
basename = desktop_entry_get_basename (entry);
|
1027 | |
g_string_append (relative_path, basename);
|
|
974 |
gboolean ret;
|
|
975 |
char *file_id;
|
|
976 |
|
|
977 |
g_string_append (relative_path,
|
|
978 |
desktop_entry_get_basename (entry));
|
1028 | 979 |
|
1029 | 980 |
file_id = get_desktop_file_id_from_path (ed,
|
1030 | 981 |
ed->entry_type,
|
|
1104 | 1055 |
DesktopEntry *entry = tmp->data;
|
1105 | 1056 |
const char *basename;
|
1106 | 1057 |
|
1107 | |
basename = desktop_entry_get_path (entry);
|
|
1058 |
basename = desktop_entry_get_basename (entry);
|
1108 | 1059 |
|
1109 | 1060 |
if (desktop_entries &&
|
1110 | 1061 |
desktop_entry_get_type (entry) == DESKTOP_ENTRY_DESKTOP)
|
|
1177 | 1128 |
g_return_val_if_fail (list != NULL, NULL);
|
1178 | 1129 |
g_return_val_if_fail (list->refcount > 0, NULL);
|
1179 | 1130 |
|
1180 | |
g_atomic_int_inc (&list->refcount);
|
|
1131 |
list->refcount += 1;
|
1181 | 1132 |
|
1182 | 1133 |
return list;
|
1183 | 1134 |
}
|
|
1185 | 1136 |
void
|
1186 | 1137 |
entry_directory_list_unref (EntryDirectoryList *list)
|
1187 | 1138 |
{
|
1188 | |
gboolean is_zero;
|
1189 | |
|
1190 | 1139 |
g_return_if_fail (list != NULL);
|
1191 | 1140 |
g_return_if_fail (list->refcount > 0);
|
1192 | 1141 |
|
1193 | |
is_zero = g_atomic_int_dec_and_test (&list->refcount);
|
1194 | |
if (is_zero)
|
|
1142 |
list->refcount -= 1;
|
|
1143 |
if (list->refcount == 0)
|
1195 | 1144 |
{
|
1196 | 1145 |
g_list_foreach (list->dirs, (GFunc) entry_directory_unref, NULL);
|
1197 | 1146 |
g_list_free (list->dirs);
|