Coverage Report

Created: 2026-07-25 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibGfx/SystemTheme.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3
 * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org>
4
 * Copyright (c) 2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 */
8
9
#pragma once
10
11
#include <AK/ByteString.h>
12
#include <AK/Forward.h>
13
#include <AK/Types.h>
14
#include <AK/Vector.h>
15
#include <LibCore/AnonymousBuffer.h>
16
#include <LibCore/ConfigFile.h>
17
#include <LibGfx/Color.h>
18
#include <LibGfx/TextAlignment.h>
19
20
namespace Gfx {
21
22
#define ENUMERATE_COLOR_ROLES(C)   \
23
    C(Accent)                      \
24
    C(ActiveLink)                  \
25
    C(ActiveWindowBorder1)         \
26
    C(ActiveWindowBorder2)         \
27
    C(ActiveWindowTitle)           \
28
    C(ActiveWindowTitleShadow)     \
29
    C(ActiveWindowTitleStripes)    \
30
    C(Base)                        \
31
    C(BaseText)                    \
32
    C(Black)                       \
33
    C(Blue)                        \
34
    C(BrightBlack)                 \
35
    C(BrightBlue)                  \
36
    C(BrightCyan)                  \
37
    C(BrightGreen)                 \
38
    C(BrightMagenta)               \
39
    C(BrightRed)                   \
40
    C(BrightWhite)                 \
41
    C(BrightYellow)                \
42
    C(Button)                      \
43
    C(ButtonText)                  \
44
    C(ColorSchemeBackground)       \
45
    C(ColorSchemeForeground)       \
46
    C(Cyan)                        \
47
    C(DisabledTextFront)           \
48
    C(DisabledTextBack)            \
49
    C(DesktopBackground)           \
50
    C(FocusOutline)                \
51
    C(Green)                       \
52
    C(Gutter)                      \
53
    C(GutterBorder)                \
54
    C(HighlightWindowBorder1)      \
55
    C(HighlightWindowBorder2)      \
56
    C(HighlightWindowTitle)        \
57
    C(HighlightWindowTitleShadow)  \
58
    C(HighlightWindowTitleStripes) \
59
    C(HighlightSearching)          \
60
    C(HighlightSearchingText)      \
61
    C(HoverHighlight)              \
62
    C(InactiveSelection)           \
63
    C(InactiveSelectionText)       \
64
    C(InactiveWindowBorder1)       \
65
    C(InactiveWindowBorder2)       \
66
    C(InactiveWindowTitle)         \
67
    C(InactiveWindowTitleShadow)   \
68
    C(InactiveWindowTitleStripes)  \
69
    C(Link)                        \
70
    C(Magenta)                     \
71
    C(MenuBase)                    \
72
    C(MenuBaseText)                \
73
    C(MenuSelection)               \
74
    C(MenuSelectionText)           \
75
    C(MenuStripe)                  \
76
    C(MovingWindowBorder1)         \
77
    C(MovingWindowBorder2)         \
78
    C(MovingWindowTitle)           \
79
    C(MovingWindowTitleShadow)     \
80
    C(MovingWindowTitleStripes)    \
81
    C(OverlayText)                 \
82
    C(OverlayBackground)           \
83
    C(PlaceholderText)             \
84
    C(Red)                         \
85
    C(RubberBandBorder)            \
86
    C(RubberBandFill)              \
87
    C(Ruler)                       \
88
    C(RulerActiveText)             \
89
    C(RulerBorder)                 \
90
    C(RulerInactiveText)           \
91
    C(Selection)                   \
92
    C(SelectionText)               \
93
    C(SyntaxComment)               \
94
    C(SyntaxControlKeyword)        \
95
    C(SyntaxIdentifier)            \
96
    C(SyntaxKeyword)               \
97
    C(SyntaxNumber)                \
98
    C(SyntaxOperator)              \
99
    C(SyntaxPreprocessorStatement) \
100
    C(SyntaxPreprocessorValue)     \
101
    C(SyntaxPunctuation)           \
102
    C(SyntaxString)                \
103
    C(SyntaxType)                  \
104
    C(SyntaxFunction)              \
105
    C(SyntaxVariable)              \
106
    C(SyntaxCustomType)            \
107
    C(SyntaxNamespace)             \
108
    C(SyntaxMember)                \
109
    C(SyntaxParameter)             \
110
    C(TextCursor)                  \
111
    C(ThreedHighlight)             \
112
    C(ThreedShadow1)               \
113
    C(ThreedShadow2)               \
114
    C(Tooltip)                     \
115
    C(TooltipText)                 \
116
    C(Tray)                        \
117
    C(TrayText)                    \
118
    C(VisitedLink)                 \
119
    C(White)                       \
120
    C(Window)                      \
121
    C(WindowText)                  \
122
    C(Yellow)
123
124
#define ENUMERATE_ALIGNMENT_ROLES(C) \
125
    C(TitleAlignment)
126
127
#define ENUMERATE_WINDOW_THEME_ROLES(C) \
128
    C(WindowTheme)
129
130
#define ENUMERATE_FLAG_ROLES(C) \
131
    C(BoldTextAsBright)         \
132
    C(IsDark)                   \
133
    C(TitleButtonsIconOnly)
134
135
#define ENUMERATE_METRIC_ROLES(C) \
136
    C(BorderThickness)            \
137
    C(BorderRadius)               \
138
    C(TitleHeight)                \
139
    C(TitleButtonWidth)           \
140
    C(TitleButtonHeight)          \
141
    C(TitleButtonInactiveAlpha)
142
143
#define ENUMERATE_PATH_ROLES(C) \
144
    C(TitleButtonIcons)         \
145
    C(InactiveWindowShadow)     \
146
    C(ActiveWindowShadow)       \
147
    C(TaskbarShadow)            \
148
    C(MenuShadow)               \
149
    C(TooltipShadow)            \
150
    C(ColorScheme)              \
151
    C(OverlayRectShadow)
152
153
enum class ColorRole {
154
    NoRole,
155
156
#undef __ENUMERATE_COLOR_ROLE
157
#define __ENUMERATE_COLOR_ROLE(role) role,
158
    ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE)
159
#undef __ENUMERATE_COLOR_ROLE
160
161
        __Count,
162
163
    Background = Window,
164
    DisabledText = ThreedShadow1,
165
};
166
167
inline StringView to_string(ColorRole role)
168
0
{
169
0
    switch (role) {
170
0
    case ColorRole::NoRole:
171
0
        return "NoRole"sv;
172
0
#undef __ENUMERATE_COLOR_ROLE
173
0
#define __ENUMERATE_COLOR_ROLE(role) \
174
0
    case ColorRole::role:            \
175
0
        return #role##sv;
176
0
        ENUMERATE_COLOR_ROLES(__ENUMERATE_COLOR_ROLE)
177
0
#undef __ENUMERATE_COLOR_ROLE
178
0
    default:
179
0
        VERIFY_NOT_REACHED();
180
0
    }
181
0
}
182
183
enum class AlignmentRole {
184
    NoRole,
185
186
#undef __ENUMERATE_ALIGNMENT_ROLE
187
#define __ENUMERATE_ALIGNMENT_ROLE(role) role,
188
    ENUMERATE_ALIGNMENT_ROLES(__ENUMERATE_ALIGNMENT_ROLE)
189
#undef __ENUMERATE_ALIGNMENT_ROLE
190
191
        __Count,
192
};
193
194
inline StringView to_string(AlignmentRole role)
195
0
{
196
0
    switch (role) {
197
0
    case AlignmentRole::NoRole:
198
0
        return "NoRole"sv;
199
0
#undef __ENUMERATE_ALIGNMENT_ROLE
200
0
#define __ENUMERATE_ALIGNMENT_ROLE(role) \
201
0
    case AlignmentRole::role:            \
202
0
        return #role##sv;
203
0
        ENUMERATE_ALIGNMENT_ROLES(__ENUMERATE_ALIGNMENT_ROLE)
204
0
#undef __ENUMERATE_ALIGNMENT_ROLE
205
0
    default:
206
0
        VERIFY_NOT_REACHED();
207
0
    }
208
0
}
209
210
enum class WindowThemeRole {
211
    NoRole,
212
213
#undef __ENUMERATE_WINDOW_THEME_ROLE
214
#define __ENUMERATE_WINDOW_THEME_ROLE(role) role,
215
    ENUMERATE_WINDOW_THEME_ROLES(__ENUMERATE_WINDOW_THEME_ROLE)
216
#undef __ENUMERATE_WINDOW_THEME_ROLE
217
218
        __Count,
219
};
220
221
inline StringView to_string(WindowThemeRole role)
222
0
{
223
0
    switch (role) {
224
0
    case WindowThemeRole::NoRole:
225
0
        return "NoRole"sv;
226
0
#undef __ENUMERATE_ALIGNMENT_ROLE
227
0
#define __ENUMERATE_ALIGNMENT_ROLE(role) \
228
0
    case WindowThemeRole::role:          \
229
0
        return #role##sv;
230
0
        ENUMERATE_WINDOW_THEME_ROLES(__ENUMERATE_ALIGNMENT_ROLE)
231
0
#undef __ENUMERATE_ALIGNMENT_ROLE
232
0
    default:
233
0
        VERIFY_NOT_REACHED();
234
0
    }
235
0
}
236
237
enum class FlagRole {
238
    NoRole,
239
240
#undef __ENUMERATE_FLAG_ROLE
241
#define __ENUMERATE_FLAG_ROLE(role) role,
242
    ENUMERATE_FLAG_ROLES(__ENUMERATE_FLAG_ROLE)
243
#undef __ENUMERATE_FLAG_ROLE
244
245
        __Count,
246
};
247
248
inline StringView to_string(FlagRole role)
249
0
{
250
0
    switch (role) {
251
0
    case FlagRole::NoRole:
252
0
        return "NoRole"sv;
253
0
#undef __ENUMERATE_FLAG_ROLE
254
0
#define __ENUMERATE_FLAG_ROLE(role) \
255
0
    case FlagRole::role:            \
256
0
        return #role##sv;
257
0
        ENUMERATE_FLAG_ROLES(__ENUMERATE_FLAG_ROLE)
258
0
#undef __ENUMERATE_FLAG_ROLE
259
0
    default:
260
0
        VERIFY_NOT_REACHED();
261
0
    }
262
0
}
263
264
enum class MetricRole {
265
    NoRole,
266
267
#undef __ENUMERATE_METRIC_ROLE
268
#define __ENUMERATE_METRIC_ROLE(role) role,
269
    ENUMERATE_METRIC_ROLES(__ENUMERATE_METRIC_ROLE)
270
#undef __ENUMERATE_METRIC_ROLE
271
272
        __Count,
273
};
274
275
inline StringView to_string(MetricRole role)
276
0
{
277
0
    switch (role) {
278
0
    case MetricRole::NoRole:
279
0
        return "NoRole"sv;
280
0
#undef __ENUMERATE_METRIC_ROLE
281
0
#define __ENUMERATE_METRIC_ROLE(role) \
282
0
    case MetricRole::role:            \
283
0
        return #role##sv;
284
0
        ENUMERATE_METRIC_ROLES(__ENUMERATE_METRIC_ROLE)
285
0
#undef __ENUMERATE_METRIC_ROLE
286
0
    default:
287
0
        VERIFY_NOT_REACHED();
288
0
    }
289
0
}
290
291
enum class PathRole {
292
    NoRole,
293
294
#undef __ENUMERATE_PATH_ROLE
295
#define __ENUMERATE_PATH_ROLE(role) role,
296
    ENUMERATE_PATH_ROLES(__ENUMERATE_PATH_ROLE)
297
#undef __ENUMERATE_PATH_ROLE
298
299
        __Count,
300
};
301
302
inline StringView to_string(PathRole role)
303
0
{
304
0
    switch (role) {
305
0
    case PathRole::NoRole:
306
0
        return "NoRole"sv;
307
0
#undef __ENUMERATE_PATH_ROLE
308
0
#define __ENUMERATE_PATH_ROLE(role) \
309
0
    case PathRole::role:            \
310
0
        return #role##sv;
311
0
        ENUMERATE_PATH_ROLES(__ENUMERATE_PATH_ROLE)
312
0
#undef __ENUMERATE_PATH_ROLE
313
0
    default:
314
0
        VERIFY_NOT_REACHED();
315
0
    }
316
0
}
317
318
#define ENUMERATE_WINDOW_THEMES(M) \
319
    M(Classic)                     \
320
    M(RedmondGlass)                \
321
    M(RedmondPlastic)
322
323
enum class WindowThemeProvider {
324
#define __ENUMERATE(x) x,
325
    ENUMERATE_WINDOW_THEMES(__ENUMERATE)
326
#undef __ENUMERATE
327
};
328
329
inline Optional<WindowThemeProvider> window_theme_provider_from_string(StringView string)
330
0
{
331
0
#define __ENUMERATE(x) \
332
0
    if (string == #x)  \
333
0
        return WindowThemeProvider::x;
334
0
    ENUMERATE_WINDOW_THEMES(__ENUMERATE)
335
0
#undef __ENUMERATE
336
0
    return {};
337
0
}
338
339
inline char const* to_string(WindowThemeProvider window_theme_provider)
340
0
{
341
0
#define __ENUMERATE(x)                                   \
342
0
    if (window_theme_provider == WindowThemeProvider::x) \
343
0
        return #x;
344
0
    ENUMERATE_WINDOW_THEMES(__ENUMERATE)
345
0
#undef __ENUMERATE
346
0
    return {};
347
0
}
348
349
struct SystemTheme {
350
    ARGB32 color[(int)ColorRole::__Count];
351
    Gfx::TextAlignment alignment[(int)AlignmentRole::__Count];
352
    WindowThemeProvider window_theme[(int)WindowThemeRole::__Count];
353
    bool flag[(int)FlagRole::__Count];
354
    int metric[(int)MetricRole::__Count];
355
    char path[(int)PathRole::__Count][256]; // TODO: PATH_MAX?
356
};
357
358
Core::AnonymousBuffer& current_system_theme_buffer();
359
void set_system_theme(Core::AnonymousBuffer);
360
ErrorOr<Core::AnonymousBuffer> load_system_theme(Core::ConfigFile const&, Optional<ByteString> const& color_scheme = OptionalNone());
361
ErrorOr<Core::AnonymousBuffer> load_system_theme(ByteString const& path, Optional<ByteString> const& color_scheme = OptionalNone());
362
363
struct SystemThemeMetaData {
364
    ByteString name;
365
    ByteString menu_name;
366
    ByteString path;
367
};
368
369
ErrorOr<Vector<SystemThemeMetaData>> list_installed_system_themes();
370
371
}
372
373
using Gfx::ColorRole;