summaryrefslogtreecommitdiff
path: root/src/bin/efreet
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-11-27 19:45:29 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2013-11-27 19:50:24 +0900
commitc69cf487463ccec7cf572220c7c0b9353f6e7db9 (patch)
tree7067f326ffca48a6ccab980c2523c0ede621b7d7 /src/bin/efreet
parent1e70d703b329499982f484ce4f7a1227fb57919d (diff)
recursive monitoring and scanning fix for icons and desktop files
this fixes T580 ... or SHOULD fix it. there is recursion detection code now and it properly follows symlinks and dirs. it also properly updates the file monitor tree for both icons and desktops and it only monitors dirs, not files (as a dir picks up changes to child data). tested and it seems not to recurse into self-referencing symlinks (once it detects the loop) and detects changes nicely in all my tests.
Diffstat (limited to 'src/bin/efreet')
-rw-r--r--src/bin/efreet/efreet_desktop_cache_create.c62
-rw-r--r--src/bin/efreet/efreet_icon_cache_create.c4
-rw-r--r--src/bin/efreet/efreetd_cache.c381
3 files changed, 266 insertions, 181 deletions
diff --git a/src/bin/efreet/efreet_desktop_cache_create.c b/src/bin/efreet/efreet_desktop_cache_create.c
index 2fc6e917d7..fd8c613305 100644
--- a/src/bin/efreet/efreet_desktop_cache_create.c
+++ b/src/bin/efreet/efreet_desktop_cache_create.c
@@ -128,54 +128,75 @@ cache_add(const char *path, const char *file_id, int priority EINA_UNUSED, int *
128 128
129 129
130static int 130static int
131cache_scan(const char *path, const char *base_id, int priority, int recurse, int *changed) 131cache_scan(Eina_Inarray *stack, const char *path, const char *base_id,
132 int priority, int recurse, int *changed)
132{ 133{
133 char *file_id = NULL; 134 char *file_id = NULL;
134 char id[PATH_MAX]; 135 char id[PATH_MAX];
135 char buf[PATH_MAX];
136 Eina_Iterator *it; 136 Eina_Iterator *it;
137 Eina_File_Direct_Info *info; 137 Eina_File_Direct_Info *info;
138 Eina_Bool free_stack = EINA_FALSE;
139 struct stat st;
140 unsigned int i;
141 int ret = 1;
138 142
139 if (!ecore_file_is_dir(path)) return 1; 143 if (!ecore_file_is_dir(path)) return 1;
140 144
141 it = eina_file_stat_ls(path); 145 if (!stack)
142 if (!it) return 1; 146 {
147 free_stack = EINA_TRUE;
148 stack = eina_inarray_new(sizeof(struct stat), 16);
149 if (!stack) goto end;
150 }
151 if (stat(path, &st) == -1) goto end;
152 for (i = 0; i < eina_inarray_count(stack); i++)
153 {
154 struct stat *st2 = eina_inarray_nth(stack, i);
155
156 if ((st2->st_dev == st.st_dev) && (st2->st_ino == st.st_ino))
157 goto end;
158 }
159 eina_inarray_push(stack, &st);
143 160
161 it = eina_file_stat_ls(path);
162 if (!it) goto end;
144 id[0] = '\0'; 163 id[0] = '\0';
145 EINA_ITERATOR_FOREACH(it, info) 164 EINA_ITERATOR_FOREACH(it, info)
146 { 165 {
147 const char *fname; 166 const char *fname = info->path + info->name_start;
148 167
149 fname = info->path + info->name_start; 168 if (info->path[info->name_start] == '.') continue;
150 if (base_id) 169 if (base_id)
151 { 170 {
152 if (*base_id) 171 if (*base_id) snprintf(id, sizeof(id), "%s-%s", base_id, fname);
153 snprintf(id, sizeof(id), "%s-%s", base_id, fname);
154 else 172 else
155 { 173 {
156 strncpy(id, fname, PATH_MAX); 174 strncpy(id, fname, PATH_MAX);
157 id[PATH_MAX - 1] = '\0'; 175 id[PATH_MAX - 1] = 0;
158 } 176 }
159 file_id = id; 177 file_id = id;
160 } 178 }
161 179
162 snprintf(buf, sizeof(buf), "%s/%s", path, fname); 180 if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) ||
163 if (info->type == EINA_FILE_DIR) 181 (info->type == EINA_FILE_DIR))
164 { 182 {
165 if (recurse) 183 if (recurse)
166 cache_scan(buf, file_id, priority, recurse, changed); 184 cache_scan(stack, info->path, file_id, priority, recurse, changed);
167 } 185 }
168 else 186 else
169 { 187 {
170 if (!cache_add(buf, file_id, priority, changed)) 188 if (!cache_add(info->path, file_id, priority, changed))
171 { 189 {
172 eina_iterator_free(it); 190 eina_iterator_free(it);
173 return 0; 191 ret = 0;
192 goto end;
174 } 193 }
175 } 194 }
176 } 195 }
177 eina_iterator_free(it); 196 eina_iterator_free(it);
178 return 1; 197end:
198 if (free_stack) eina_inarray_free(stack);
199 return ret;
179} 200}
180 201
181static int 202static int
@@ -342,15 +363,16 @@ main(int argc, char **argv)
342 if (!dirs) goto error; 363 if (!dirs) goto error;
343 364
344 EINA_LIST_FREE(dirs, path) 365 EINA_LIST_FREE(dirs, path)
345 { 366 {
346 char file_id[PATH_MAX] = { '\0' }; 367 char file_id[PATH_MAX] = { '\0' };
347 368
348 if (!cache_scan(path, file_id, priority++, 1, &changed)) goto error; 369 if (!cache_scan(NULL, path, file_id, priority++, 1, &changed))
370 goto error;
349 systemdirs = eina_list_append(systemdirs, path); 371 systemdirs = eina_list_append(systemdirs, path);
350 } 372 }
351 373
352 EINA_LIST_FOREACH(extra_dirs, l, path) 374 EINA_LIST_FOREACH(extra_dirs, l, path)
353 if (!cache_scan(path, NULL, priority, 0, &changed)) goto error; 375 if (!cache_scan(NULL, path, NULL, priority, 0, &changed)) goto error;
354 376
355 /* store util */ 377 /* store util */
356#define STORE_HASH_ARRAY(_hash) \ 378#define STORE_HASH_ARRAY(_hash) \
diff --git a/src/bin/efreet/efreet_icon_cache_create.c b/src/bin/efreet/efreet_icon_cache_create.c
index 3b22e0cc00..9759b758ca 100644
--- a/src/bin/efreet/efreet_icon_cache_create.c
+++ b/src/bin/efreet/efreet_icon_cache_create.c
@@ -618,6 +618,10 @@ cache_theme_scan(const char *dir)
618 (entry->type != EINA_FILE_LNK)) 618 (entry->type != EINA_FILE_LNK))
619 continue; 619 continue;
620 620
621 if ((entry->type == EINA_FILE_LNK) &&
622 (!ecore_file_is_dir(entry->path)))
623 continue;
624
621 name = entry->path + entry->name_start; 625 name = entry->path + entry->name_start;
622 theme = eina_hash_find(icon_themes, name); 626 theme = eina_hash_find(icon_themes, name);
623 627
diff --git a/src/bin/efreet/efreetd_cache.c b/src/bin/efreet/efreetd_cache.c
index 23ff1ab656..6ca556ad25 100644
--- a/src/bin/efreet/efreetd_cache.c
+++ b/src/bin/efreet/efreetd_cache.c
@@ -14,7 +14,12 @@
14#include "efreet_private.h" 14#include "efreet_private.h"
15#include "efreetd_cache.h" 15#include "efreetd_cache.h"
16 16
17static Eina_Hash *change_monitors = NULL; 17#include <sys/types.h>
18#include <sys/stat.h>
19#include <unistd.h>
20
21static Eina_Hash *icon_change_monitors = NULL;
22static Eina_Hash *desktop_change_monitors = NULL;
18 23
19static Ecore_Event_Handler *cache_exe_del_handler = NULL; 24static Ecore_Event_Handler *cache_exe_del_handler = NULL;
20static Ecore_Event_Handler *cache_exe_data_handler = NULL; 25static Ecore_Event_Handler *cache_exe_data_handler = NULL;
@@ -37,6 +42,9 @@ static Eina_Bool icon_queue = EINA_FALSE;
37 42
38static void desktop_changes_monitor_add(const char *path); 43static void desktop_changes_monitor_add(const char *path);
39 44
45static void icon_changes_listen(void);
46static void desktop_changes_listen(void);
47
40/* internal */ 48/* internal */
41static Eina_Bool 49static Eina_Bool
42icon_cache_update_cache_cb(void *data EINA_UNUSED) 50icon_cache_update_cache_cb(void *data EINA_UNUSED)
@@ -53,6 +61,11 @@ icon_cache_update_cache_cb(void *data EINA_UNUSED)
53 icon_queue = EINA_FALSE; 61 icon_queue = EINA_FALSE;
54 if ((!icon_flush) && (!icon_exts)) return ECORE_CALLBACK_CANCEL; 62 if ((!icon_flush) && (!icon_exts)) return ECORE_CALLBACK_CANCEL;
55 63
64 if (icon_change_monitors) eina_hash_free(icon_change_monitors);
65 icon_change_monitors = eina_hash_string_superfast_new
66 (EINA_FREE_CB(ecore_file_monitor_del));
67 icon_changes_listen();
68
56 /* TODO: Queue if already running */ 69 /* TODO: Queue if already running */
57 snprintf(file, sizeof(file), 70 snprintf(file, sizeof(file),
58 "%s/efreet/" MODULE_ARCH "/efreet_icon_cache_create", 71 "%s/efreet/" MODULE_ARCH "/efreet_icon_cache_create",
@@ -90,16 +103,6 @@ icon_cache_update_cache_cb(void *data EINA_UNUSED)
90 return ECORE_CALLBACK_CANCEL; 103 return ECORE_CALLBACK_CANCEL;
91} 104}
92 105
93static void
94cache_icon_update(Eina_Bool flush)
95{
96 if (icon_cache_timer)
97 ecore_timer_del(icon_cache_timer);
98 if (flush)
99 icon_flush = flush;
100 icon_cache_timer = ecore_timer_add(1.0, icon_cache_update_cache_cb, NULL);
101}
102
103static Eina_Bool 106static Eina_Bool
104desktop_cache_update_cache_cb(void *data EINA_UNUSED) 107desktop_cache_update_cache_cb(void *data EINA_UNUSED)
105{ 108{
@@ -114,6 +117,11 @@ desktop_cache_update_cache_cb(void *data EINA_UNUSED)
114 } 117 }
115 desktop_queue = EINA_FALSE; 118 desktop_queue = EINA_FALSE;
116 119
120 if (desktop_change_monitors) eina_hash_free(desktop_change_monitors);
121 desktop_change_monitors = eina_hash_string_superfast_new
122 (EINA_FREE_CB(ecore_file_monitor_del));
123 desktop_changes_listen();
124
117 snprintf(file, sizeof(file), 125 snprintf(file, sizeof(file),
118 "%s/efreet/" MODULE_ARCH "/efreet_desktop_cache_create", 126 "%s/efreet/" MODULE_ARCH "/efreet_desktop_cache_create",
119 eina_prefix_lib_get(pfx)); 127 eina_prefix_lib_get(pfx));
@@ -130,64 +138,63 @@ desktop_cache_update_cache_cb(void *data EINA_UNUSED)
130 } 138 }
131 } 139 }
132 INF("Run desktop cache creation: %s", file); 140 INF("Run desktop cache creation: %s", file);
133 desktop_cache_exe = 141 desktop_cache_exe = ecore_exe_pipe_run
134 ecore_exe_pipe_run(file, ECORE_EXE_PIPE_READ|ECORE_EXE_PIPE_READ_LINE_BUFFERED, NULL); 142 (file, ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_READ_LINE_BUFFERED, NULL);
135 143
136 return ECORE_CALLBACK_CANCEL; 144 return ECORE_CALLBACK_CANCEL;
137} 145}
138 146
139static Eina_Bool 147static void
140cache_exe_data_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) 148cache_icon_update(Eina_Bool flush)
141{ 149{
142 Ecore_Exe_Event_Data *ev; 150 if (icon_cache_timer) ecore_timer_del(icon_cache_timer);
143 151 if (flush) icon_flush = flush;
144 ev = event; 152 icon_cache_timer = ecore_timer_add(0.2, icon_cache_update_cache_cb, NULL);
145 if (ev->exe == desktop_cache_exe) 153}
146 {
147 Eina_Bool update = EINA_FALSE;
148 154
149 if ((ev->lines) && (*ev->lines->line == 'c')) 155void
150 update = EINA_TRUE; 156cache_desktop_update(void)
157{
158 if (desktop_cache_timer) ecore_timer_del(desktop_cache_timer);
159 desktop_cache_timer = ecore_timer_add(0.2, desktop_cache_update_cache_cb, NULL);
160}
151 161
152 desktop_exists = EINA_TRUE; 162static void
153 send_signal_desktop_cache_update(update); 163icon_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
154 } 164 Ecore_File_Event event, const char *path EINA_UNUSED)
155 else if (ev->exe == icon_cache_exe) 165{
166 switch (event)
156 { 167 {
157 Eina_Bool update = EINA_FALSE; 168 case ECORE_FILE_EVENT_NONE:
158 169 /* noop */
159 if ((ev->lines) && (*ev->lines->line == 'c')) 170 break;
160 update = EINA_TRUE;
161 171
162 send_signal_icon_cache_update(update); 172 case ECORE_FILE_EVENT_CREATED_FILE:
163 } 173 case ECORE_FILE_EVENT_DELETED_FILE:
164 return ECORE_CALLBACK_RENEW; 174 case ECORE_FILE_EVENT_MODIFIED:
165} 175 case ECORE_FILE_EVENT_CLOSED:
176 // a FILE was changed, added or removed
177 cache_icon_update(EINA_FALSE);
178 break;
166 179
167static Eina_Bool 180 case ECORE_FILE_EVENT_DELETED_DIRECTORY:
168cache_exe_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) 181 case ECORE_FILE_EVENT_CREATED_DIRECTORY:
169{ 182 // the whole tree needs re-monitoring
170 Ecore_Exe_Event_Del *ev; 183 cache_icon_update(EINA_FALSE);
184 break;
171 185
172 ev = event; 186 case ECORE_FILE_EVENT_DELETED_SELF:
173 if (ev->exe == desktop_cache_exe) 187 // the whole tree needs re-monitoring
174 { 188 cache_icon_update(EINA_FALSE);
175 desktop_cache_exe = NULL; 189 break;
176 if (desktop_queue) cache_desktop_update();
177 }
178 else if (ev->exe == icon_cache_exe)
179 {
180 icon_cache_exe = NULL;
181 if (icon_queue) cache_icon_update(EINA_FALSE);
182 } 190 }
183 return ECORE_CALLBACK_RENEW;
184} 191}
185 192
186static void 193static void
187icon_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED, 194desktop_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
188 Ecore_File_Event event, const char *path) 195 Ecore_File_Event event, const char *path EINA_UNUSED)
189{ 196{
190 /* TODO: If we get a stale symlink, we need to rerun cache creation */ 197 /* TODO: Check for desktop*.cache, as this will be created when app is installed */
191 switch (event) 198 switch (event)
192 { 199 {
193 case ECORE_FILE_EVENT_NONE: 200 case ECORE_FILE_EVENT_NONE:
@@ -198,15 +205,20 @@ icon_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
198 case ECORE_FILE_EVENT_DELETED_FILE: 205 case ECORE_FILE_EVENT_DELETED_FILE:
199 case ECORE_FILE_EVENT_MODIFIED: 206 case ECORE_FILE_EVENT_MODIFIED:
200 case ECORE_FILE_EVENT_CLOSED: 207 case ECORE_FILE_EVENT_CLOSED:
208 // a FILE was changed, added or removed
209 cache_desktop_update();
210 break;
211
201 case ECORE_FILE_EVENT_DELETED_DIRECTORY: 212 case ECORE_FILE_EVENT_DELETED_DIRECTORY:
202 case ECORE_FILE_EVENT_CREATED_DIRECTORY: 213 case ECORE_FILE_EVENT_CREATED_DIRECTORY:
203 cache_icon_update(EINA_FALSE); 214 // the whole tree needs re-monitoring
204 break; 215 cache_desktop_update();
216 break;
205 217
206 case ECORE_FILE_EVENT_DELETED_SELF: 218 case ECORE_FILE_EVENT_DELETED_SELF:
207 eina_hash_del_by_key(change_monitors, path); 219 // the whole tree needs re-monitoring
208 cache_icon_update(EINA_FALSE); 220 cache_desktop_update();
209 break; 221 break;
210 } 222 }
211} 223}
212 224
@@ -214,21 +226,52 @@ static void
214icon_changes_monitor_add(const char *path) 226icon_changes_monitor_add(const char *path)
215{ 227{
216 Ecore_File_Monitor *mon; 228 Ecore_File_Monitor *mon;
229 char *realp;
230
231 if (eina_hash_find(icon_change_monitors, path)) return;
232 realp = ecore_file_realpath(path);
233 if (!realp) return;
234 mon = ecore_file_monitor_add(realp, icon_changes_cb, NULL);
235 free(realp);
236 if (mon) eina_hash_add(icon_change_monitors, path, mon);
237}
217 238
218 if (eina_hash_find(change_monitors, path)) return; 239static void
240desktop_changes_monitor_add(const char *path)
241{
242 Ecore_File_Monitor *mon;
243
244 if (eina_hash_find(desktop_change_monitors, path)) return;
219 /* TODO: Check for symlink and monitor the real path */ 245 /* TODO: Check for symlink and monitor the real path */
220 mon = ecore_file_monitor_add(path, 246 mon = ecore_file_monitor_add(path, desktop_changes_cb, NULL);
221 icon_changes_cb,
222 NULL);
223 if (mon) 247 if (mon)
224 eina_hash_add(change_monitors, path, mon); 248 eina_hash_add(desktop_change_monitors, path, mon);
225} 249}
226 250
227static void 251static void
228icon_changes_listen_recursive(const char *path, Eina_Bool base) 252icon_changes_listen_recursive(Eina_Inarray *stack, const char *path, Eina_Bool base)
229{ 253{
230 Eina_Iterator *it; 254 Eina_Iterator *it;
231 Eina_File_Direct_Info *info; 255 Eina_File_Direct_Info *info;
256 Eina_Bool free_stack = EINA_FALSE;
257 struct stat st;
258 unsigned int i;
259
260 if (!stack)
261 {
262 free_stack = EINA_TRUE;
263 stack = eina_inarray_new(sizeof(struct stat), 16);
264 if (!stack) return;
265 }
266 if (stat(path, &st) == -1) return;
267 for (i = 0; i < eina_inarray_count(stack); i++)
268 {
269 struct stat *st2 = eina_inarray_nth(stack, i);
270
271 if ((st2->st_dev == st.st_dev) && (st2->st_ino == st.st_ino))
272 return;
273 }
274 eina_inarray_push(stack, &st);
232 275
233 if ((!ecore_file_is_dir(path)) && (base)) 276 if ((!ecore_file_is_dir(path)) && (base))
234 { 277 {
@@ -240,16 +283,68 @@ icon_changes_listen_recursive(const char *path, Eina_Bool base)
240 // monitoring the next specific child dir down until we are 283 // monitoring the next specific child dir down until we are
241 // monitoring the original path again. 284 // monitoring the original path again.
242 } 285 }
243 icon_changes_monitor_add(path); 286 if (ecore_file_is_dir(path)) icon_changes_monitor_add(path);
244 it = eina_file_stat_ls(path); 287 it = eina_file_stat_ls(path);
245 if (!it) return; 288 if (!it) goto end;
246 EINA_ITERATOR_FOREACH(it, info) 289 EINA_ITERATOR_FOREACH(it, info)
247 { 290 {
291 if (info->path[info->name_start] == '.') continue;
248 if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) || 292 if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) ||
249 (info->type == EINA_FILE_DIR)) 293 (info->type == EINA_FILE_DIR))
250 icon_changes_monitor_add(info->path); 294 icon_changes_listen_recursive(stack, info->path, EINA_FALSE);
251 } 295 }
252 eina_iterator_free(it); 296 eina_iterator_free(it);
297end:
298 if (free_stack) eina_inarray_free(stack);
299}
300
301static void
302desktop_changes_listen_recursive(Eina_Inarray *stack, const char *path, Eina_Bool base)
303{
304 Eina_Iterator *it;
305 Eina_File_Direct_Info *info;
306 Eina_Bool free_stack = EINA_FALSE;
307 struct stat st;
308 unsigned int i;
309
310 if (!stack)
311 {
312 free_stack = EINA_TRUE;
313 stack = eina_inarray_new(sizeof(struct stat), 16);
314 if (!stack) return;
315 }
316 if (stat(path, &st) == -1) return;
317 for (i = 0; i < eina_inarray_count(stack); i++)
318 {
319 struct stat *st2 = eina_inarray_nth(stack, i);
320
321 if ((st2->st_dev == st.st_dev) && (st2->st_ino == st.st_ino))
322 return;
323 }
324 eina_inarray_push(stack, &st);
325 if ((!ecore_file_is_dir(path)) && (base))
326 {
327 // XXX: if it doesn't exist... walk the parent dirs back down
328 // to this path until we find one that doesn't exist, then
329 // monitor its parent, and treat it specially as it needs
330 // to look for JUST the creation of this specific child
331 // and when this child is created, replace this monitor with
332 // monitoring the next specific child dir down until we are
333 // monitoring the original path again.
334 }
335 if (ecore_file_is_dir(path)) desktop_changes_monitor_add(path);
336 it = eina_file_stat_ls(path);
337 if (!it) goto end;
338 EINA_ITERATOR_FOREACH(it, info)
339 {
340 if (info->path[info->name_start] == '.') continue;
341 if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) ||
342 (info->type == EINA_FILE_DIR))
343 desktop_changes_listen_recursive(stack, info->path, EINA_FALSE);
344 }
345 eina_iterator_free(it);
346end:
347 if (free_stack) eina_inarray_free(stack);
253} 348}
254 349
255static void 350static void
@@ -260,113 +355,40 @@ icon_changes_listen(void)
260 char buf[PATH_MAX]; 355 char buf[PATH_MAX];
261 const char *dir; 356 const char *dir;
262 357
263 icon_changes_listen_recursive(efreet_icon_deprecated_user_dir_get(), EINA_TRUE); 358 icon_changes_listen_recursive(NULL, efreet_icon_deprecated_user_dir_get(), EINA_TRUE);
264 icon_changes_listen_recursive(efreet_icon_user_dir_get(), EINA_TRUE); 359 icon_changes_listen_recursive(NULL, efreet_icon_user_dir_get(), EINA_TRUE);
265 EINA_LIST_FOREACH(icon_extra_dirs, l, dir) 360 EINA_LIST_FOREACH(icon_extra_dirs, l, dir)
266 { 361 {
267 icon_changes_listen_recursive(dir, EINA_TRUE); 362 icon_changes_listen_recursive(NULL, dir, EINA_TRUE);
268 } 363 }
269 364
270 xdg_dirs = efreet_data_dirs_get(); 365 xdg_dirs = efreet_data_dirs_get();
271 EINA_LIST_FOREACH(xdg_dirs, l, dir) 366 EINA_LIST_FOREACH(xdg_dirs, l, dir)
272 { 367 {
273 snprintf(buf, sizeof(buf), "%s/icons", dir); 368 snprintf(buf, sizeof(buf), "%s/icons", dir);
274 icon_changes_listen_recursive(buf, EINA_TRUE); 369 icon_changes_listen_recursive(NULL, buf, EINA_TRUE);
275 } 370 }
276 371
277#ifndef STRICT_SPEC 372#ifndef STRICT_SPEC
278 EINA_LIST_FOREACH(xdg_dirs, l, dir) 373 EINA_LIST_FOREACH(xdg_dirs, l, dir)
279 { 374 {
280 snprintf(buf, sizeof(buf), "%s/pixmaps", dir); 375 snprintf(buf, sizeof(buf), "%s/pixmaps", dir);
281 icon_changes_listen_recursive(buf, EINA_TRUE); 376 icon_changes_listen_recursive(NULL, buf, EINA_TRUE);
282 } 377 }
283#endif 378#endif
284
285 icon_changes_monitor_add("/usr/share/pixmaps"); 379 icon_changes_monitor_add("/usr/share/pixmaps");
286} 380}
287 381
288static void 382static void
289desktop_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
290 Ecore_File_Event event, const char *path)
291{
292 const char *ext;
293
294 /* TODO: If we get a stale symlink, we need to rerun cache creation */
295 /* TODO: Check for desktop*.cache, as this will be created when app is installed */
296 /* TODO: Do efreet_cache_icon_update() when app is installed, as it has the same
297 * symlink problem */
298 switch (event)
299 {
300 case ECORE_FILE_EVENT_NONE:
301 /* noop */
302 break;
303
304 case ECORE_FILE_EVENT_CREATED_FILE:
305 case ECORE_FILE_EVENT_DELETED_FILE:
306 case ECORE_FILE_EVENT_MODIFIED:
307 case ECORE_FILE_EVENT_CLOSED:
308 ext = strrchr(path, '.');
309 if (ext && (!strcmp(ext, ".desktop") || !strcmp(ext, ".directory")))
310 cache_desktop_update();
311 break;
312
313 case ECORE_FILE_EVENT_DELETED_SELF:
314 case ECORE_FILE_EVENT_DELETED_DIRECTORY:
315 eina_hash_del_by_key(change_monitors, path);
316 cache_desktop_update();
317 break;
318
319 case ECORE_FILE_EVENT_CREATED_DIRECTORY:
320 desktop_changes_monitor_add(path);
321 cache_desktop_update();
322 break;
323 }
324}
325
326static void
327desktop_changes_monitor_add(const char *path)
328{
329 Ecore_File_Monitor *mon;
330
331 if (eina_hash_find(change_monitors, path)) return;
332 /* TODO: Check for symlink and monitor the real path */
333 mon = ecore_file_monitor_add(path,
334 desktop_changes_cb,
335 NULL);
336 if (mon)
337 eina_hash_add(change_monitors, path, mon);
338}
339
340static void
341desktop_changes_listen_recursive(const char *path)
342{
343 Eina_Iterator *it;
344 Eina_File_Direct_Info *info;
345
346 if (!ecore_file_is_dir(path)) return;
347 desktop_changes_monitor_add(path);
348 it = eina_file_stat_ls(path);
349 if (!it) return;
350 EINA_ITERATOR_FOREACH(it, info)
351 {
352 if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) ||
353 (info->type == EINA_FILE_DIR))
354 desktop_changes_listen_recursive(info->path);
355 }
356 eina_iterator_free(it);
357}
358
359static void
360desktop_changes_listen(void) 383desktop_changes_listen(void)
361{ 384{
362 Eina_List *l; 385 Eina_List *l;
363 const char *path; 386 const char *path;
364 387
365 EINA_LIST_FOREACH(desktop_system_dirs, l, path) 388 EINA_LIST_FOREACH(desktop_system_dirs, l, path)
366 desktop_changes_listen_recursive(path); 389 desktop_changes_listen_recursive(NULL, path, EINA_TRUE);
367
368 EINA_LIST_FOREACH(desktop_extra_dirs, l, path) 390 EINA_LIST_FOREACH(desktop_extra_dirs, l, path)
369 desktop_changes_listen_recursive(path); 391 desktop_changes_listen_recursive(NULL, path, EINA_TRUE);
370} 392}
371 393
372static void 394static void
@@ -420,7 +442,48 @@ save_list(const char *file, Eina_List *l)
420static int 442static int
421strcmplen(const void *data1, const void *data2) 443strcmplen(const void *data1, const void *data2)
422{ 444{
423 return strncmp(data1, data2, eina_stringshare_strlen(data1)); 445 return strncmp(data1, data2, eina_stringshare_strlen(data1));
446}
447
448static Eina_Bool
449cache_exe_data_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
450{
451 Ecore_Exe_Event_Data *ev = event;
452
453 if (ev->exe == desktop_cache_exe)
454 {
455 Eina_Bool update = EINA_FALSE;
456
457 if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE;
458 desktop_exists = EINA_TRUE;
459 send_signal_desktop_cache_update(update);
460 }
461 else if (ev->exe == icon_cache_exe)
462 {
463 Eina_Bool update = EINA_FALSE;
464
465 if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE;
466 send_signal_icon_cache_update(update);
467 }
468 return ECORE_CALLBACK_RENEW;
469}
470
471static Eina_Bool
472cache_exe_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
473{
474 Ecore_Exe_Event_Del *ev = event;
475
476 if (ev->exe == desktop_cache_exe)
477 {
478 desktop_cache_exe = NULL;
479 if (desktop_queue) cache_desktop_update();
480 }
481 else if (ev->exe == icon_cache_exe)
482 {
483 icon_cache_exe = NULL;
484 if (icon_queue) cache_icon_update(EINA_FALSE);
485 }
486 return ECORE_CALLBACK_RENEW;
424} 487}
425 488
426/* external */ 489/* external */
@@ -436,7 +499,7 @@ cache_desktop_dir_add(const char *dir)
436 { 499 {
437 /* Path is registered, but maybe not monitored */ 500 /* Path is registered, but maybe not monitored */
438 const char *path = eina_list_data_get(l); 501 const char *path = eina_list_data_get(l);
439 if (!eina_hash_find(change_monitors, path)) 502 if (!eina_hash_find(desktop_change_monitors, path))
440 cache_desktop_update(); 503 cache_desktop_update();
441 } 504 }
442 else if (!eina_list_search_unsorted_list(desktop_extra_dirs, EINA_COMPARE_CB(strcmp), san)) 505 else if (!eina_list_search_unsorted_list(desktop_extra_dirs, EINA_COMPARE_CB(strcmp), san))
@@ -476,14 +539,6 @@ cache_icon_ext_add(const char *ext)
476 } 539 }
477} 540}
478 541
479void
480cache_desktop_update(void)
481{
482 if (desktop_cache_timer)
483 ecore_timer_del(desktop_cache_timer);
484 desktop_cache_timer = ecore_timer_add(1.0, desktop_cache_update_cache_cb, NULL);
485}
486
487Eina_Bool 542Eina_Bool
488cache_desktop_exists(void) 543cache_desktop_exists(void)
489{ 544{
@@ -519,7 +574,10 @@ cache_init(void)
519 goto error; 574 goto error;
520 } 575 }
521 576
522 change_monitors = eina_hash_string_superfast_new(EINA_FREE_CB(ecore_file_monitor_del)); 577 icon_change_monitors = eina_hash_string_superfast_new
578 (EINA_FREE_CB(ecore_file_monitor_del));
579 desktop_change_monitors = eina_hash_string_superfast_new
580 (EINA_FREE_CB(ecore_file_monitor_del));
523 581
524 efreet_cache_update = 0; 582 efreet_cache_update = 0;
525 if (!efreet_init()) goto error; 583 if (!efreet_init()) goto error;
@@ -561,9 +619,10 @@ cache_shutdown(void)
561 if (cache_exe_data_handler) ecore_event_handler_del(cache_exe_data_handler); 619 if (cache_exe_data_handler) ecore_event_handler_del(cache_exe_data_handler);
562 cache_exe_data_handler = NULL; 620 cache_exe_data_handler = NULL;
563 621
564 if (change_monitors) 622 if (icon_change_monitors) eina_hash_free(icon_change_monitors);
565 eina_hash_free(change_monitors); 623 icon_change_monitors = NULL;
566 change_monitors = NULL; 624 if (desktop_change_monitors) eina_hash_free(desktop_change_monitors);
625 desktop_change_monitors = NULL;
567 EINA_LIST_FREE(desktop_system_dirs, data) 626 EINA_LIST_FREE(desktop_system_dirs, data)
568 eina_stringshare_del(data); 627 eina_stringshare_del(data);
569 EINA_LIST_FREE(desktop_extra_dirs, data) 628 EINA_LIST_FREE(desktop_extra_dirs, data)