Libplasma

plasmawindow.cpp
1/*
2 SPDX-FileCopyrightText: 2023 David Edmundson <davidedmundson@kde.org>
3 SPDX-License-Identifier: LGPL-2.0-or-later
4*/
5
6#include "plasmawindow.h"
7
8#include "dialogbackground_p.h"
9#include "dialogshadows_p.h"
10
11#include <QMarginsF>
12#include <QQuickItem>
13
14#include <KWindowEffects>
15#include <KWindowSystem>
16#include <KX11Extras>
17
18#include <Plasma/Theme>
19
20using namespace Plasma;
21
22namespace PlasmaQuick
23{
24class PlasmaWindowPrivate
25{
26public:
27 PlasmaWindowPrivate(PlasmaWindow *_q)
28 : q(_q)
29 {
30 }
31 void handleFrameChanged();
32 void updateMainItemGeometry();
33 PlasmaWindow *q;
34 DialogShadows *shadows;
35 // Keep a theme instance as a memeber to create one as soon as possible,
36 // as Theme creation will set KSvg to correctly fetch images form the Plasma Theme.
37 // This makes sure elements are correct, both in the dialog surface and the shadows.
38 Plasma::Theme theme;
39 QPointer<QQuickItem> mainItem;
40 DialogBackground *dialogBackground;
41 PlasmaWindow::BackgroundHints backgroundHints = PlasmaWindow::StandardBackground;
42};
43
44PlasmaWindow::PlasmaWindow(const QString &svgPrefix)
45 : QQuickWindow()
46 , d(new PlasmaWindowPrivate(this))
47{
48 setColor(QColor(Qt::transparent));
50
51 d->shadows = DialogShadows::instance(svgPrefix);
52 d->dialogBackground = new DialogBackground(contentItem());
53 d->dialogBackground->setImagePath(svgPrefix);
54 connect(d->dialogBackground, &DialogBackground::fixedMarginsChanged, this, [this]() {
55 d->updateMainItemGeometry();
56 Q_EMIT paddingChanged();
57 });
58 connect(d->dialogBackground, &DialogBackground::maskChanged, this, [this]() {
59 d->handleFrameChanged();
60 });
61
62 d->shadows->addWindow(this, d->dialogBackground->enabledBorders());
63}
64
65PlasmaWindow::~PlasmaWindow()
66{
67}
68
69void PlasmaWindow::setMainItem(QQuickItem *mainItem)
70{
71 if (d->mainItem == mainItem)
72 return;
73
74 if (d->mainItem) {
75 d->mainItem->setParentItem(nullptr);
76 }
77
78 d->mainItem = mainItem;
79 Q_EMIT mainItemChanged();
80
81 if (d->mainItem) {
82 mainItem->setParentItem(contentItem());
83 d->updateMainItemGeometry();
84 }
85}
86
87QQuickItem *PlasmaWindow::mainItem() const
88{
89 return d->mainItem;
90}
91
92static KSvg::FrameSvg::EnabledBorders edgeToBorder(Qt::Edges edges)
93{
94 KSvg::FrameSvg::EnabledBorders borders = KSvg::FrameSvg::EnabledBorders(0);
95
96 if (edges & Qt::Edge::TopEdge) {
97 borders |= KSvg::FrameSvg::EnabledBorder::TopBorder;
98 }
99 if (edges & Qt::Edge::BottomEdge) {
100 borders |= KSvg::FrameSvg::EnabledBorder::BottomBorder;
101 }
102 if (edges & Qt::Edge::LeftEdge) {
103 borders |= KSvg::FrameSvg::EnabledBorder::LeftBorder;
104 }
105 if (edges & Qt::Edge::RightEdge) {
106 borders |= KSvg::FrameSvg::EnabledBorder::RightBorder;
107 }
108
109 return borders;
110}
111
112static Qt::Edges bordersToEdge(KSvg::FrameSvg::EnabledBorders borders)
113{
114 Qt::Edges edges;
115 if (borders & KSvg::FrameSvg::EnabledBorder::TopBorder) {
116 edges |= Qt::Edge::TopEdge;
117 }
118 if (borders & KSvg::FrameSvg::EnabledBorder::BottomBorder) {
119 edges |= Qt::Edge::BottomEdge;
120 }
121 if (borders & KSvg::FrameSvg::EnabledBorder::LeftBorder) {
122 edges |= Qt::Edge::LeftEdge;
123 }
124 if (borders & KSvg::FrameSvg::EnabledBorder::RightBorder) {
125 edges |= Qt::Edge::RightEdge;
126 }
127 return edges;
128}
129
130void PlasmaWindow::setBorders(Qt::Edges bordersToShow)
131{
132 d->dialogBackground->setEnabledBorders(edgeToBorder(bordersToShow));
133 d->shadows->setEnabledBorders(this, d->dialogBackground->enabledBorders());
134 Q_EMIT bordersChanged();
135}
136
137Qt::Edges PlasmaWindow::borders()
138{
139 return bordersToEdge(d->dialogBackground->enabledBorders());
140}
141
142void PlasmaWindow::showEvent(QShowEvent *e)
143{
144 // EWMH states that the state is reset every hide
145 // Qt supports external factors setting state before the next show
148 }
150}
151
152void PlasmaWindow::resizeEvent(QResizeEvent *e)
153{
155 const QSize windowSize = e->size();
156 d->dialogBackground->setSize(windowSize);
157 if (d->mainItem) {
158 const QSize contentSize = windowSize.shrunkBy(padding());
159 d->mainItem->setSize(contentSize);
160 }
161}
162
163void PlasmaWindowPrivate::handleFrameChanged()
164{
165 const QRegion mask = dialogBackground->mask();
166 KWindowEffects::enableBlurBehind(q, theme.blurBehindEnabled(), mask);
168 theme.backgroundContrastEnabled(),
169 theme.backgroundContrast(),
170 theme.backgroundIntensity(),
171 theme.backgroundSaturation(),
172 mask);
173
175 q->setMask(QRegion());
176 } else {
177 q->setMask(mask);
178 }
179}
180
181void PlasmaWindowPrivate::updateMainItemGeometry()
182{
183 if (!mainItem) {
184 return;
185 }
186 const QMargins frameMargins = q->padding();
187 const QSize windowSize = q->size();
188
189 mainItem->setX(frameMargins.left());
190 mainItem->setY(frameMargins.top());
191
192 const QSize contentSize = windowSize.shrunkBy(frameMargins);
193 mainItem->setSize(contentSize);
194}
195
196QMargins PlasmaWindow::padding() const
197{
198 return QMargins(d->dialogBackground->leftMargin(),
199 d->dialogBackground->topMargin(),
200 d->dialogBackground->rightMargin(),
201 d->dialogBackground->bottomMargin());
202}
203
204PlasmaWindow::BackgroundHints PlasmaWindow::backgroundHints() const
205{
206 return d->backgroundHints;
207}
208
209void PlasmaWindow::setBackgroundHints(BackgroundHints hints)
210{
211 if (d->backgroundHints == hints) {
212 return;
213 }
214 d->backgroundHints = hints;
215
216 auto prefix = QStringLiteral("");
217 if (d->backgroundHints == PlasmaWindow::SolidBackground) {
218 prefix = QStringLiteral("solid/");
219 }
220 d->dialogBackground->setImagePath(prefix + QStringLiteral("dialogs/background"));
221
222 Q_EMIT backgroundHintsChanged();
223}
224
225qreal PlasmaWindow::topPadding() const
226{
227 return d->dialogBackground->topMargin();
228}
229
230qreal PlasmaWindow::bottomPadding() const
231{
232 return d->dialogBackground->bottomMargin();
233}
234
235qreal PlasmaWindow::leftPadding() const
236{
237 return d->dialogBackground->leftMargin();
238}
239
240qreal PlasmaWindow::rightPadding() const
241{
242 return d->dialogBackground->rightMargin();
243}
244}
245
246#include "moc_plasmawindow.cpp"
Internal type used by DialogBackground in plasmaquick to load the actual background SVG.
static bool isPlatformX11()
static void setState(WId win, NET::States state)
bool compositingActive
SkipTaskbar
SkipSwitcher
Interface to the Plasma theme.
Definition theme.h:40
KCRASH_EXPORT void setFlags(KCrash::CrashFlags flags)
void enableBlurBehind(QWindow *window, bool enable=true, const QRegion &region=QRegion())
void enableBackgroundContrast(QWindow *window, bool enable=true, qreal contrast=1, qreal intensity=1, qreal saturation=1, const QRegion &region=QRegion())
The EdgeEventForwarder class This class forwards edge events to be replayed within the given margin T...
Definition action.h:20
Namespace for everything in libplasma.
int left() const const
int top() const const
void setParentItem(QQuickItem *parent)
void setSize(const QSizeF &size)
void setX(qreal)
void setY(qreal)
virtual void resizeEvent(QResizeEvent *ev) override
virtual void showEvent(QShowEvent *) override
const QSize & size() const const
QSize shrunkBy(QMargins margins) const const
typedef Edges
transparent
FramelessWindowHint
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:10:41 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.