Skip to content

Commit

Permalink
query: theme: improve query + add makefile USE_GLIB
Browse files Browse the repository at this point in the history
  • Loading branch information
Toni500github committed Sep 15, 2024
1 parent 0f9f888 commit c17a248
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 102 deletions.
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
10 changes: 4 additions & 6 deletions include/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
"$<builtin.title>",
"$<builtin.title_sep>",
Expand Down Expand Up @@ -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
Expand Down
226 changes: 130 additions & 96 deletions src/query/unix/theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,55 @@
#include "switch_fnv1a.hpp"
#include "util.hpp"

#if USE_GLIB
# include <dconf/client/dconf-client.h>
# include <glib/gvariant.h>
#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<char>(f)), std::istreambuf_iterator<char>());
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
Expand Down Expand Up @@ -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<char>(f)), std::istreambuf_iterator<char>());
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;
Expand Down Expand Up @@ -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__);

Expand All @@ -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.");
Expand Down Expand Up @@ -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;
Expand All @@ -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<char>(f)), std::istreambuf_iterator<char>());
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)
{
Expand All @@ -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<std::string>& 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)
Expand Down Expand Up @@ -409,7 +443,7 @@ Theme::Theme(const std::uint8_t ver, systemInfo_t& queried_themes, std::vector<s
}

// only use it for cursor
Theme::Theme(systemInfo_t& queried_themes, const Config &config) : m_queried_themes(queried_themes), m_Config(config)
Theme::Theme(systemInfo_t& queried_themes, const Config& config) : m_queried_themes(queried_themes), m_Config(config)
{
static bool done = false;
if (hasStart(query_user.term_name(), "/dev") || done)
Expand Down

0 comments on commit c17a248

Please sign in to comment.