2012-10-20 21:53:23 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <Eina.h>
|
|
|
|
#include <Ecore.h>
|
|
|
|
#include <Ecore_File.h>
|
|
|
|
|
|
|
|
#include "efreetd.h"
|
|
|
|
#include "efreetd_dbus.h"
|
|
|
|
|
|
|
|
#include "Efreet.h"
|
|
|
|
#define EFREET_MODULE_LOG_DOM efreetd_log_dom
|
|
|
|
#include "efreet_private.h"
|
2012-11-01 18:46:44 -07:00
|
|
|
#include "efreetd_cache.h"
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
static Eina_Hash *icon_change_monitors = NULL;
|
|
|
|
static Eina_Hash *desktop_change_monitors = NULL;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
|
|
|
static Ecore_Event_Handler *cache_exe_del_handler = NULL;
|
|
|
|
static Ecore_Event_Handler *cache_exe_data_handler = NULL;
|
|
|
|
static Ecore_Exe *icon_cache_exe = NULL;
|
|
|
|
static Ecore_Exe *desktop_cache_exe = NULL;
|
|
|
|
static Ecore_Timer *icon_cache_timer = NULL;
|
|
|
|
static Ecore_Timer *desktop_cache_timer = NULL;
|
2013-01-04 09:42:23 -08:00
|
|
|
static Eina_Prefix *pfx = NULL;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2012-11-01 18:47:06 -07:00
|
|
|
static Eina_Bool desktop_exists = EINA_FALSE;
|
|
|
|
|
2012-11-01 18:46:44 -07:00
|
|
|
static Eina_List *desktop_system_dirs = NULL;
|
2012-10-20 21:53:23 -07:00
|
|
|
static Eina_List *desktop_extra_dirs = NULL;
|
|
|
|
static Eina_List *icon_extra_dirs = NULL;
|
2012-11-01 18:46:44 -07:00
|
|
|
static Eina_List *icon_exts = NULL;
|
|
|
|
static Eina_Bool icon_flush = EINA_FALSE;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2012-11-26 08:07:55 -08:00
|
|
|
static Eina_Bool desktop_queue = EINA_FALSE;
|
|
|
|
static Eina_Bool icon_queue = EINA_FALSE;
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
static void desktop_changes_monitor_add(const char *path);
|
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
static void icon_changes_listen(void);
|
|
|
|
static void desktop_changes_listen(void);
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
/* internal */
|
|
|
|
static Eina_Bool
|
2012-12-29 15:04:40 -08:00
|
|
|
icon_cache_update_cache_cb(void *data EINA_UNUSED)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
|
|
|
char file[PATH_MAX];
|
|
|
|
|
|
|
|
icon_cache_timer = NULL;
|
|
|
|
|
2012-11-26 08:07:55 -08:00
|
|
|
if (icon_cache_exe)
|
|
|
|
{
|
|
|
|
icon_queue = EINA_TRUE;
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
icon_queue = EINA_FALSE;
|
2012-11-01 18:46:44 -07:00
|
|
|
if ((!icon_flush) && (!icon_exts)) return ECORE_CALLBACK_CANCEL;
|
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
if (icon_change_monitors) eina_hash_free(icon_change_monitors);
|
|
|
|
icon_change_monitors = eina_hash_string_superfast_new
|
|
|
|
(EINA_FREE_CB(ecore_file_monitor_del));
|
|
|
|
icon_changes_listen();
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
/* TODO: Queue if already running */
|
2013-01-09 14:31:59 -08:00
|
|
|
snprintf(file, sizeof(file),
|
|
|
|
"%s/efreet/" MODULE_ARCH "/efreet_icon_cache_create",
|
2013-01-04 09:42:23 -08:00
|
|
|
eina_prefix_lib_get(pfx));
|
2012-10-20 21:53:23 -07:00
|
|
|
if (icon_extra_dirs)
|
|
|
|
{
|
|
|
|
Eina_List *ll;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
eina_strlcat(file, " -d", sizeof(file));
|
|
|
|
EINA_LIST_FOREACH(icon_extra_dirs, ll, p)
|
|
|
|
{
|
|
|
|
eina_strlcat(file, " ", sizeof(file));
|
|
|
|
eina_strlcat(file, p, sizeof(file));
|
|
|
|
}
|
|
|
|
}
|
2012-11-01 18:46:44 -07:00
|
|
|
if (icon_exts)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
|
|
|
Eina_List *ll;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
eina_strlcat(file, " -e", sizeof(file));
|
2012-11-01 18:46:44 -07:00
|
|
|
EINA_LIST_FOREACH(icon_exts, ll, p)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
|
|
|
eina_strlcat(file, " ", sizeof(file));
|
|
|
|
eina_strlcat(file, p, sizeof(file));
|
|
|
|
}
|
|
|
|
}
|
2012-11-01 18:46:44 -07:00
|
|
|
if (icon_flush)
|
|
|
|
eina_strlcat(file, " -f", sizeof(file));
|
|
|
|
icon_flush = EINA_FALSE;
|
|
|
|
icon_cache_exe =
|
|
|
|
ecore_exe_pipe_run(file, ECORE_EXE_PIPE_READ|ECORE_EXE_PIPE_READ_LINE_BUFFERED, NULL);
|
2012-10-20 21:53:23 -07:00
|
|
|
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-12-29 15:04:40 -08:00
|
|
|
desktop_cache_update_cache_cb(void *data EINA_UNUSED)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
|
|
|
char file[PATH_MAX];
|
|
|
|
|
|
|
|
desktop_cache_timer = NULL;
|
|
|
|
|
2012-11-26 08:07:55 -08:00
|
|
|
if (desktop_cache_exe)
|
|
|
|
{
|
|
|
|
desktop_queue = EINA_TRUE;
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
desktop_queue = EINA_FALSE;
|
2013-01-04 09:42:23 -08:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
if (desktop_change_monitors) eina_hash_free(desktop_change_monitors);
|
|
|
|
desktop_change_monitors = eina_hash_string_superfast_new
|
|
|
|
(EINA_FREE_CB(ecore_file_monitor_del));
|
|
|
|
desktop_changes_listen();
|
|
|
|
|
2013-01-09 14:31:59 -08:00
|
|
|
snprintf(file, sizeof(file),
|
|
|
|
"%s/efreet/" MODULE_ARCH "/efreet_desktop_cache_create",
|
2013-01-04 09:42:23 -08:00
|
|
|
eina_prefix_lib_get(pfx));
|
2012-10-20 21:53:23 -07:00
|
|
|
if (desktop_extra_dirs)
|
|
|
|
{
|
|
|
|
Eina_List *ll;
|
|
|
|
const char *str;
|
|
|
|
|
|
|
|
eina_strlcat(file, " -d", sizeof(file));
|
|
|
|
EINA_LIST_FOREACH(desktop_extra_dirs, ll, str)
|
|
|
|
{
|
|
|
|
eina_strlcat(file, " ", sizeof(file));
|
|
|
|
eina_strlcat(file, str, sizeof(file));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
INF("Run desktop cache creation: %s", file);
|
2013-11-27 02:45:29 -08:00
|
|
|
desktop_cache_exe = ecore_exe_pipe_run
|
|
|
|
(file, ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_READ_LINE_BUFFERED, NULL);
|
2012-10-20 21:53:23 -07:00
|
|
|
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
|
|
}
|
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
static void
|
|
|
|
cache_icon_update(Eina_Bool flush)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
2013-11-27 02:45:29 -08:00
|
|
|
if (icon_cache_timer) ecore_timer_del(icon_cache_timer);
|
|
|
|
if (flush) icon_flush = flush;
|
|
|
|
icon_cache_timer = ecore_timer_add(0.2, icon_cache_update_cache_cb, NULL);
|
|
|
|
}
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
void
|
|
|
|
cache_desktop_update(void)
|
|
|
|
{
|
|
|
|
if (desktop_cache_timer) ecore_timer_del(desktop_cache_timer);
|
|
|
|
desktop_cache_timer = ecore_timer_add(0.2, desktop_cache_update_cache_cb, NULL);
|
|
|
|
}
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
static void
|
|
|
|
icon_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
|
|
|
|
Ecore_File_Event event, const char *path EINA_UNUSED)
|
|
|
|
{
|
|
|
|
switch (event)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
2013-11-27 02:45:29 -08:00
|
|
|
case ECORE_FILE_EVENT_NONE:
|
|
|
|
/* noop */
|
|
|
|
break;
|
2012-11-01 18:46:44 -07:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
case ECORE_FILE_EVENT_CREATED_FILE:
|
|
|
|
case ECORE_FILE_EVENT_DELETED_FILE:
|
|
|
|
case ECORE_FILE_EVENT_MODIFIED:
|
|
|
|
case ECORE_FILE_EVENT_CLOSED:
|
|
|
|
// a FILE was changed, added or removed
|
|
|
|
cache_icon_update(EINA_FALSE);
|
|
|
|
break;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
case ECORE_FILE_EVENT_DELETED_DIRECTORY:
|
|
|
|
case ECORE_FILE_EVENT_CREATED_DIRECTORY:
|
|
|
|
// the whole tree needs re-monitoring
|
|
|
|
cache_icon_update(EINA_FALSE);
|
|
|
|
break;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
case ECORE_FILE_EVENT_DELETED_SELF:
|
|
|
|
// the whole tree needs re-monitoring
|
|
|
|
cache_icon_update(EINA_FALSE);
|
|
|
|
break;
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-11-27 02:45:29 -08:00
|
|
|
desktop_changes_cb(void *data EINA_UNUSED, Ecore_File_Monitor *em EINA_UNUSED,
|
|
|
|
Ecore_File_Event event, const char *path EINA_UNUSED)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
2013-11-27 02:45:29 -08:00
|
|
|
/* TODO: Check for desktop*.cache, as this will be created when app is installed */
|
2012-10-20 21:53:23 -07:00
|
|
|
switch (event)
|
|
|
|
{
|
|
|
|
case ECORE_FILE_EVENT_NONE:
|
|
|
|
/* noop */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ECORE_FILE_EVENT_CREATED_FILE:
|
|
|
|
case ECORE_FILE_EVENT_DELETED_FILE:
|
|
|
|
case ECORE_FILE_EVENT_MODIFIED:
|
|
|
|
case ECORE_FILE_EVENT_CLOSED:
|
2013-11-27 02:45:29 -08:00
|
|
|
// a FILE was changed, added or removed
|
|
|
|
cache_desktop_update();
|
|
|
|
break;
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
case ECORE_FILE_EVENT_DELETED_DIRECTORY:
|
|
|
|
case ECORE_FILE_EVENT_CREATED_DIRECTORY:
|
2013-11-27 02:45:29 -08:00
|
|
|
// the whole tree needs re-monitoring
|
|
|
|
cache_desktop_update();
|
|
|
|
break;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
|
|
|
case ECORE_FILE_EVENT_DELETED_SELF:
|
2013-11-27 02:45:29 -08:00
|
|
|
// the whole tree needs re-monitoring
|
|
|
|
cache_desktop_update();
|
|
|
|
break;
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
icon_changes_monitor_add(const char *path)
|
|
|
|
{
|
2012-11-01 18:46:44 -07:00
|
|
|
Ecore_File_Monitor *mon;
|
2013-11-27 02:45:29 -08:00
|
|
|
char *realp;
|
|
|
|
|
|
|
|
if (eina_hash_find(icon_change_monitors, path)) return;
|
|
|
|
realp = ecore_file_realpath(path);
|
|
|
|
if (!realp) return;
|
|
|
|
mon = ecore_file_monitor_add(realp, icon_changes_cb, NULL);
|
|
|
|
free(realp);
|
|
|
|
if (mon) eina_hash_add(icon_change_monitors, path, mon);
|
|
|
|
}
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
static void
|
|
|
|
desktop_changes_monitor_add(const char *path)
|
|
|
|
{
|
|
|
|
Ecore_File_Monitor *mon;
|
|
|
|
|
|
|
|
if (eina_hash_find(desktop_change_monitors, path)) return;
|
2012-11-01 18:47:06 -07:00
|
|
|
/* TODO: Check for symlink and monitor the real path */
|
2013-11-27 02:45:29 -08:00
|
|
|
mon = ecore_file_monitor_add(path, desktop_changes_cb, NULL);
|
2012-11-01 18:46:44 -07:00
|
|
|
if (mon)
|
2013-11-27 02:45:29 -08:00
|
|
|
eina_hash_add(desktop_change_monitors, path, mon);
|
2012-11-11 13:34:49 -08:00
|
|
|
}
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-12-04 00:03:56 -08:00
|
|
|
static int
|
|
|
|
stat_cmp(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const struct stat *st1 = a;
|
|
|
|
const struct stat *st2 = b;
|
|
|
|
|
|
|
|
if ((st2->st_dev == st1->st_dev) && (st2->st_ino == st1->st_ino))
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-11-11 13:34:49 -08:00
|
|
|
static void
|
2013-11-27 02:45:29 -08:00
|
|
|
icon_changes_listen_recursive(Eina_Inarray *stack, const char *path, Eina_Bool base)
|
2012-11-11 13:34:49 -08:00
|
|
|
{
|
|
|
|
Eina_Iterator *it;
|
|
|
|
Eina_File_Direct_Info *info;
|
2013-11-27 02:45:29 -08:00
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(path, &st) == -1) return;
|
2013-12-04 00:03:56 -08:00
|
|
|
if (eina_inarray_search(stack, &st, stat_cmp) >= 0) return;
|
2013-12-04 03:22:26 -08:00
|
|
|
// protect against too deep recursion even if it's valid.
|
|
|
|
if (eina_inarray_count(stack) >= 8) return;
|
2013-11-27 02:45:29 -08:00
|
|
|
eina_inarray_push(stack, &st);
|
2012-11-11 13:34:49 -08:00
|
|
|
|
|
|
|
if ((!ecore_file_is_dir(path)) && (base))
|
|
|
|
{
|
|
|
|
// XXX: if it doesn't exist... walk the parent dirs back down
|
|
|
|
// to this path until we find one that doesn't exist, then
|
|
|
|
// monitor its parent, and treat it specially as it needs
|
|
|
|
// to look for JUST the creation of this specific child
|
|
|
|
// and when this child is created, replace this monitor with
|
|
|
|
// monitoring the next specific child dir down until we are
|
|
|
|
// monitoring the original path again.
|
|
|
|
}
|
2013-11-27 02:45:29 -08:00
|
|
|
if (ecore_file_is_dir(path)) icon_changes_monitor_add(path);
|
2012-10-20 21:53:23 -07:00
|
|
|
it = eina_file_stat_ls(path);
|
2013-12-05 00:41:48 -08:00
|
|
|
if (!it) goto end;
|
2012-10-20 21:53:23 -07:00
|
|
|
EINA_ITERATOR_FOREACH(it, info)
|
|
|
|
{
|
2013-11-27 02:45:29 -08:00
|
|
|
if (info->path[info->name_start] == '.') continue;
|
2012-11-13 12:36:26 -08:00
|
|
|
if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) ||
|
|
|
|
(info->type == EINA_FILE_DIR))
|
2013-11-27 02:45:29 -08:00
|
|
|
icon_changes_listen_recursive(stack, info->path, EINA_FALSE);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
eina_iterator_free(it);
|
2013-12-05 00:41:48 -08:00
|
|
|
end:
|
|
|
|
eina_inarray_pop(stack);
|
2013-11-27 02:45:29 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_changes_listen_recursive(Eina_Inarray *stack, const char *path, Eina_Bool base)
|
|
|
|
{
|
|
|
|
Eina_Iterator *it;
|
|
|
|
Eina_File_Direct_Info *info;
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(path, &st) == -1) return;
|
2013-12-04 00:03:56 -08:00
|
|
|
if (eina_inarray_search(stack, &st, stat_cmp) >= 0) return;
|
2013-12-04 03:22:26 -08:00
|
|
|
// protect against too deep recursion even if it's valid.
|
|
|
|
if (eina_inarray_count(stack) >= 3) return;
|
2013-11-27 02:45:29 -08:00
|
|
|
eina_inarray_push(stack, &st);
|
|
|
|
if ((!ecore_file_is_dir(path)) && (base))
|
|
|
|
{
|
|
|
|
// XXX: if it doesn't exist... walk the parent dirs back down
|
|
|
|
// to this path until we find one that doesn't exist, then
|
|
|
|
// monitor its parent, and treat it specially as it needs
|
|
|
|
// to look for JUST the creation of this specific child
|
|
|
|
// and when this child is created, replace this monitor with
|
|
|
|
// monitoring the next specific child dir down until we are
|
|
|
|
// monitoring the original path again.
|
|
|
|
}
|
|
|
|
if (ecore_file_is_dir(path)) desktop_changes_monitor_add(path);
|
|
|
|
it = eina_file_stat_ls(path);
|
2013-12-05 00:41:48 -08:00
|
|
|
if (!it) goto end;
|
2013-11-27 02:45:29 -08:00
|
|
|
EINA_ITERATOR_FOREACH(it, info)
|
|
|
|
{
|
|
|
|
if (info->path[info->name_start] == '.') continue;
|
|
|
|
if (((info->type == EINA_FILE_LNK) && (ecore_file_is_dir(info->path))) ||
|
|
|
|
(info->type == EINA_FILE_DIR))
|
|
|
|
desktop_changes_listen_recursive(stack, info->path, EINA_FALSE);
|
|
|
|
}
|
|
|
|
eina_iterator_free(it);
|
2013-12-05 00:41:48 -08:00
|
|
|
end:
|
|
|
|
eina_inarray_pop(stack);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
icon_changes_listen(void)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
Eina_List *xdg_dirs;
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
const char *dir;
|
2013-12-04 00:03:56 -08:00
|
|
|
Eina_Inarray *stack;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-12-04 00:03:56 -08:00
|
|
|
stack = eina_inarray_new(sizeof(struct stat), 16);
|
|
|
|
if (!stack) return;
|
|
|
|
icon_changes_listen_recursive(stack, efreet_icon_deprecated_user_dir_get(), EINA_TRUE);
|
|
|
|
eina_inarray_flush(stack);
|
|
|
|
icon_changes_listen_recursive(stack, efreet_icon_user_dir_get(), EINA_TRUE);
|
2012-10-20 21:53:23 -07:00
|
|
|
EINA_LIST_FOREACH(icon_extra_dirs, l, dir)
|
2012-11-11 13:34:49 -08:00
|
|
|
{
|
2013-12-04 00:03:56 -08:00
|
|
|
eina_inarray_flush(stack);
|
|
|
|
icon_changes_listen_recursive(stack, dir, EINA_TRUE);
|
2012-11-11 13:34:49 -08:00
|
|
|
}
|
2012-10-20 21:53:23 -07:00
|
|
|
|
|
|
|
xdg_dirs = efreet_data_dirs_get();
|
|
|
|
EINA_LIST_FOREACH(xdg_dirs, l, dir)
|
|
|
|
{
|
|
|
|
snprintf(buf, sizeof(buf), "%s/icons", dir);
|
2013-12-04 00:03:56 -08:00
|
|
|
eina_inarray_flush(stack);
|
|
|
|
icon_changes_listen_recursive(stack, buf, EINA_TRUE);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef STRICT_SPEC
|
|
|
|
EINA_LIST_FOREACH(xdg_dirs, l, dir)
|
|
|
|
{
|
|
|
|
snprintf(buf, sizeof(buf), "%s/pixmaps", dir);
|
2013-12-04 00:03:56 -08:00
|
|
|
eina_inarray_flush(stack);
|
|
|
|
icon_changes_listen_recursive(stack, buf, EINA_TRUE);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
icon_changes_monitor_add("/usr/share/pixmaps");
|
2013-12-04 00:03:56 -08:00
|
|
|
eina_inarray_free(stack);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
desktop_changes_listen(void)
|
|
|
|
{
|
2012-11-01 18:46:44 -07:00
|
|
|
Eina_List *l;
|
2012-10-20 21:53:23 -07:00
|
|
|
const char *path;
|
2013-12-04 00:03:56 -08:00
|
|
|
Eina_Inarray *stack;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-12-04 00:03:56 -08:00
|
|
|
stack = eina_inarray_new(sizeof(struct stat), 16);
|
|
|
|
if (!stack) return;
|
2012-11-01 18:46:44 -07:00
|
|
|
EINA_LIST_FOREACH(desktop_system_dirs, l, path)
|
2013-12-04 00:03:56 -08:00
|
|
|
{
|
|
|
|
eina_inarray_flush(stack);
|
|
|
|
desktop_changes_listen_recursive(stack, path, EINA_TRUE);
|
|
|
|
}
|
2012-10-20 21:53:23 -07:00
|
|
|
EINA_LIST_FOREACH(desktop_extra_dirs, l, path)
|
2013-12-04 00:03:56 -08:00
|
|
|
{
|
|
|
|
eina_inarray_flush(stack);
|
|
|
|
desktop_changes_listen_recursive(stack, path, EINA_TRUE);
|
|
|
|
}
|
|
|
|
eina_inarray_free(stack);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-01 18:46:44 -07:00
|
|
|
fill_list(const char *file, Eina_List **l)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
|
|
|
Eina_File *f = NULL;
|
|
|
|
Eina_Iterator *it = NULL;
|
|
|
|
Eina_File_Line *line = NULL;
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s/efreet/%s", efreet_cache_home_get(), file);
|
|
|
|
f = eina_file_open(buf, EINA_FALSE);
|
|
|
|
if (!f) return;
|
|
|
|
it = eina_file_map_lines(f);
|
|
|
|
if (!it) goto error;
|
|
|
|
EINA_ITERATOR_FOREACH(it, line)
|
|
|
|
{
|
|
|
|
const char *end;
|
|
|
|
end = line->end - 1;
|
|
|
|
*l = eina_list_append(*l, eina_stringshare_add_length(line->start, end - line->start));
|
|
|
|
}
|
|
|
|
eina_iterator_free(it);
|
|
|
|
error:
|
|
|
|
eina_file_close(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-01 18:46:44 -07:00
|
|
|
read_lists(void)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
2012-11-01 18:46:44 -07:00
|
|
|
fill_list("extra_desktop.dirs", &desktop_extra_dirs);
|
|
|
|
fill_list("extra_icon.dirs", &icon_extra_dirs);
|
|
|
|
fill_list("icon.exts", &icon_exts);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-11-01 18:46:44 -07:00
|
|
|
save_list(const char *file, Eina_List *l)
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
|
|
|
FILE *f;
|
|
|
|
char buf[PATH_MAX];
|
|
|
|
Eina_List *ll;
|
|
|
|
const char *path;
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s/efreet/%s", efreet_cache_home_get(), file);
|
2012-11-01 18:46:44 -07:00
|
|
|
f = fopen(buf, "wb");
|
2012-10-20 21:53:23 -07:00
|
|
|
if (!f) return;
|
|
|
|
EINA_LIST_FOREACH(l, ll, path)
|
|
|
|
fprintf(f, "%s\n", path);
|
|
|
|
fclose(f);
|
|
|
|
}
|
|
|
|
|
2012-11-01 18:46:44 -07:00
|
|
|
static int
|
|
|
|
strcmplen(const void *data1, const void *data2)
|
|
|
|
{
|
2013-11-27 02:45:29 -08:00
|
|
|
return strncmp(data1, data2, eina_stringshare_strlen(data1));
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
cache_exe_data_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
|
|
|
{
|
|
|
|
Ecore_Exe_Event_Data *ev = event;
|
|
|
|
|
|
|
|
if (ev->exe == desktop_cache_exe)
|
|
|
|
{
|
|
|
|
Eina_Bool update = EINA_FALSE;
|
|
|
|
|
|
|
|
if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE;
|
|
|
|
desktop_exists = EINA_TRUE;
|
|
|
|
send_signal_desktop_cache_update(update);
|
|
|
|
}
|
|
|
|
else if (ev->exe == icon_cache_exe)
|
|
|
|
{
|
|
|
|
Eina_Bool update = EINA_FALSE;
|
|
|
|
|
|
|
|
if ((ev->lines) && (*ev->lines->line == 'c')) update = EINA_TRUE;
|
|
|
|
send_signal_icon_cache_update(update);
|
|
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
cache_exe_del_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
|
|
|
{
|
|
|
|
Ecore_Exe_Event_Del *ev = event;
|
|
|
|
|
|
|
|
if (ev->exe == desktop_cache_exe)
|
|
|
|
{
|
|
|
|
desktop_cache_exe = NULL;
|
|
|
|
if (desktop_queue) cache_desktop_update();
|
|
|
|
}
|
|
|
|
else if (ev->exe == icon_cache_exe)
|
|
|
|
{
|
|
|
|
icon_cache_exe = NULL;
|
|
|
|
if (icon_queue) cache_icon_update(EINA_FALSE);
|
|
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
2012-11-01 18:46:44 -07:00
|
|
|
}
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
/* external */
|
|
|
|
void
|
|
|
|
cache_desktop_dir_add(const char *dir)
|
|
|
|
{
|
|
|
|
char *san;
|
2012-11-13 12:36:35 -08:00
|
|
|
Eina_List *l;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
|
|
|
san = eina_file_path_sanitize(dir);
|
|
|
|
if (!san) return;
|
2012-11-13 14:51:11 -08:00
|
|
|
if ((l = eina_list_search_unsorted_list(desktop_system_dirs, strcmplen, san)))
|
2012-11-13 12:36:35 -08:00
|
|
|
{
|
|
|
|
/* Path is registered, but maybe not monitored */
|
|
|
|
const char *path = eina_list_data_get(l);
|
2013-11-27 02:45:29 -08:00
|
|
|
if (!eina_hash_find(desktop_change_monitors, path))
|
2012-11-13 12:36:35 -08:00
|
|
|
cache_desktop_update();
|
|
|
|
}
|
2012-11-13 14:51:11 -08:00
|
|
|
else if (!eina_list_search_unsorted_list(desktop_extra_dirs, EINA_COMPARE_CB(strcmp), san))
|
|
|
|
{
|
|
|
|
/* Not a registered path */
|
|
|
|
desktop_extra_dirs = eina_list_append(desktop_extra_dirs, eina_stringshare_add(san));
|
|
|
|
save_list("extra_desktop.dirs", desktop_extra_dirs);
|
|
|
|
cache_desktop_update();
|
|
|
|
}
|
2012-10-20 21:53:23 -07:00
|
|
|
free(san);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cache_icon_dir_add(const char *dir)
|
|
|
|
{
|
|
|
|
char *san;
|
|
|
|
|
|
|
|
san = eina_file_path_sanitize(dir);
|
|
|
|
if (!san) return;
|
|
|
|
if (!eina_list_search_unsorted_list(icon_extra_dirs, EINA_COMPARE_CB(strcmp), san))
|
|
|
|
{
|
|
|
|
icon_extra_dirs = eina_list_append(icon_extra_dirs, eina_stringshare_add(san));
|
2012-11-01 18:46:44 -07:00
|
|
|
save_list("extra_icon.dirs", icon_extra_dirs);
|
|
|
|
cache_icon_update(EINA_TRUE);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
free(san);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cache_icon_ext_add(const char *ext)
|
|
|
|
{
|
2012-11-01 18:46:44 -07:00
|
|
|
if (!eina_list_search_unsorted_list(icon_exts, EINA_COMPARE_CB(strcmp), ext))
|
2012-10-20 21:53:23 -07:00
|
|
|
{
|
2012-11-01 18:46:44 -07:00
|
|
|
icon_exts = eina_list_append(icon_exts, eina_stringshare_add(ext));
|
|
|
|
save_list("icon.exts", icon_exts);
|
|
|
|
cache_icon_update(EINA_TRUE);
|
2012-10-20 21:53:23 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-01 18:47:06 -07:00
|
|
|
Eina_Bool
|
|
|
|
cache_desktop_exists(void)
|
|
|
|
{
|
|
|
|
return desktop_exists;
|
|
|
|
}
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
Eina_Bool
|
|
|
|
cache_init(void)
|
|
|
|
{
|
2013-01-04 09:42:23 -08:00
|
|
|
char **argv;
|
2012-10-20 21:53:23 -07:00
|
|
|
|
2013-01-04 09:42:23 -08:00
|
|
|
ecore_app_args_get(NULL, &argv);
|
|
|
|
|
|
|
|
pfx = eina_prefix_new(argv[0], cache_init,
|
|
|
|
"EFREET", "efreet", "checkme",
|
|
|
|
PACKAGE_BIN_DIR,
|
|
|
|
PACKAGE_LIB_DIR,
|
|
|
|
PACKAGE_DATA_DIR,
|
|
|
|
PACKAGE_DATA_DIR);
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
cache_exe_del_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DEL,
|
2012-11-01 18:46:44 -07:00
|
|
|
cache_exe_del_cb, NULL);
|
2012-10-20 21:53:23 -07:00
|
|
|
if (!cache_exe_del_handler)
|
|
|
|
{
|
2012-11-02 13:11:56 -07:00
|
|
|
ERR("Failed to add exe del handler");
|
2012-10-20 21:53:23 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
cache_exe_data_handler = ecore_event_handler_add(ECORE_EXE_EVENT_DATA,
|
2012-11-01 18:46:44 -07:00
|
|
|
cache_exe_data_cb, NULL);
|
2012-10-20 21:53:23 -07:00
|
|
|
if (!cache_exe_data_handler)
|
|
|
|
{
|
2012-11-02 13:11:56 -07:00
|
|
|
ERR("Failed to add exe data handler");
|
2012-10-20 21:53:23 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
icon_change_monitors = eina_hash_string_superfast_new
|
|
|
|
(EINA_FREE_CB(ecore_file_monitor_del));
|
|
|
|
desktop_change_monitors = eina_hash_string_superfast_new
|
|
|
|
(EINA_FREE_CB(ecore_file_monitor_del));
|
2012-10-20 21:53:23 -07:00
|
|
|
|
|
|
|
efreet_cache_update = 0;
|
|
|
|
if (!efreet_init()) goto error;
|
|
|
|
|
2012-11-01 18:46:44 -07:00
|
|
|
read_lists();
|
|
|
|
/* TODO: Should check if system dirs has changed and handles extra_dirs */
|
|
|
|
desktop_system_dirs = efreet_default_dirs_get(efreet_data_home_get(),
|
|
|
|
efreet_data_dirs_get(), "applications");
|
2012-11-02 13:12:47 -07:00
|
|
|
desktop_system_dirs =
|
|
|
|
eina_list_merge(
|
|
|
|
desktop_system_dirs, efreet_default_dirs_get(efreet_data_home_get(),
|
|
|
|
efreet_data_dirs_get(), "desktop-directories"));
|
2012-10-20 21:53:23 -07:00
|
|
|
icon_changes_listen();
|
|
|
|
desktop_changes_listen();
|
2012-11-01 18:46:44 -07:00
|
|
|
cache_icon_update(EINA_FALSE);
|
2012-10-20 21:53:23 -07:00
|
|
|
cache_desktop_update();
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
error:
|
|
|
|
if (cache_exe_del_handler) ecore_event_handler_del(cache_exe_del_handler);
|
|
|
|
cache_exe_del_handler = NULL;
|
|
|
|
if (cache_exe_data_handler) ecore_event_handler_del(cache_exe_data_handler);
|
|
|
|
cache_exe_data_handler = NULL;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
cache_shutdown(void)
|
|
|
|
{
|
|
|
|
const char *data;
|
|
|
|
|
2013-01-04 09:42:23 -08:00
|
|
|
eina_prefix_free(pfx);
|
|
|
|
pfx = NULL;
|
|
|
|
|
2012-10-20 21:53:23 -07:00
|
|
|
efreet_shutdown();
|
|
|
|
|
|
|
|
if (cache_exe_del_handler) ecore_event_handler_del(cache_exe_del_handler);
|
|
|
|
cache_exe_del_handler = NULL;
|
|
|
|
if (cache_exe_data_handler) ecore_event_handler_del(cache_exe_data_handler);
|
|
|
|
cache_exe_data_handler = NULL;
|
|
|
|
|
2013-11-27 02:45:29 -08:00
|
|
|
if (icon_change_monitors) eina_hash_free(icon_change_monitors);
|
|
|
|
icon_change_monitors = NULL;
|
|
|
|
if (desktop_change_monitors) eina_hash_free(desktop_change_monitors);
|
|
|
|
desktop_change_monitors = NULL;
|
2012-11-01 18:46:44 -07:00
|
|
|
EINA_LIST_FREE(desktop_system_dirs, data)
|
|
|
|
eina_stringshare_del(data);
|
2012-10-20 21:53:23 -07:00
|
|
|
EINA_LIST_FREE(desktop_extra_dirs, data)
|
|
|
|
eina_stringshare_del(data);
|
|
|
|
EINA_LIST_FREE(icon_extra_dirs, data)
|
|
|
|
eina_stringshare_del(data);
|
2012-11-01 18:46:44 -07:00
|
|
|
EINA_LIST_FREE(icon_exts, data)
|
2012-10-20 21:53:23 -07:00
|
|
|
eina_stringshare_del(data);
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|