diff --git a/Makefile b/Makefile index 0b15cdb..e3e3485 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,8 @@ DEBUG ?= 1 GUI_MODE ?= 0 VENDOR_TEST ?= 0 DEVICE_TEST ?= 0 + +USE_GLIB ?= 1 # https://stackoverflow.com/a/1079861 # WAY easier way to build debug and release builds ifeq ($(DEBUG), 1) @@ -48,6 +50,14 @@ LDFLAGS += -L./$(BUILDDIR)/fmt -lfmt -ldl CXXFLAGS ?= -mtune=generic -march=native CXXFLAGS += -fvisibility=hidden -Iinclude -std=c++20 $(VARS) -DVERSION=\"$(VERSION)\" -DBRANCH=\"$(BRANCH)\" +ifeq ($(USE_GLIB), 1) + ifeq ($(shell pkg-config --exists glib-2.0 && echo 1 || echo 0), 1) + CXXFLAGS += -DUSE_GLIB=1 `pkg-config --cflags glib-2.0` + else + CXXFLAGS += -DUSE_GLIB=0 + endif +endif + all: fmt toml $(TARGET) fmt: diff --git a/include/config.hpp b/include/config.hpp index 203258a..9600d64 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -152,12 +152,6 @@ inline constexpr std::string_view AUTOCONFIG = R"#([config] # # Read the manual cufetch.1 for more infos with $() tag -# cufetch behavioural settings - -# Warn against tradeoffs between slower queries for availability -# e.g. falling back to gsettings when we can't find the config file for GTK -slow-query-warnings = true - layout = [ "$", "$", @@ -213,6 +207,10 @@ sep-reset = ":" # false = before ("test ${0}-> ") sep-reset-after = false +# Warn against tradeoffs between slower queries for availability +# e.g. falling back to gsettings when we can't find the config file for GTK +slow-query-warnings = true + # Offset between the ascii art and the layout offset = 5 diff --git a/src/query/unix/theme.cpp b/src/query/unix/theme.cpp index e277f14..66c82f8 100644 --- a/src/query/unix/theme.cpp +++ b/src/query/unix/theme.cpp @@ -8,11 +8,55 @@ #include "switch_fnv1a.hpp" #include "util.hpp" +#if USE_GLIB +# include +# include +#endif + using namespace Query; const std::string& configDir = getHomeConfigDir(); +static bool get_xsettings_xfce4(const std::string_view property, const std::string_view subproperty, std::string& ret) +{ + static bool done = false; + static rapidxml::xml_document<> doc; + + if (!done) + { + const std::string& path = configDir + "/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml"; + std::ifstream f(path, std::ios::in); + if (!f.is_open()) + return false; + + std::string buffer((std::istreambuf_iterator(f)), std::istreambuf_iterator()); + buffer.push_back('\0'); + + doc.parse<0>(&buffer[0]); + done = true; + } + + rapidxml::xml_node<>* node1 = doc.first_node("channel")->first_node("property"); + for (; node1 && std::string_view(node1->first_attribute("name")->value()) != property; node1 = node1->next_sibling("property")); + + rapidxml::xml_node<>* node2 = node1->first_node("property"); + for (; node2; node2 = node2->next_sibling()) + { + if (std::string_view(node2->first_attribute("name")->value()) == subproperty && + node2->first_attribute("value")) + { + ret = node2->first_attribute("value")->value(); + return true; + } + } + + return false; +} + +// +// // 1. Cursor +// static bool assert_cursor(Theme::Theme_t& theme) { return @@ -138,43 +182,14 @@ static bool get_de_cursor(const std::string_view de_name, Theme::Theme_t& theme) { case "xfce"_fnv1a16: case "xfce4"_fnv1a16: - { - debug("calling {} and getting info on xfce4", __PRETTY_FUNCTION__); - const std::string& path = configDir + "/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml"; - std::ifstream f(path, std::ios::in); - if (!f.is_open()) - return true; - - std::string buffer((std::istreambuf_iterator(f)), std::istreambuf_iterator()); - buffer.push_back('\0'); - - rapidxml::xml_document<> doc; - doc.parse<0>(&buffer[0]); - rapidxml::xml_node<>* net_node = doc.first_node("channel")->first_node("property"); - for (; net_node && std::string(net_node->first_attribute("name")->value()) != "Gtk"; net_node = net_node->next_sibling("property")); - - unsigned short iter_index = 0; - rapidxml::xml_node<>* theme_node = net_node->first_node("property"); - for (; theme_node && iter_index < 2; theme_node = theme_node->next_sibling()) - { - if (std::string(theme_node->first_attribute("name")->value()) == "CursorThemeName" && - theme_node->first_attribute("value")) - { - theme.cursor = theme_node->first_attribute("value")->value(); - iter_index++; - } - else if (std::string(theme_node->first_attribute("name")->value()) == "CursorThemeSize" && - theme_node->first_attribute("value")) - { - theme.cursor_size = theme_node->first_attribute("value")->value(); - iter_index++; - } - } - - if (!assert_cursor(theme)) - return false; - } - break; + { + debug("calling {} and getting info on xfce4", __PRETTY_FUNCTION__); + get_xsettings_xfce4("Gtk", "CursorThemeName", theme.cursor); + get_xsettings_xfce4("Gtk", "CursorThemeSize", theme.cursor_size); + + if (!assert_cursor(theme)) + return false; + } break; default: return false; @@ -215,7 +230,60 @@ static bool get_gtk_theme_config(const std::string_view path, Theme::Theme_t& th return true; } -static void get_gtk_theme_settings(const std::string_view de_name, Theme::Theme_t& theme, const Config &config) +static bool get_gtk_theme_dconf(const std::string_view de_name, Theme::Theme_t& theme) +{ +#if USE_GLIB + + LOAD_LIBRARY("libdconf.so", return false); + LOAD_LIB_SYMBOL(DConfClient *, dconf_client_new, void); + LOAD_LIB_SYMBOL(GVariant *, dconf_client_read, DConfClient *client, const char *); + LOAD_LIB_SYMBOL(const gchar *, g_variant_get_string, GVariant *value, gsize *lenght); + + debug("calling {}", __PRETTY_FUNCTION__); + DConfClient *client = dconf_client_new(); + GVariant *variant; + + std::string interface; + switch(fnv1a16::hash(str_tolower(de_name.data()))) + { + case "cinnamon"_fnv1a16: interface = "/org/cinnamon/desktop/interface/"; break; + case "mate"_fnv1a16: interface = "/org/mate/interface/"; break; + + case "gnome"_fnv1a16: + case "budgie"_fnv1a16: + case "unity"_fnv1a16: + default: + interface = "/org/gnome/desktop/interface/"; + } + + if (theme.gtk_theme_name == MAGIC_LINE || theme.gtk_theme_name.empty()) + { + variant = dconf_client_read(client, (interface + "gtk-theme").c_str()); + theme.gtk_theme_name = g_variant_get_string(variant, NULL); + } + + if (theme.gtk_icon_theme == MAGIC_LINE || theme.gtk_icon_theme.empty()) + { + variant = dconf_client_read(client, (interface + "icon-theme").c_str()); + theme.gtk_icon_theme = g_variant_get_string(variant, NULL); + } + + if (theme.gtk_font == MAGIC_LINE || theme.gtk_font.empty()) + { + variant = dconf_client_read(client, (interface + "font-name").c_str()); + theme.gtk_font = g_variant_get_string(variant, NULL); + } + + return theme.gtk_font != MAGIC_LINE && + theme.gtk_icon_theme != MAGIC_LINE && + theme.gtk_theme_name != MAGIC_LINE; + +#else + return false; +#endif +} + +static void get_gtk_theme_gsettings(const std::string_view de_name, Theme::Theme_t& theme, const Config& config) { debug("calling {}", __PRETTY_FUNCTION__); @@ -227,7 +295,11 @@ static void get_gtk_theme_settings(const std::string_view de_name, Theme::Theme_ theme.gtk_theme_name = gtk_theme_env; } - if (config.slow_query_warnings) { + if (get_gtk_theme_dconf(de_name, theme)) + return; + + if (config.slow_query_warnings) + { warn("cufetch could not detect a gtk configuration file. cufetch will use the much-slower gsettings."); warn("If there's a file in a standard location that we aren't detecting, please file an issue on our GitHub."); info("You can disable this warning by disabling slow-query-warnings in your config.toml file."); @@ -269,7 +341,7 @@ static void get_gtk_theme_settings(const std::string_view de_name, Theme::Theme_ theme.gtk_font.erase(std::remove(theme.gtk_font.begin(), theme.gtk_font.end(), '\''), theme.gtk_font.end()); } -static void get_gtk_theme_from_configs(const std::uint8_t ver, const std::string_view de_name, Theme::Theme_t& theme, const Config &config) +static void get_gtk_theme_from_configs(const std::uint8_t ver, const std::string_view de_name, Theme::Theme_t& theme, const Config& config) { if (get_gtk_theme_config(fmt::format("{}/gtk-{}.0/settings.ini", configDir, ver), theme)) return; @@ -289,73 +361,35 @@ static void get_gtk_theme_from_configs(const std::uint8_t ver, const std::string if (get_gtk_theme_config(fmt::format("{}/.gtkrc-{}.0-kde4", std::getenv("HOME"), ver), theme)) return; - get_gtk_theme_settings(de_name, theme, config); + get_gtk_theme_gsettings(de_name, theme, config); } -static void get_de_gtk_theme(const std::string_view de_name, const std::uint8_t ver, Theme::Theme_t& theme, const Config &config) +static void get_de_gtk_theme(const std::string_view de_name, const std::uint8_t ver, Theme::Theme_t& theme, const Config& config) { switch (fnv1a16::hash(str_tolower(de_name.data()))) { case "xfce"_fnv1a16: case "xfce4"_fnv1a16: - { - debug("calling {} and getting info on xfce4", __PRETTY_FUNCTION__); - const std::string& path = configDir + "/xfce4/xfconf/xfce-perchannel-xml/xsettings.xml"; - std::ifstream f(path, std::ios::in); - if (!f.is_open()) - { - get_gtk_theme_from_configs(ver, de_name, theme, config); - return; - } - - std::string buffer((std::istreambuf_iterator(f)), std::istreambuf_iterator()); - buffer.push_back('\0'); - - rapidxml::xml_document<> doc; - doc.parse<0>(&buffer[0]); - rapidxml::xml_node<>* net_node = doc.first_node("channel")->first_node("property"); - for (; net_node && std::string(net_node->first_attribute("name")->value()) != "Net"; net_node = net_node->next_sibling("property")); - - rapidxml::xml_node<>* theme_node = net_node->first_node("property"); - unsigned short iter_index = 0; - for (; theme_node && iter_index < 2; theme_node = theme_node->next_sibling()) - { - if (std::string(theme_node->first_attribute("name")->value()) == "ThemeName" && - theme_node->first_attribute("value")) - { - theme.gtk_theme_name = theme_node->first_attribute("value")->value(); - iter_index++; - } - else if (std::string(theme_node->first_attribute("name")->value()) == "IconThemeName" && - theme_node->first_attribute("value")) - { - theme.gtk_icon_theme = theme_node->first_attribute("value")->value(); - iter_index++; - } - } - - for (; net_node && std::string(net_node->first_attribute("name")->value()) != "Gtk"; net_node = net_node->next_sibling("property")); - theme_node = net_node->first_node("property"); - - for (; theme_node; theme_node = theme_node->next_sibling()) - { - if (std::string(theme_node->first_attribute("name")->value()) == "FontName" && - theme_node->first_attribute("value")) - { - theme.gtk_font = theme_node->first_attribute("value")->value(); - break; - } - } - - } - break; + { + debug("calling {} and getting info on xfce4", __PRETTY_FUNCTION__); + get_xsettings_xfce4("Net", "ThemeName", theme.gtk_theme_name); + get_xsettings_xfce4("Net", "IconThemeName", theme.gtk_icon_theme); + get_xsettings_xfce4("Gtk", "FontName", theme.gtk_font); + + if (theme.gtk_font == MAGIC_LINE || + theme.gtk_icon_theme == MAGIC_LINE || + theme.gtk_theme_name == MAGIC_LINE) + get_gtk_theme_from_configs(ver, de_name, theme, config); + + } break; + default: get_gtk_theme_from_configs(ver, de_name, theme, config); } } static void get_gtk_theme(const bool dont_query_dewm, const std::uint8_t ver, const std::string_view de_name, - Theme::Theme_t& theme, const Config &config) + Theme::Theme_t& theme, const Config& config) { if (dont_query_dewm) { @@ -368,7 +402,7 @@ static void get_gtk_theme(const bool dont_query_dewm, const std::uint8_t ver, co // clang-format off Theme::Theme(const std::uint8_t ver, systemInfo_t& queried_themes, std::vector& queried_themes_names, - const std::string& theme_name_version, const Config &config) + const std::string& theme_name_version, const Config& config) : m_queried_themes(queried_themes), m_theme_name_version(theme_name_version), m_Config(config) @@ -409,7 +443,7 @@ Theme::Theme(const std::uint8_t ver, systemInfo_t& queried_themes, std::vector