Use XDG paths in addition to the defaults when looking for icons and applications

This commit is contained in:
o9000 2016-02-28 14:53:15 +01:00
parent edbf9f4437
commit fcbc006e43
6 changed files with 95 additions and 13 deletions

View file

@ -19,6 +19,7 @@
/* http://standards.freedesktop.org/desktop-entry-spec/ */
#include "apps-common.h"
#include "common.h"
#include <glib.h>
#include <stdio.h>
@ -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;
}

View file

@ -7,6 +7,8 @@
#ifndef APPS_COMMON_H
#define APPS_COMMON_H
#include <glib.h>
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

View file

@ -20,11 +20,13 @@
#include "icon-theme-common.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

View file

@ -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);

View file

@ -22,6 +22,7 @@
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -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;
}

View file

@ -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)