From 728ec54dc50eb6c50f0bfae141817119f2f5f2bc Mon Sep 17 00:00:00 2001 From: Jason Beetham Date: Sun, 28 Dec 2025 23:47:34 -0700 Subject: [PATCH 1/2] Unix now uses XDG paths to find icons, making it easier to provide images. Defaulting to hicolor for icons --- .gitignore | 1 + src/image.c | 44 +++++++++++++++++++++++++++++++++++++++++++- src/image.h | 3 +++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c94817c..487fbaf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ docs/Gemfile.lock docs/_site docs/.jekyll-cache +build/ diff --git a/src/image.c b/src/image.c index df4a7c8..a06a686 100644 --- a/src/image.c +++ b/src/image.c @@ -11,6 +11,7 @@ #include "util.h" #include "debug.h" #include +#include #define NANOSVG_IMPLEMENTATION #include #define NANOSVGRAST_IMPLEMENTATION @@ -106,6 +107,42 @@ int load_next_slideshow_background_async(void *data) return 0; } +#ifdef __unix__ +SDL_Surface *load_surface_from_xdg(const char *path){ + // TODO: allow the user to specify a specific theme in the config.ini + // then prefer that to `hicolor`. + // Spec for this is here: https://specifications.freedesktop.org/icon-theme/latest/#icon_lookup + SDL_Surface *surface = NULL; + const char* xdg_dirs = getenv("XDG_DATA_DIRS"); + const char* icon_path = "/icons/hicolor/scalable/apps/"; + if(xdg_dirs != NULL){ + ssize_t last_delim = -1; + ssize_t dirs_len = strlen(xdg_dirs); + while(surface == NULL && last_delim < dirs_len){ + char xdg_path[4096] = {0}; + ssize_t start_ind = last_delim; + if(start_ind < 0) + start_ind = 0; + + ssize_t end = strcspn(&xdg_dirs[start_ind], ":"); + memcpy(&xdg_path, &xdg_dirs[start_ind], end); + memcpy(&xdg_path[end], icon_path, strlen(icon_path)); + memcpy(&xdg_path[end + strlen(icon_path)], path, strlen(path)); + surface = IMG_Load(xdg_path); + if (surface == NULL) { + log_error( + "Could not load image from xdg %s\n%s", + xdg_path, + IMG_GetError() + ); + } + last_delim += end + 1; + } + } + return surface; +} +#endif + // A function to load a texture from a file SDL_Texture *load_texture_from_file(const char *path) { @@ -119,8 +156,13 @@ SDL_Texture *load_texture_from_file(const char *path) path, IMG_GetError() ); +#ifdef __unix__ + // we failed to find the image normally, lets try xdg on unix + surface = load_surface_from_xdg(path); +#endif } - else + + if(surface != NULL) texture = load_texture(surface); } return texture; diff --git a/src/image.h b/src/image.h index b32d612..065719a 100644 --- a/src/image.h +++ b/src/image.h @@ -28,6 +28,9 @@ void render_scroll_indicators(Scroll *scroll, int height, Geometry *geo); SDL_Surface *load_next_slideshow_background(Slideshow *slideshow, bool transition); int load_next_slideshow_background_async(void *data); SDL_Texture *load_texture(SDL_Surface *surface); +#ifdef __unix__ +SDL_Surface *load_surface_from_xdg(const char *path); +#endif SDL_Texture *load_texture_from_file(const char *path); SDL_Texture *rasterize_svg(char *buffer, int w, int h, SDL_Rect *rect); SDL_Texture *rasterize_svg_from_file(const char *path, int w, int h, SDL_Rect *rect); From 140057e753640a17a6d46faad652ea2f48a568f8 Mon Sep 17 00:00:00 2001 From: Jason Beetham Date: Mon, 29 Dec 2025 23:11:01 -0700 Subject: [PATCH 2/2] Support more image types from xdg data directories --- src/image.c | 59 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/src/image.c b/src/image.c index a06a686..88987c6 100644 --- a/src/image.c +++ b/src/image.c @@ -114,32 +114,45 @@ SDL_Surface *load_surface_from_xdg(const char *path){ // Spec for this is here: https://specifications.freedesktop.org/icon-theme/latest/#icon_lookup SDL_Surface *surface = NULL; const char* xdg_dirs = getenv("XDG_DATA_DIRS"); - const char* icon_path = "/icons/hicolor/scalable/apps/"; - if(xdg_dirs != NULL){ - ssize_t last_delim = -1; - ssize_t dirs_len = strlen(xdg_dirs); - while(surface == NULL && last_delim < dirs_len){ - char xdg_path[4096] = {0}; - ssize_t start_ind = last_delim; - if(start_ind < 0) - start_ind = 0; - - ssize_t end = strcspn(&xdg_dirs[start_ind], ":"); - memcpy(&xdg_path, &xdg_dirs[start_ind], end); - memcpy(&xdg_path[end], icon_path, strlen(icon_path)); - memcpy(&xdg_path[end + strlen(icon_path)], path, strlen(path)); - surface = IMG_Load(xdg_path); - if (surface == NULL) { - log_error( - "Could not load image from xdg %s\n%s", - xdg_path, - IMG_GetError() - ); + const char* sizes[] = { + "scalable", + "512x512", + "256x256", + "128x128", + "64x64", + "32x32" + }; + + for(int i = 0; i < sizeof(sizes) / sizeof(void*); i++){ + char icon_path[128] = {}; + snprintf(icon_path, 127, "/icons/hicolor/%s/apps/", sizes[i]); + + if(xdg_dirs != NULL){ + ssize_t last_delim = -1; + ssize_t dirs_len = strlen(xdg_dirs); + while(surface == NULL && last_delim < dirs_len){ + char xdg_path[4096] = {0}; + ssize_t start_ind = last_delim; + if(start_ind < 0) + start_ind = 0; + + ssize_t end = strcspn(&xdg_dirs[start_ind], ":"); + memcpy(&xdg_path, &xdg_dirs[start_ind], end); + memcpy(&xdg_path[end], icon_path, strlen(icon_path)); + memcpy(&xdg_path[end + strlen(icon_path)], path, strlen(path)); + surface = IMG_Load(xdg_path); + if (surface != NULL) + return surface; + + last_delim += end + 1; } - last_delim += end + 1; } } - return surface; + + log_error( + "Could not load %s from XDG_DATA_DIRS", + path + ); } #endif