KWin
Loading...
Searching...
No Matches
auroraetheme.cpp
Go to the documentation of this file.
1/*
2 Library for Aurorae window decoration themes.
3 SPDX-FileCopyrightText: 2009, 2010, 2012 Martin Gräßlin <mgraesslin@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6
7*/
8
9#include "auroraetheme.h"
10#include "themeconfig.h"
11// Qt
12#include <QDebug>
13#include <QHash>
14#include <QStandardPaths>
15// KDE
16#include <KConfig>
17#include <KConfigGroup>
18
19Q_LOGGING_CATEGORY(AURORAE, "aurorae", QtWarningMsg)
20
21namespace Aurorae
22{
23
24/************************************************
25 * AuroraeThemePrivate
26 ************************************************/
28{
29public:
33 QString themeName;
35 QHash<AuroraeButtonType, QString> pathes;
37 KDecoration2::BorderSize borderSize;
38 KDecoration2::BorderSize buttonSize;
39 QString dragMimeType;
41};
42
44 : activeCompositing(true)
45 , borderSize(KDecoration2::BorderSize::Normal)
46 , buttonSize(KDecoration2::BorderSize::Normal)
47{
48}
49
53
55{
56 QString file(QLatin1String("aurorae/themes/") + themeName + QLatin1Char('/') + AuroraeTheme::mapButtonToName(type) + QLatin1String(".svg"));
57 QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, file);
58 if (path.isEmpty()) {
59 // let's look for svgz
60 file += QLatin1String("z");
61 path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, file);
62 }
63 if (!path.isEmpty()) {
64 pathes[type] = path;
65 } else {
66 qCDebug(AURORAE) << "No button for: " << AuroraeTheme::mapButtonToName(type);
67 }
68}
69
70/************************************************
71 * AuroraeTheme
72 ************************************************/
74 : QObject(parent)
75 , d(std::make_unique<AuroraeThemePrivate>())
76{
79}
80
82
84{
85 return !d->themeName.isNull();
86}
87
88void AuroraeTheme::loadTheme(const QString &name)
89{
90 KConfig conf(QStringLiteral("auroraerc"));
91 KConfig config(QLatin1String("aurorae/themes/") + name + QLatin1Char('/') + name + QLatin1String("rc"),
92 KConfig::FullConfig, QStandardPaths::GenericDataLocation);
93 KConfigGroup themeGroup(&conf, name);
94 loadTheme(name, config);
95}
96
97void AuroraeTheme::loadTheme(const QString &name, const KConfig &config)
98{
99 d->themeName = name;
100 QString file(QLatin1String("aurorae/themes/") + d->themeName + QLatin1String("/decoration.svg"));
101 QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, file);
102 if (path.isEmpty()) {
103 file += QLatin1String("z");
104 path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, file);
105 }
106 if (path.isEmpty()) {
107 qCDebug(AURORAE) << "Could not find decoration svg: aborting";
108 d->themeName.clear();
109 return;
110 }
111 d->decorationPath = path;
112
113 // load the buttons
114 d->initButtonFrame(MinimizeButton);
115 d->initButtonFrame(MaximizeButton);
116 d->initButtonFrame(RestoreButton);
117 d->initButtonFrame(CloseButton);
118 d->initButtonFrame(AllDesktopsButton);
119 d->initButtonFrame(KeepAboveButton);
120 d->initButtonFrame(KeepBelowButton);
121 d->initButtonFrame(ShadeButton);
122 d->initButtonFrame(HelpButton);
123
124 d->themeConfig.load(config);
125 Q_EMIT themeChanged();
126}
127
129{
130 return d->pathes.contains(button);
131}
132
134{
135 switch (type) {
136 case MinimizeButton:
137 return QLatin1String("minimize");
138 case MaximizeButton:
139 return QLatin1String("maximize");
140 case RestoreButton:
141 return QLatin1String("restore");
142 case CloseButton:
143 return QLatin1String("close");
145 return QLatin1String("alldesktops");
146 case KeepAboveButton:
147 return QLatin1String("keepabove");
148 case KeepBelowButton:
149 return QLatin1String("keepbelow");
150 case ShadeButton:
151 return QLatin1String("shade");
152 case HelpButton:
153 return QLatin1String("help");
154 case MenuButton:
155 return QLatin1String("menu");
156 case AppMenuButton:
157 return QLatin1String("appmenu");
158 default:
159 return QLatin1String("");
160 }
161}
162
163const QString &AuroraeTheme::themeName() const
164{
165 return d->themeName;
166}
167
168void AuroraeTheme::borders(int &left, int &top, int &right, int &bottom, bool maximized) const
169{
170 const qreal titleHeight = std::max((qreal)d->themeConfig.titleHeight(),
171 d->themeConfig.buttonHeight() * buttonSizeFactor() + d->themeConfig.buttonMarginTop());
172 if (maximized) {
173 const qreal title = titleHeight + d->themeConfig.titleEdgeTopMaximized() + d->themeConfig.titleEdgeBottomMaximized();
174 switch ((DecorationPosition)d->themeConfig.decorationPosition()) {
175 case DecorationTop:
176 left = right = bottom = 0;
177 top = title;
178 break;
179 case DecorationBottom:
180 left = right = top = 0;
181 bottom = title;
182 break;
183 case DecorationLeft:
184 top = right = bottom = 0;
185 left = title;
186 break;
187 case DecorationRight:
188 left = top = bottom = 0;
189 right = title;
190 break;
191 default:
192 left = right = bottom = top = 0;
193 break;
194 }
195 } else {
196 int minMargin;
197 int maxMargin;
198 switch (d->borderSize) {
199 case KDecoration2::BorderSize::NoSides:
200 case KDecoration2::BorderSize::Tiny:
201 minMargin = 1;
202 maxMargin = 4;
203 break;
204 case KDecoration2::BorderSize::Normal:
205 minMargin = 4;
206 maxMargin = 6;
207 break;
208 case KDecoration2::BorderSize::Large:
209 minMargin = 6;
210 maxMargin = 8;
211 break;
212 case KDecoration2::BorderSize::VeryLarge:
213 minMargin = 8;
214 maxMargin = 12;
215 break;
216 case KDecoration2::BorderSize::Huge:
217 minMargin = 12;
218 maxMargin = 20;
219 break;
220 case KDecoration2::BorderSize::VeryHuge:
221 minMargin = 23;
222 maxMargin = 30;
223 break;
224 case KDecoration2::BorderSize::Oversized:
225 minMargin = 36;
226 maxMargin = 48;
227 break;
228 default:
229 minMargin = 0;
230 maxMargin = 0;
231 }
232
233 left = std::clamp(d->themeConfig.borderLeft(), minMargin, maxMargin);
234 right = std::clamp(d->themeConfig.borderRight(), minMargin, maxMargin);
235 bottom = std::clamp(d->themeConfig.borderBottom(), minMargin, maxMargin);
236
237 if (d->borderSize == KDecoration2::BorderSize::None) {
238 left = 0;
239 right = 0;
240 bottom = 0;
241 } else if (d->borderSize == KDecoration2::BorderSize::NoSides) {
242 left = 0;
243 right = 0;
244 }
245
246 const qreal title = titleHeight + d->themeConfig.titleEdgeTop() + d->themeConfig.titleEdgeBottom();
247 switch ((DecorationPosition)d->themeConfig.decorationPosition()) {
248 case DecorationTop:
249 top = title;
250 break;
251 case DecorationBottom:
252 bottom = title;
253 break;
254 case DecorationLeft:
255 left = title;
256 break;
257 case DecorationRight:
258 right = title;
259 break;
260 default:
261 left = right = bottom = top = 0;
262 break;
263 }
264 }
265}
266
268{
269 int left, top, right, bottom;
270 left = top = right = bottom = 0;
271 borders(left, top, right, bottom, false);
272 return bottom;
273}
274
276{
277 int left, top, right, bottom;
278 left = top = right = bottom = 0;
279 borders(left, top, right, bottom, false);
280 return left;
281}
282
284{
285 int left, top, right, bottom;
286 left = top = right = bottom = 0;
287 borders(left, top, right, bottom, false);
288 return right;
289}
290
292{
293 int left, top, right, bottom;
294 left = top = right = bottom = 0;
295 borders(left, top, right, bottom, false);
296 return top;
297}
298
300{
301 int left, top, right, bottom;
302 left = top = right = bottom = 0;
303 borders(left, top, right, bottom, true);
304 return bottom;
305}
306
308{
309 int left, top, right, bottom;
310 left = top = right = bottom = 0;
311 borders(left, top, right, bottom, true);
312 return left;
313}
314
316{
317 int left, top, right, bottom;
318 left = top = right = bottom = 0;
319 borders(left, top, right, bottom, true);
320 return right;
321}
322
324{
325 int left, top, right, bottom;
326 left = top = right = bottom = 0;
327 borders(left, top, right, bottom, true);
328 return top;
329}
330
331void AuroraeTheme::padding(int &left, int &top, int &right, int &bottom) const
332{
333 left = d->themeConfig.paddingLeft();
334 top = d->themeConfig.paddingTop();
335 right = d->themeConfig.paddingRight();
336 bottom = d->themeConfig.paddingBottom();
337}
338
339#define THEME_CONFIG(prototype) \
340 int AuroraeTheme::prototype() const \
341 { \
342 return d->themeConfig.prototype(); \
343 }
344
345THEME_CONFIG(paddingBottom)
346THEME_CONFIG(paddingLeft)
347THEME_CONFIG(paddingRight)
348THEME_CONFIG(paddingTop)
349THEME_CONFIG(buttonWidth)
350THEME_CONFIG(buttonWidthMinimize)
351THEME_CONFIG(buttonWidthMaximizeRestore)
352THEME_CONFIG(buttonWidthClose)
353THEME_CONFIG(buttonWidthAllDesktops)
354THEME_CONFIG(buttonWidthKeepAbove)
355THEME_CONFIG(buttonWidthKeepBelow)
356THEME_CONFIG(buttonWidthShade)
357THEME_CONFIG(buttonWidthHelp)
358THEME_CONFIG(buttonWidthMenu)
359THEME_CONFIG(buttonWidthAppMenu)
360THEME_CONFIG(buttonHeight)
361THEME_CONFIG(buttonSpacing)
362THEME_CONFIG(buttonMarginTop)
363THEME_CONFIG(explicitButtonSpacer)
364THEME_CONFIG(animationTime)
365THEME_CONFIG(titleEdgeLeft)
366THEME_CONFIG(titleEdgeRight)
367THEME_CONFIG(titleEdgeTop)
368THEME_CONFIG(titleEdgeLeftMaximized)
369THEME_CONFIG(titleEdgeRightMaximized)
370THEME_CONFIG(titleEdgeTopMaximized)
371THEME_CONFIG(titleBorderLeft)
372THEME_CONFIG(titleBorderRight)
373THEME_CONFIG(titleHeight)
374
375#undef THEME_CONFIG
376
377#define THEME_CONFIG_TYPE(rettype, prototype) \
378 rettype AuroraeTheme::prototype() const \
379 { \
380 return d->themeConfig.prototype(); \
381 }
382
383THEME_CONFIG_TYPE(QColor, activeTextColor)
384THEME_CONFIG_TYPE(QColor, inactiveTextColor)
385THEME_CONFIG_TYPE(Qt::Alignment, alignment)
386THEME_CONFIG_TYPE(Qt::Alignment, verticalAlignment)
387
388#undef THEME_CONFIG_TYPE
389
391{
392 return d->decorationPath;
393}
394
395#define BUTTON_PATH(prototype, buttonType) \
396 QString AuroraeTheme::prototype() const \
397 { \
398 if (hasButton(buttonType)) { \
399 return d->pathes[buttonType]; \
400 } else { \
401 return QString(); \
402 } \
403 }
404
405BUTTON_PATH(minimizeButtonPath, MinimizeButton)
406BUTTON_PATH(maximizeButtonPath, MaximizeButton)
407BUTTON_PATH(restoreButtonPath, RestoreButton)
408BUTTON_PATH(closeButtonPath, CloseButton)
409BUTTON_PATH(allDesktopsButtonPath, AllDesktopsButton)
410BUTTON_PATH(keepAboveButtonPath, KeepAboveButton)
411BUTTON_PATH(keepBelowButtonPath, KeepBelowButton)
412BUTTON_PATH(shadeButtonPath, ShadeButton)
413BUTTON_PATH(helpButtonPath, HelpButton)
414
415#undef BUTTON_PATH
416
417void AuroraeTheme::titleEdges(int &left, int &top, int &right, int &bottom, bool maximized) const
418{
419 if (maximized) {
420 left = d->themeConfig.titleEdgeLeftMaximized();
421 top = d->themeConfig.titleEdgeTopMaximized();
422 right = d->themeConfig.titleEdgeRightMaximized();
423 bottom = d->themeConfig.titleEdgeBottomMaximized();
424 } else {
425 left = d->themeConfig.titleEdgeLeft();
426 top = d->themeConfig.titleEdgeTop();
427 right = d->themeConfig.titleEdgeRight();
428 bottom = d->themeConfig.titleEdgeBottom();
429 }
430}
431
433{
434 return d->activeCompositing;
435}
436
438{
439 d->activeCompositing = active;
440}
441
442void AuroraeTheme::setBorderSize(KDecoration2::BorderSize size)
443{
444 if (d->borderSize == size) {
445 return;
446 }
447 d->borderSize = size;
448 Q_EMIT borderSizesChanged();
449}
450
451void AuroraeTheme::setButtonSize(KDecoration2::BorderSize size)
452{
453 if (d->buttonSize == size) {
454 return;
455 }
456 d->buttonSize = size;
457 Q_EMIT buttonSizesChanged();
458}
459
460void AuroraeTheme::setTabDragMimeType(const QString &mime)
461{
462 d->dragMimeType = mime;
463}
464
465const QString &AuroraeTheme::tabDragMimeType() const
466{
467 return d->dragMimeType;
468}
469
471{
472 switch (d->buttonSize) {
473 case KDecoration2::BorderSize::Tiny:
474 return 0.8;
475 case KDecoration2::BorderSize::Large:
476 return 1.2;
477 case KDecoration2::BorderSize::VeryLarge:
478 return 1.4;
479 case KDecoration2::BorderSize::Huge:
480 return 1.6;
481 case KDecoration2::BorderSize::VeryHuge:
482 return 1.8;
483 case KDecoration2::BorderSize::Oversized:
484 return 2.0;
485 case KDecoration2::BorderSize::Normal: // fall through
486 default:
487 return 1.0;
488 }
489}
490
492{
493 return (DecorationPosition)d->themeConfig.decorationPosition();
494}
495
496} // namespace
497
498#include "moc_auroraetheme.cpp"
#define THEME_CONFIG(prototype)
#define BUTTON_PATH(prototype, buttonType)
#define THEME_CONFIG_TYPE(rettype, prototype)
const QString & tabDragMimeType() const
static QLatin1String mapButtonToName(AuroraeButtonType type)
int rightBorderMaximized() const
bool hasButton(AuroraeButtonType button) const
int bottomBorderMaximized() const
bool isCompositingActive() const
void titleEdges(int &left, int &top, int &right, int &bottom, bool maximized) const
void setCompositingActive(bool active)
void setButtonSize(KDecoration2::BorderSize size)
void setTabDragMimeType(const QString &mime)
int leftBorderMaximized() const
void loadTheme(const QString &name, const KConfig &config)
~AuroraeTheme() override
void setBorderSize(KDecoration2::BorderSize size)
AuroraeTheme(QObject *parent=nullptr)
int topBorderMaximized() const
DecorationPosition decorationPosition() const
KDecoration2::BorderSize borderSize
KDecoration2::BorderSize buttonSize
Aurorae::ThemeConfig themeConfig
QHash< AuroraeButtonType, QString > pathes
void initButtonFrame(AuroraeButtonType type)
@ DecorationBottom
@ DecorationRight
@ DecorationLeft
@ DecorationTop
@ AllDesktopsButton
@ KeepAboveButton
@ KeepBelowButton
@ MaximizeButton
@ RestoreButton
@ MinimizeButton
@ AppMenuButton