From fcbc006e43d0963e24c5be9409a842cf55b33769 Mon Sep 17 00:00:00 2001 From: o9000 Date: Sun, 28 Feb 2016 14:53:15 +0100 Subject: [PATCH] Use XDG paths in addition to the defaults when looking for icons and applications --- src/launcher/apps-common.c | 23 +++++++++++++++++ src/launcher/apps-common.h | 6 +++++ src/launcher/icon-theme-common.c | 19 ++++++++------ src/tint2conf/properties.c | 10 +++----- src/util/common.c | 43 ++++++++++++++++++++++++++++++++ src/util/common.h | 7 ++++++ 6 files changed, 95 insertions(+), 13 deletions(-) diff --git a/src/launcher/apps-common.c b/src/launcher/apps-common.c index 72ebdbb..793b602 100644 --- a/src/launcher/apps-common.c +++ b/src/launcher/apps-common.c @@ -19,6 +19,7 @@ /* http://standards.freedesktop.org/desktop-entry-spec/ */ #include "apps-common.h" +#include "common.h" #include #include @@ -194,3 +195,25 @@ void test_read_desktop_file() printf("Name:%s Icon:%s Exec:%s\n", entry.name, entry.icon, entry.exec); fprintf(stdout, "\033[0m"); } + +GSList *apps_locations = NULL; +// Do not free the result. +const GSList *get_apps_locations() +{ + if (apps_locations) + return apps_locations; + + apps_locations = load_locations_from_env(apps_locations, "XDG_DATA_HOME", "applications", NULL); + + apps_locations = g_slist_append(apps_locations, g_build_filename(g_get_home_dir(), ".local/share/applications", NULL)); + + apps_locations = load_locations_from_env(apps_locations, "XDG_DATA_DIRS", "applications", NULL); + + apps_locations = g_slist_append(apps_locations, g_strdup("/usr/local/share/applications")); + apps_locations = g_slist_append(apps_locations, g_strdup("/usr/share/applications")); + apps_locations = g_slist_append(apps_locations, g_strdup("/opt/share/applications")); + + apps_locations = slist_remove_duplicates(apps_locations, g_str_equal, g_free); + + return apps_locations; +} diff --git a/src/launcher/apps-common.h b/src/launcher/apps-common.h index 64a26af..80afe69 100644 --- a/src/launcher/apps-common.h +++ b/src/launcher/apps-common.h @@ -7,6 +7,8 @@ #ifndef APPS_COMMON_H #define APPS_COMMON_H +#include + typedef struct DesktopEntry { char *name; char *exec; @@ -27,4 +29,8 @@ int read_desktop_file(const char *path, DesktopEntry *entry); // Empties DesktopEntry: releases the memory of the *members* of entry. void free_desktop_entry(DesktopEntry *entry); +// Returns a list of the directories used to store desktop files. +// Do not free the result, it is cached. +const GSList *get_apps_locations(); + #endif diff --git a/src/launcher/icon-theme-common.c b/src/launcher/icon-theme-common.c index 426aab5..3e59c8e 100644 --- a/src/launcher/icon-theme-common.c +++ b/src/launcher/icon-theme-common.c @@ -20,11 +20,13 @@ #include "icon-theme-common.h" +#include #include #include #include #include "apps-common.h" +#include "common.h" #define ICON_DIR_TYPE_SCALABLE 0 #define ICON_DIR_TYPE_FIXED 1 @@ -50,19 +52,22 @@ const GSList *get_icon_locations() if (icon_locations) return icon_locations; - gchar *path; - path = g_build_filename(g_get_home_dir(), ".icons", NULL); - icon_locations = g_slist_append(icon_locations, g_strdup(path)); - g_free(path); - path = g_build_filename(g_get_home_dir(), ".local/share/icons", NULL); - icon_locations = g_slist_append(icon_locations, g_strdup(path)); - g_free(path); + icon_locations = load_locations_from_env(icon_locations, "XDG_DATA_HOME", ".icons", NULL); + + icon_locations = g_slist_append(icon_locations, g_build_filename(g_get_home_dir(), ".icons", NULL)); + icon_locations = g_slist_append(icon_locations, g_build_filename(g_get_home_dir(), ".local/share/icons", NULL)); + + icon_locations = load_locations_from_env(icon_locations, "XDG_DATA_DIRS", ".icons", ".pixmaps", NULL); + icon_locations = g_slist_append(icon_locations, g_strdup("/usr/local/share/icons")); icon_locations = g_slist_append(icon_locations, g_strdup("/usr/local/share/pixmaps")); icon_locations = g_slist_append(icon_locations, g_strdup("/usr/share/icons")); icon_locations = g_slist_append(icon_locations, g_strdup("/usr/share/pixmaps")); icon_locations = g_slist_append(icon_locations, g_strdup("/opt/share/icons")); icon_locations = g_slist_append(icon_locations, g_strdup("/opt/share/pixmaps")); + + icon_locations = slist_remove_duplicates(icon_locations, g_str_equal, g_free); + return icon_locations; } diff --git a/src/tint2conf/properties.c b/src/tint2conf/properties.c index d80f412..065d783 100644 --- a/src/tint2conf/properties.c +++ b/src/tint2conf/properties.c @@ -2893,10 +2893,10 @@ void create_launcher(GtkWidget *parent) fprintf(stderr, "Loading .desktop files\n"); GList *entries = NULL; - load_desktop_entries("/usr/share/applications", &entries); - load_desktop_entries("/usr/local/share/applications", &entries); - gchar *path = g_build_filename(g_get_home_dir(), ".local/share/applications", NULL); - load_desktop_entries(path, &entries); + for (location = get_apps_locations(); location; location = g_slist_next(location)) { + const gchar *path = (gchar*) location->data; + load_desktop_entries(path, &entries); + } entries = g_list_sort(entries, compare_entries); populate_from_entries(entries, FALSE); @@ -2905,8 +2905,6 @@ void create_launcher(GtkWidget *parent) } g_list_free(entries); - g_free(path); - icon_theme_changed(); load_icons(launcher_apps); load_icons(all_apps); diff --git a/src/util/common.c b/src/util/common.c index bc30fa9..997d959 100644 --- a/src/util/common.c +++ b/src/util/common.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -591,3 +592,45 @@ GList *g_list_copy_deep(GList *list, GCopyFunc func, gpointer user_data) return list; } #endif + +GSList *load_locations_from_env(GSList *locations, const char *var, ...) +{ + char *value = getenv(var); + if (value) { + value = strdup(value); + char *p = value; + for (char *token = strsep(&value, ":"); token; token = strsep(&value, ":")) { + va_list ap; + va_start(ap, var); + for (const char *suffix = va_arg(ap, const char *); suffix; suffix = va_arg(ap, const char *)) { + locations = g_slist_append(locations, g_build_filename(token, suffix, NULL)); + } + va_end(ap); + } + free(p); + } + return locations; +} + +GSList *slist_remove_duplicates(GSList *list, GCompareFunc eq, GDestroyNotify fr) +{ + GSList *new_list = NULL; + + for (GSList *l1 = list; l1; l1 = g_slist_next(l1)) { + gboolean duplicate = FALSE; + for (GSList *l2 = new_list; l2; l2 = g_slist_next(l2)) { + if (eq(l1->data, l2->data)) { + duplicate = TRUE; + break; + } + } + if (!duplicate) { + new_list = g_slist_append(new_list, l1->data); + l1->data = NULL; + } + } + + g_slist_free_full(list, fr); + + return new_list; +} diff --git a/src/util/common.h b/src/util/common.h index 276034b..a9876a9 100644 --- a/src/util/common.h +++ b/src/util/common.h @@ -96,6 +96,13 @@ void draw_rect(cairo_t *c, double x, double y, double w, double h, double r); // Clears the pixmap (with transparent color) void clear_pixmap(Pixmap p, int x, int y, int w, int h); +// Appends to the list locations all the directories contained in the environment variable var (split by ":"). +// Optional suffixes are added to each directory. The suffix arguments MUST end with NULL. +// Returns the new value of the list. +GSList *load_locations_from_env(GSList *locations, const char *var, ...); + +GSList *slist_remove_duplicates(GSList *list, GCompareFunc eq, GDestroyNotify fr); + #define free_and_null(p) { free(p); p = NULL; } #if !GLIB_CHECK_VERSION (2, 33, 4)