1 /*
2     SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3 
4     SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6 
7 #include "kwindowshadow.h"
8 #include "kwindowshadow_dummy_p.h"
9 #include "kwindowshadow_p.h"
10 #include "kwindowsystem_debug.h"
11 #include "pluginwrapper_p.h"
12 
13 #include <array>
14 
KWindowShadowTile()15 KWindowShadowTile::KWindowShadowTile()
16     : d(KWindowSystemPluginWrapper::self().createWindowShadowTile())
17 {
18 }
19 
~KWindowShadowTile()20 KWindowShadowTile::~KWindowShadowTile()
21 {
22     if (d->isCreated) {
23         d->destroy();
24     }
25 }
26 
image() const27 QImage KWindowShadowTile::image() const
28 {
29     return d->image;
30 }
31 
setImage(const QImage & image)32 void KWindowShadowTile::setImage(const QImage &image)
33 {
34     if (d->isCreated) {
35         qCWarning(LOG_KWINDOWSYSTEM,
36                   "Cannot change the image on a tile that already has native "
37                   "platform resources allocated.");
38         return;
39     }
40     d->image = image;
41 }
42 
isCreated() const43 bool KWindowShadowTile::isCreated() const
44 {
45     return d->isCreated;
46 }
47 
create()48 bool KWindowShadowTile::create()
49 {
50     if (d->isCreated) {
51         return true;
52     }
53     d->isCreated = d->create();
54     return d->isCreated;
55 }
56 
KWindowShadow(QObject * parent)57 KWindowShadow::KWindowShadow(QObject *parent)
58     : QObject(parent)
59     , d(KWindowSystemPluginWrapper::self().createWindowShadow())
60 {
61 }
62 
~KWindowShadow()63 KWindowShadow::~KWindowShadow()
64 {
65     destroy();
66 }
67 
leftTile() const68 KWindowShadowTile::Ptr KWindowShadow::leftTile() const
69 {
70     return d->leftTile;
71 }
72 
setLeftTile(KWindowShadowTile::Ptr tile)73 void KWindowShadow::setLeftTile(KWindowShadowTile::Ptr tile)
74 {
75     if (d->isCreated) {
76         qCWarning(LOG_KWINDOWSYSTEM,
77                   "Cannot attach a left tile to a shadow that already has "
78                   "native platform resources allocated. To do so, destroy() the shadow and then "
79                   "setLeftTile() and create()");
80         return;
81     }
82     d->leftTile = tile;
83 }
84 
topLeftTile() const85 KWindowShadowTile::Ptr KWindowShadow::topLeftTile() const
86 {
87     return d->topLeftTile;
88 }
89 
setTopLeftTile(KWindowShadowTile::Ptr tile)90 void KWindowShadow::setTopLeftTile(KWindowShadowTile::Ptr tile)
91 {
92     if (d->isCreated) {
93         qCWarning(LOG_KWINDOWSYSTEM,
94                   "Cannot attach a top-left tile to a shadow that already has "
95                   "native platform resources allocated. To do so, destroy() the shadow and then "
96                   "setTopLeftTile() and create()");
97         return;
98     }
99     d->topLeftTile = tile;
100 }
101 
topTile() const102 KWindowShadowTile::Ptr KWindowShadow::topTile() const
103 {
104     return d->topTile;
105 }
106 
setTopTile(KWindowShadowTile::Ptr tile)107 void KWindowShadow::setTopTile(KWindowShadowTile::Ptr tile)
108 {
109     if (d->isCreated) {
110         qCWarning(LOG_KWINDOWSYSTEM,
111                   "Cannot attach a top tile to a shadow that already has "
112                   "native platform resources allocated. To do so, destroy() the shadow and then "
113                   "setTopTile() and create()");
114         return;
115     }
116     d->topTile = tile;
117 }
118 
topRightTile() const119 KWindowShadowTile::Ptr KWindowShadow::topRightTile() const
120 {
121     return d->topRightTile;
122 }
123 
setTopRightTile(KWindowShadowTile::Ptr tile)124 void KWindowShadow::setTopRightTile(KWindowShadowTile::Ptr tile)
125 {
126     if (d->isCreated) {
127         qCWarning(LOG_KWINDOWSYSTEM,
128                   "Cannot attach a top-right tile to a shadow that already "
129                   "has native platform resources allocated. To do so, destroy() the shadow and "
130                   "then setTopRightTile() and create()");
131         return;
132     }
133     d->topRightTile = tile;
134 }
135 
rightTile() const136 KWindowShadowTile::Ptr KWindowShadow::rightTile() const
137 {
138     return d->rightTile;
139 }
140 
setRightTile(KWindowShadowTile::Ptr tile)141 void KWindowShadow::setRightTile(KWindowShadowTile::Ptr tile)
142 {
143     if (d->isCreated) {
144         qCWarning(LOG_KWINDOWSYSTEM,
145                   "Cannot attach a right tile to a shadow that already has "
146                   "native platform resources allocated. To do so, destroy() the shadow and then "
147                   "setRightTile() and create()");
148         return;
149     }
150     d->rightTile = tile;
151 }
152 
bottomRightTile() const153 KWindowShadowTile::Ptr KWindowShadow::bottomRightTile() const
154 {
155     return d->bottomRightTile;
156 }
157 
setBottomRightTile(KWindowShadowTile::Ptr tile)158 void KWindowShadow::setBottomRightTile(KWindowShadowTile::Ptr tile)
159 {
160     if (d->isCreated) {
161         qCWarning(LOG_KWINDOWSYSTEM,
162                   "Cannot attach a bottom-right tile to a shadow that already "
163                   "has native platform resources allocated. To do so, destroy() the shadow and "
164                   "then setBottomRightTile() and create()");
165         return;
166     }
167     d->bottomRightTile = tile;
168 }
169 
bottomTile() const170 KWindowShadowTile::Ptr KWindowShadow::bottomTile() const
171 {
172     return d->bottomTile;
173 }
174 
setBottomTile(KWindowShadowTile::Ptr tile)175 void KWindowShadow::setBottomTile(KWindowShadowTile::Ptr tile)
176 {
177     if (d->isCreated) {
178         qCWarning(LOG_KWINDOWSYSTEM,
179                   "Cannot attach a bottom tile to a shadow that already has "
180                   "native platform resources allocated. To do so, destroy() the shadow and then "
181                   "setBottomTile() and create()");
182         return;
183     }
184     d->bottomTile = tile;
185 }
186 
bottomLeftTile() const187 KWindowShadowTile::Ptr KWindowShadow::bottomLeftTile() const
188 {
189     return d->bottomLeftTile;
190 }
191 
setBottomLeftTile(KWindowShadowTile::Ptr tile)192 void KWindowShadow::setBottomLeftTile(KWindowShadowTile::Ptr tile)
193 {
194     if (d->isCreated) {
195         qCWarning(LOG_KWINDOWSYSTEM,
196                   "Cannot attach a bottom-left tile to a shadow that already "
197                   "has native platform resources allocated. To do so, destroy() the shadow and "
198                   "then setBottomLeftTile() and create()");
199         return;
200     }
201     d->bottomLeftTile = tile;
202 }
203 
padding() const204 QMargins KWindowShadow::padding() const
205 {
206     return d->padding;
207 }
208 
setPadding(const QMargins & padding)209 void KWindowShadow::setPadding(const QMargins &padding)
210 {
211     if (d->isCreated) {
212         qCWarning(LOG_KWINDOWSYSTEM,
213                   "Cannot set the padding on a shadow that already has "
214                   "native platform resources allocated. To do so, destroy() the shadow and "
215                   "then setPadding() and create()");
216         return;
217     }
218     d->padding = padding;
219 }
220 
window() const221 QWindow *KWindowShadow::window() const
222 {
223     return d->window;
224 }
225 
setWindow(QWindow * window)226 void KWindowShadow::setWindow(QWindow *window)
227 {
228     if (d->isCreated) {
229         qCWarning(LOG_KWINDOWSYSTEM,
230                   "Cannot set the target window on a shadow that already has "
231                   "native platform resources allocated. To do so, destroy() the shadow and then "
232                   "setWindow() and create()");
233         return;
234     }
235     d->window = window;
236 }
237 
isCreated() const238 bool KWindowShadow::isCreated() const
239 {
240     return d->isCreated;
241 }
242 
create()243 bool KWindowShadow::create()
244 {
245     if (d->isCreated) {
246         return true;
247     }
248     if (!d->window) {
249         qCWarning(LOG_KWINDOWSYSTEM,
250                   "Cannot allocate the native platform resources for the shadow "
251                   "because the target window is not specified.");
252         return false;
253     }
254     if (!d->prepareTiles()) {
255         return false;
256     }
257     d->isCreated = d->create();
258     return d->isCreated;
259 }
260 
destroy()261 void KWindowShadow::destroy()
262 {
263     if (!d->isCreated) {
264         return;
265     }
266     d->destroy();
267     d->isCreated = false;
268 }
269 
~KWindowShadowTilePrivate()270 KWindowShadowTilePrivate::~KWindowShadowTilePrivate()
271 {
272 }
273 
get(const KWindowShadowTile * tile)274 KWindowShadowTilePrivate *KWindowShadowTilePrivate::get(const KWindowShadowTile *tile)
275 {
276     return tile->d.data();
277 }
278 
~KWindowShadowPrivate()279 KWindowShadowPrivate::~KWindowShadowPrivate()
280 {
281 }
282 
create()283 bool KWindowShadowPrivate::create()
284 {
285     return false;
286 }
287 
destroy()288 void KWindowShadowPrivate::destroy()
289 {
290 }
291 
prepareTiles()292 bool KWindowShadowPrivate::prepareTiles()
293 {
294     const std::array<KWindowShadowTile *, 8> tiles{
295         leftTile.data(),
296         topLeftTile.data(),
297         topTile.data(),
298         topRightTile.data(),
299         rightTile.data(),
300         bottomRightTile.data(),
301         bottomTile.data(),
302         bottomLeftTile.data(),
303     };
304 
305     for (KWindowShadowTile *tile : tiles) {
306         if (!tile) {
307             continue;
308         }
309         if (tile->isCreated()) {
310             continue;
311         }
312         if (!tile->create()) {
313             return false;
314         }
315     }
316 
317     return true;
318 }
319 
create()320 bool KWindowShadowTilePrivateDummy::create()
321 {
322     return false;
323 }
324 
destroy()325 void KWindowShadowTilePrivateDummy::destroy()
326 {
327 }
328 
create()329 bool KWindowShadowPrivateDummy::create()
330 {
331     return false;
332 }
333 
destroy()334 void KWindowShadowPrivateDummy::destroy()
335 {
336 }
337