diff --git a/src/draw.c b/src/draw.c index 7b8bd72..7059830 100644 --- a/src/draw.c +++ b/src/draw.c @@ -269,13 +269,11 @@ static colored_layout *r_init_shared(cairo_t *c, notification *n) GdkPixbuf *pixbuf = NULL; - if (n->raw_icon && - settings.icon_position != icons_off) { - - pixbuf = get_pixbuf_from_raw_image(n->raw_icon); - - } else if (n->icon && settings.icon_position != icons_off) { - pixbuf = get_pixbuf_from_path(n->icon); + if (settings.icon_position != icons_off) { + if (n->raw_icon) + pixbuf = get_pixbuf_from_raw_image(n->raw_icon); + else if (n->icon) + pixbuf = get_pixbuf_from_icon(n->icon); } if (pixbuf != NULL) { diff --git a/src/icon.c b/src/icon.c index 2fa6eae..2d2bd44 100644 --- a/src/icon.c +++ b/src/icon.c @@ -9,11 +9,6 @@ #include "notification.h" #include "settings.h" -static bool does_file_exist(const char *filename) -{ - return (access(filename, F_OK) != -1); -} - static bool is_readable_file(const char *filename) { return (access(filename, R_OK) != -1); @@ -62,67 +57,68 @@ cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf) return icon_surface; } -static GdkPixbuf *get_pixbuf_from_file(const char *icon_path) +static GdkPixbuf *get_pixbuf_from_file(const char *filename) { GdkPixbuf *pixbuf = NULL; - if (is_readable_file(icon_path)) { + if (is_readable_file(filename)) { GError *error = NULL; - pixbuf = gdk_pixbuf_new_from_file(icon_path, &error); - if (pixbuf == NULL) + pixbuf = gdk_pixbuf_new_from_file(filename, &error); + if (!pixbuf) g_error_free(error); } return pixbuf; } -GdkPixbuf *get_pixbuf_from_path(char *icon_path) +GdkPixbuf *get_pixbuf_from_icon(const char *iconname) { + if (!iconname || iconname[0] == '\0') + return NULL; + + const char *suffixes[] = { ".svg", ".png", NULL }; GdkPixbuf *pixbuf = NULL; gchar *uri_path = NULL; - if (strlen(icon_path) > 0) { - if (g_str_has_prefix(icon_path, "file://")) { - uri_path = g_filename_from_uri(icon_path, NULL, NULL); - if (uri_path != NULL) { - icon_path = uri_path; - } - } - /* absolute path? */ - if (icon_path[0] == '/' || icon_path[0] == '~') { - pixbuf = get_pixbuf_from_file(icon_path); - } - /* search in icon_path */ - if (pixbuf == NULL) { - char *start = settings.icon_path, - *end, *current_folder, *maybe_icon_path; - do { - end = strchr(start, ':'); - if (end == NULL) end = strchr(settings.icon_path, '\0'); /* end = end of string */ - current_folder = g_strndup(start, end - start); - /* try svg */ - maybe_icon_path = g_strconcat(current_folder, "/", icon_path, ".svg", NULL); - if (!does_file_exist(maybe_icon_path)) { - g_free(maybe_icon_path); - /* fallback to png */ - maybe_icon_path = g_strconcat(current_folder, "/", icon_path, ".png", NULL); - } - g_free(current_folder); + if (g_str_has_prefix(iconname, "file://")) { + uri_path = g_filename_from_uri(iconname, NULL, NULL); + if (uri_path) + iconname = uri_path; + } + /* absolute path? */ + if (iconname[0] == '/' || iconname[0] == '~') { + pixbuf = get_pixbuf_from_file(iconname); + } + + /* search in icon_path */ + if (!pixbuf) { + char *start = settings.icon_path, + *end, *current_folder, *maybe_icon_path; + do { + end = strchr(start, ':'); + if (!end) end = strchr(settings.icon_path, '\0'); /* end = end of string */ + + current_folder = g_strndup(start, end - start); + + for (const char **suf = suffixes; *suf; suf++) { + maybe_icon_path = g_strconcat(current_folder, "/", iconname, *suf, NULL); pixbuf = get_pixbuf_from_file(maybe_icon_path); g_free(maybe_icon_path); - if (pixbuf != NULL) { - return pixbuf; - } - start = end + 1; - } while (*(end) != '\0'); - } - if (pixbuf == NULL) { - LOG_W("Could not load icon: '%s'", icon_path); - } - if (uri_path != NULL) { - g_free(uri_path); - } + if (pixbuf) + break; + } + + g_free(current_folder); + if (pixbuf) + break; + + start = end + 1; + } while (*(end) != '\0'); } + if (!pixbuf) + LOG_W("Could not load icon: '%s'", iconname); + + g_free(uri_path); return pixbuf; } diff --git a/src/icon.h b/src/icon.h index 838a0dc..dcd6f3d 100644 --- a/src/icon.h +++ b/src/icon.h @@ -7,7 +7,19 @@ #include "notification.h" cairo_surface_t *gdk_pixbuf_to_cairo_surface(GdkPixbuf *pixbuf); -GdkPixbuf *get_pixbuf_from_path(char *icon_path); + +/** Retrieve an icon by its name sent via the notification bus + * + * @param iconname A string describing a `file://` URL, an arbitary filename + * or an icon name, which then gets searched for in the + * settings.icon_path + * + * @return an instance of `GdkPixbuf` or `NULL` if not found + */ +GdkPixbuf *get_pixbuf_from_icon(const char *iconname); + +/** Convert a RawImage to a `GdkPixbuf` + */ GdkPixbuf *get_pixbuf_from_raw_image(const RawImage *raw_image); #endif diff --git a/test/icon.c b/test/icon.c index 56abb07..5695a82 100644 --- a/test/icon.c +++ b/test/icon.c @@ -14,18 +14,18 @@ #define IS_ICON_PNG(pb) 4 == gdk_pixbuf_get_width(pb) #define IS_ICON_SVG(pb) 16 == gdk_pixbuf_get_width(pb) -TEST test_get_pixbuf_from_path_invalid(void) +TEST test_get_pixbuf_from_icon_invalid(void) { - GdkPixbuf *pixbuf = get_pixbuf_from_path("invalid"); + GdkPixbuf *pixbuf = get_pixbuf_from_icon("invalid"); ASSERT(pixbuf == NULL); g_clear_pointer(&pixbuf, g_object_unref); PASS(); } -TEST test_get_pixbuf_from_path_both(void) +TEST test_get_pixbuf_from_icon_both(void) { - GdkPixbuf *pixbuf = get_pixbuf_from_path("icon1"); + GdkPixbuf *pixbuf = get_pixbuf_from_icon("icon1"); ASSERT(pixbuf); ASSERTm("SVG pixbuf hasn't precedence", IS_ICON_SVG(pixbuf)); g_clear_pointer(&pixbuf, g_object_unref); @@ -33,9 +33,9 @@ TEST test_get_pixbuf_from_path_both(void) PASS(); } -TEST test_get_pixbuf_from_path_onlysvg(void) +TEST test_get_pixbuf_from_icon_onlysvg(void) { - GdkPixbuf *pixbuf = get_pixbuf_from_path("onlysvg"); + GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlysvg"); ASSERT(pixbuf); ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf)); g_clear_pointer(&pixbuf, g_object_unref); @@ -43,9 +43,9 @@ TEST test_get_pixbuf_from_path_onlysvg(void) PASS(); } -TEST test_get_pixbuf_from_path_onlypng(void) +TEST test_get_pixbuf_from_icon_onlypng(void) { - GdkPixbuf *pixbuf = get_pixbuf_from_path("onlypng"); + GdkPixbuf *pixbuf = get_pixbuf_from_icon("onlypng"); ASSERT(pixbuf); ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf)); g_clear_pointer(&pixbuf, g_object_unref); @@ -53,10 +53,10 @@ TEST test_get_pixbuf_from_path_onlypng(void) PASS(); } -TEST test_get_pixbuf_from_path_filename(void) +TEST test_get_pixbuf_from_icon_filename(void) { char *icon = string_append(g_get_current_dir(), "/data/icons/valid.png", NULL); - GdkPixbuf *pixbuf = get_pixbuf_from_path(icon); + GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon); ASSERT(pixbuf); ASSERTm("PNG pixbuf isn't loaded", IS_ICON_PNG(pixbuf)); g_clear_pointer(&pixbuf, g_object_unref); @@ -65,11 +65,11 @@ TEST test_get_pixbuf_from_path_filename(void) PASS(); } -TEST test_get_pixbuf_from_path_fileuri(void) +TEST test_get_pixbuf_from_icon_fileuri(void) { char *curdir = g_get_current_dir(); char *icon = g_strconcat("file://", curdir,"/data/icons/valid.svg", NULL); - GdkPixbuf *pixbuf = get_pixbuf_from_path(icon); + GdkPixbuf *pixbuf = get_pixbuf_from_icon(icon); ASSERT(pixbuf); ASSERTm("SVG pixbuf isn't loaded", IS_ICON_SVG(pixbuf)); g_clear_pointer(&pixbuf, g_object_unref); @@ -86,12 +86,12 @@ SUITE(suite_icon) ":" ICONPREFIX "/valid" ":" ICONPREFIX "/both"; - RUN_TEST(test_get_pixbuf_from_path_invalid); - RUN_TEST(test_get_pixbuf_from_path_both); - RUN_TEST(test_get_pixbuf_from_path_onlysvg); - RUN_TEST(test_get_pixbuf_from_path_onlypng); - RUN_TEST(test_get_pixbuf_from_path_filename); - RUN_TEST(test_get_pixbuf_from_path_fileuri); + RUN_TEST(test_get_pixbuf_from_icon_invalid); + RUN_TEST(test_get_pixbuf_from_icon_both); + RUN_TEST(test_get_pixbuf_from_icon_onlysvg); + RUN_TEST(test_get_pixbuf_from_icon_onlypng); + RUN_TEST(test_get_pixbuf_from_icon_filename); + RUN_TEST(test_get_pixbuf_from_icon_fileuri); settings.icon_path = NULL; }