diff --git a/CMakeLists.txt b/CMakeLists.txt index d5cd54240..6675f802b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,6 +301,7 @@ if(LINUX) src/detection/board/board_linux.c src/detection/cpu/cpu_linux.c src/detection/cpuUsage/cpuUsage_linux.c + src/detection/cursor/cursor_linux.c src/detection/disk/disk_linux.c src/detection/displayserver/linux/displayserver_linux.c src/detection/displayserver/linux/wayland.c @@ -336,6 +337,7 @@ elseif(ANDROID) src/detection/bios/bios_nosupport.c src/detection/board/board_nosupport.c src/detection/cpu/cpu_linux.c + src/detection/cursor/cursor_nosupport.c src/detection/cpuUsage/cpuUsage_linux.c src/detection/disk/disk_linux.c src/detection/displayserver/displayserver_nosupport.c @@ -370,6 +372,7 @@ elseif(BSD) src/detection/board/board_nosupport.c src/detection/cpu/cpu_bsd.c src/detection/cpuUsage/cpuUsage_bsd.c + src/detection/cursor/cursor_linux.c src/detection/disk/disk_bsd.c src/detection/host/host_bsd.c src/detection/localip/localip_linux.c @@ -394,6 +397,7 @@ elseif(APPLE) src/detection/board/board_nosupport.c src/detection/cpu/cpu_apple.c src/detection/cpuUsage/cpuUsage_apple.c + src/detection/cursor/cursor_nosupport.c src/detection/disk/disk_apple.m src/detection/disk/disk_bsd.c src/detection/displayserver/displayserver_apple.c @@ -428,6 +432,7 @@ elseif(WIN32) src/detection/cpu/cpu_windows.c src/detection/cpuUsage/cpuUsage_nowait_windows.cpp src/detection/cpuUsage/cpuUsage_windows.c + src/detection/cursor/cursor_windows.c src/detection/disk/disk_windows.c src/detection/displayserver/displayserver_windows.c src/detection/font/font_windows.cpp diff --git a/src/detection/cursor/cursor.h b/src/detection/cursor/cursor.h new file mode 100644 index 000000000..268631240 --- /dev/null +++ b/src/detection/cursor/cursor.h @@ -0,0 +1,17 @@ +#pragma once + +#ifndef FF_INCLUDED_detection_cursor_cursor +#define FF_INCLUDED_detection_cursor_cursor + +#include "fastfetch.h" + +typedef struct FFCursorResult +{ + FFstrbuf theme; + FFstrbuf size; + FFstrbuf error; +} FFCursorResult; + +void ffDetectCursor(const FFinstance* instance, FFCursorResult* result); + +#endif diff --git a/src/detection/cursor/cursor_linux.c b/src/detection/cursor/cursor_linux.c new file mode 100644 index 000000000..a8dfb8810 --- /dev/null +++ b/src/detection/cursor/cursor_linux.c @@ -0,0 +1,131 @@ +#include "cursor.h" + +#include "common/properties.h" +#include "common/parsing.h" +#include "common/settings.h" +#include "detection/gtk.h" +#include "detection/displayserver/displayserver.h" + +#include + +static void detectCursorGTK(const FFinstance* instance, FFCursorResult* result) +{ + 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) + { + ffStrbufAppendS(&result->error, "Couldn't detect GTK Cursor"); + return; + } + + ffStrbufAppend(&result->theme, >k->cursor); + ffStrbufAppend(&result->size, >k->cursorSize); +} + +static void detectCursorXFCE(const FFinstance* instance, FFCursorResult* result) +{ + ffStrbufAppendS(&result->theme, ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeName", FF_VARIANT_TYPE_STRING).strValue); + + if(result->theme.length == 0) + ffStrbufAppendS(&result->error, "Couldn't find xfce cursor in xfconf (xsettings::/Gtk/CursorThemeName)"); + + int cursorSizeVal = ffSettingsGetXFConf(instance, "xsettings", "/Gtk/CursorThemeSize", FF_VARIANT_TYPE_INT).intValue; + if(cursorSizeVal > 0) + ffStrbufAppendF(&result->size, "%i", cursorSizeVal); +} + +static void detectCursorFromConfigFile(const FFinstance* instance, const char* relativeFilePath, const char* themeStart, const char* themeDefault, const char* sizeStart, const char* sizeDefault, FFCursorResult* result) +{ + if(ffParsePropFileConfigValues(instance, relativeFilePath, 2, (FFpropquery[]) { + {themeStart, &result->theme}, + {sizeStart, &result->size} + })) { + + if(result->theme.length == 0) + ffStrbufAppendS(&result->theme, themeDefault); + + if(result->size.length == 0) + ffStrbufAppendS(&result->size, sizeDefault); + } + + if(result->theme.length == 0) + ffStrbufAppendF(&result->error, "Couldn't find cursor in %s", relativeFilePath); +} + +static bool detectCursorFromXResources(const FFinstance* instance, FFCursorResult* result) +{ + ffParsePropFileHomeValues(instance, ".Xresources", 2, (FFpropquery[]) { + {"Xcursor.theme :", &result->theme}, + {"Xcursor.size :", &result->size} + }); + + return result->theme.length > 0; +} + +static bool detectCursorFromXDG(const FFinstance* instance, bool user, FFCursorResult* result) +{ + if(user) + ffParsePropFileHome(instance, ".icons/default/index.theme", "Inherits =", &result->theme); + else + ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/icons/default/index.theme", "Inherits =", &result->theme); + + return result->theme.length > 0; +} + +static bool detectCursorFromEnv(const FFinstance* instance, FFCursorResult* result) +{ + FF_UNUSED(instance); + const char* xcursor_theme = getenv("XCURSOR_THEME"); + + if(!ffStrSet(xcursor_theme)) + return false; + + ffStrbufAppendS(&result->theme, xcursor_theme); + ffStrbufAppendS(&result->size, getenv("XCURSOR_SIZE")); + + return true; +} + +void ffDetectCursor(const FFinstance* instance, FFCursorResult* result) +{ + const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); + + if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0) + { + ffStrbufAppendS(&result->error, "WSLg uses native windows cursor"); + return; + } + + if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) + { + ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY"); + return; + } + + if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0) + return detectCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result); + + if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "XFCE")) + return detectCursorXFCE(instance, result); + + if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "LXQt")) + return detectCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result); + + if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0) + return detectCursorGTK(instance, result); + + if( + detectCursorFromEnv(instance, result) || + detectCursorFromXDG(instance, true, result) || + detectCursorFromXResources(instance, result) || + detectCursorFromXDG(instance, false, result) + ) return; + + detectCursorGTK(instance, result); +} diff --git a/src/detection/cursor/cursor_nosupport.c b/src/detection/cursor/cursor_nosupport.c new file mode 100644 index 000000000..c548b2f6c --- /dev/null +++ b/src/detection/cursor/cursor_nosupport.c @@ -0,0 +1,6 @@ +#include "cursor.h" + +void ffDetectCursor(const FFinstance* instance, FFCursorResult* result) +{ + ffStrbufInitS(&result->error, "Not supported on this platform"); +} diff --git a/src/detection/cursor/cursor_windows.c b/src/detection/cursor/cursor_windows.c new file mode 100644 index 000000000..fd3785637 --- /dev/null +++ b/src/detection/cursor/cursor_windows.c @@ -0,0 +1,12 @@ +#include "cursor.h" + +#include "util/windows/register.h" + +void ffDetectCursor(const FFinstance* instance, FFCursorResult* result) +{ + FF_UNUSED(instance); + + FF_HKEY_AUTO_DESTROY hKey; + if(ffRegOpenKeyForRead(HKEY_CURRENT_USER, "Control Panel\\Cursors", &hKey, &result->error)) + ffRegReadStrbuf(hKey, NULL, &result->theme, &result->error); +} diff --git a/src/modules/cursor.c b/src/modules/cursor.c index c7285427e..a5ddc90be 100644 --- a/src/modules/cursor.c +++ b/src/modules/cursor.c @@ -1,255 +1,55 @@ #include "fastfetch.h" -#include "common/properties.h" -#include "common/printing.h" -#include "common/parsing.h" -#include "common/settings.h" -#include "detection/gtk.h" -#include "detection/displayserver/displayserver.h" -#include +#include "common/printing.h" +#include "detection/cursor/cursor.h" #define FF_CURSOR_MODULE_NAME "Cursor" #define FF_CURSOR_NUM_FORMAT_ARGS 2 -#if !(defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32)) - -static void printCursor(FFinstance* instance, FFstrbuf* cursorTheme, const FFstrbuf* cursorSize) +static void printCursor(FFinstance* instance, FFCursorResult* cursor) { - ffStrbufRemoveIgnCaseEndS(cursorTheme, "cursors"); - ffStrbufRemoveIgnCaseEndS(cursorTheme, "cursor"); - ffStrbufTrimRight(cursorTheme, '_'); - ffStrbufTrimRight(cursorTheme, '-'); - if(cursorTheme->length == 0) - ffStrbufAppendS(cursorTheme, "default"); + ffStrbufRemoveIgnCaseEndS(&cursor->theme, "cursors"); + ffStrbufRemoveIgnCaseEndS(&cursor->theme, "cursor"); + ffStrbufTrimRight(&cursor->theme, '_'); + ffStrbufTrimRight(&cursor->theme, '-'); + if(cursor->theme.length == 0) + ffStrbufAppendS(&cursor->theme, "default"); if(instance->config.cursor.outputFormat.length == 0) { ffPrintLogoAndKey(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor.key); - ffStrbufWriteTo(cursorTheme, stdout); + ffStrbufWriteTo(&cursor->theme, stdout); - if(cursorSize != NULL && cursorSize->length > 0) - { - fputs(" (", stdout); - ffStrbufWriteTo(cursorSize, stdout); - fputs("px)", stdout); - } + if(cursor->size.length > 0) + printf(" (%spx)", cursor->size.chars); putchar('\n'); } else { ffPrintFormat(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, FF_CURSOR_NUM_FORMAT_ARGS, (FFformatarg[]){ - {FF_FORMAT_ARG_TYPE_STRBUF, cursorTheme}, - {FF_FORMAT_ARG_TYPE_STRBUF, cursorSize} + {FF_FORMAT_ARG_TYPE_STRBUF, &cursor->theme}, + {FF_FORMAT_ARG_TYPE_STRBUF, &cursor->size} }); } } -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.cursor, "Couldn't detect GTK Cursor"); - return; - } - - //gtk->cursor is const, so we don't want to modify it - FFstrbuf theme; - ffStrbufInitCopy(&theme, >k->cursor); - - printCursor(instance, &theme, >k->cursorSize); - - ffStrbufDestroy(&theme); -} - -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.cursor, "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); -} - -static void printCursorFromConfigFile(FFinstance* instance, const char* relativeFilePath, const char* themeStart, const char* themeDefault, const char* sizeStart, const char* sizeDefault) -{ - FFstrbuf cursorTheme; - ffStrbufInit(&cursorTheme); - - FFstrbuf cursorSize; - ffStrbufInit(&cursorSize); - - if(ffParsePropFileConfigValues(instance, relativeFilePath, 2, (FFpropquery[]) { - {themeStart, &cursorTheme}, - {sizeStart, &cursorSize} - })) { - - if(cursorTheme.length == 0) - ffStrbufAppendS(&cursorTheme, themeDefault); - - if(cursorSize.length == 0) - ffStrbufAppendS(&cursorSize, sizeDefault); - } - - if(cursorTheme.length == 0) - ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Couldn't find cursor in %s", relativeFilePath); - else - printCursor(instance, &cursorTheme, &cursorSize); - - ffStrbufDestroy(&cursorTheme); - ffStrbufDestroy(&cursorSize); -} - -static bool printCursorFromXResources(FFinstance* instance) -{ - FFstrbuf theme; - ffStrbufInit(&theme); - - FFstrbuf size; - ffStrbufInit(&size); - - ffParsePropFileHomeValues(instance, ".Xresources", 2, (FFpropquery[]) { - {"Xcursor.theme :", &theme}, - {"Xcursor.size :", &size} - }); - - if(theme.length == 0) - { - ffStrbufDestroy(&size); - ffStrbufDestroy(&theme); - return false; - } - - printCursor(instance, &theme, &size); - ffStrbufDestroy(&size); - ffStrbufDestroy(&theme); - return true; -} - -static bool printCursorFromXDG(FFinstance* instance, bool user) -{ - FFstrbuf theme; - ffStrbufInit(&theme); - - if(user) - ffParsePropFileHome(instance, ".icons/default/index.theme", "Inherits =", &theme); - else - ffParsePropFile(FASTFETCH_TARGET_DIR_USR"/share/icons/default/index.theme", "Inherits =", &theme); - - if(theme.length == 0) - { - ffStrbufDestroy(&theme); - return false; - } - - printCursor(instance, &theme, NULL); - ffStrbufDestroy(&theme); - return true; -} - -static bool printCursorFromEnv(FFinstance* instance) -{ - const char* xcursor_theme = getenv("XCURSOR_THEME"); - - if(!ffStrSet(xcursor_theme)) - return false; - - FFstrbuf theme; - ffStrbufInit(&theme); - ffStrbufAppendS(&theme, xcursor_theme); - - FFstrbuf size; - ffStrbufInit(&size); - ffStrbufAppendS(&size, getenv("XCURSOR_SIZE")); - - printCursor(instance, &theme, &size); - - ffStrbufDestroy(&size); - ffStrbufDestroy(&theme); - return true; -} - -#endif void ffPrintCursor(FFinstance* instance) { - #if defined(__ANDROID__) || defined(__APPLE__) || defined(_WIN32) + FFCursorResult result; + ffStrbufInit(&result.error); + ffStrbufInit(&result.theme); + ffStrbufInit(&result.size); - FF_UNUSED(instance); - ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor detection is not supported"); - return; + ffDetectCursor(instance, &result); - #else + if(result.error.length) + ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "%s", result.error.chars); + else + printCursor(instance, &result); - const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance); - - if(ffStrbufCompS(&wmde->wmPrettyName, "WSLg") == 0) - { - ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "WSLg uses native windows cursor"); - return; - } - - if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0) - { - ffPrintError(instance, FF_CURSOR_MODULE_NAME, 0, &instance->config.cursor, "Cursor isn't supported in TTY"); - return; - } - - if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "KDE Plasma") == 0) - { - printCursorFromConfigFile(instance, "kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24"); - return; - } - - if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "XFCE")) - { - printCursorXFCE(instance); - return; - } - - if(ffStrbufStartsWithIgnCaseS(&wmde->dePrettyName, "LXQt")) - { - printCursorFromConfigFile(instance, "lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24"); - return; - } - - if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Gnome") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0 || ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Mate") == 0) - { - printCursorGTK(instance); - return; - } - - if( - printCursorFromEnv(instance) || - printCursorFromXDG(instance, true) || - printCursorFromXResources(instance) || - printCursorFromXDG(instance, false) - ) return; - - printCursorGTK(instance); - - #endif + ffStrbufDestroy(&result.error); + ffStrbufDestroy(&result.theme); + ffStrbufDestroy(&result.size); } diff --git a/src/util/windows/register.c b/src/util/windows/register.c index 1e477f2e0..f8ea9e4b1 100644 --- a/src/util/windows/register.c +++ b/src/util/windows/register.c @@ -34,13 +34,13 @@ bool ffRegReadStrbuf(HKEY hKey, const char* valueName, FFstrbuf* result, FFstrbu DWORD bufSize; //with tailing '\0' if(RegGetValueA(hKey, NULL, valueName, RRF_RT_REG_SZ, NULL, NULL, &bufSize) != ERROR_SUCCESS) { - if(error) ffStrbufAppendF(error, "RegGetValueA(%s, NULL, RRF_RT_REG_SZ) failed", valueName); + if(error) ffStrbufAppendF(error, "RegGetValueA(%s, NULL, RRF_RT_REG_SZ) failed", valueName ? valueName : "(default)"); return false; } ffStrbufEnsureFree(result, bufSize - 1); if(RegGetValueA(hKey, NULL, valueName, RRF_RT_REG_SZ, NULL, result->chars, &bufSize) != ERROR_SUCCESS) { - if(error) ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_REG_SZ) failed", valueName); + if(error) ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_REG_SZ) failed", valueName ? valueName : "(default)"); return false; } result->length = bufSize - 1; @@ -52,7 +52,7 @@ bool ffRegReadUint(HKEY hKey, const char* valueName, uint32_t* result, FFstrbuf* DWORD bufSize = sizeof(*result); if(RegGetValueA(hKey, NULL, valueName, RRF_RT_DWORD, NULL, result, &bufSize) != ERROR_SUCCESS) { - if(error) ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_DWORD) failed", valueName); + if(error) ffStrbufAppendF(error, "RegGetValueA(%s, result, RRF_RT_DWORD) failed", valueName ? valueName : "(default)"); return false; } return true;