aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar/tray/icon.c
diff options
context:
space:
mode:
Diffstat (limited to 'swaybar/tray/icon.c')
-rw-r--r--swaybar/tray/icon.c68
1 files changed, 62 insertions, 6 deletions
diff --git a/swaybar/tray/icon.c b/swaybar/tray/icon.c
index c146bf32..fc9b176d 100644
--- a/swaybar/tray/icon.c
+++ b/swaybar/tray/icon.c
@@ -80,6 +80,17 @@ static bool isdir(const char *path) {
80 80
81} 81}
82 82
83static bool isfile(const char *path) {
84 struct stat statbuf;
85 if (stat(path, &statbuf) != -1) {
86 if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) {
87 return true;
88 }
89 }
90 return false;
91
92}
93
83/** 94/**
84 * Returns the directory of a given theme if it exists. 95 * Returns the directory of a given theme if it exists.
85 * The returned pointer must be freed. 96 * The returned pointer must be freed.
@@ -111,15 +122,28 @@ static char *find_theme_dir(const char *theme) {
111 } 122 }
112 123
113 if ((basedir = getenv("XDG_DATA_DIRS"))) { 124 if ((basedir = getenv("XDG_DATA_DIRS"))) {
114 if (snprintf(icon_dir, 1024, "%s/icons/%s", basedir, theme) >= 1024) { 125 if (!(basedir = strdup(basedir))) {
115 sway_log(L_ERROR, "Path too long to render"); 126 sway_log_errno(L_ERROR, "Path too long to render");
116 // ditto
117 goto fail; 127 goto fail;
118 } 128 }
129 char *token = strtok(basedir, ":");
130 while (token) {
131 // By peeking at the spec, there should be a slash at
132 // the end of the data dir.
133 if (snprintf(icon_dir, 1024, "%sicons/%s", token, theme) >= 1024) {
134 sway_log(L_ERROR, "Path too long to render");
135 // ditto
136 free(basedir);
137 goto fail;
138 }
119 139
120 if (isdir(icon_dir)) { 140 if (isdir(icon_dir)) {
121 return icon_dir; 141 free(basedir);
142 return icon_dir;
143 }
144 token = strtok(NULL, ":");
122 } 145 }
146 free(basedir);
123 } 147 }
124 148
125 // Spec says use "/usr/share/pixmaps/", but I see everything in 149 // Spec says use "/usr/share/pixmaps/", but I see everything in
@@ -162,6 +186,15 @@ static list_t *find_all_theme_dirs(const char *theme) {
162 list_cat(dirs, inherits); 186 list_cat(dirs, inherits);
163 list_free(inherits); 187 list_free(inherits);
164 } 188 }
189 // 'default' usually inherits the default theme. I don't believe it has
190 // any icons, but look for them anyway
191 dir = find_theme_dir("default");
192 if (dir) {
193 list_add(dirs, dir);
194 list_t *inherits = find_inherits(dir);
195 list_cat(dirs, inherits);
196 list_free(inherits);
197 }
165 dir = find_theme_dir("hicolor"); 198 dir = find_theme_dir("hicolor");
166 if (dir) { 199 if (dir) {
167 list_add(dirs, dir); 200 list_add(dirs, dir);
@@ -290,6 +323,24 @@ fail:
290 return dirs; 323 return dirs;
291} 324}
292 325
326/* Returns true if full path and file exists */
327static bool is_valid_path(const char *file) {
328 if (strstr(file, "/") == NULL || !isfile(file)) {
329 return false;
330 }
331#ifdef WITH_GDK_PIXBUF
332 if (strstr(file, ".png") == NULL &&
333 strstr(file, ".xpm") == NULL &&
334 strstr(file, ".svg") == NULL) {
335#else
336 if (strstr(file, ".png") == NULL) {
337#endif
338 return false;
339 }
340
341 return true;
342}
343
293/* Returns the file of an icon given its name and size */ 344/* Returns the file of an icon given its name and size */
294static char *find_icon_file(const char *name, int size) { 345static char *find_icon_file(const char *name, int size) {
295 int namelen = strlen(name); 346 int namelen = strlen(name);
@@ -372,7 +423,12 @@ static char *find_icon_file(const char *name, int size) {
372} 423}
373 424
374cairo_surface_t *find_icon(const char *name, int size) { 425cairo_surface_t *find_icon(const char *name, int size) {
375 char *image_path = find_icon_file(name, size); 426 char *image_path;
427 if (is_valid_path(name)) {
428 image_path = strdup(name);
429 } else {
430 image_path = find_icon_file(name, size);
431 }
376 if (image_path == NULL) { 432 if (image_path == NULL) {
377 return NULL; 433 return NULL;
378 } 434 }