|
diff --git a/launcher.c b/launcher.c
|
| ... |
| 10 |
#include <X11/Xutil.h> |
10 |
#include <X11/Xutil.h> |
| 11 |
#include <X11/keysym.h> |
11 |
#include <X11/keysym.h> |
| 12 |
|
12 |
|
|
|
13 |
#include <gio/gio.h> |
|
|
14 |
|
| 13 |
#include "glitch.h" |
15 |
#include "glitch.h" |
| 14 |
#include "config.h" |
16 |
#include "config.h" |
| 15 |
|
17 |
|
| ... |
| 17 |
|
19 |
|
| 18 |
static void launcher_filter(void); |
20 |
static void launcher_filter(void); |
| 19 |
|
21 |
|
| 20 |
static char *trim_whitespace(char *str) { |
|
|
| 21 |
char *end; |
|
|
| 22 |
while (isspace((unsigned char)*str)) str++; |
|
|
| 23 |
if (*str == 0) return str; |
|
|
| 24 |
end = str + strlen(str) - 1; |
|
|
| 25 |
while (end > str && isspace((unsigned char)*end)) end--; |
|
|
| 26 |
end[1] = '\0'; |
|
|
| 27 |
return str; |
|
|
| 28 |
} |
|
|
| 29 |
|
|
|
| 30 |
static void load_applications(void) { |
22 |
static void load_applications(void) { |
| 31 |
const char *system_dirs[] = { |
|
|
| 32 |
"/usr/share/applications", |
|
|
| 33 |
"/usr/local/share/applications" |
|
|
| 34 |
}; |
|
|
| 35 |
|
|
|
| 36 |
char home_dir[1024]; |
|
|
| 37 |
char *home = getenv("HOME"); |
|
|
| 38 |
if (home) { |
|
|
| 39 |
snprintf(home_dir, sizeof(home_dir), "%s/.local/share/applications", home); |
|
|
| 40 |
} |
|
|
| 41 |
|
|
|
| 42 |
if (wm.launcher_items) { |
23 |
if (wm.launcher_items) { |
| 43 |
for (int i = 0; i < wm.launcher_items_count; i++) { |
24 |
for (int i = 0; i < wm.launcher_items_count; i++) { |
| 44 |
free(wm.launcher_items[i].name); |
25 |
free(wm.launcher_items[i].name); |
| ... |
| 49 |
wm.launcher_items_count = 0; |
30 |
wm.launcher_items_count = 0; |
| 50 |
} |
31 |
} |
| 51 |
|
32 |
|
| 52 |
int capacity = 100; |
33 |
GList *apps = g_app_info_get_all(); |
| 53 |
wm.launcher_items = malloc(sizeof(LauncherItem) * capacity); |
34 |
int total_apps = g_list_length(apps); |
|
|
35 |
wm.launcher_items = malloc(sizeof(LauncherItem) * total_apps); |
| 54 |
|
36 |
|
| 55 |
for (int d = -1; d < (int)LENGTH(system_dirs); d++) { |
37 |
for (GList *l = apps; l != NULL; l = l->next) { |
| 56 |
const char *path_to_open; |
38 |
GAppInfo *app = (GAppInfo *)l->data; |
| 57 |
if (d == -1) { |
39 |
|
| 58 |
if (!home) continue; |
40 |
if (!g_app_info_should_show(app)) { |
| 59 |
path_to_open = home_dir; |
41 |
g_object_unref(app); |
| 60 |
} else { |
42 |
continue; |
| 61 |
path_to_open = system_dirs[d]; |
|
|
| 62 |
} |
43 |
} |
| 63 |
|
44 |
|
| 64 |
DIR *dir = opendir(path_to_open); |
45 |
const char *name = g_app_info_get_name(app); |
| 65 |
if (!dir) continue; |
46 |
const char *exec = g_app_info_get_commandline(app); |
| 66 |
|
47 |
|
| 67 |
struct dirent *entry; |
48 |
if (name && exec) { |
| 68 |
while ((entry = readdir(dir))) { |
49 |
wm.launcher_items[wm.launcher_items_count].name = strdup(name); |
| 69 |
if (strstr(entry->d_name, ".desktop")) { |
|
|
| 70 |
char desktop_path[2048]; |
|
|
| 71 |
snprintf(desktop_path, sizeof(desktop_path), "%s/%s", path_to_open, entry->d_name); |
|
|
| 72 |
|
50 |
|
| 73 |
FILE *f = fopen(desktop_path, "r"); |
51 |
char *e = strdup(exec); |
| 74 |
if (!f) continue; |
52 |
char *percent = strchr(e, '%'); |
|
|
53 |
if (percent) *percent = '\0'; |
| 75 |
|
54 |
|
| 76 |
char line[1024]; |
55 |
// Trim potential trailing space after removing % |
| 77 |
char *name = NULL; |
56 |
int len = strlen(e); |
| 78 |
char *exec = NULL; |
57 |
while (len > 0 && isspace((unsigned char)e[len-1])) { |
| 79 |
int no_display = 0; |
58 |
e[--len] = '\0'; |
| 80 |
int in_desktop_entry = 0; |
59 |
} |
| 81 |
|
|
|
| 82 |
while (fgets(line, sizeof(line), f)) { |
|
|
| 83 |
char *trimmed = trim_whitespace(line); |
|
|
| 84 |
if (trimmed[0] == '[' && strstr(trimmed, "[Desktop Entry]")) { |
|
|
| 85 |
in_desktop_entry = 1; |
|
|
| 86 |
continue; |
|
|
| 87 |
} |
|
|
| 88 |
if (trimmed[0] == '[' && !strstr(trimmed, "[Desktop Entry]")) { |
|
|
| 89 |
in_desktop_entry = 0; |
|
|
| 90 |
} |
|
|
| 91 |
|
60 |
|
| 92 |
if (!in_desktop_entry) continue; |
61 |
wm.launcher_items[wm.launcher_items_count].exec = strdup(e); |
|
|
62 |
free(e); |
| 93 |
|
63 |
|
| 94 |
if (strncmp(trimmed, "Name=", 5) == 0 && !name) { |
64 |
wm.launcher_items_count++; |
| 95 |
name = strdup(trim_whitespace(trimmed + 5)); |
|
|
| 96 |
} else if (strncmp(trimmed, "Exec=", 5) == 0 && !exec) { |
|
|
| 97 |
char *e = strdup(trimmed + 5); |
|
|
| 98 |
char *percent = strchr(e, '%'); |
|
|
| 99 |
if (percent) *percent = '\0'; |
|
|
| 100 |
exec = strdup(trim_whitespace(e)); |
|
|
| 101 |
free(e); |
|
|
| 102 |
} else if (strncmp(trimmed, "NoDisplay=true", 14) == 0) { |
|
|
| 103 |
no_display = 1; |
|
|
| 104 |
} |
|
|
| 105 |
} |
|
|
| 106 |
fclose(f); |
|
|
| 107 |
|
|
|
| 108 |
if (name && exec && !no_display) { |
|
|
| 109 |
if (wm.launcher_items_count >= capacity) { |
|
|
| 110 |
capacity *= 2; |
|
|
| 111 |
wm.launcher_items = realloc(wm.launcher_items, sizeof(LauncherItem) * capacity); |
|
|
| 112 |
} |
|
|
| 113 |
wm.launcher_items[wm.launcher_items_count].name = name; |
|
|
| 114 |
wm.launcher_items[wm.launcher_items_count].exec = exec; |
|
|
| 115 |
wm.launcher_items_count++; |
|
|
| 116 |
} else { |
|
|
| 117 |
if (name) free(name); |
|
|
| 118 |
if (exec) free(exec); |
|
|
| 119 |
} |
|
|
| 120 |
} |
|
|
| 121 |
} |
65 |
} |
| 122 |
closedir(dir); |
66 |
g_object_unref(app); |
| 123 |
} |
67 |
} |
|
|
68 |
g_list_free(apps); |
| 124 |
} |
69 |
} |
| 125 |
|
70 |
|
| 126 |
void toggle_launcher(const Arg *arg) { |
71 |
void toggle_launcher(const Arg *arg) { |
| ... |