summaryrefslogtreecommitdiffstats
path: root/src/detection/cursor
diff options
context:
space:
mode:
authorsumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
committersumuel <samuel@yakubos.org>2026-08-17 20:44:55 +0000
commit76424950e373d3b04ac3dd13019151bfba3e8423 (patch)
tree4c3cfdbda039e592b9186be3e28f8d7cfd439e8a /src/detection/cursor
Add the files
Diffstat (limited to 'src/detection/cursor')
-rw-r--r--src/detection/cursor/cursor.h12
-rw-r--r--src/detection/cursor/cursor_apple.m63
-rw-r--r--src/detection/cursor/cursor_linux.c101
-rw-r--r--src/detection/cursor/cursor_nosupport.c5
-rw-r--r--src/detection/cursor/cursor_windows.c17
5 files changed, 198 insertions, 0 deletions
diff --git a/src/detection/cursor/cursor.h b/src/detection/cursor/cursor.h
new file mode 100644
index 0000000..34ef86c
--- /dev/null
+++ b/src/detection/cursor/cursor.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "fastfetch.h"
+#include "modules/cursor/option.h"
+
+typedef struct FFCursorResult {
+ FFstrbuf theme;
+ FFstrbuf size;
+ FFstrbuf error;
+} FFCursorResult;
+
+void ffDetectCursor(FFCursorResult* result);
diff --git a/src/detection/cursor/cursor_apple.m b/src/detection/cursor/cursor_apple.m
new file mode 100644
index 0000000..610bd1e
--- /dev/null
+++ b/src/detection/cursor/cursor_apple.m
@@ -0,0 +1,63 @@
+#include "cursor.h"
+
+#import <Foundation/Foundation.h>
+
+static void appendColor(FFstrbuf* str, NSDictionary* dict)
+{
+ uint32_t r = (uint32_t) (((NSNumber*) dict[@"red"]).doubleValue * 255 + .5);
+ uint32_t g = (uint32_t) (((NSNumber*) dict[@"green"]).doubleValue * 255 + .5);
+ uint32_t b = (uint32_t) (((NSNumber*) dict[@"blue"]).doubleValue * 255 + .5);
+ uint32_t a = (uint32_t) (((NSNumber*) dict[@"alpha"]).doubleValue * 255 + .5);
+ uint32_t color = (r << 24) | (g << 16) | (b << 8) | a;
+
+ switch (color)
+ {
+ case 0x000000FF: ffStrbufAppendS(str, "Black"); return;
+ case 0x0433FFFF: ffStrbufAppendS(str, "Blue"); return;
+ case 0xAA7942FF: ffStrbufAppendS(str, "Brown"); return;
+ case 0x00FDFFFF: ffStrbufAppendS(str, "Cyan"); return;
+ case 0x00F900FF: ffStrbufAppendS(str, "Green"); return;
+ case 0xFF40FFFF: ffStrbufAppendS(str, "Magenta"); return;
+ case 0xFF9300FF: ffStrbufAppendS(str, "Orange"); return;
+ case 0x942192FF: ffStrbufAppendS(str, "Purple"); return;
+ case 0xFF2600FF: ffStrbufAppendS(str, "Red"); return;
+ case 0xFFFB00FF: ffStrbufAppendS(str, "Yellow"); return;
+ case 0xFFFFFFFF: ffStrbufAppendS(str, "White"); return;
+ case 0x00000000: ffStrbufAppendS(str, "Transparent"); return;
+ default: ffStrbufAppendF(str, "#%08X", color); return;
+ }
+}
+
+void ffDetectCursor(FFCursorResult* result)
+{
+ NSError* error;
+ NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.apple.universalaccess.plist", instance.state.platform.homeDir.chars];
+ NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
+ error:&error];
+ if(error)
+ {
+ ffStrbufAppendS(&result->error, error.localizedDescription.UTF8String);
+ return;
+ }
+
+ NSDictionary* color;
+
+ ffStrbufAppendS(&result->theme, "Fill - ");
+ if ((color = dict[@"cursorFill"]))
+ appendColor(&result->theme, color);
+ else
+ ffStrbufAppendS(&result->theme, "Black");
+
+ ffStrbufAppendS(&result->theme, ", Outline - ");
+
+ if ((color = dict[@"cursorOutline"]))
+ appendColor(&result->theme, color);
+ else
+ ffStrbufAppendS(&result->theme, "White");
+
+ NSNumber* mouseDriverCursorSize = dict[@"mouseDriverCursorSize"];
+ if (mouseDriverCursorSize)
+ ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32 + 0.5));
+ else
+ ffStrbufAppendS(&result->size, "32");
+}
diff --git a/src/detection/cursor/cursor_linux.c b/src/detection/cursor/cursor_linux.c
new file mode 100644
index 0000000..89dabbc
--- /dev/null
+++ b/src/detection/cursor/cursor_linux.c
@@ -0,0 +1,101 @@
+#include "cursor.h"
+
+#include "detection/gtk_qt/gtk_qt.h"
+#include "detection/displayserver/displayserver.h"
+#include "common/properties.h"
+#include "common/parsing.h"
+#include "common/settings.h"
+#include "common/strutil.h"
+
+#include <stdlib.h>
+
+static bool detectCursorGTK(FFCursorResult* result) {
+ const FFGTKResult* gtk = ffDetectGTK4();
+
+ if (gtk->cursor.length == 0) {
+ gtk = ffDetectGTK3();
+ }
+
+ if (gtk->cursor.length == 0) {
+ gtk = ffDetectGTK2();
+ }
+
+ if (gtk->cursor.length == 0) {
+ return false;
+ }
+
+ ffStrbufAppend(&result->theme, &gtk->cursor);
+ ffStrbufAppend(&result->size, &gtk->cursorSize);
+ return true;
+}
+
+static void detectCursorFromConfigFile(const char* relativeFilePath, const char* themeStart, const char* themeDefault, const char* sizeStart, const char* sizeDefault, FFCursorResult* result) {
+ if (ffParsePropFileConfigValues(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(FFCursorResult* result) {
+ ffParsePropFileHomeValues(".Xresources", 2, (FFpropquery[]) { { "Xcursor.theme :", &result->theme }, { "Xcursor.size :", &result->size } });
+
+ return result->theme.length > 0;
+}
+
+static bool detectCursorFromEnv(FFCursorResult* result) {
+ 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;
+}
+
+static bool detectCursorHyprcursor(FFCursorResult* result) {
+ const char* hyprcursor_theme = getenv("HYPRCURSOR_THEME");
+
+ if (!ffStrSet(hyprcursor_theme)) {
+ return false;
+ }
+
+ ffStrbufAppendS(&result->theme, hyprcursor_theme);
+ ffStrbufAppendS(&result->size, getenv("HYPRCURSOR_SIZE"));
+
+ return true;
+}
+
+void ffDetectCursor(FFCursorResult* result) {
+ const FFDisplayServerResult* wmde = ffConnectDisplayServer();
+
+ if (ffStrbufEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_WSLG)) {
+ ffStrbufAppendS(&result->error, "WSLg uses native windows cursor");
+ } else if (ffStrbufIgnCaseEqualS(&wmde->wmProtocolName, FF_WM_PROTOCOL_TTY)) {
+ ffStrbufAppendS(&result->error, "Cursor isn't supported in TTY");
+ } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_PLASMA)) {
+ detectCursorFromConfigFile("kcminputrc", "cursorTheme =", "Breeze", "cursorSize =", "24", result);
+ } else if (ffStrbufIgnCaseEqualS(&wmde->dePrettyName, FF_DE_PRETTY_LXQT)) {
+ detectCursorFromConfigFile("lxqt/session.conf", "cursor_theme =", "Adwaita", "cursor_size =", "24", result);
+ } else if (ffStrbufIgnCaseEqualS(&wmde->wmPrettyName, FF_WM_PRETTY_HYPRLAND) && detectCursorHyprcursor(result)) {
+ return;
+ } else if (
+ !detectCursorGTK(result) &&
+ !detectCursorFromEnv(result) &&
+ !ffParsePropFileHome(".icons/default/index.theme", "Inherits =", &result->theme) &&
+ !detectCursorFromXResources(result) &&
+ !ffParsePropFileData("icons/default/index.theme", "Inherits =", &result->theme)) {
+ ffStrbufAppendS(&result->error, "Couldn't find cursor");
+ }
+}
diff --git a/src/detection/cursor/cursor_nosupport.c b/src/detection/cursor/cursor_nosupport.c
new file mode 100644
index 0000000..6413d92
--- /dev/null
+++ b/src/detection/cursor/cursor_nosupport.c
@@ -0,0 +1,5 @@
+#include "cursor.h"
+
+void ffDetectCursor(FF_A_UNUSED 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 0000000..a6814ec
--- /dev/null
+++ b/src/detection/cursor/cursor_windows.c
@@ -0,0 +1,17 @@
+#include "cursor.h"
+
+#include "common/io.h"
+#include "common/windows/registry.h"
+
+void ffDetectCursor(FFCursorResult* result) {
+ FF_AUTO_CLOSE_FD HANDLE hKey = NULL;
+ if (ffRegOpenKeyForRead(HKEY_CURRENT_USER, L"Control Panel\\Cursors", &hKey, &result->error)) {
+ if (ffRegReadStrbuf(hKey, NULL, &result->theme, &result->error)) {
+ uint32_t cursorBaseSize;
+ if (ffRegReadUint(hKey, L"CursorBaseSize", &cursorBaseSize, NULL)) {
+ // Not available on Windows 8.1
+ ffStrbufAppendUInt(&result->size, cursorBaseSize);
+ };
+ }
+ }
+}