summaryrefslogtreecommitdiffstats
path: root/src/detection/cursor/cursor_linux.c
blob: 89dabbc3711b51266e79e3679041141a4d8b3505 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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");
    }
}