* efreet: improve icon cache, increase speed and consume a little

more memory than previous version.

	TODO: efreet_icon_cache_create could be speeded up if we did
	reuse already generated theme instead when doing inherit work.

	NOTE: Let me add a rant against Freedesktop standard. Walking
	around 22731 paths for 3051 icons is insane and that's just for
	one theme ! Maybe they could give me one SSD...


SVN revision: 55018
This commit is contained in:
Cedric BAIL 2010-11-26 14:56:23 +00:00
parent fbfa54bc05
commit a90e2e4aff
6 changed files with 913 additions and 753 deletions

View File

@ -31,7 +31,7 @@ static char file[PATH_MAX] = { '\0' };
static char util_file[PATH_MAX] = { '\0' }; static char util_file[PATH_MAX] = { '\0' };
static void static void
term_handler (int sig, siginfo_t * info, void *data) term_handler(int sig __UNUSED__, siginfo_t * info __UNUSED__, void *data __UNUSED__)
{ {
if (util_file[0]) unlink(util_file); if (util_file[0]) unlink(util_file);
if (file[0]) unlink(file); if (file[0]) unlink(file);
@ -39,6 +39,19 @@ term_handler (int sig, siginfo_t * info, void *data)
exit(1); exit(1);
} }
static void
catch_sigterm(void)
{
struct sigaction act;
act.sa_sigaction = term_handler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act.sa_mask);
if (sigaction(SIGTERM, &act, NULL) < 0)
perror("sigaction"); /* It's bad if we can't deal with SIGTERM, but not dramatic */
}
static int static int
strcmplen(const void *data1, const void *data2) strcmplen(const void *data1, const void *data2)
{ {
@ -248,15 +261,7 @@ main(int argc, char **argv)
if (!ecore_init()) goto ecore_error; if (!ecore_init()) goto ecore_error;
// Trap SIGTERM for clean shutdown // Trap SIGTERM for clean shutdown
act.sa_sigaction = term_handler; catch_sigterm();
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act.sa_mask);
if (sigaction(SIGTERM, &act, NULL) < 0)
{
perror("sigaction");
goto efreet_error;
}
efreet_cache_update = 0; efreet_cache_update = 0;

View File

@ -18,75 +18,83 @@
#include "Efreet.h" #include "Efreet.h"
#include "efreet_private.h" #include "efreet_private.h"
static Eet_Data_Descriptor *edd = NULL; static const char *exts[] = { ".png", ".xpm", ".svg", NULL };
static Eet_Data_Descriptor *fallback_edd = NULL;
static Eina_List *extensions;
static int verbose = 0; static int verbose = 0;
static char file[PATH_MAX] = { '\0' }; static Eina_Bool
_cache_extention_lookup(const char *ext)
static void
term_handler (int sig, siginfo_t * info, void *data)
{ {
if (file[0]) unlink(file); unsigned int i;
if (verbose) printf("EXIT\n");
exit(1); for (i = 0; exts[i]; ++i)
if (!strcmp(exts[i], ext))
return EINA_TRUE;
return EINA_FALSE;
} }
static int static Eina_Bool
cache_fallback_scan_dir(Eet_File *ef, Eina_Hash *dirs, const char *dir, int *changed) cache_fallback_scan_dir(Eina_Hash *icons, Eina_Hash *dirs, const char *dir, Eina_Bool *changed)
{ {
Eina_Iterator *it; Eina_Iterator *it;
const char *ext, *ent; Eina_File_Direct_Info *entry;
if (eina_hash_find(dirs, dir)) return 1; if (eina_hash_find(dirs, dir)) return 1;
eina_hash_add(dirs, dir, (void *)-1); eina_hash_add(dirs, dir, (void *)-1);
it = eina_file_ls(dir); it = eina_file_stat_ls(dir);
if (!it) return 1; if (!it) return 1;
EINA_ITERATOR_FOREACH(it, ent)
{
Efreet_Cache_Icon *icon;
char *name, *tmp;
ext = strrchr(ent, '.'); EINA_ITERATOR_FOREACH(it, entry)
if (!ext) continue; {
ext = eina_stringshare_add(ext); Efreet_Cache_Fallback_Icon *icon;
if (!eina_list_data_find(extensions, ext)) char *name;
{ char *ext;
eina_stringshare_del(ext); unsigned int i;
continue;
} if (entry->type == EINA_FILE_DIR)
/* icon with known extension */ continue;
name = strdup(ecore_file_file_get(ent));
tmp = strrchr(name, '.'); ext = strrchr(entry->path + entry->name_start, '.');
if (tmp) *tmp = '\0'; if (!ext || !_cache_extention_lookup(ext))
icon = eet_data_read(ef, fallback_edd, name); continue;
if (!icon)
{ /* icon with known extension */
icon = NEW(Efreet_Cache_Icon, 1); name = entry->path + entry->name_start;
icon->free = 1; *ext = '\0';
icon->fallback = 1;
icon->theme = NULL; icon = eina_hash_find(icons, name);
} if (!icon)
{
icon = NEW(Efreet_Cache_Fallback_Icon, 1);
icon->free = 1;
icon->theme = NULL;
eina_hash_add(icons, name, icon);
}
*ext = '.';
for (i = 0; i < icon->icons_count; ++i)
if (!strcmp(icon->icons[i], entry->path))
break;
if (i != icon->icons_count)
continue ;
/* we don't really track path deat here, so we will leak... */
icon->icons = realloc(icon->icons, sizeof (char *) * (icon->icons_count + 1));
icon->icons[icon->icons_count++] = eina_stringshare_add(entry->path);
*changed = EINA_TRUE;
}
icon->icons = eina_list_append(icon->icons, eina_stringshare_ref(ent));
if (!eet_data_write(ef, fallback_edd, name, icon, 1))
{
free(name);
break;
}
efreet_cache_icon_free(icon);
free(name);
}
eina_iterator_free(it); eina_iterator_free(it);
return 1; return 1;
} }
static int static Eina_Bool
cache_fallback_scan(Eet_File *ef, int *changed) cache_fallback_scan(Eina_Hash *icons, Eina_Bool *changed)
{ {
Eina_List *xdg_dirs, *l; Eina_List *xdg_dirs, *l;
const char *dir; const char *dir;
@ -94,123 +102,144 @@ cache_fallback_scan(Eet_File *ef, int *changed)
Eina_Hash *dirs; Eina_Hash *dirs;
dirs = eina_hash_string_superfast_new(NULL); dirs = eina_hash_string_superfast_new(NULL);
cache_fallback_scan_dir(ef, dirs, efreet_icon_deprecated_user_dir_get(), changed);
cache_fallback_scan_dir(ef, dirs, efreet_icon_user_dir_get(), changed); cache_fallback_scan_dir(icons, dirs, efreet_icon_deprecated_user_dir_get(), changed);
cache_fallback_scan_dir(icons, dirs, efreet_icon_user_dir_get(), changed);
xdg_dirs = efreet_data_dirs_get(); xdg_dirs = efreet_data_dirs_get();
EINA_LIST_FOREACH(xdg_dirs, l, dir) EINA_LIST_FOREACH(xdg_dirs, l, dir)
{ {
snprintf(path, sizeof(path), "%s/icons", dir); snprintf(path, sizeof(path), "%s/icons", dir);
cache_fallback_scan_dir(ef, dirs, path, changed); cache_fallback_scan_dir(icons, dirs, path, changed);
} }
#ifndef STRICT_SPEC #ifndef STRICT_SPEC
EINA_LIST_FOREACH(xdg_dirs, l, dir) EINA_LIST_FOREACH(xdg_dirs, l, dir)
{ {
snprintf(path, sizeof(path), "%s/pixmaps", dir); snprintf(path, sizeof(path), "%s/pixmaps", dir);
cache_fallback_scan_dir(ef, dirs, path, changed); cache_fallback_scan_dir(icons, dirs, path, changed);
} }
#endif #endif
cache_fallback_scan_dir(ef, dirs, "/usr/share/pixmaps", changed); cache_fallback_scan_dir(icons, dirs, "/usr/share/pixmaps", changed);
eina_hash_free(dirs); eina_hash_free(dirs);
return 1; return 1;
} }
static int static Eina_Bool
cache_scan_path_dir(Efreet_Icon_Theme *theme, const char *path, Efreet_Icon_Theme_Directory *dir, Eet_File *ef, int *changed) cache_scan_path_dir(Efreet_Icon_Theme *theme,
const char *path,
Efreet_Icon_Theme_Directory *dir,
Eina_Hash *icons,
Eina_Bool *changed)
{ {
Eina_Iterator *it; Eina_Iterator *it;
char buf[PATH_MAX]; char buf[PATH_MAX];
const char *ext, *ent; Eina_File_Direct_Info *entry;
snprintf(buf, sizeof(buf), "%s/%s", path, dir->name); snprintf(buf, sizeof(buf), "%s/%s", path, dir->name);
it = eina_file_ls(buf);
it = eina_file_stat_ls(buf);
if (!it) return 1; if (!it) return 1;
EINA_ITERATOR_FOREACH(it, ent)
{
Eina_List *l;
Efreet_Cache_Icon *icon;
Efreet_Cache_Icon_Element *elem = NULL, *oelem = NULL;
char *name, *tmp;
ext = strrchr(ent, '.'); EINA_ITERATOR_FOREACH(it, entry)
if (!ext) continue; {
ext = eina_stringshare_add(ext); Efreet_Cache_Icon *icon;
if (!eina_list_data_find(extensions, ext)) char *name;
{ char *ext;
eina_stringshare_del(ext); unsigned int i;
continue;
}
/* icon with known extension */
name = strdup(ecore_file_file_get(ent));
tmp = strrchr(name, '.');
if (tmp) *tmp = '\0';
icon = eet_data_read(ef, edd, name);
if (!icon)
{
icon = NEW(Efreet_Cache_Icon, 1);
icon->free = 1;
icon->theme = eina_stringshare_add(theme->name.internal);
}
else if (strcmp(icon->theme, theme->name.internal))
{
/* We got this icon from a parent theme */
free(name);
continue;
}
/* find if we have the same icon in another type */ if (entry->type == EINA_FILE_DIR)
EINA_LIST_FOREACH(icon->icons, l, oelem) continue;
{
if ((oelem->type == dir->type) && ext = strrchr(entry->path + entry->name_start, '.');
(oelem->size.normal == dir->size.normal) && if (!ext || !_cache_extention_lookup(ext))
(oelem->size.max == dir->size.max) && continue;
(oelem->size.min == dir->size.min))
{ /* icon with known extension */
elem = oelem; name = entry->path + entry->name_start;
*ext = '\0';
icon = eina_hash_find(icons, name);
if (!icon)
{
icon = NEW(Efreet_Cache_Icon, 1);
icon->free = 1;
icon->theme = eina_stringshare_add(theme->name.internal);
eina_hash_add(icons, name, icon);
}
else if (icon->theme && strcmp(icon->theme, theme->name.internal))
{
/* We got this icon from a parent theme */
continue;
}
/* find if we have the same icon in another type */
for (i = 0; i < icon->icons_count; ++i)
{
if ((icon->icons[i]->type == dir->type) &&
(icon->icons[i]->normal == dir->size.normal) &&
(icon->icons[i]->max == dir->size.max) &&
(icon->icons[i]->min == dir->size.min))
break; break;
} }
}
if (elem) *ext = '.';
{
elem->paths = eina_list_append(elem->paths, eina_stringshare_ref(ent)); if (i != icon->icons_count)
} {
else unsigned int j;
{
elem = NEW(Efreet_Cache_Icon_Element, 1); /* check if the path already exist */
elem->paths = eina_list_append(elem->paths, eina_stringshare_ref(ent)); for (j = 0; j < icon->icons[i]->paths_count; ++j)
elem->type = dir->type; if (!strcmp(icon->icons[i]->paths[j], entry->path))
elem->size.normal = dir->size.normal; break ;
elem->size.min = dir->size.min;
elem->size.max = dir->size.max; if (j != icon->icons[i]->paths_count)
icon->icons = eina_list_append(icon->icons, elem); continue ;
} }
if (!eet_data_write(ef, edd, name, icon, 1)) /* no icon match so add a new one */
{ else
free(name); {
break; icon->icons = realloc(icon->icons,
} sizeof (Efreet_Cache_Icon_Element*) * (++icon->icons_count));
efreet_cache_icon_free(icon); icon->icons[i] = NEW(Efreet_Cache_Icon_Element, 1);
free(name); icon->icons[i]->type = dir->type;
} icon->icons[i]->normal = dir->size.normal;
icon->icons[i]->min = dir->size.min;
icon->icons[i]->max = dir->size.max;
icon->icons[i]->paths = NULL;
icon->icons[i]->paths_count = 0;
}
/* and finally store the path */
icon->icons[i]->paths = realloc(icon->icons[i]->paths,
sizeof (char*) * (icon->icons[i]->paths_count + 1));
icon->icons[i]->paths[icon->icons[i]->paths_count++] = eina_stringshare_add(entry->path);
*changed = EINA_TRUE;
}
eina_iterator_free(it); eina_iterator_free(it);
return 1; return 1;
} }
static int static int
cache_scan_path(Efreet_Icon_Theme *theme, const char *path, Eet_File *ef, int *changed) cache_scan_path(Efreet_Icon_Theme *theme, Eina_Hash *icons, const char *path, Eina_Bool *changed)
{ {
Eina_List *l; Eina_List *l;
Efreet_Icon_Theme_Directory *dir; Efreet_Icon_Theme_Directory *dir;
EINA_LIST_FOREACH(theme->directories, l, dir) EINA_LIST_FOREACH(theme->directories, l, dir)
if (!cache_scan_path_dir(theme, path, dir, ef, changed)) return 0; if (!cache_scan_path_dir(theme, path, dir, icons, changed)) return 0;
return 1; return 1;
} }
static int static Eina_Bool
cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eet_File *ef, int *changed) cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eina_Hash *icons, Eina_Bool *changed)
{ {
Eina_List *l; Eina_List *l;
const char *path; const char *path;
@ -219,29 +248,76 @@ cache_scan(Efreet_Icon_Theme *theme, Eina_Hash *themes, Eet_File *ef, int *chang
if (!theme) return 1; if (!theme) return 1;
if (eina_hash_find(themes, theme->name.internal)) return 1; if (eina_hash_find(themes, theme->name.internal)) return 1;
eina_hash_direct_add(themes, theme->name.internal, theme); eina_hash_direct_add(themes, theme->name.internal, theme);
/* TODO: Maybe always read entry from eet, so when can check changed */
/* scan theme */ /* scan theme */
EINA_LIST_FOREACH(theme->paths, l, path) EINA_LIST_FOREACH(theme->paths, l, path)
if (!cache_scan_path(theme, path, ef, changed)) return 0; if (!cache_scan_path(theme, icons, path, changed)) return 0;
/* scan inherits */ /* scan inherits */
if (theme->inherits) if (theme->inherits)
{ {
EINA_LIST_FOREACH(theme->inherits, l, name) EINA_LIST_FOREACH(theme->inherits, l, name)
{ {
theme = efreet_icon_theme_find(name); Efreet_Icon_Theme *inherit;
if (!cache_scan(theme, themes, ef, changed)) return 0;
} inherit = efreet_icon_theme_find(name);
} if (!inherit) fprintf(stderr, "Theme `%s` not found for `%s`.\n",
name, theme->name.internal);
if (!cache_scan(inherit, themes, icons, changed)) return 0;
}
}
else if (strcmp(theme->name.internal, "hicolor")) else if (strcmp(theme->name.internal, "hicolor"))
{ {
theme = efreet_icon_theme_find("hicolor"); theme = efreet_icon_theme_find("hicolor");
if (!cache_scan(theme, themes, ef, changed)) return 0; if (!cache_scan(theme, themes, icons, changed)) return 0;
} }
return 1; return 1;
} }
static int
cache_lock_file(void)
{
char file[PATH_MAX];
struct flock fl;
int lockfd;
snprintf(file, sizeof(file), "%s/.efreet/icon_data.lock", efreet_home_dir_get());
lockfd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (lockfd < 0) return -1;
memset(&fl, 0, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(lockfd, F_SETLK, &fl) < 0)
{
if (verbose) printf("LOCKED! You may want to delete %s if this persists\n", file);
close(lockfd);
return -1;
}
return lockfd;
}
static void
term_handler(int sig __UNUSED__, siginfo_t * info __UNUSED__, void *data __UNUSED__)
{
}
/* prevent early death */
static void
catch_sigterm(void)
{
struct sigaction act;
act.sa_sigaction = term_handler;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act.sa_mask);
if (sigaction(SIGTERM, &act, NULL) < 0)
perror("sigaction"); /* It's bad if we can't deal with SIGTERM, but not dramatic */
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
@ -252,233 +328,170 @@ main(int argc, char **argv)
* - pass extra dirs to binary, and read them * - pass extra dirs to binary, and read them
* - make sure programs with different extra dirs all work together * - make sure programs with different extra dirs all work together
*/ */
Eet_File *ef; Efreet_Cache_Theme *cache;
Eina_List *l = NULL; Efreet_Icon_Theme *theme;
Efreet_Icon_Theme *theme; Eet_Data_Descriptor *edd;
char *dir = NULL; Eet_File *ef;
int lockfd = -1, tmpfd; Eina_List *l = NULL;
int changed = 0; char file[PATH_MAX];
int i; char *dir = NULL;
struct flock fl; Eina_Bool changed = EINA_FALSE;
const char *exts[] = { ".png", ".xpm", ".svg", NULL }; int lockfd = -1;
struct sigaction act; int i;
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
{ {
if (!strcmp(argv[i], "-v")) verbose = 1; if (!strcmp(argv[i], "-v")) verbose = 1;
else if ((!strcmp(argv[i], "-h")) || else if ((!strcmp(argv[i], "-h")) ||
(!strcmp(argv[i], "-help")) || (!strcmp(argv[i], "-help")) ||
(!strcmp(argv[i], "--h")) || (!strcmp(argv[i], "--h")) ||
(!strcmp(argv[i], "--help"))) (!strcmp(argv[i], "--help")))
{ {
printf("Options:\n"); printf("Options:\n");
printf(" -v Verbose mode\n"); printf(" -v Verbose mode\n");
exit(0); exit(0);
} }
} }
/* init external subsystems */
if (!eina_init()) goto eina_error;
if (!eet_init()) goto eet_error;
if (!ecore_init()) goto ecore_error;
// Trap SIGTERM for clean shutdown /* init external subsystems */
act.sa_sigaction = term_handler; if (!eina_init()) return -1;
act.sa_flags = SA_RESTART | SA_SIGINFO; if (!eet_init()) return -1;
sigemptyset(&act.sa_mask); if (!ecore_init()) return -1;
if (sigaction(SIGTERM, &act, NULL) < 0)
{
perror("sigaction");
goto efreet_error;
}
for (i = 0; exts[i]; i++)
extensions = eina_list_append(extensions, eina_stringshare_add(exts[i]));
efreet_cache_update = 0; efreet_cache_update = 0;
/* FIXME: should be in cache dir maybe */
/* create homedir */ /* create homedir */
snprintf(file, sizeof(file), "%s/.efreet", efreet_home_dir_get()); snprintf(file, sizeof(file), "%s/.efreet", efreet_home_dir_get());
if (!ecore_file_mkpath(file)) goto efreet_error; if (!ecore_file_mkpath(file)) return -1;
catch_sigterm();
/* lock process, so that we only run one copy of this program */ /* lock process, so that we only run one copy of this program */
snprintf(file, sizeof(file), "%s/.efreet/icon_data.lock", efreet_home_dir_get()); lockfd = cache_lock_file();
lockfd = open(file, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); if (lockfd == -1) return -1;
if (lockfd < 0) goto efreet_error;
memset(&fl, 0, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(lockfd, F_SETLK, &fl) < 0)
{
if (verbose)
{
printf("LOCKED! You may want to delete %s if this persists\n", file);
}
goto efreet_error;
}
/* create dir for icon cache */ /* create dir for icon cache */
dir = ecore_file_dir_get(efreet_icon_cache_file("")); dir = ecore_file_dir_get(efreet_icon_cache_file());
if (!ecore_file_mkpath(dir)) goto efreet_error; if (!ecore_file_mkpath(dir)) goto on_error;
free(dir); free(dir);
/* finish efreet init */ /* finish efreet init */
if (!efreet_init()) goto efreet_error; if (!efreet_init()) goto on_error;
edd = efreet_icon_edd_init();
if (!edd) goto edd_error;
fallback_edd = efreet_icon_fallback_edd_init();
if (!edd) goto edd_error;
if (argc > 1) if (argc > 1)
{ {
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
{ {
theme = efreet_icon_theme_find(argv[i]); theme = efreet_icon_theme_find(argv[i]);
if (theme) l = eina_list_append(l, theme); if (theme) l = eina_list_append(l, theme);
} }
} }
if (!l)
l = efreet_icon_theme_list_get(); if (!l) l = efreet_icon_theme_list_get();
ef = eet_open(efreet_icon_cache_file(), EET_FILE_MODE_READ_WRITE);
if (!ef) goto on_error_efreet;
edd = efreet_icon_theme_edd();
EINA_LIST_FREE(l, theme) EINA_LIST_FREE(l, theme)
{ {
Eina_Hash *themes; Eina_Hash *themes;
changed = 0; themes = eina_hash_string_superfast_new(NULL);
/* create cache */
/* TODO: Copy old cache to temp file, so we can check whether something has changed */
snprintf(file, sizeof(file), "%s.XXXXXX", efreet_icon_cache_file(theme->name.internal));
tmpfd = mkstemp(file);
if (tmpfd < 0) goto error;
close(tmpfd);
ef = eet_open(file, EET_FILE_MODE_READ_WRITE);
if (!ef) goto error;
themes = eina_hash_string_superfast_new(NULL); /* read icons from the eet file */
if (!cache_scan(theme, themes, ef, &changed)) cache = eet_data_read(ef, edd, theme->name.internal);
{
eet_close(ef);
eina_hash_free(themes);
goto error;
}
changed = 1; /* Wype out in case of version change */
/* check if old and new caches contain the same number of entries */ if (cache
#if 0 && cache->version.major != EFREET_CACHE_MAJOR
if (!changed) && cache->version.minor != EFREET_CACHE_MINOR)
{ {
Eet_File *old; eina_hash_free(cache->icons);
free(cache);
cache = NULL;
}
old = eet_open(efreet_icon_cache_file(), EET_FILE_MODE_READ); /* No existing cache before, so create it */
if (!old || eet_num_entries(old) != eet_num_entries(ef)) changed = 1; if (!cache)
if (old) eet_close(old); {
cache = malloc(sizeof (Efreet_Cache_Theme));
if (!cache) goto on_error_efreet;
} cache->version.major = EFREET_CACHE_MAJOR;
#endif cache->version.minor = EFREET_CACHE_MINOR;
/* cleanup */ cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_free);
eet_close(ef);
eina_hash_free(themes);
/* unlink old cache files */ changed = EINA_TRUE;
if (changed) }
{
if (unlink(efreet_icon_cache_file(theme->name.internal)) < 0)
{
if (errno != ENOENT) goto error;
}
/* rename tmp files to real files */
if (rename(file, efreet_icon_cache_file(theme->name.internal)) < 0) goto error;
}
else
{
unlink(file);
}
eet_clearcache(); if (cache_scan(theme, themes, cache->icons, &changed))
{
fprintf(stderr, "generated: '%s' %i (%i)\n",
theme->name.internal,
changed,
eina_hash_population(cache->icons));
if (changed)
eet_data_write(ef, edd, theme->name.internal, cache, 1);
changed = EINA_FALSE;
}
eina_hash_free(themes);
eina_hash_free(cache->icons);
free(cache);
} }
/* fallback */ edd = efreet_icon_fallback_edd();
changed = 0;
/* TODO: Copy old cache to temp file, so we can check whether something has changed */
snprintf(file, sizeof(file), "%s.XXXXXX", efreet_icon_cache_file("_fallback"));
tmpfd = mkstemp(file);
if (tmpfd < 0) goto error;
close(tmpfd);
ef = eet_open(file, EET_FILE_MODE_READ_WRITE);
if (!ef) goto error;
if (!cache_fallback_scan(ef, &changed)) /* read fallback icons from the eet file */
{ cache = eet_data_read(ef, edd, "efreet/fallback");
eet_close(ef); if (cache && cache->version.major != EFREET_CACHE_MAJOR)
goto error; {
} eina_hash_free(cache->icons);
free(cache);
cache = NULL;
}
changed = 1; /* No existing fallback, create it */
/* check if old and new caches contain the same number of entries */ if (!cache)
#if 0 {
if (!changed) cache = malloc(sizeof (Efreet_Cache_Theme));
{ if (!cache) goto on_error_efreet;
Eet_File *old;
old = eet_open(efreet_icon_cache_file(), EET_FILE_MODE_READ); cache->version.major = EFREET_CACHE_MAJOR;
if (!old || eet_num_entries(old) != eet_num_entries(ef)) changed = 1; cache->version.minor = EFREET_CACHE_MINOR;
if (old) eet_close(old);
} cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_fallback_free);
#endif
/* cleanup */ changed = EINA_TRUE;
}
/* Save fallback in the right part */
if (cache_fallback_scan(cache->icons, &changed))
{
fprintf(stderr, "generated: fallback %i (%i)\n", changed, eina_hash_population(cache->icons));
if (changed)
eet_data_write(ef, edd, "efreet/fallback", cache, 1);
}
eina_hash_free(cache->icons);
free(cache);
/* save data */
eet_close(ef); eet_close(ef);
/* unlink old cache files */ on_error_efreet:
if (changed)
{
if (unlink(efreet_icon_cache_file("_fallback")) < 0)
{
if (errno != ENOENT) goto error;
}
/* rename tmp files to real files */
if (rename(file, efreet_icon_cache_file("_fallback")) < 0) goto error;
}
else
{
unlink(file);
}
/* Remove signal handler, no need to exit now */
act.sa_sigaction = SIG_IGN;
act.sa_flags = SA_RESTART | SA_SIGINFO;
sigemptyset(&act.sa_mask);
sigaction(SIGTERM, &act, NULL);
eina_list_free(extensions);
/* touch update file */
snprintf(file, sizeof(file), "%s/.efreet/icon_data.update", efreet_home_dir_get());
tmpfd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
if (tmpfd >= 0)
{
write(tmpfd, "a", 1);
close(tmpfd);
}
efreet_shutdown(); efreet_shutdown();
ecore_shutdown();
eet_shutdown(); on_error:
eina_shutdown();
close(lockfd); close(lockfd);
return 0;
error:
printf("error\n");
IF_FREE(dir);
edd_error:
efreet_shutdown();
efreet_error:
ecore_shutdown(); ecore_shutdown();
ecore_error:
eet_shutdown(); eet_shutdown();
eet_error:
eina_shutdown(); eina_shutdown();
eina_error:
if (lockfd >= 0) close(lockfd); return 0;
return 1;
} }

View File

@ -23,78 +23,79 @@ static Eet_Data_Descriptor *edd = NULL;
int verbose = 0; int verbose = 0;
static void static void
dump(Efreet_Icon_Theme *theme) dump(Efreet_Icon_Theme *theme, Eet_File *ef)
{ {
Eet_File *ef; Efreet_Cache_Theme *cache;
char **keys; Eina_Iterator *it;
int i, num; const char *key;
double start, max, avg; unsigned int count;
double start, avg;
start = ecore_time_get(); start = ecore_time_get();
ef = eet_open(efreet_icon_cache_file(theme->name.internal), EET_FILE_MODE_READ);
printf("open: %s %f\n", theme->name.internal, ecore_time_get() - start); printf("open: %s\n", theme->name.internal);
if (!ef) return;
start = ecore_time_get(); cache = eet_data_read(ef, edd, theme->name.internal);
keys = eet_list(ef, "*", &num);
printf("list: %s %d, %f\n", theme->name.internal, num, ecore_time_get() - start); printf("read: %s %f\n", theme->name.internal, ecore_time_get() - start);
if (!keys)
{ if (!cache || !cache->icons) return ;
eet_close(ef);
return; it = eina_hash_iterator_key_new(cache->icons);
}
start = ecore_time_get(); EINA_ITERATOR_FOREACH(it, key)
for (i = 0; i < num; i++) {
{
Efreet_Cache_Icon *icon; Efreet_Cache_Icon *icon;
double dt; unsigned int i;
dt = ecore_time_get(); icon = eina_hash_find(cache->icons, key);
icon = eet_data_read(ef, edd, keys[i]);
if (!icon) continue; for (i = 0; i < icon->icons_count; ++i)
dt = ecore_time_get() - dt; count += icon->icons[i]->paths_count;
if (dt > max) }
max = dt;
efreet_cache_icon_free(icon); eina_iterator_free(it);
}
start = ecore_time_get() - start; eina_hash_free(cache->icons);
avg = start / num; free(cache);
printf("read: %s %f %f %f\n", theme->name.internal, start, avg, max);
free(keys); start = ecore_time_get() - start;
eet_close(ef); avg = start / count;
printf("read: %s - %i paths (time: %f) (avg %f)\n", theme->name.internal, count, start, avg);
} }
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
Eina_List *l = NULL; Eet_File *ef;
Efreet_Icon_Theme *theme; Eina_List *l = NULL;
int i; Efreet_Icon_Theme *theme;
int i;
efreet_cache_update = 0; efreet_cache_update = 0;
if (!efreet_init()) goto efreet_error; if (!efreet_init()) return -1;
edd = efreet_icon_edd_init();
if (!edd) goto edd_error;
if (argc > 1) edd = efreet_icon_theme_edd();
{ if (!edd) return -1;
for (i = 1; i < argc; i++)
{
theme = efreet_icon_theme_find(argv[i]);
if (theme) l = eina_list_append(l, theme);
}
}
if (!l)
l = efreet_icon_theme_list_get();
EINA_LIST_FREE(l, theme)
{
dump(theme);
}
efreet_shutdown(); if (argc > 1)
return 0; for (i = 1; i < argc; i++)
edd_error: {
efreet_shutdown(); theme = efreet_icon_theme_find(argv[i]);
efreet_error: if (theme) l = eina_list_append(l, theme);
return 1; }
if (!l) l = efreet_icon_theme_list_get();
ef = eet_open(efreet_icon_cache_file(), EET_FILE_MODE_READ);
if (!ef) return -1;
EINA_LIST_FREE(l, theme)
dump(theme, ef);
eet_close(ef);
efreet_shutdown();
return 0;
} }

View File

@ -19,18 +19,29 @@ struct _Efreet_Old_Cache
Eet_File *ef; Eet_File *ef;
}; };
#ifdef EFREET_MODULE_LOG_DOM
#undef EFREET_MODULE_LOG_DOM
#endif
#define EFREET_MODULE_LOG_DOM _efreet_cache_log_dom
static int _efreet_cache_log_dom = -1;
/** /**
* Data for cache files * Data for cache files
*/ */
#ifdef ICON_CACHE #ifdef ICON_CACHE
static Eet_Data_Descriptor *cache_icon_edd = NULL; static Eet_Data_Descriptor *cache_theme_edd = NULL;
static Eet_Data_Descriptor *cache_icon_element_edd = NULL; static Eet_Data_Descriptor *cache_fallback_edd = NULL;
static Eet_Data_Descriptor *cache_icon_fallback_edd = NULL;
static Eet_File *icon_cache = NULL; static Eet_Data_Descriptor *icon_element_pointer_edd;
static const char *icon_cache_name = NULL; static Eet_Data_Descriptor *icon_element_edd;
static Eet_File *icon_fallback_cache = NULL; static Eet_Data_Descriptor *icon_edd;
static Eet_File *cache = NULL;
static const char *theme_name = NULL;
static Efreet_Cache_Theme *theme_cache = NULL;
static Efreet_Cache_Theme *fallback_cache = NULL;
#endif #endif
static Eet_Data_Descriptor *desktop_edd = NULL; static Eet_Data_Descriptor *desktop_edd = NULL;
@ -41,10 +52,6 @@ static const char *desktop_cache_file = NULL;
static Ecore_File_Monitor *cache_monitor = NULL; static Ecore_File_Monitor *cache_monitor = NULL;
#ifdef ICON_CACHE
static Ecore_Timer *cache_timer = NULL;
#endif
static Ecore_Event_Handler *cache_exe_handler = NULL; static Ecore_Event_Handler *cache_exe_handler = NULL;
#ifdef ICON_CACHE #ifdef ICON_CACHE
static Ecore_Job *icon_cache_job = NULL; static Ecore_Job *icon_cache_job = NULL;
@ -66,15 +73,6 @@ static Eina_Bool cache_exe_cb(void *data, int type, void *event);
static void cache_update_cb(void *data, Ecore_File_Monitor *em, static void cache_update_cb(void *data, Ecore_File_Monitor *em,
Ecore_File_Event event, const char *path); Ecore_File_Event event, const char *path);
#ifdef ICON_CACHE
static void cache_timer_update(void);
static Eina_Bool cache_timer_cb(void *data);
#endif
#ifdef ICON_CACHE
static void icon_cache_close(void);
#endif
static void desktop_cache_update_cache_job(void *data); static void desktop_cache_update_cache_job(void *data);
#ifdef ICON_CACHE #ifdef ICON_CACHE
static void icon_cache_update_cache_job(void *data); static void icon_cache_update_cache_job(void *data);
@ -91,12 +89,9 @@ efreet_cache_init(void)
{ {
char buf[PATH_MAX]; char buf[PATH_MAX];
#ifdef ICON_CACHE _efreet_cache_log_dom = eina_log_domain_register("efreet_cache", EFREET_DEFAULT_LOG_COLOR);
if (!efreet_icon_edd_init()) if (_efreet_cache_log_dom < 0)
goto error; return 0;
if (!efreet_icon_fallback_edd_init())
goto error;
#endif
if (!efreet_desktop_edd_init()) if (!efreet_desktop_edd_init())
goto error; goto error;
@ -144,10 +139,27 @@ efreet_cache_shutdown(void)
Efreet_Old_Cache *d; Efreet_Old_Cache *d;
#ifdef ICON_CACHE #ifdef ICON_CACHE
if (cache_timer) ecore_timer_del(cache_timer); if (theme_cache)
cache_timer = NULL; {
icon_cache_close(); eina_hash_free(theme_cache->icons);
free(theme_cache);
theme_cache = NULL;
}
if (theme_name) eina_stringshare_del(theme_name);
theme_name = NULL;
if (fallback_cache)
{
eina_hash_free(fallback_cache->icons);
free(fallback_cache);
fallback_cache = NULL;
}
if (cache) eet_close(cache);
cache = NULL;
#endif #endif
if (desktop_cache) eet_close(desktop_cache); if (desktop_cache) eet_close(desktop_cache);
desktop_cache = NULL; desktop_cache = NULL;
IF_RELEASE(desktop_cache_file); IF_RELEASE(desktop_cache_file);
@ -157,9 +169,11 @@ efreet_cache_shutdown(void)
cache_exe_handler = NULL; cache_exe_handler = NULL;
if (cache_monitor) ecore_file_monitor_del(cache_monitor); if (cache_monitor) ecore_file_monitor_del(cache_monitor);
cache_monitor = NULL; cache_monitor = NULL;
#ifdef ICON_CACHE #ifdef ICON_CACHE
efreet_icon_edd_shutdown(); efreet_icon_edd_shutdown();
#endif #endif
efreet_desktop_edd_shutdown(); efreet_desktop_edd_shutdown();
if (desktop_cache_job) if (desktop_cache_job)
{ {
@ -174,6 +188,7 @@ efreet_cache_shutdown(void)
icon_cache_exe_lock = -1; icon_cache_exe_lock = -1;
} }
#endif #endif
if (desktop_cache_exe) ecore_exe_terminate(desktop_cache_exe); if (desktop_cache_exe) ecore_exe_terminate(desktop_cache_exe);
if (desktop_cache_exe_lock > 0) if (desktop_cache_exe_lock > 0)
{ {
@ -186,6 +201,8 @@ efreet_cache_shutdown(void)
eina_hash_free(d->hash); eina_hash_free(d->hash);
free(d); free(d);
} }
eina_log_domain_unregister(_efreet_cache_log_dom);
} }
#ifdef ICON_CACHE #ifdef ICON_CACHE
@ -193,14 +210,14 @@ efreet_cache_shutdown(void)
* Needs EAPI because of helper binaries * Needs EAPI because of helper binaries
*/ */
EAPI const char * EAPI const char *
efreet_icon_cache_file(const char *theme) efreet_icon_cache_file(void)
{ {
static char cache_file[PATH_MAX] = { '\0' }; static char cache_file[PATH_MAX] = { '\0' };
const char *home; const char *home;
home = efreet_home_dir_get(); home = efreet_home_dir_get();
snprintf(cache_file, sizeof(cache_file), "%s/.efreet/icon_%s.cache", home, theme); snprintf(cache_file, sizeof(cache_file), "%s/.efreet/icons.eet", home);
return cache_file; return cache_file;
} }
@ -252,72 +269,145 @@ efreet_desktop_cache_dirs(void)
} }
#ifdef ICON_CACHE #ifdef ICON_CACHE
/*
* Needs EAPI because of helper binaries #define EFREET_POINTER_TYPE(Edd_Dest, Edd_Source, Type) \
*/ { \
EAPI Eet_Data_Descriptor * typedef struct _Efreet_##Type##_Pointer Efreet_##Type##_Pointer; \
efreet_icon_edd_init(void) struct _Efreet_##Type##_Pointer \
{ \
Efreet_##Type *pointer; \
}; \
\
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_##Type##_Pointer); \
Edd_Dest = eet_data_descriptor_file_new(&eddc); \
EET_DATA_DESCRIPTOR_ADD_SUB(Edd_Dest, Efreet_##Type##_Pointer, \
"pointer", pointer, Edd_Source); \
}
static void *
_efreet_icon_hash_add(void *h, const char *key, void *d)
{ {
Eet_Data_Descriptor_Class iconeddc; Eina_Hash *hash = h;
Eet_Data_Descriptor_Class elemeddc;
if (!cache_icon_edd) if (!hash) hash = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_free);
{ if (!hash) return NULL;
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&iconeddc, Efreet_Cache_Icon);
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&elemeddc, Efreet_Cache_Icon_Element);
cache_icon_edd = eet_data_descriptor_file_new(&iconeddc);
if (!cache_icon_edd)
goto error;
cache_icon_element_edd = eet_data_descriptor_file_new(&elemeddc);
if (!cache_icon_element_edd)
goto error;
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_icon_edd, Efreet_Cache_Icon, "theme", theme, EET_T_STRING); eina_hash_direct_add(hash, key, d);
EET_DATA_DESCRIPTOR_ADD_LIST(cache_icon_edd, Efreet_Cache_Icon, "icons", icons, cache_icon_element_edd);
eet_data_descriptor_element_add(cache_icon_element_edd, "paths", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Cache_Icon_Element, paths), 0, NULL, NULL); return hash;
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_icon_element_edd, Efreet_Cache_Icon_Element, "size.normal", size.normal, EET_T_USHORT);
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_icon_element_edd, Efreet_Cache_Icon_Element, "size.min", size.min, EET_T_USHORT);
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_icon_element_edd, Efreet_Cache_Icon_Element, "size.max", size.max, EET_T_USHORT);
}
return cache_icon_edd;
error:
efreet_icon_edd_shutdown();
return NULL;
} }
/* /*
* Needs EAPI because of helper binaries * Needs EAPI because of helper binaries
*/ */
EAPI Eet_Data_Descriptor * EAPI Eet_Data_Descriptor *
efreet_icon_fallback_edd_init(void) efreet_icon_theme_edd(void)
{ {
Eet_Data_Descriptor_Class eddc; Eet_Data_Descriptor_Class eddc;
if (!cache_icon_fallback_edd) if (cache_theme_edd) return cache_theme_edd;
{
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Icon);
cache_icon_fallback_edd = eet_data_descriptor_file_new(&eddc);
if (!cache_icon_fallback_edd)
goto error;
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_icon_fallback_edd, Efreet_Cache_Icon, "fallback", fallback, EET_T_UCHAR); EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Icon_Element);
eet_data_descriptor_element_add(cache_icon_fallback_edd, "icons", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Cache_Icon, icons), 0, NULL, NULL); icon_element_edd = eet_data_descriptor_file_new(&eddc);
} if (!icon_element_edd) return NULL;
return cache_icon_fallback_edd;
error: EET_DATA_DESCRIPTOR_ADD_BASIC(icon_element_edd, Efreet_Cache_Icon_Element,
efreet_icon_edd_shutdown(); "type", type, EET_T_USHORT);
return NULL; EET_DATA_DESCRIPTOR_ADD_BASIC(icon_element_edd, Efreet_Cache_Icon_Element,
"normal", normal, EET_T_USHORT);
EET_DATA_DESCRIPTOR_ADD_BASIC(icon_element_edd, Efreet_Cache_Icon_Element,
"normal", normal, EET_T_USHORT);
EET_DATA_DESCRIPTOR_ADD_BASIC(icon_element_edd, Efreet_Cache_Icon_Element,
"min", min, EET_T_USHORT);
EET_DATA_DESCRIPTOR_ADD_BASIC(icon_element_edd, Efreet_Cache_Icon_Element,
"max", max, EET_T_USHORT);
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING(icon_element_edd, Efreet_Cache_Icon_Element,
"paths", paths);
EFREET_POINTER_TYPE(icon_element_pointer_edd, icon_element_edd, Cache_Icon_Element);
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Icon);
icon_edd = eet_data_descriptor_file_new(&eddc);
if (!icon_edd) return NULL;
EET_DATA_DESCRIPTOR_ADD_BASIC(icon_edd, Efreet_Cache_Icon,
"theme", theme, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY(icon_edd, Efreet_Cache_Icon,
"icons", icons, icon_element_pointer_edd);
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Icon);
eddc.func.hash_add = _efreet_icon_hash_add;
cache_theme_edd = eet_data_descriptor_file_new(&eddc);
if (!cache_theme_edd) return NULL;
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_theme_edd, Efreet_Cache_Theme,
"version.minor", version.minor, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_theme_edd, Efreet_Cache_Theme,
"version.major", version.major, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_HASH(cache_theme_edd, Efreet_Cache_Theme,
"icons", icons, icon_edd);
return cache_theme_edd;
} }
static void *
_efreet_icon_fallback_hash_add(void *h, const char *key, void *d)
{
Eina_Hash *hash = h;
if (!hash) hash = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_fallback_free);
if (!hash) return NULL;
eina_hash_direct_add(hash, key, d);
return hash;
}
/*
* Needs EAPI because of helper binaries
*/
EAPI Eet_Data_Descriptor *
efreet_icon_fallback_edd(void)
{
Eet_Data_Descriptor_Class eddc;
Eet_Data_Descriptor *icon_fallback_edd;
if (cache_fallback_edd) return cache_fallback_edd;
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Fallback_Icon);
icon_fallback_edd = eet_data_descriptor_file_new(&eddc);
if (!icon_fallback_edd) return NULL;
EET_DATA_DESCRIPTOR_ADD_VAR_ARRAY_STRING(icon_fallback_edd,
Efreet_Cache_Fallback_Icon, "icons", icons);
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Cache_Icon);
eddc.func.hash_add = _efreet_icon_fallback_hash_add;
cache_fallback_edd = eet_data_descriptor_file_new(&eddc);
if (!cache_fallback_edd) return NULL;
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_fallback_edd, Efreet_Cache_Theme,
"version.minor", version.minor, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(cache_fallback_edd, Efreet_Cache_Theme,
"version.major", version.major, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_HASH(cache_fallback_edd, Efreet_Cache_Theme,
"icons", icons, icon_fallback_edd);
return cache_fallback_edd;
}
#define EDD_SHUTDOWN(Edd) \
if (Edd) eet_data_descriptor_free(Edd); \
Edd = NULL;
static void static void
efreet_icon_edd_shutdown(void) efreet_icon_edd_shutdown(void)
{ {
if (cache_icon_edd) eet_data_descriptor_free(cache_icon_edd); EDD_SHUTDOWN(cache_fallback_edd);
cache_icon_edd = NULL; EDD_SHUTDOWN(cache_theme_edd);
if (cache_icon_element_edd) eet_data_descriptor_free(cache_icon_element_edd); EDD_SHUTDOWN(icon_element_pointer_edd);
cache_icon_element_edd = NULL; EDD_SHUTDOWN(icon_element_edd);
if (cache_icon_fallback_edd) eet_data_descriptor_free(cache_icon_fallback_edd); EDD_SHUTDOWN(icon_edd);
cache_icon_fallback_edd = NULL;
} }
#endif #endif
@ -327,44 +417,45 @@ efreet_icon_edd_shutdown(void)
EAPI Eet_Data_Descriptor * EAPI Eet_Data_Descriptor *
efreet_desktop_edd_init(void) efreet_desktop_edd_init(void)
{ {
if (!desktop_edd) Eet_Data_Descriptor_Class eddc;
{
Eet_Data_Descriptor_Class eddc;
EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Desktop); if (desktop_edd) return desktop_edd;
desktop_edd = eet_data_descriptor_file_new(&eddc);
if (!desktop_edd) return NULL; EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Efreet_Desktop);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "type", type, EET_T_INT); desktop_edd = eet_data_descriptor_file_new(&eddc);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "version", version, EET_T_STRING); if (!desktop_edd) return NULL;
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "orig_path", orig_path, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "load_time", load_time, EET_T_LONG_LONG); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "type", type, EET_T_INT);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "name", name, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "version", version, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "generic_name", generic_name, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "orig_path", orig_path, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "comment", comment, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "load_time", load_time, EET_T_LONG_LONG);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "icon", icon, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "name", name, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "try_exec", try_exec, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "generic_name", generic_name, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "exec", exec, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "comment", comment, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "path", path, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "icon", icon, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "startup_wm_class", startup_wm_class, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "try_exec", try_exec, EET_T_STRING);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "url", url, EET_T_STRING); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "exec", exec, EET_T_STRING);
eet_data_descriptor_element_add(desktop_edd, "only_show_in", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, only_show_in), 0, NULL, NULL); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "path", path, EET_T_STRING);
eet_data_descriptor_element_add(desktop_edd, "not_show_in", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, not_show_in), 0, NULL, NULL); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "startup_wm_class", startup_wm_class, EET_T_STRING);
eet_data_descriptor_element_add(desktop_edd, "categories", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, categories), 0, NULL, NULL); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "url", url, EET_T_STRING);
eet_data_descriptor_element_add(desktop_edd, "mime_types", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, mime_types), 0, NULL, NULL); eet_data_descriptor_element_add(desktop_edd, "only_show_in", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, only_show_in), 0, NULL, NULL);
eet_data_descriptor_element_add(desktop_edd, "x", EET_T_STRING, EET_G_HASH, offsetof(Efreet_Desktop, x), 0, NULL, NULL); eet_data_descriptor_element_add(desktop_edd, "not_show_in", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, not_show_in), 0, NULL, NULL);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "no_display", no_display, EET_T_UCHAR); eet_data_descriptor_element_add(desktop_edd, "categories", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, categories), 0, NULL, NULL);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "hidden", hidden, EET_T_UCHAR); eet_data_descriptor_element_add(desktop_edd, "mime_types", EET_T_STRING, EET_G_LIST, offsetof(Efreet_Desktop, mime_types), 0, NULL, NULL);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "terminal", terminal, EET_T_UCHAR); eet_data_descriptor_element_add(desktop_edd, "x", EET_T_STRING, EET_G_HASH, offsetof(Efreet_Desktop, x), 0, NULL, NULL);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "startup_notify", startup_notify, EET_T_UCHAR); EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "no_display", no_display, EET_T_UCHAR);
} EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "hidden", hidden, EET_T_UCHAR);
return desktop_edd; EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "terminal", terminal, EET_T_UCHAR);
EET_DATA_DESCRIPTOR_ADD_BASIC(desktop_edd, Efreet_Desktop, "startup_notify", startup_notify, EET_T_UCHAR);
return desktop_edd;
} }
static void static void
efreet_desktop_edd_shutdown(void) efreet_desktop_edd_shutdown(void)
{ {
if (desktop_edd) eet_data_descriptor_free(desktop_edd); if (desktop_edd) eet_data_descriptor_free(desktop_edd);
desktop_edd = NULL; desktop_edd = NULL;
} }
#ifdef ICON_CACHE #ifdef ICON_CACHE
@ -374,85 +465,97 @@ efreet_desktop_edd_shutdown(void)
EAPI void EAPI void
efreet_cache_icon_free(Efreet_Cache_Icon *icon) efreet_cache_icon_free(Efreet_Cache_Icon *icon)
{ {
void *data; unsigned int i;
if (!icon) return; if (!icon) return;
if (icon->free)
{
unsigned int j;
if (icon->free)
eina_stringshare_del(icon->theme); eina_stringshare_del(icon->theme);
EINA_LIST_FREE(icon->icons, data) for (i = 0; i < icon->icons_count; ++i)
{ {
const char *path; for (j = 0; j < icon->icons[i]->paths_count; ++j)
eina_stringshare_del(icon->icons[i]->paths[j]);
}
}
if (icon->fallback) for (i = 0; i < icon->icons_count; ++i)
{ {
if (icon->free) free(icon->icons[i]->paths);
eina_stringshare_del(data); free(icon->icons[i]);
} }
else
{
Efreet_Cache_Icon_Element *elem;
elem = data; free(icon->icons);
if (icon->free) free(icon);
{ }
EINA_LIST_FREE(elem->paths, path)
eina_stringshare_del(path); EAPI void
} efreet_cache_icon_fallback_free(Efreet_Cache_Fallback_Icon *icon)
else {
eina_list_free(elem->paths); unsigned int i;
free(elem);
} if (!icon) return ;
}
free(icon); if (icon->free)
for (i = 0; i < icon->icons_count; ++i)
eina_stringshare_del(icon->icons[i]);
free(icon->icons);
free(icon);
} }
Efreet_Cache_Icon * Efreet_Cache_Icon *
efreet_cache_icon_find(Efreet_Icon_Theme *theme, const char *icon) efreet_cache_icon_find(Efreet_Icon_Theme *theme, const char *icon)
{ {
if (icon_cache) if (!cache) cache = eet_open(efreet_icon_cache_file(), EET_FILE_MODE_READ);
{ if (!cache) return NULL;
if (!strcmp(icon_cache_name, theme->name.internal))
{
eet_close(icon_cache);
eina_stringshare_del(icon_cache_name);
icon_cache = NULL;
icon_cache_name = NULL;
}
}
if (!icon_cache)
{
const char *path;
path = efreet_icon_cache_file(theme->name.internal); if (theme_name && strcmp(theme_name, theme->name.internal))
icon_cache = eet_open(path, EET_FILE_MODE_READ); {
if (icon_cache) /* FIXME: this is bad if people have pointer to this cache, things will go wrong */
{ INFO("theme_name change from `%s` to `%s`", theme_name, theme->name.internal);
icon_cache_name = eina_stringshare_add(theme->name.internal); eina_hash_free(theme_cache->icons);
cache_timer_update(); free(theme_cache);
} eina_stringshare_del(theme_name);
} theme_cache = NULL;
if (icon_cache) theme_name = NULL;
return eet_data_read(icon_cache, cache_icon_edd, icon); }
return NULL;
if (!theme_name)
{
INFO("loading theme %s", theme->name.internal);
theme_cache = eet_data_read(cache, efreet_icon_theme_edd(), theme->name.internal);
if (theme_cache && !theme_cache->icons)
theme_cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_free);
if (theme_cache)
theme_name = eina_stringshare_add(theme->name.internal);
}
if (!theme_cache || theme_cache->version.major != EFREET_CACHE_MAJOR) return NULL;
return eina_hash_find(theme_cache->icons, icon);
} }
Efreet_Cache_Icon * Efreet_Cache_Fallback_Icon *
efreet_cache_icon_fallback_find(const char *icon) efreet_cache_icon_fallback_find(const char *icon)
{ {
if (!icon_fallback_cache) if (!cache) cache = eet_open(efreet_icon_cache_file(), EET_FILE_MODE_READ);
{ if (!cache) return NULL;
const char *path;
path = efreet_icon_cache_file("_fallback"); if (!fallback_cache)
icon_fallback_cache = eet_open(path, EET_FILE_MODE_READ); {
if (icon_fallback_cache) INFO("loading fallback cache");
cache_timer_update(); fallback_cache = eet_data_read(cache, efreet_icon_fallback_edd(), "efreet/fallback");
} if (fallback_cache && !fallback_cache->icons)
if (icon_fallback_cache) fallback_cache->icons = eina_hash_string_superfast_new((Eina_Free_Cb) efreet_cache_icon_fallback_free);
return eet_data_read(icon_fallback_cache, cache_icon_fallback_edd, icon); }
return NULL;
if (!fallback_cache || fallback_cache->version.major != EFREET_CACHE_MAJOR) return NULL;
return eina_hash_find(fallback_cache->icons, icon);
} }
#endif #endif
@ -586,14 +689,34 @@ cache_update_cb(void *data __UNUSED__, Ecore_File_Monitor *em __UNUSED__,
ecore_event_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, ev, desktop_cache_update_free, d); ecore_event_add(EFREET_EVENT_DESKTOP_CACHE_UPDATE, ev, desktop_cache_update_free, d);
} }
#ifdef ICON_CACHE #ifdef ICON_CACHE
else if (!strcmp(file, "icon_data.update")) else if (!strcmp(file, efreet_icon_cache_file()))
{ {
icon_cache_close(); if (theme_cache)
{
INFO("Destorying theme cache due to cache change.");
eina_hash_free(theme_cache->icons);
free(theme_cache);
theme_cache = NULL;
}
ev = NEW(Efreet_Event_Cache_Update, 1); if (theme_name) eina_stringshare_del(theme_name);
if (!ev) return; theme_name = NULL;
ecore_event_add(EFREET_EVENT_ICON_CACHE_UPDATE, ev, NULL, NULL);
} if (fallback_cache)
{
INFO("Destroying fallback cache due to cache change.");
eina_hash_free(fallback_cache->icons);
free(fallback_cache);
fallback_cache = NULL;
}
if (cache) eet_close(cache);
cache = NULL;
ev = NEW(Efreet_Event_Cache_Update, 1);
if (!ev) return;
ecore_event_add(EFREET_EVENT_ICON_CACHE_UPDATE, ev, NULL, NULL);
}
#endif #endif
return; return;
error: error:
@ -602,36 +725,6 @@ error:
if (tmp) eet_close(tmp); if (tmp) eet_close(tmp);
} }
#ifdef ICON_CACHE
static void
cache_timer_update(void)
{
if (cache_timer)
ecore_timer_interval_set(cache_timer, 60.0);
else
cache_timer = ecore_timer_add(60.0, cache_timer_cb, NULL);
}
static Eina_Bool
cache_timer_cb(void *data __UNUSED__)
{
cache_timer = NULL;
icon_cache_close();
return ECORE_CALLBACK_DONE;
}
static void
icon_cache_close(void)
{
if (icon_cache) eet_close(icon_cache);
icon_cache = NULL;
if (icon_fallback_cache) eet_close(icon_fallback_cache);
icon_fallback_cache = NULL;
IF_RELEASE(icon_cache_name);
}
#endif
static void static void
desktop_cache_update_cache_job(void *data __UNUSED__) desktop_cache_update_cache_job(void *data __UNUSED__)
{ {

View File

@ -122,13 +122,14 @@ static int efreet_cache_icon_size_match(Efreet_Cache_Icon_Element *elem, unsigne
static double efreet_cache_icon_size_distance(Efreet_Cache_Icon_Element *elem, unsigned int size); static double efreet_cache_icon_size_distance(Efreet_Cache_Icon_Element *elem, unsigned int size);
static const char *efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem); static const char *efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem);
static const char *efreet_cache_icon_lookup_path_path(Efreet_Cache_Icon_Element *elem, const char *path); static const char *efreet_cache_icon_lookup_path_path(Efreet_Cache_Icon_Element *elem, const char *path);
static const char *efreet_cache_icon_fallback_lookup_path(Efreet_Cache_Icon *icon); static const char *efreet_cache_icon_fallback_lookup_path(Efreet_Cache_Fallback_Icon *icon);
static const char *efreet_cache_icon_fallback_lookup_path_path(Efreet_Cache_Icon *icon, const char *path); static const char *efreet_cache_icon_fallback_lookup_path_path(Efreet_Cache_Fallback_Icon *icon,
const char *path);
static void efreet_icon_changes_listen(void); static void efreet_icon_changes_listen(void);
static void efreet_icon_changes_monitor_add(const char *path); static void efreet_icon_changes_monitor_add(const char *path);
static void efreet_icon_changes_cb(void *data, Ecore_File_Monitor *em, static void efreet_icon_changes_cb(void *data, Ecore_File_Monitor *em,
Ecore_File_Event event, const char *path); Ecore_File_Event event, const char *path);
#endif #endif
@ -400,14 +401,15 @@ efreet_icon_path_find(const char *theme_name, const char *icon, unsigned int siz
{ {
const char *value = NULL; const char *value = NULL;
Efreet_Icon_Theme *theme; Efreet_Icon_Theme *theme;
#ifdef ICON_CACHE
Efreet_Cache_Icon *cache;
#endif
theme = efreet_icon_find_theme_check(theme_name); theme = efreet_icon_find_theme_check(theme_name);
if (theme) if (theme)
{ {
#ifdef ICON_CACHE
Efreet_Cache_Icon *cache;
#endif
#ifdef SLOPPY_SPEC #ifdef SLOPPY_SPEC
{ {
char *tmp; char *tmp;
@ -417,7 +419,7 @@ efreet_icon_path_find(const char *theme_name, const char *icon, unsigned int siz
#ifdef ICON_CACHE #ifdef ICON_CACHE
cache = efreet_cache_icon_find(theme, tmp); cache = efreet_cache_icon_find(theme, tmp);
value = efreet_cache_icon_lookup_icon(cache, size); value = efreet_cache_icon_lookup_icon(cache, size);
efreet_cache_icon_free(cache); if (!value) INFO("lookup for `%s` failed in theme `%s` with %p.", icon, theme_name, cache);
#else #else
value = efreet_icon_find_helper(theme, tmp, size); value = efreet_icon_find_helper(theme, tmp, size);
#endif #endif
@ -427,7 +429,7 @@ efreet_icon_path_find(const char *theme_name, const char *icon, unsigned int siz
#ifdef ICON_CACHE #ifdef ICON_CACHE
cache = efreet_cache_icon_find(theme, icon); cache = efreet_cache_icon_find(theme, icon);
value = efreet_cache_icon_lookup_icon(cache, size); value = efreet_cache_icon_lookup_icon(cache, size);
efreet_cache_icon_free(cache); if (!value) INFO("lookup for `%s` failed in theme `%s` with %p.", icon, theme_name, cache);
#else #else
value = efreet_icon_find_helper(theme, icon, size); value = efreet_icon_find_helper(theme, icon, size);
#endif #endif
@ -439,13 +441,15 @@ efreet_icon_path_find(const char *theme_name, const char *icon, unsigned int siz
*/ */
if (!value || (value == NON_EXISTING)) if (!value || (value == NON_EXISTING))
#ifdef ICON_CACHE #ifdef ICON_CACHE
{ {
cache = efreet_cache_icon_fallback_find(icon); Efreet_Cache_Fallback_Icon *cache;
value = efreet_cache_icon_fallback_lookup_path(cache);
efreet_cache_icon_free(cache); cache = efreet_cache_icon_fallback_find(icon);
} value = efreet_cache_icon_fallback_lookup_path(cache);
if (!value) INFO("lookup for `%s` failed in fallback too with %p.", icon, cache);
}
#else #else
value = efreet_icon_fallback_icon(icon); value = efreet_icon_fallback_icon(icon);
#endif #endif
if (value == NON_EXISTING) value = NULL; if (value == NON_EXISTING) value = NULL;
@ -1668,77 +1672,76 @@ efreet_icon_cache_add(Efreet_Icon_Theme *theme, const char *icon, unsigned int s
static const char * static const char *
efreet_cache_icon_lookup_icon(Efreet_Cache_Icon *icon, unsigned int size) efreet_cache_icon_lookup_icon(Efreet_Cache_Icon *icon, unsigned int size)
{ {
Eina_List *l; const char *path = NULL;
Efreet_Cache_Icon_Element *elem; double minimal_distance = INT_MAX;
const char *path = NULL; unsigned int ret_size = 0;
const char *tmp = NULL; unsigned int i;
double minimal_distance = INT_MAX;
unsigned int ret_size = 0;
if (!icon) return NULL; if (!icon) return NULL;
/* search for allowed size == requested size */ /* search for allowed size == requested size */
EINA_LIST_FOREACH(icon->icons, l, elem) for (i = 0; i < icon->icons_count; ++i)
{ {
if (!efreet_cache_icon_size_match(elem, size)) continue; if (!efreet_cache_icon_size_match(icon->icons[i], size)) continue;
path = efreet_cache_icon_lookup_path(elem); path = efreet_cache_icon_lookup_path(icon->icons[i]);
if (path) return path; if (path) return path;
} }
/* search for any icon that matches */ /* search for any icon that matches */
EINA_LIST_FOREACH(icon->icons, l, elem) for (i = 0; i < icon->icons_count; ++i)
{ {
const char *tmp = NULL;
double distance; double distance;
distance = efreet_cache_icon_size_distance(elem, size); distance = efreet_cache_icon_size_distance(icon->icons[i], size);
if (distance > minimal_distance) continue; if (distance > minimal_distance) continue;
// prefer downsizing // prefer downsizing
if ((distance == minimal_distance) && (size < ret_size)) continue; if ((distance == minimal_distance) && (size < ret_size)) continue;
tmp = efreet_cache_icon_lookup_path(elem); tmp = efreet_cache_icon_lookup_path(icon->icons[i]);
if (tmp) if (tmp)
{ {
path = tmp; path = tmp;
minimal_distance = distance; minimal_distance = distance;
ret_size = size; ret_size = size;
} }
} }
return path; return path;
} }
static int static int
efreet_cache_icon_size_match(Efreet_Cache_Icon_Element *elem, unsigned int size) efreet_cache_icon_size_match(Efreet_Cache_Icon_Element *elem, unsigned int size)
{ {
if (elem->type == EFREET_ICON_SIZE_TYPE_FIXED) if (elem->type == EFREET_ICON_SIZE_TYPE_FIXED)
return (elem->size.normal == size); return (elem->normal == size);
if ((elem->type == EFREET_ICON_SIZE_TYPE_SCALABLE) || if ((elem->type == EFREET_ICON_SIZE_TYPE_SCALABLE) ||
(elem->type == EFREET_ICON_SIZE_TYPE_THRESHOLD)) (elem->type == EFREET_ICON_SIZE_TYPE_THRESHOLD))
return ((elem->size.min < size) && (size < elem->size.max)); return ((elem->min < size) && (size < elem->max));
return 0; return 0;
} }
static double static double
efreet_cache_icon_size_distance(Efreet_Cache_Icon_Element *elem, unsigned int size) efreet_cache_icon_size_distance(Efreet_Cache_Icon_Element *elem, unsigned int size)
{ {
if (elem->type == EFREET_ICON_SIZE_TYPE_FIXED) if (elem->type == EFREET_ICON_SIZE_TYPE_FIXED)
return (abs(elem->size.normal - size)); return (abs(elem->normal - size));
if ((elem->type == EFREET_ICON_SIZE_TYPE_SCALABLE) || if ((elem->type == EFREET_ICON_SIZE_TYPE_SCALABLE) ||
(elem->type == EFREET_ICON_SIZE_TYPE_THRESHOLD)) (elem->type == EFREET_ICON_SIZE_TYPE_THRESHOLD))
{ {
#ifdef STRICT_SPEC #ifdef STRICT_SPEC
if (size < elem->size.min) if (size < elem->min)
return (elem->size.min - size); return (elem->min - size);
if (elem->size.max < size) if (elem->max < size)
return (size - elem->size.max); return (size - elem->max);
#else #else
if (size < elem->size.min) if (size < elem->min)
return (elem->size.min / (double)size); return (elem->min / (double)size);
if (elem->size.max < size) if (elem->max < size)
return (size / (double)elem->size.max); return (size / (double)elem->max);
#endif #endif
return 0; return 0;
} }
@ -1749,28 +1752,30 @@ efreet_cache_icon_size_distance(Efreet_Cache_Icon_Element *elem, unsigned int si
static const char * static const char *
efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem) efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem)
{ {
const char *path; Eina_List *xdg_dirs, *l;
Eina_List *xdg_dirs, *l; const char *path;
const char *dir; const char *dir;
char buf[PATH_MAX]; char buf[PATH_MAX];
if (eina_list_count(elem->paths) == 1) if (elem->paths_count == 1)
{ {
const char *pp, *ext; const char *pp, *ext;
path = eina_list_data_get(elem->paths); pp = strrchr(elem->paths[0], '.');
pp = strrchr(path, '.'); if (!pp) return NULL;
EINA_LIST_FOREACH(efreet_icon_extensions, l, ext) EINA_LIST_FOREACH(efreet_icon_extensions, l, ext)
if (!strcmp(pp, ext)) if (!strcmp(pp, ext))
return path; return elem->paths[0];
return NULL; return NULL;
} }
path = efreet_cache_icon_lookup_path_path(elem, efreet_icon_deprecated_user_dir_get());
if (path) return path;
path = efreet_cache_icon_lookup_path_path(elem, efreet_icon_user_dir_get());
if (path) return path;
path = efreet_cache_icon_lookup_path_path(elem, efreet_icon_deprecated_user_dir_get());
if (path) return path;
path = efreet_cache_icon_lookup_path_path(elem, efreet_icon_user_dir_get());
if (path) return path;
#if 0 #if 0
EINA_LIST_FOREACH(efreet_extra_icon_dirs, l, dir) EINA_LIST_FOREACH(efreet_extra_icon_dirs, l, dir)
{ {
@ -1782,11 +1787,12 @@ efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem)
xdg_dirs = efreet_data_dirs_get(); xdg_dirs = efreet_data_dirs_get();
EINA_LIST_FOREACH(xdg_dirs, l, dir) EINA_LIST_FOREACH(xdg_dirs, l, dir)
{ {
snprintf(buf, sizeof(buf), "%s/icons", dir); snprintf(buf, sizeof(buf), "%s/icons", dir);
path = efreet_cache_icon_lookup_path_path(elem, buf);
if (path) return path; path = efreet_cache_icon_lookup_path_path(elem, buf);
} if (path) return path;
}
return NULL; return NULL;
} }
@ -1794,53 +1800,56 @@ efreet_cache_icon_lookup_path(Efreet_Cache_Icon_Element *elem)
static const char * static const char *
efreet_cache_icon_lookup_path_path(Efreet_Cache_Icon_Element *elem, const char *path) efreet_cache_icon_lookup_path_path(Efreet_Cache_Icon_Element *elem, const char *path)
{ {
Eina_List *l, *ll; Eina_List *ll;
const char *ext, *p, *pp; const char *ext, *pp;
int len; unsigned int i;
int len;
len = strlen(path); len = strlen(path);
EINA_LIST_FOREACH(elem->paths, l, p) for (i = 0; i < elem->paths_count; ++i)
{ {
if (strncmp(path, elem->paths[i], len)) continue;
if (strncmp(path, p, len)) continue; pp = strrchr(elem->paths[i], '.');
pp = strrchr(p, '.');
if (!pp) continue; if (!pp) continue;
EINA_LIST_FOREACH(efreet_icon_extensions, ll, ext) EINA_LIST_FOREACH(efreet_icon_extensions, ll, ext)
if (!strcmp(pp, ext)) if (!strcmp(pp, ext))
return p; return elem->paths[i];
} }
return NULL;
return NULL;
} }
static const char * static const char *
efreet_cache_icon_fallback_lookup_path(Efreet_Cache_Icon *icon) efreet_cache_icon_fallback_lookup_path(Efreet_Cache_Fallback_Icon *icon)
{ {
const char *path; const char *path;
Eina_List *xdg_dirs, *l; Eina_List *xdg_dirs, *l;
const char *dir; const char *dir;
char buf[PATH_MAX]; char buf[PATH_MAX];
if (!icon) return NULL; if (!icon) return NULL;
if (eina_list_count(icon->icons) == 1) if (icon->icons_count == 1)
{ {
const char *pp, *ext; const char *pp, *ext;
path = eina_list_data_get(icon->icons); pp = strrchr(icon->icons[0], '.');
pp = strrchr(path, '.'); if (!pp) return NULL;
EINA_LIST_FOREACH(efreet_icon_extensions, l, ext) EINA_LIST_FOREACH(efreet_icon_extensions, l, ext)
if (!strcmp(pp, ext)) if (!strcmp(pp, ext))
return path; return icon->icons[0];
return NULL; return NULL;
} }
path = efreet_cache_icon_fallback_lookup_path_path(icon, efreet_icon_deprecated_user_dir_get());
if (path) return path;
path = efreet_cache_icon_fallback_lookup_path_path(icon, efreet_icon_user_dir_get());
if (path) return path;
path = efreet_cache_icon_fallback_lookup_path_path(icon, efreet_icon_deprecated_user_dir_get());
if (path) return path;
path = efreet_cache_icon_fallback_lookup_path_path(icon, efreet_icon_user_dir_get());
if (path) return path;
#if 0 #if 0
EINA_LIST_FOREACH(efreet_extra_icon_dirs, l, dir) EINA_LIST_FOREACH(efreet_extra_icon_dirs, l, dir)
{ {
@ -1852,19 +1861,21 @@ efreet_cache_icon_fallback_lookup_path(Efreet_Cache_Icon *icon)
xdg_dirs = efreet_data_dirs_get(); xdg_dirs = efreet_data_dirs_get();
EINA_LIST_FOREACH(xdg_dirs, l, dir) EINA_LIST_FOREACH(xdg_dirs, l, dir)
{ {
snprintf(buf, sizeof(buf), "%s/icons", dir); snprintf(buf, sizeof(buf), "%s/icons", dir);
path = efreet_cache_icon_fallback_lookup_path_path(icon, buf);
if (path) return path; path = efreet_cache_icon_fallback_lookup_path_path(icon, buf);
} if (path) return path;
}
#ifndef STRICT_SPEC #ifndef STRICT_SPEC
EINA_LIST_FOREACH(xdg_dirs, l, dir) EINA_LIST_FOREACH(xdg_dirs, l, dir)
{ {
snprintf(buf, sizeof(buf), "%s/pixmaps", dir); snprintf(buf, sizeof(buf), "%s/pixmaps", dir);
path = efreet_cache_icon_fallback_lookup_path_path(icon, buf);
if (path) return path; path = efreet_cache_icon_fallback_lookup_path_path(icon, buf);
} if (path) return path;
}
#endif #endif
path = efreet_cache_icon_fallback_lookup_path_path(icon, "/usr/share/pixmaps"); path = efreet_cache_icon_fallback_lookup_path_path(icon, "/usr/share/pixmaps");
@ -1874,26 +1885,28 @@ efreet_cache_icon_fallback_lookup_path(Efreet_Cache_Icon *icon)
} }
static const char * static const char *
efreet_cache_icon_fallback_lookup_path_path(Efreet_Cache_Icon *icon, const char *path) efreet_cache_icon_fallback_lookup_path_path(Efreet_Cache_Fallback_Icon *icon, const char *path)
{ {
Eina_List *l, *ll; Eina_List *ll;
const char *ext, *p, *pp; const char *ext, *pp;
int len; unsigned int i;
int len;
len = strlen(path); len = strlen(path);
EINA_LIST_FOREACH(icon->icons, l, p) for (i = 0; i < icon->icons_count; ++i)
{ {
if (strncmp(path, icon->icons[i], len)) continue;
if (strncmp(path, p, len)) continue; pp = strrchr(icon->icons[i], '.');
pp = strrchr(p, '.');
if (!pp) continue; if (!pp) continue;
EINA_LIST_FOREACH(efreet_icon_extensions, ll, ext) EINA_LIST_FOREACH(efreet_icon_extensions, ll, ext)
if (!strcmp(pp, ext)) if (!strcmp(pp, ext))
return p; return icon->icons[i];
} }
return NULL;
return NULL;
} }
static void static void

View File

@ -120,26 +120,60 @@ extern int _efreet_log_dom_global;
extern Eina_Hash *efreet_desktop_cache; extern Eina_Hash *efreet_desktop_cache;
#ifdef ICON_CACHE #ifdef ICON_CACHE
typedef struct Efreet_Cache_Icon Efreet_Cache_Icon; #define EFREET_CACHE_MAJOR 0
struct Efreet_Cache_Icon #define EFREET_CACHE_MINOR 2
typedef struct _Efreet_Cache_Icon_Element Efreet_Cache_Icon_Element;
typedef struct _Efreet_Cache_Fallback_Icon Efreet_Cache_Fallback_Icon;
typedef struct _Efreet_Cache_Icon Efreet_Cache_Icon;
typedef struct _Efreet_Cache_Theme Efreet_Cache_Theme;
struct _Efreet_Cache_Theme
{ {
const char *theme; struct {
Eina_List *icons; unsigned char major;
unsigned char fallback; unsigned char minor;
unsigned char free:1; } version;
Eina_Hash *icons;
}; };
typedef struct Efreet_Cache_Icon_Element Efreet_Cache_Icon_Element; struct _Efreet_Cache_Icon
struct Efreet_Cache_Icon_Element
{ {
int type; /* size type of icon */ const char *theme;
Eina_List *paths; /* possible paths for icon */
struct Efreet_Cache_Icon_Element **icons;
{ unsigned int icons_count;
unsigned short normal; /* The size for this icon */
unsigned short min; /* The minimum size for this icon */ unsigned char free:1;
unsigned short max; /* The maximum size for this icon */ };
} size;
struct _Efreet_Cache_Icon_Element
{
const char **paths; /* possible paths for icon */
unsigned int paths_count;
unsigned short type; /* size type of icon */
unsigned short normal; /* The size for this icon */
unsigned short min; /* The minimum size for this icon */
unsigned short max; /* The maximum size for this icon */
};
struct _Efreet_Cache_Fallback_Icon
{
#if 0
const char *name;
#endif
const char *theme;
#if 0
int context; /* the type of icon */
#endif
const char **icons;
unsigned int icons_count;
unsigned char free:1;
}; };
#endif #endif
@ -193,13 +227,14 @@ void efreet_cache_desktop_free(Efreet_Desktop *desktop);
Efreet_Desktop *efreet_cache_desktop_find(const char *file); Efreet_Desktop *efreet_cache_desktop_find(const char *file);
#ifdef ICON_CACHE #ifdef ICON_CACHE
EAPI const char *efreet_icon_cache_file(const char *theme); EAPI const char *efreet_icon_cache_file(void);
EAPI Eet_Data_Descriptor *efreet_icon_edd_init(void); EAPI Eet_Data_Descriptor *efreet_icon_theme_edd(void);
EAPI Eet_Data_Descriptor *efreet_icon_fallback_edd_init(void); EAPI Eet_Data_Descriptor *efreet_icon_fallback_edd(void);
EAPI void efreet_cache_icon_free(Efreet_Cache_Icon *icon); EAPI void efreet_cache_icon_free(Efreet_Cache_Icon *icon);
EAPI void efreet_cache_icon_fallback_free(Efreet_Cache_Fallback_Icon *icon);
Efreet_Cache_Icon *efreet_cache_icon_find(Efreet_Icon_Theme *theme, const char *icon); Efreet_Cache_Icon *efreet_cache_icon_find(Efreet_Icon_Theme *theme, const char *icon);
Efreet_Cache_Icon *efreet_cache_icon_fallback_find(const char *icon); Efreet_Cache_Fallback_Icon *efreet_cache_icon_fallback_find(const char *icon);
#endif #endif
#define NON_EXISTING (void *)-1 #define NON_EXISTING (void *)-1