From fe7b02b10c872ce7cc9d32a292dcade56742a466 Mon Sep 17 00:00:00 2001 From: scorpion-26 Date: Tue, 25 Jul 2023 01:45:26 +0200 Subject: [PATCH] SNI: Honor XDG_DATA_DIRS as icon directory Also don't crash in Utils::FindFileWithName when directory doesn't exist Potential fix for https://github.com/scorpion-26/gBar/issues/25 --- src/Common.h | 20 ++++++++++++++++++++ src/SNI.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/Common.h b/src/Common.h index 5c52237..8bd4fcd 100644 --- a/src/Common.h +++ b/src/Common.h @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "Log.h" @@ -84,8 +85,27 @@ namespace Utils return buf; } + static std::vector Split(const std::string& str, char delim) + { + std::stringstream strstr(str); + std::string curElem; + std::vector result; + while (std::getline(strstr, curElem, delim)) + { + if (!curElem.empty()) + { + result.emplace_back(curElem); + } + } + return result; + } + inline std::string FindFileWithName(const std::string& directory, const std::string& name, const std::string& extension) { + if (!std::filesystem::exists(directory)) + { + return ""; + } for (auto& path : std::filesystem::recursive_directory_iterator(directory)) { if (path.is_directory()) diff --git a/src/SNI.cpp b/src/SNI.cpp index 96f4499..2c91225 100644 --- a/src/SNI.cpp +++ b/src/SNI.cpp @@ -15,6 +15,7 @@ #include #include +#include namespace SNI { @@ -122,6 +123,35 @@ namespace SNI } else { + auto findIconWithoutPath = [](const char* iconName) -> std::string + { + std::string iconPath; + const char* dataDirs = getenv("XDG_DATA_DIRS"); + // Nothing defined, look in $XDG_DATA_DIRS/icons + // network-manager-applet does this e.g. + if (dataDirs) + { + for (auto& dataDir : Utils::Split(dataDirs, ':')) + { + LOG("SNI: Searching icon " << iconName << " in " << dataDir << "/icons"); + std::string path = Utils::FindFileWithName(dataDir + "/icons", iconName, ".png"); + if (path != "") + { + iconPath = path; + break; + } + } + } + if (iconPath == "") + { + // Fallback to /usr/share/icons + LOG("SNI: Searching icon " << iconName << " in " + << "/usr/share/icons"); + iconPath = Utils::FindFileWithName("/usr/share/icons", iconName, ".png"); + } + return iconPath; + }; + // Get icon theme path GVariant* themePathVariant = getProperty("IconThemePath"); // Not defined by freedesktop, I think ayatana does this... GVariant* iconNameVariant = getProperty("IconName"); @@ -139,9 +169,7 @@ namespace SNI const char* iconName = g_variant_get_string(iconNameStr, nullptr); if (strlen(themePath) == 0) { - // Nothing defined, look in /usr/share/icons - // network-manager-applet does this - iconPath = Utils::FindFileWithName("/usr/share/icons", iconName, ".png"); + iconPath = findIconWithoutPath(iconName); } else { @@ -159,7 +187,12 @@ namespace SNI g_variant_get(iconNameVariant, "(v)", &iconNameStr); const char* iconName = g_variant_get_string(iconNameStr, nullptr); - iconPath = std::string(iconName); + iconPath = findIconWithoutPath(iconName); + if (iconPath == "") + { + // Try our luck with just using iconName, maybe its just an absolute path + iconPath = iconName; + } g_variant_unref(iconNameVariant); g_variant_unref(iconNameStr); @@ -170,6 +203,12 @@ namespace SNI return item; } + if (iconPath == "") + { + LOG("SNI: Cannot find icon path for " << name); + return item; + } + int width, height, channels; stbi_uc* pixels = stbi_load(iconPath.c_str(), &width, &height, &channels, STBI_rgb_alpha); if (!pixels)