From 35504b33b19d785498ffa16b1b744d7ca88bf2db Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 2 May 2021 18:52:42 +0200 Subject: [PATCH] ffGSettingsGetValue --- CMakeLists.txt | 20 +++-- README.md | 3 +- src/common/dconf.c | 86 ------------------ src/common/detectGTK.c | 6 +- src/common/gsettings.c | 196 +++++++++++++++++++++++++++++++++++++++++ src/common/init.c | 1 + src/fastfetch.c | 3 + src/fastfetch.h | 5 +- src/modules/wmtheme.c | 31 ++----- 9 files changed, 229 insertions(+), 122 deletions(-) delete mode 100644 src/common/dconf.c create mode 100644 src/common/gsettings.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 4914422a0..8ad0e2fb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,20 +34,28 @@ find_package(Threads REQUIRED) find_package (PkgConfig) if(${PkgConfig_FOUND}) - pkg_check_modules (GLIB2 glib-2.0) + pkg_check_modules (GIO2 gio-2.0) + pkg_check_modules (DCONF dconf) endif(${PkgConfig_FOUND}) -if(NOT DEFINED GLIB2_INCLUDE_DIRS) - set(GLIB2_INCLUDE_DIRS +if(NOT DEFINED GIO2_INCLUDE_DIRS) + set(GIO2_INCLUDE_DIRS /usr/include/glib-2.0/ /usr/lib/glib-2.0/include/ ) -endif(NOT DEFINED GLIB2_INCLUDE_DIRS) +endif(NOT DEFINED GIO2_INCLUDE_DIRS) + +if(NOT DEFINED DCONF_INCLUDE_DIRS) + set(DCONF_INCLUDE_DIRS + /usr/include/dconf/ + ) +endif(NOT DEFINED DCONF_INCLUDE_DIRS) include_directories( ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/src - ${GLIB2_INCLUDE_DIRS} + ${GIO2_INCLUDE_DIRS} + ${DCONF_INCLUDE_DIRS} ) link_libraries( @@ -65,7 +73,7 @@ set(SRCS src/common/logo.c src/common/format.c src/common/parsing.c - src/common/dconf.c + src/common/gsettings.c src/common/detectPlasma.c src/common/detectGTK.c src/common/detectWMDE.c diff --git a/README.md b/README.md index d5bd44490..61c6b8786 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ The following libraries are used if present: * [`libpci`](https://github.com/pciutils/pciutils): Needed for GPU output. _Should_ be available on every linux system. * [`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): Needed for resolution output * [`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr): Needed for appending refresh rate to resolution output. -* [`libDConf`](https://developer.gnome.org/dconf/unstable/DConfClient.html): GTK theme/font/icons output on DEs which dont use config files (e.g. Gnome). +* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored in gsettings / dconf. +* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Fallback for libGIO. Usually not needed if libGIO was loaded sucessfully. * [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance + support for monitors with different refresh rates in wayland sessions. ## Support status diff --git a/src/common/dconf.c b/src/common/dconf.c deleted file mode 100644 index 98b6c3d67..000000000 --- a/src/common/dconf.c +++ /dev/null @@ -1,86 +0,0 @@ -#include "fastfetch.h" - -#include -#include -#include - -typedef struct DConfData -{ - void* library; - DConfClient*(*ffdconf_client_new)(void); - GVariant*(*ffdconf_client_read_full)(DConfClient*, const gchar*, DConfReadFlags, const GQueue*); - const gchar*(*ffg_variant_get_string)(GVariant*, gsize*); - DConfClient* dconfClient; -} DConfData; - -static inline const char* getDConfValue(DConfData* dconf, const char* key) -{ - if(dconf->dconfClient == NULL) - return NULL; - - GVariant* variant = dconf->ffdconf_client_read_full(dconf->dconfClient, key, DCONF_READ_USER_VALUE, NULL); - - if(variant == NULL) - variant = dconf->ffdconf_client_read_full(dconf->dconfClient, key, DCONF_READ_DEFAULT_VALUE, NULL); - - if(variant != NULL) - return dconf->ffg_variant_get_string(variant, NULL); - - return NULL; -} - -const char* ffDConfGetValue(FFinstance* instance, const char* key) -{ - static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - static bool init = false; - - static DConfData dconf; - - pthread_mutex_lock(&mutex); - - if(init) - { - pthread_mutex_unlock(&mutex); - return getDConfValue(&dconf, key); - } - - init = true; - - dconf.dconfClient = NULL; //error indicator - - if(instance->config.libDConf.length == 0) - dconf.library = dlopen("libdconf.so", RTLD_LAZY); - else - dconf.library = dlopen(instance->config.libDConf.chars, RTLD_LAZY); - - if(dconf.library == NULL) - { - pthread_mutex_unlock(&mutex); - return NULL; - } - - dconf.ffdconf_client_new = dlsym(dconf.library, "dconf_client_new"); - dconf.ffdconf_client_read_full = dlsym(dconf.library, "dconf_client_read_full"); - dconf.ffg_variant_get_string = dlsym(dconf.library, "g_variant_get_string"); - - if( - dconf.ffdconf_client_new == NULL || - dconf.ffdconf_client_read_full == NULL || - dconf.ffg_variant_get_string == NULL - ) { - pthread_mutex_unlock(&mutex); - dlclose(dconf.library); - return NULL; - } - - dconf.dconfClient = dconf.ffdconf_client_new(); - if(dconf.dconfClient == NULL) - { - pthread_mutex_unlock(&mutex); - dlclose(dconf.library); - return NULL; - } - - pthread_mutex_unlock(&mutex); - return getDConfValue(&dconf, key); -} diff --git a/src/common/detectGTK.c b/src/common/detectGTK.c index 9cada673d..d843dff8d 100644 --- a/src/common/detectGTK.c +++ b/src/common/detectGTK.c @@ -51,9 +51,9 @@ static void parseGTKDConfSettings(FFinstance* instance, FFGTKResult* result) init = true; - themeName = ffDConfGetValue(instance, "/org/gnome/desktop/interface/gtk-theme"); - iconsName = ffDConfGetValue(instance, "/org/gnome/desktop/interface/font-name"); - fontName = ffDConfGetValue(instance, "/org/gnome/desktop/interface/icon-theme"); + themeName = ffGSettingsGetValue(instance, "org.gnome.desktop.interface", "gtk-theme"); + iconsName = ffGSettingsGetValue(instance, "org.gnome.desktop.interface", "icon-theme"); + fontName = ffGSettingsGetValue(instance, "org.gnome.desktop.interface", "font-name"); pthread_mutex_unlock(&mutex); applyGTKDConfSettings(result, themeName, iconsName, fontName); diff --git a/src/common/gsettings.c b/src/common/gsettings.c new file mode 100644 index 000000000..2f5b6dca3 --- /dev/null +++ b/src/common/gsettings.c @@ -0,0 +1,196 @@ +#include "fastfetch.h" + +#include +#include +#include +#include + +typedef struct DConfData +{ + void* library; + GVariant*(*ffdconf_client_read_full)(DConfClient*, const gchar*, DConfReadFlags, const GQueue*); + const gchar*(*ffg_variant_get_string)(GVariant*, gsize*); + DConfClient* client; +} DConfData; + +typedef struct GSettingsData +{ + void* library; + GSettingsSchemaSource* schemaSource; + GSettingsSchema*(*ffg_settings_schema_source_lookup)(GSettingsSchemaSource*, const gchar*, gboolean); + gboolean(*ffg_settings_schema_has_key)(GSettingsSchema*, const gchar*); + GSettings*(*ffg_settings_new_full)(GSettingsSchema*, GSettingsBackend*, const gchar*); + GVariant*(*ffg_settings_get_value)(GSettings*, const gchar*); + GVariant*(*ffg_settings_get_user_value)(GSettings*, const gchar*); + GVariant*(*ffg_settings_get_default_value)(GSettings*, const gchar*); + const gchar*(*ffg_variant_get_string)(GVariant*, gsize*); +} GSettingsData; + +static int transformGSettingsToDConf(int c) +{ + return c == '.' ? '/' : c; +} + +static const char* getDConfValue(DConfData* data, const char* schemaName, const char* key) +{ + if(data->client == NULL) + return NULL; + + FFstrbuf dconfStyleKey; + ffStrbufInitA(&dconfStyleKey, 64); + ffStrbufAppendC(&dconfStyleKey, '/'); + ffStrbufAppendTransformS(&dconfStyleKey, schemaName, transformGSettingsToDConf); + ffStrbufAppendC(&dconfStyleKey, '/'); + ffStrbufAppendS(&dconfStyleKey, key); + + GVariant* variant = data->ffdconf_client_read_full(data->client, dconfStyleKey.chars, DCONF_READ_FLAGS_NONE, NULL); + + if(variant == NULL) + variant = data->ffdconf_client_read_full(data->client, dconfStyleKey.chars, DCONF_READ_USER_VALUE, NULL); + + if(variant == NULL) + variant = data->ffdconf_client_read_full(data->client, dconfStyleKey.chars, DCONF_READ_DEFAULT_VALUE, NULL); + + ffStrbufDestroy(&dconfStyleKey); + + if(variant != NULL) + return data->ffg_variant_get_string(variant, NULL); + + return NULL; +} + +static const char* dconfGetValue(FFinstance* instance, const char* schemaName, const char* key) +{ + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static bool init = false; + + static DConfData data; + + pthread_mutex_lock(&mutex); + + if(init) + { + pthread_mutex_unlock(&mutex); + return getDConfValue(&data, schemaName, key); + } + + init = true; + + data.client = NULL; //error indicator + + data.library = dlopen(instance->config.libDConf.chars == NULL ? "libdconf.so" : instance->config.libDConf.chars, RTLD_LAZY); + if(data.library == NULL) + { + pthread_mutex_unlock(&mutex); + return NULL; + } + + data.ffdconf_client_read_full = dlsym(data.library, "dconf_client_read_full"); + data.ffg_variant_get_string = dlsym(data.library, "g_variant_get_string"); + + DConfClient*(*ffdconf_client_new)(void) = dlsym(data.library, "dconf_client_new"); + + if( + data.ffdconf_client_read_full == NULL || + data.ffg_variant_get_string == NULL || + (data.client = ffdconf_client_new()) == NULL + ) { + pthread_mutex_unlock(&mutex); + dlclose(data.library); + return NULL; + } + + pthread_mutex_unlock(&mutex); + return getDConfValue(&data, schemaName, key); +} + +static const char* getGSettingsValue(FFinstance* instance, GSettingsData* data, const char* schemaName, const char* key) +{ + if(data->schemaSource == NULL) + return dconfGetValue(instance, schemaName, key); + + GSettingsSchema* schema = data->ffg_settings_schema_source_lookup(data->schemaSource, schemaName, true); + if(schema == NULL) + return dconfGetValue(instance, schemaName, key); + + if(data->ffg_settings_schema_has_key(schema, key) == 0) + return dconfGetValue(instance, schemaName, key); + + GSettings* settings = data->ffg_settings_new_full(schema, NULL, NULL); + if(settings == NULL) + return dconfGetValue(instance, schemaName, key); + + GVariant* variant = data->ffg_settings_get_value(settings, key); + + if(variant == NULL) + variant = data->ffg_settings_get_user_value(settings, key); + + if(variant == NULL) + variant = data->ffg_settings_get_default_value(settings, key); + + if(variant == NULL) + return dconfGetValue(instance, schemaName, key); + + const char* value = data->ffg_variant_get_string(variant, NULL); + + if(value == NULL || *value == '\0') + return dconfGetValue(instance, schemaName, key); + + return value; +} + +const char* ffGSettingsGetValue(FFinstance* instance, const char* schemaName, const char* key) +{ + static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + static bool init = false; + + static GSettingsData data; + + pthread_mutex_lock(&mutex); + + if(init) + { + pthread_mutex_unlock(&mutex); + return getGSettingsValue(instance, &data, schemaName, key); + } + + init = true; + + data.schemaSource = NULL; //error indicator + + data.library = dlopen(instance->config.libGIO.length == 0 ? "libgio-2.0.so" : instance->config.libGIO.chars, RTLD_LAZY); + if(data.library == NULL) + { + pthread_mutex_unlock(&mutex); + return NULL; + } + + data.ffg_settings_schema_source_lookup = dlsym(data.library, "g_settings_schema_source_lookup"); + data.ffg_settings_schema_has_key = dlsym(data.library, "g_settings_schema_has_key"); + data.ffg_settings_new_full = dlsym(data.library, "g_settings_new_full"); + data.ffg_settings_get_value = dlsym(data.library, "g_settings_get_value"); + data.ffg_settings_get_user_value = dlsym(data.library, "g_settings_get_user_value"); + data.ffg_settings_get_default_value = dlsym(data.library, "g_settings_get_default_value"); + data.ffg_variant_get_string = dlsym(data.library, "g_variant_get_string"); + + GSettingsSchemaSource*(*ffg_settings_schema_source_get_default)(void) = dlsym(data.library, "g_settings_schema_source_get_default"); + + if( + data.ffg_settings_schema_source_lookup == NULL || + data.ffg_settings_schema_has_key == NULL || + data.ffg_settings_new_full == NULL || + data.ffg_settings_get_value == NULL || + data.ffg_settings_get_user_value == NULL || + data.ffg_settings_get_default_value == NULL || + data.ffg_variant_get_string == NULL || + ffg_settings_schema_source_get_default == NULL || + (data.schemaSource = ffg_settings_schema_source_get_default()) == NULL + ) { + pthread_mutex_unlock(&mutex); + dlclose(data.library); + return NULL; + } + + pthread_mutex_unlock(&mutex); + return getGSettingsValue(instance, &data, schemaName, key); +} diff --git a/src/common/init.c b/src/common/init.c index f154c866d..8c7d78f49 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -70,6 +70,7 @@ static void defaultConfig(FFconfig* config) ffStrbufInitA(&config->libPCI, 1); ffStrbufInitA(&config->libX11, 1); ffStrbufInitA(&config->libXrandr, 1); + ffStrbufInitA(&config->libGIO, 1); ffStrbufInitA(&config->libDConf, 1); ffStrbufInitA(&config->libWayland, 1); diff --git a/src/fastfetch.c b/src/fastfetch.c index 58163c7e0..bf057b6ca 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -113,6 +113,7 @@ static inline void printHelp() " --lib-PCI \n" " --lib-X11 \n" " --lib-Xrandr \n" + " --lib-gio \n" " --lib-DConf \n" " --lib-wayland \n" "\n" @@ -874,6 +875,8 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.libX11); else if(strcasecmp(key, "--lib-Xrandr") == 0) optionParseString(key, value, &instance->config.libXrandr); + else if(strcasecmp(key, "--lib-gio") == 0) + optionParseString(key, value, &instance->config.libGIO); else if(strcasecmp(key, "--lib-DConf") == 0) optionParseString(key, value, &instance->config.libDConf); else if(strcasecmp(key, "--lib-wayland") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index 55e99dc22..1e2a9d92d 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -94,6 +94,7 @@ typedef struct FFconfig FFstrbuf libX11; FFstrbuf libXrandr; FFstrbuf libWayland; + FFstrbuf libGIO; FFstrbuf libDConf; FFstrbuf diskFolders; @@ -247,8 +248,8 @@ void ffGetGtkPretty(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3 void ffGetFont(const char* font, FFstrbuf* name, double* size); void ffGetFontPretty(FFstrbuf* buffer, const FFstrbuf* name, double size); -//common/dconf.c -const char* ffDConfGetValue(FFinstance* instance, const char* key); +//common/gsettings.c +const char* ffGSettingsGetValue(FFinstance* instance, const char* schema, const char* key); //common/detectPlasma.c const FFPlasmaResult* ffDetectPlasma(FFinstance* instance); diff --git a/src/modules/wmtheme.c b/src/modules/wmtheme.c index bb76962ea..25c3e7eea 100644 --- a/src/modules/wmtheme.c +++ b/src/modules/wmtheme.c @@ -36,35 +36,18 @@ static void printKWin(FFinstance* instance) static void printMutter(FFinstance* instance) { - FFstrbuf theme; - ffStrbufInit(&theme); + char const* theme = ffGSettingsGetValue(instance, "org.gnome.shell.extensions.user-theme", "name"); - ffProcessAppendStdOut(&theme, (char* const[]) { - "gsettings", - "get", - "org.gnome.shell.extensions.user-theme", - "name", - NULL - }); + if(theme == NULL) + theme = ffGSettingsGetValue(instance, "org.gnome.desktop.wm.preferences", "theme"); - ffStrbufTrim(&theme, '\''); - - if(theme.length == 0) + if(theme == NULL) { - ffProcessAppendStdOut(&theme, (char* const[]) { - "gsettings", - "get", - "org.gnome.desktop.wm.preferences", - "theme", - NULL - }); + ffPrintError(instance, FF_WMTHEME_MODULE_NAME, 0, &instance->config.wmThemeKey, &instance->config.wmThemeFormat, FF_WMTHEME_NUM_FORMAT_ARGS, "Couldn't found mutter theme in GSettings / DConf"); + return; } - ffStrbufTrim(&theme, '\''); - - printWMTheme(instance, theme.chars); - - ffStrbufDestroy(&theme); + printWMTheme(instance, theme); } static void printOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName)