From 8cb3ff7c2bfffe8da4a7745ef0c7a5640aba39a1 Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 20 Jun 2021 21:04:55 +0200 Subject: [PATCH] Cursor support --- CMakeLists.txt | 1 + README.md | 5 -- completions/bash | 2 + src/common/detectGTK.c | 58 +++++++++++----------- src/common/detectWMDE.c | 24 ++++++---- src/common/init.c | 2 + src/common/io.c | 72 +++++++++++++++++++++++----- src/common/parsing.c | 24 ++++++++++ src/common/settings.c | 34 ++++++++----- src/fastfetch.c | 18 ++++++- src/fastfetch.h | 63 +++++++++++++++--------- src/flashfetch.c | 1 + src/modules/cursor.c | 104 ++++++++++++++++++++++++++++++++++++++++ 13 files changed, 319 insertions(+), 89 deletions(-) create mode 100644 src/modules/cursor.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e984ea3fc..f59d76886 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ set(SRCS src/modules/theme.c src/modules/icons.c src/modules/font.c + src/modules/cursor.c src/modules/terminal.c src/modules/terminalfont.c src/modules/cpu.c diff --git a/README.md b/README.md index 8d56dd88d..85eba8f54 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,6 @@ Arch, Artix, Debian, Fedora, Garuda, Gentoo, Manjaro, Mint, Pop!_OS, Ubuntu, Voi Pacman, dpkg, rpm, xbps, Flatpak, Snap ``` -##### Window managers -``` -KWin, Mutter, Muffin, Marco, XFWM, Openbox, Sway, Wayfire, Weston -``` - ##### WM themes ``` KWin, Mutter, Muffin, Marco, XFWM, Openbox (LXDE, LXQT & without DE) diff --git a/completions/bash b/completions/bash index 0b8988ad9..dcffc4489 100644 --- a/completions/bash +++ b/completions/bash @@ -159,6 +159,8 @@ __fastfetch_completion() "--icons-key" "--font-format" "--font-key" + "--cursor-format" + "--cursor-key" "--terminal-format" "--terminal-key" "--terminal-font-format" diff --git a/src/common/detectGTK.c b/src/common/detectGTK.c index deb83b1d7..f4c24841a 100644 --- a/src/common/detectGTK.c +++ b/src/common/detectGTK.c @@ -11,7 +11,7 @@ static inline bool allPropertiesSet(FFGTKResult* result) result->font.length > 0; } -static inline void applyGTKDConfSettings(FFGTKResult* result, const char* themeName, const char* iconsName, const char* fontName) +static inline void applyGTKDConfSettings(FFGTKResult* result, const char* themeName, const char* iconsName, const char* fontName, const char* cursorTheme, int cursorSize) { if(result->theme.length == 0) ffStrbufAppendS(&result->theme, themeName); @@ -21,6 +21,12 @@ static inline void applyGTKDConfSettings(FFGTKResult* result, const char* themeN if(result->font.length == 0) ffStrbufAppendS(&result->font, fontName); + + if(result->cursor.length == 0) + ffStrbufAppendS(&result->cursor, cursorTheme); + + if(result->cursorSize.length == 0 && cursorSize > 0) + ffStrbufAppendF(&result->cursorSize, "%i", cursorSize); } static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result) @@ -30,6 +36,8 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result) static const char* themeName = NULL; static const char* iconsName = NULL; static const char* fontName = NULL; + static const char* cursorTheme = NULL; + static int cursorSize = 0; static bool init = false; @@ -38,7 +46,7 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result) if(init) { pthread_mutex_unlock(&mutex); - applyGTKDConfSettings(result, themeName, iconsName, fontName); + applyGTKDConfSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize); return; } @@ -51,12 +59,16 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result) themeName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/gtk-theme", "org.cinnamon.desktop.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/icon-theme", "org.cinnamon.desktop.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; fontName = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/font-name", "org.cinnamon.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-theme", "org.cinnamon.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGet(instance, "/org/cinnamon/desktop/interface/cursor-size", "org.cinnamon.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue; } else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0) { themeName = ffSettingsGet(instance, "/org/mate/interface/gtk-theme", "org.mate.interface", NULL, "gtk-theme", FF_VARIANT_TYPE_STRING).strValue; iconsName = ffSettingsGet(instance, "/org/mate/interface/icon-theme", "org.mate.interface", NULL, "icon-theme", FF_VARIANT_TYPE_STRING).strValue; fontName = ffSettingsGet(instance, "/org/mate/interface/font-name", "org.mate.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue; + cursorTheme = ffSettingsGet(instance, "/org/mate/interface/cursor-theme", "org.mate.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + cursorSize = ffSettingsGet(instance, "/org/mate/interface/cursor-size", "org.mate.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue; } //Fallback + Gnome impl @@ -67,37 +79,25 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result) if(fontName == NULL) fontName = ffSettingsGet(instance, "/org/gnome/desktop/interface/font-name", "org.gnome.desktop.interface", NULL, "font-name", FF_VARIANT_TYPE_STRING).strValue; + if(cursorTheme == NULL) + cursorTheme = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-theme", "org.gnome.desktop.interface", NULL, "cursor-theme", FF_VARIANT_TYPE_STRING).strValue; + + if(cursorSize <= 0) + cursorSize = ffSettingsGet(instance, "/org/gnome/desktop/interface/cursor-size", "org.gnome.desktop.interface", NULL, "cursor-size", FF_VARIANT_TYPE_INT).intValue; + pthread_mutex_unlock(&mutex); - applyGTKDConfSettings(result, themeName, iconsName, fontName); + applyGTKDConfSettings(result, themeName, iconsName, fontName, cursorTheme, cursorSize); } static void detectGTKFromConfigFile(const char* filename, FFGTKResult* result) { - FILE* file = fopen(filename, "r"); - if(file == NULL) - return; - - char* line = NULL; - size_t len = 0; - - bool needsTheme = result->theme.length == 0; - bool needsIcons = result->icons.length == 0; - bool needsFont = result->font.length == 0; - - while(getline(&line, &len, file) != -1) - { - if(needsTheme) - ffGetPropValue(line, "gtk-theme-name =", &result->theme); - if(needsIcons) - ffGetPropValue(line, "gtk-icon-theme-name =", &result->icons); - if(needsFont) - ffGetPropValue(line, "gtk-font-name =", &result->font); - } - - if(line != NULL) - free(line); - - fclose(file); + ffParsePropFileValues(filename, 5, (FFpropquery[]) { + {"gtk-theme-name =", &result->theme}, + {"gtk-icon-theme-name =", &result->icons}, + {"gtk-font-name =", &result->font}, + {"gtk-cursor-theme-name =", &result->cursor}, + {"gtk-cursor-theme-size =", &result->cursorSize} + }); } static void detectGTKFromConfigDir(FFstrbuf* configDir, const char* version, FFGTKResult* result) @@ -211,6 +211,8 @@ static void detectGTK(FFinstance* instance, const char* version, const char* env ffStrbufInit(&result.theme); \ ffStrbufInit(&result.icons); \ ffStrbufInit(&result.font); \ + ffStrbufInit(&result.cursor); \ + ffStrbufInit(&result.cursorSize); \ detectGTK(instance, #version, "GTK"#version"_RC_FILES", &result); \ pthread_mutex_unlock(&mutex); \ return &result; diff --git a/src/common/detectWMDE.c b/src/common/detectWMDE.c index 41e714df7..0bb42bf17 100644 --- a/src/common/detectWMDE.c +++ b/src/common/detectWMDE.c @@ -153,15 +153,21 @@ static void getMate(FFinstance* instance, FFWMDEResult* result) ffStrbufSetS(&result->deProcessName, "mate-session"); ffStrbufSetS(&result->dePrettyName, "MATE"); - //I parse the file 3 times by purpose, because the properties are not guaranteed to be in order - ffParsePropFile("/usr/share/mate-about/mate-version.xml", "", &result->deVersion); - if(result->deVersion.length > 0) - { - ffStrbufAppendC(&result->deVersion, '.'); - ffParsePropFile("/usr/share/mate-about/mate-version.xml", "", &result->deVersion); - ffStrbufAppendC(&result->deVersion, '.'); - ffParsePropFile("/usr/share/mate-about/mate-version.xml", "", &result->deVersion); - } + FFstrbuf major; ffStrbufInit(&major); + FFstrbuf minor; ffStrbufInit(&minor); + FFstrbuf micro; ffStrbufInit(µ); + + ffParsePropFileValues("/usr/share/mate-about/mate-version.xml", 3, (FFpropquery[]) { + {"", &major}, + {"", &minor}, + {"", µ} + }); + + ffParseSemver(&result->deVersion, &major, &minor, µ); + + ffStrbufDestroy(&major); + ffStrbufDestroy(&minor); + ffStrbufDestroy(µ); if(result->deVersion.length == 0 && instance->config.allowSlowOperations) { diff --git a/src/common/init.c b/src/common/init.c index 7c88cc146..d78965ac9 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -145,6 +145,8 @@ static void defaultConfig(FFinstance* instance) ffStrbufInitA(&instance->config.iconsKey, 1); ffStrbufInitA(&instance->config.fontFormat, 1); ffStrbufInitA(&instance->config.fontKey, 1); + ffStrbufInitA(&instance->config.cursorKey, 1); + ffStrbufInitA(&instance->config.cursorFormat, 1); ffStrbufInitA(&instance->config.terminalFormat, 1); ffStrbufInitA(&instance->config.terminalKey, 1); ffStrbufInitA(&instance->config.termFontFormat, 1); diff --git a/src/common/io.c b/src/common/io.c index 6879256e5..71ae493e9 100644 --- a/src/common/io.c +++ b/src/common/io.c @@ -290,21 +290,45 @@ void ffCacheClose(FFcache* cache) fclose(cache->split); } -bool ffParsePropFile(const char* fileName, const char* start, FFstrbuf* buffer) +bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries) { - FILE* file = fopen(fileName, "r"); + bool* searchedValues = malloc(sizeof(bool) * numQueries); + bool allSet = true; + for(uint32_t i = 0; i < numQueries; i++) + { + if((searchedValues[i] = queries[i].buffer->length == 0)) + allSet = false; + } + + if(allSet) + { + free(searchedValues); + return access(filename, R_OK) == 0; + } + + FILE* file = fopen(filename, "r"); if(file == NULL) - return false; // handle errors in higher functions + return false; char* line = NULL; size_t len = 0; while (getline(&line, &len, file) != -1) { - if(ffGetPropValue(line, start, buffer)) - break; + for(uint32_t i = 0; i < numQueries; i++) + { + if(!searchedValues[i]) + continue; + + uint32_t currentLength = queries[i].buffer->length; + queries[i].buffer->length = 0; + if(!ffGetPropValue(line, queries[i].start, queries[i].buffer)) + queries[i].buffer->length = currentLength; + } } + free(searchedValues); + if(line != NULL) free(line); @@ -313,7 +337,12 @@ bool ffParsePropFile(const char* fileName, const char* start, FFstrbuf* buffer) return true; } -bool ffParsePropFileHome(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) +bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}}); +} + +bool ffParsePropFileHomeValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) { FFstrbuf absolutePath; ffStrbufInitA(&absolutePath, 64); @@ -321,16 +350,20 @@ bool ffParsePropFileHome(FFinstance* instance, const char* relativeFile, const c ffStrbufAppendC(&absolutePath, '/'); ffStrbufAppendS(&absolutePath, relativeFile); - bool result = ffParsePropFile(absolutePath.chars, start, buffer); + bool result = ffParsePropFileValues(absolutePath.chars, numQueries, queries); ffStrbufDestroy(&absolutePath); return result; } -bool ffParsePropFileConfig(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) +bool ffParsePropFileHome(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}}); +} + +bool ffParsePropFileConfigValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries) { - uint32_t bufferLengthStart = buffer->length; bool foundAFile = false; for(uint32_t i = 0; i < instance->state.configDirs.length; i++) @@ -343,18 +376,33 @@ bool ffParsePropFileConfig(FFinstance* instance, const char* relativeFile, const ffStrbufAppendS(baseDir, relativeFile); - if(ffParsePropFile(baseDir->chars, start, buffer)) + if(ffParsePropFileValues(baseDir->chars, numQueries, queries)) foundAFile = true; ffStrbufSubstrBefore(baseDir, baseDirLength); - if(bufferLengthStart < buffer->length) - return foundAFile; + bool allSet = true; + for(uint32_t i = 0; i < numQueries; i++) + { + if(queries[i].buffer->length == 0) + { + allSet = false; + break; + } + } + + if(allSet) + break; } return foundAFile; } +bool ffParsePropFileConfig(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer) +{ + return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}}); +} + bool ffWriteFDContent(int fd, const FFstrbuf* content) { return write(fd, content->chars, content->length) != -1; diff --git a/src/common/parsing.c b/src/common/parsing.c index c3e0470b0..cadd6e0cf 100644 --- a/src/common/parsing.c +++ b/src/common/parsing.c @@ -368,3 +368,27 @@ bool ffGetPropValueFromLines(const char* lines, const char* start, FFstrbuf* buf return true; } + +void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch) +{ + if(major->length == 0 && minor->length == 0 && patch->length == 0) + return; + + if(major->length > 0) + ffStrbufAppend(buffer, major); + else + ffStrbufAppendC(buffer, '1'); + + ffStrbufAppendC(buffer, '.'); + + if(minor->length > 0) + ffStrbufAppend(buffer, minor); + else if(patch->length > 0) + ffStrbufAppendC(buffer, '0'); + else + return; + + ffStrbufAppendC(buffer, '.'); + + ffStrbufAppend(buffer, patch); +} diff --git a/src/common/settings.c b/src/common/settings.c index 1384f39cc..9b646fccc 100644 --- a/src/common/settings.c +++ b/src/common/settings.c @@ -29,24 +29,26 @@ typedef struct GVariantGetters { const gchar*(*ffg_variant_get_string)(GVariant*, gsize*); gboolean(*ffg_variant_get_boolean)(GVariant*); + gint32(*ffg_variant_get_int32)(GVariant*); } GVariantGetters; #define FF_LIBRARY_GVARIANT_GETTERS_INIT(library, object, mutex) \ object.ffg_variant_get_string = FF_LIBRARY_LOAD_SYMBOL(library, "g_variant_get_string", mutex, FF_VARIANT_NULL); \ - object.ffg_variant_get_boolean = FF_LIBRARY_LOAD_SYMBOL(library, "g_variant_get_boolean", mutex, FF_VARIANT_NULL); + object.ffg_variant_get_boolean = FF_LIBRARY_LOAD_SYMBOL(library, "g_variant_get_boolean", mutex, FF_VARIANT_NULL); \ + object.ffg_variant_get_int32 = FF_LIBRARY_LOAD_SYMBOL(library, "g_variant_get_int32", mutex, FF_VARIANT_NULL) static FFvariant getGVariantValue(GVariant* variant, FFvarianttype type, GVariantGetters* variantGetters) { if(variant == NULL) return FF_VARIANT_NULL; - - if(type == FF_VARIANT_TYPE_STRING) - return (FFvariant) variantGetters->ffg_variant_get_string(variant, NULL); - - if(type == FF_VARIANT_TYPE_BOOL) - return (FFvariant) { .boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true}; - - return FF_VARIANT_NULL; + else if(type == FF_VARIANT_TYPE_STRING) + return (FFvariant) {.strValue = variantGetters->ffg_variant_get_string(variant, NULL)}; + else if(type == FF_VARIANT_TYPE_BOOL) + return (FFvariant) {.boolValue = (bool) variantGetters->ffg_variant_get_boolean(variant), .boolValueSet = true}; + else if(type == FF_VARIANT_TYPE_INT) + return (FFvariant) {.intValue = variantGetters->ffg_variant_get_int32(variant)}; + else + return FF_VARIANT_NULL; } typedef struct DConfData @@ -182,9 +184,12 @@ FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, c FFvariant ffSettingsGet(FFinstance* instance, const char* dconfKey, const char* gsettingsSchemaName, const char* gsettingsPath, const char* gsettingsKey, FFvarianttype type) { - FFvariant gsettings = ffSettingsGetGSettings(instance, gsettingsSchemaName, gsettingsPath, gsettingsKey, FF_VARIANT_TYPE_STRING); - if(gsettings.strValue != NULL) - return gsettings; + FFvariant gsettings = ffSettingsGetGSettings(instance, gsettingsSchemaName, gsettingsPath, gsettingsKey, type); + + if( + (type == FF_VARIANT_TYPE_BOOL && gsettings.boolValueSet) || + (type != FF_VARIANT_TYPE_BOOL && gsettings.strValue != NULL) + ) return gsettings; return ffSettingsGetDConf(instance, dconfKey, type); } @@ -198,6 +203,7 @@ typedef struct XFConfData gboolean(*ffxfconf_channel_has_property)(XfconfChannel*, const gchar*); gchar*(*ffxfconf_channel_get_string)(XfconfChannel*, const gchar*, const gchar*); gboolean(*ffxfconf_channel_get_bool)(XfconfChannel*, const gchar*, gboolean); + gint32(*ffxfconf_channel_get_int)(XfconfChannel*, const gchar*, gint32); } XFConfData; static FFvariant getXFConfValue(XFConfData* data, const char* channelName, const char* propertyName, FFvarianttype type) @@ -210,6 +216,9 @@ static FFvariant getXFConfValue(XFConfData* data, const char* channelName, const if(!data->ffxfconf_channel_has_property(channel, propertyName)) return FF_VARIANT_NULL; + if(type == FF_VARIANT_TYPE_INT) + return (FFvariant) {.intValue = data->ffxfconf_channel_get_int(channel, propertyName, 0)}; + if(type == FF_VARIANT_TYPE_STRING) return (FFvariant) {.strValue = data->ffxfconf_channel_get_string(channel, propertyName, NULL)}; @@ -243,6 +252,7 @@ FFvariant ffSettingsGetXFConf(FFinstance* instance, const char* channelName, con data.ffxfconf_channel_has_property = FF_LIBRARY_LOAD_SYMBOL(library, "xfconf_channel_has_property", mutex, FF_VARIANT_NULL); data.ffxfconf_channel_get_string = FF_LIBRARY_LOAD_SYMBOL(library, "xfconf_channel_get_string", mutex, FF_VARIANT_NULL); data.ffxfconf_channel_get_bool = FF_LIBRARY_LOAD_SYMBOL(library, "xfconf_channel_get_bool", mutex, FF_VARIANT_NULL); + data.ffxfconf_channel_get_int = FF_LIBRARY_LOAD_SYMBOL(library, "xfconf_channel_get_int", mutex, FF_VARIANT_NULL); gboolean(*ffxfconf_init)(GError **) = FF_LIBRARY_LOAD_SYMBOL(library, "xfconf_init", mutex, FF_VARIANT_NULL); if((data.init = ffxfconf_init(NULL)) == FALSE) diff --git a/src/fastfetch.c b/src/fastfetch.c index 670b40887..5e0acfdaf 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -8,7 +8,7 @@ #include #include -#define FASTFETCH_DEFAULT_STRUCTURE "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors" +#define FASTFETCH_DEFAULT_STRUCTURE "Title:Separator:OS:Host:Kernel:Uptime:Packages:Shell:Resolution:DE:WM:WMTheme:Theme:Icons:Font:Cursor:Terminal:TerminalFont:CPU:GPU:Memory:Disk:Battery:Locale:Break:Colors" #define FASTFETCH_DEFAULT_CONFIG \ "# Fastfetch configuration\n" \ @@ -80,6 +80,7 @@ static inline void printHelp() " --theme-format \n" " --icons-format \n" " --font-format \n" + " --cursor-format \n" " --terminal-format \n" " --terminal-font-format \n" " --cpu-format \n" @@ -103,6 +104,7 @@ static inline void printHelp() " --theme-key \n" " --icons-key \n" " --font-key \n" + " --cursor-key \n" " --terminal-key \n" " --terminal-font-key \n" " --cpu-key \n" @@ -384,6 +386,13 @@ static inline void printCommandHelp(const char* command) "GTK2/3/4 pretty" ); } + else if(strcasecmp(command, "cursor-format") == 0) + { + constructAndPrintCommandHelpFormat("cursor", "{} ({}pt)", 2, + "Cursor theme", + "Cursor size" + ); + } else if(strcasecmp(command, "terminal-format") == 0) { constructAndPrintCommandHelpFormat("terminal", "{3}", 3, @@ -474,6 +483,7 @@ static inline void printAvailableModules() "Break\n" "Colors\n" "CPU\n" + "Cursor\n" "DE\n" "Disk\n" "Font\n" @@ -868,6 +878,10 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con optionParseString(key, value, &instance->config.fontFormat); else if(strcasecmp(key, "--font-key") == 0) optionParseString(key, value, &instance->config.fontKey); + else if(strcasecmp(key, "--cursor-key") == 0) + optionParseString(key, value, &instance->config.cursorKey); + else if(strcasecmp(key, "--cursor-format") == 0) + optionParseString(key, value, &instance->config.cursorFormat); else if(strcasecmp(key, "--terminal-format") == 0) optionParseString(key, value, &instance->config.terminalFormat); else if(strcasecmp(key, "--terminal-key") == 0) @@ -1031,6 +1045,8 @@ static void parseStructureCommand(FFinstance* instance, FFdata* data, const char ffPrintIcons(instance); else if(strcasecmp(line, "font") == 0) ffPrintFont(instance); + else if(strcasecmp(line, "cursor") == 0) + ffPrintCursor(instance); else if(strcasecmp(line, "terminal") == 0) ffPrintTerminal(instance); else if(strcasecmp(line, "terminalfont") == 0) diff --git a/src/fastfetch.h b/src/fastfetch.h index dd09b69d6..2a0233565 100644 --- a/src/fastfetch.h +++ b/src/fastfetch.h @@ -73,6 +73,8 @@ typedef struct FFconfig FFstrbuf iconsKey; FFstrbuf fontFormat; FFstrbuf fontKey; + FFstrbuf cursorFormat; + FFstrbuf cursorKey; FFstrbuf terminalFormat; FFstrbuf terminalKey; FFstrbuf termFontFormat; @@ -105,6 +107,24 @@ typedef struct FFconfig } FFconfig; +typedef struct FFstate +{ + uint32_t logoWidth; + + struct passwd* passwd; + struct utsname utsname; + struct sysinfo sysinfo; + + FFlist configDirs; + FFstrbuf cacheDir; +} FFstate; + +typedef struct FFinstance +{ + FFconfig config; + FFstate state; +} FFinstance; + typedef struct FFTitleResult { FFstrbuf userName; @@ -141,6 +161,8 @@ typedef struct FFGTKResult FFstrbuf theme; FFstrbuf icons; FFstrbuf font; + FFstrbuf cursor; + FFstrbuf cursorSize; } FFGTKResult; typedef struct FFTerminalShellResult @@ -170,24 +192,6 @@ typedef struct FFWMDEResult FFstrbuf deVersion; } FFWMDEResult; -typedef struct FFstate -{ - uint32_t logoWidth; - - struct passwd* passwd; - struct utsname utsname; - struct sysinfo sysinfo; - - FFlist configDirs; - FFstrbuf cacheDir; -} FFstate; - -typedef struct FFinstance -{ - FFconfig config; - FFstate state; -} FFinstance; - typedef enum FFformatargtype { FF_FORMAT_ARG_TYPE_NULL = 0, @@ -215,13 +219,14 @@ typedef struct FFcache typedef enum FFvarianttype { FF_VARIANT_TYPE_STRING, - FF_VARIANT_TYPE_BOOL + FF_VARIANT_TYPE_BOOL, + FF_VARIANT_TYPE_INT } FFvarianttype; typedef union FFvariant { const char* strValue; - + int32_t intValue; struct { bool boolValueSet; @@ -237,6 +242,12 @@ typedef struct FFfont FFlist styles; } FFfont; +typedef struct FFpropquery +{ + const char* start; + FFstrbuf* buffer; +} FFpropquery; + /*************************/ /* Common util functions */ /*************************/ @@ -270,9 +281,14 @@ bool ffGetFileContent(const char* fileName, FFstrbuf* buffer); bool ffWriteFDContent(int fd, const FFstrbuf* content); void ffWriteFileContent(const char* fileName, const FFstrbuf* buffer); -// They return true if the file was found, independently if regex was found -bool ffParsePropFile(const char* file, const char* start, FFstrbuf* buffer); +// They return true if the file was found, independently if start was found +// Buffers which already contain content are not overwritten +// The last occurence of start in the first file will be the one used +bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries); +bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer); +bool ffParsePropFileHomeValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries); bool ffParsePropFileHome(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer); +bool ffParsePropFileConfigValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries); bool ffParsePropFileConfig(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer); //common/processing.c @@ -304,6 +320,8 @@ void ffFontDestroy(FFfont* font); bool ffGetPropValue(const char* line, const char* start, FFstrbuf* buffer); bool ffGetPropValueFromLines(const char* lines, const char* start, FFstrbuf* buffer); +void ffParseSemver(FFstrbuf* buffer, const FFstrbuf* major, const FFstrbuf* minor, const FFstrbuf* patch); + //common/settings.c FFvariant ffSettingsGetDConf(FFinstance* instance, const char* key, FFvarianttype type); FFvariant ffSettingsGetGSettings(FFinstance* instance, const char* schemaName, const char* path, const char* key, FFvarianttype type); @@ -353,6 +371,7 @@ void ffPrintWMTheme(FFinstance* instance); void ffPrintTheme(FFinstance* instance); void ffPrintIcons(FFinstance* instance); void ffPrintFont(FFinstance* instance); +void ffPrintCursor(FFinstance* instance); void ffPrintTerminal(FFinstance* instance); void ffPrintTerminalFont(FFinstance* instance); void ffPrintCPU(FFinstance* instance); diff --git a/src/flashfetch.c b/src/flashfetch.c index 49fd7f680..5a293bcea 100644 --- a/src/flashfetch.c +++ b/src/flashfetch.c @@ -35,6 +35,7 @@ int main(int argc, char** argv) ffPrintTheme(&instance); ffPrintIcons(&instance); ffPrintFont(&instance); + ffPrintCursor(&instance); ffPrintTerminal(&instance); ffPrintTerminalFont(&instance); ffPrintCPU(&instance); diff --git a/src/modules/cursor.c b/src/modules/cursor.c new file mode 100644 index 000000000..78aa09c2e --- /dev/null +++ b/src/modules/cursor.c @@ -0,0 +1,104 @@ +#include "fastfetch.h" + +#define FF_CURSOR_MODULE_NAME "Cursor" +#define FF_CURSOR_NUM_FORMAT_ARGS 2 + +static void printCursor(FFinstance* instance, const FFstrbuf* cursorTheme, const FFstrbuf* cursorSize) +{ + ffPrintLogoAndKey(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey); + ffStrbufWriteTo(cursorTheme, stdout); + + if(cursorSize->length > 0) + { + fputs(" (", stdout); + ffStrbufWriteTo(cursorSize, stdout); + fputs("pt)", stdout); + } + + putchar('\n'); +} + +static void printCursorGTK(FFinstance* instance) +{ + const FFGTKResult* gtk = ffDetectGTK4(instance); + + if(gtk->cursor.length == 0) + gtk = ffDetectGTK3(instance); + + if(gtk->cursor.length == 0) + gtk = ffDetectGTK2(instance); + + if(gtk->cursor.length == 0) + { + ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Couldn't detect GTK Cursor"); + return; + } + + printCursor(instance, >k->cursor, >k->cursorSize); +} + +static void printCursorPlasma(FFinstance* instance) +{ + FFstrbuf cursorTheme; + ffStrbufInit(&cursorTheme); + + FFstrbuf cursorSize; + ffStrbufInit(&cursorSize); + + if(ffParsePropFileConfigValues(instance, "kcminputrc", 2, (FFpropquery[]) { + {"cursorTheme =", &cursorTheme}, + {"cursorSize =", &cursorSize} + })) { + if(cursorTheme.length == 0) + ffStrbufAppendS(&cursorTheme, "Breeze"); + + if(cursorSize.length == 0) + ffStrbufAppendS(&cursorSize, "24"); + } + + if(cursorTheme.length == 0) + { + ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Couldn't find plasma cursor in kcminputrc"); + return; + } + + printCursor(instance, &cursorTheme, &cursorSize); + ffStrbufDestroy(&cursorTheme); + ffStrbufDestroy(&cursorSize); +} + +static void printCursorXFCE(FFinstance* instance) +{ + FFstrbuf cursorTheme; + ffStrbufInit(&cursorTheme); + + ffStrbufAppendS(&cursorTheme, ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue); + + if(cursorTheme.length == 0) + { + ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursorKey, &instance->config.cursorFormat, FF_CURSOR_NUM_FORMAT_ARGS, "Couldn't find xfce cursor in xfconf (xsettings::/Gtk/CursorThemeName)"); + return; + } + + FFstrbuf cursorSize; + ffStrbufInit(&cursorSize); + int cursorSizeVal = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; + if(cursorSizeVal > 0) + ffStrbufAppendF(&cursorSize, "%i", cursorSizeVal); + + printCursor(instance, &cursorTheme, &cursorSize); + ffStrbufDestroy(&cursorTheme); + ffStrbufDestroy(&cursorSize); +} + +void ffPrintCursor(FFinstance* instance) +{ + const FFWMDEResult* wmde = ffDetectWMDE(instance); + + if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0) + printCursorPlasma(instance); + else if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "XFCE") == 0) + printCursorXFCE(instance); + else + printCursorGTK(instance); +}