1 /*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include <kwineffects.h>
11
12 #include "virtualdesktops.h"
13
14 #include <QVector2D>
15 #include <QGraphicsRotation>
16 #include <QGraphicsScale>
17
18 #include <QtTest>
19
20 using namespace KWin;
21
22 class MockEffectWindow : public EffectWindow
23 {
24 Q_OBJECT
25 public:
26 MockEffectWindow(QObject *parent = nullptr);
27 QVariant data(int role) const override;
28 QRect decorationInnerRect() const override;
29 void deleteProperty(long int atom) const override;
30 void disablePainting(int reason) override;
31 void enablePainting(int reason) override;
32 void addRepaint(const QRect &r) override;
33 void addRepaint(int x, int y, int w, int h) override;
34 void addRepaintFull() override;
35 void addLayerRepaint(const QRect &r) override;
36 void addLayerRepaint(int x, int y, int w, int h) override;
37 EffectWindow *findModal() override;
38 EffectWindow *transientFor() override;
39 const EffectWindowGroup *group() const override;
40 bool isPaintingEnabled() override;
41 EffectWindowList mainWindows() const override;
42 QByteArray readProperty(long int atom, long int type, int format) const override;
43 void refWindow() override;
44 void unrefWindow() override;
45 void setData(int role, const QVariant &data) override;
46 void minimize() override;
47 void unminimize() override;
48 void closeWindow() override;
referencePreviousWindowPixmap()49 void referencePreviousWindowPixmap() override {}
unreferencePreviousWindowPixmap()50 void unreferencePreviousWindowPixmap() override {}
internalWindow() const51 QWindow *internalWindow() const override {
52 return nullptr;
53 }
isDeleted() const54 bool isDeleted() const override {
55 return false;
56 }
isMinimized() const57 bool isMinimized() const override {
58 return false;
59 }
opacity() const60 double opacity() const override {
61 return m_opacity;
62 }
setOpacity(qreal opacity)63 void setOpacity(qreal opacity) {
64 m_opacity = opacity;
65 }
hasAlpha() const66 bool hasAlpha() const override {
67 return true;
68 }
activities() const69 QStringList activities() const override {
70 return QStringList();
71 }
desktop() const72 int desktop() const override {
73 return 0;
74 }
desktops() const75 QVector<uint> desktops() const override {
76 return {};
77 }
x() const78 int x() const override {
79 return 0;
80 }
y() const81 int y() const override {
82 return 0;
83 }
width() const84 int width() const override {
85 return 100;
86 }
height() const87 int height() const override {
88 return 100;
89 }
basicUnit() const90 QSize basicUnit() const override {
91 return QSize();
92 }
geometry() const93 QRect geometry() const override {
94 return QRect();
95 }
expandedGeometry() const96 QRect expandedGeometry() const override {
97 return QRect();
98 }
frameGeometry() const99 QRect frameGeometry() const override {
100 return QRect();
101 }
bufferGeometry() const102 QRect bufferGeometry() const override {
103 return QRect();
104 }
clientGeometry() const105 QRect clientGeometry() const override {
106 return QRect();
107 }
screen() const108 int screen() const override {
109 return 0;
110 }
pos() const111 QPoint pos() const override {
112 return QPoint();
113 }
size() const114 QSize size() const override {
115 return QSize(100,100);
116 }
rect() const117 QRect rect() const override {
118 return QRect(0,0,100,100);
119 }
isMovable() const120 bool isMovable() const override {
121 return true;
122 }
isMovableAcrossScreens() const123 bool isMovableAcrossScreens() const override {
124 return true;
125 }
isUserMove() const126 bool isUserMove() const override {
127 return false;
128 }
isUserResize() const129 bool isUserResize() const override {
130 return false;
131 }
iconGeometry() const132 QRect iconGeometry() const override {
133 return QRect();
134 }
isDesktop() const135 bool isDesktop() const override {
136 return false;
137 }
isDock() const138 bool isDock() const override {
139 return false;
140 }
isToolbar() const141 bool isToolbar() const override {
142 return false;
143 }
isMenu() const144 bool isMenu() const override {
145 return false;
146 }
isNormalWindow() const147 bool isNormalWindow() const override {
148 return true;
149 }
isSpecialWindow() const150 bool isSpecialWindow() const override {
151 return false;
152 }
isDialog() const153 bool isDialog() const override {
154 return false;
155 }
isSplash() const156 bool isSplash() const override {
157 return false;
158 }
isUtility() const159 bool isUtility() const override {
160 return false;
161 }
isDropdownMenu() const162 bool isDropdownMenu() const override {
163 return false;
164 }
isPopupMenu() const165 bool isPopupMenu() const override {
166 return false;
167 }
isTooltip() const168 bool isTooltip() const override {
169 return false;
170 }
isNotification() const171 bool isNotification() const override {
172 return false;
173 }
isCriticalNotification() const174 bool isCriticalNotification() const override {
175 return false;
176 }
isOnScreenDisplay() const177 bool isOnScreenDisplay() const override {
178 return false;
179 }
isComboBox() const180 bool isComboBox() const override {
181 return false;
182 }
isDNDIcon() const183 bool isDNDIcon() const override {
184 return false;
185 }
contentsRect() const186 QRect contentsRect() const override {
187 return QRect();
188 }
decorationHasAlpha() const189 bool decorationHasAlpha() const override {
190 return false;
191 }
caption() const192 QString caption() const override {
193 return QString();
194 }
icon() const195 QIcon icon() const override {
196 return QIcon();
197 }
windowClass() const198 QString windowClass() const override {
199 return QString();
200 }
windowRole() const201 QString windowRole() const override {
202 return QString();
203 }
windowType() const204 NET::WindowType windowType() const override {
205 return NET::Normal;
206 }
acceptsFocus() const207 bool acceptsFocus() const override {
208 return true;
209 }
keepAbove() const210 bool keepAbove() const override {
211 return false;
212 }
keepBelow() const213 bool keepBelow() const override {
214 return false;
215 }
isModal() const216 bool isModal() const override {
217 return false;
218 }
isSkipSwitcher() const219 bool isSkipSwitcher() const override {
220 return false;
221 }
isCurrentTab() const222 bool isCurrentTab() const override {
223 return true;
224 }
skipsCloseAnimation() const225 bool skipsCloseAnimation() const override {
226 return false;
227 }
surface() const228 KWaylandServer::SurfaceInterface *surface() const override {
229 return nullptr;
230 }
isFullScreen() const231 bool isFullScreen() const override {
232 return false;
233 }
isUnresponsive() const234 bool isUnresponsive() const override {
235 return false;
236 }
isPopupWindow() const237 bool isPopupWindow() const override {
238 return false;
239 }
isManaged() const240 bool isManaged() const override {
241 return true;
242 }
isWaylandClient() const243 bool isWaylandClient() const override {
244 return true;
245 }
isX11Client() const246 bool isX11Client() const override {
247 return false;
248 }
isOutline() const249 bool isOutline() const override {
250 return false;
251 }
isLockScreen() const252 bool isLockScreen() const override {
253 return false;
254 }
pid() const255 pid_t pid() const override {
256 return 0;
257 }
windowId() const258 qlonglong windowId() const override {
259 return 0;
260 }
261
262 private:
263 qreal m_opacity = 1.0;
264 };
265
MockEffectWindow(QObject * parent)266 MockEffectWindow::MockEffectWindow(QObject *parent)
267 : EffectWindow(parent)
268 {
269 }
270
data(int role) const271 QVariant MockEffectWindow::data(int role) const
272 {
273 Q_UNUSED(role)
274 return QVariant();
275 }
276
decorationInnerRect() const277 QRect MockEffectWindow::decorationInnerRect() const
278 {
279 return QRect();
280 }
281
deleteProperty(long int atom) const282 void MockEffectWindow::deleteProperty(long int atom) const
283 {
284 Q_UNUSED(atom)
285 }
286
disablePainting(int reason)287 void MockEffectWindow::disablePainting(int reason)
288 {
289 Q_UNUSED(reason)
290 }
291
enablePainting(int reason)292 void MockEffectWindow::enablePainting(int reason)
293 {
294 Q_UNUSED(reason)
295 }
296
addRepaint(const QRect & r)297 void MockEffectWindow::addRepaint(const QRect &r)
298 {
299 Q_UNUSED(r)
300 }
301
addRepaint(int x,int y,int w,int h)302 void MockEffectWindow::addRepaint(int x, int y, int w, int h)
303 {
304 Q_UNUSED(x)
305 Q_UNUSED(y)
306 Q_UNUSED(w)
307 Q_UNUSED(h)
308 }
309
addRepaintFull()310 void MockEffectWindow::addRepaintFull()
311 {
312 }
313
addLayerRepaint(const QRect & r)314 void MockEffectWindow::addLayerRepaint(const QRect &r)
315 {
316 Q_UNUSED(r)
317 }
318
addLayerRepaint(int x,int y,int w,int h)319 void MockEffectWindow::addLayerRepaint(int x, int y, int w, int h)
320 {
321 Q_UNUSED(x)
322 Q_UNUSED(y)
323 Q_UNUSED(w)
324 Q_UNUSED(h)
325 }
326
findModal()327 EffectWindow *MockEffectWindow::findModal()
328 {
329 return nullptr;
330 }
331
transientFor()332 EffectWindow *MockEffectWindow::transientFor()
333 {
334 return nullptr;
335 }
336
group() const337 const EffectWindowGroup *MockEffectWindow::group() const
338 {
339 return nullptr;
340 }
341
isPaintingEnabled()342 bool MockEffectWindow::isPaintingEnabled()
343 {
344 return true;
345 }
346
mainWindows() const347 EffectWindowList MockEffectWindow::mainWindows() const
348 {
349 return EffectWindowList();
350 }
351
readProperty(long int atom,long int type,int format) const352 QByteArray MockEffectWindow::readProperty(long int atom, long int type, int format) const
353 {
354 Q_UNUSED(atom)
355 Q_UNUSED(type)
356 Q_UNUSED(format)
357 return QByteArray();
358 }
359
refWindow()360 void MockEffectWindow::refWindow()
361 {
362 }
363
setData(int role,const QVariant & data)364 void MockEffectWindow::setData(int role, const QVariant &data)
365 {
366 Q_UNUSED(role)
367 Q_UNUSED(data)
368 }
369
minimize()370 void MockEffectWindow::minimize()
371 {
372 }
373
unminimize()374 void MockEffectWindow::unminimize()
375 {
376 }
377
closeWindow()378 void MockEffectWindow::closeWindow()
379 {
380 }
381
unrefWindow()382 void MockEffectWindow::unrefWindow()
383 {
384 }
385
386 class TestWindowPaintData : public QObject
387 {
388 Q_OBJECT
389 private Q_SLOTS:
390 void testCtor();
391 void testCopyCtor();
392 void testOperatorMultiplyAssign();
393 void testOperatorPlus();
394 void testMultiplyOpacity();
395 void testMultiplySaturation();
396 void testMultiplyBrightness();
397 };
398
testCtor()399 void TestWindowPaintData::testCtor()
400 {
401 MockEffectWindow w;
402 w.setOpacity(0.5);
403 WindowPaintData data(&w);
404 QCOMPARE(data.xScale(), 1.0);
405 QCOMPARE(data.yScale(), 1.0);
406 QCOMPARE(data.zScale(), 1.0);
407 QCOMPARE(data.xTranslation(), 0.0);
408 QCOMPARE(data.yTranslation(), 0.0);
409 QCOMPARE(data.zTranslation(), 0.0);
410 QCOMPARE(data.translation(), QVector3D());
411 QCOMPARE(data.rotationAngle(), 0.0);
412 QCOMPARE(data.rotationOrigin(), QVector3D());
413 QCOMPARE(data.rotationAxis(), QVector3D(0.0, 0.0, 1.0));
414 QCOMPARE(data.opacity(), 0.5);
415 QCOMPARE(data.brightness(), 1.0);
416 QCOMPARE(data.saturation(), 1.0);
417 }
418
testCopyCtor()419 void TestWindowPaintData::testCopyCtor()
420 {
421 MockEffectWindow w;
422 WindowPaintData data(&w);
423 WindowPaintData data2(data);
424 // no value had been changed
425 QCOMPARE(data2.xScale(), 1.0);
426 QCOMPARE(data2.yScale(), 1.0);
427 QCOMPARE(data2.zScale(), 1.0);
428 QCOMPARE(data2.xTranslation(), 0.0);
429 QCOMPARE(data2.yTranslation(), 0.0);
430 QCOMPARE(data2.zTranslation(), 0.0);
431 QCOMPARE(data2.translation(), QVector3D());
432 QCOMPARE(data2.rotationAngle(), 0.0);
433 QCOMPARE(data2.rotationOrigin(), QVector3D());
434 QCOMPARE(data2.rotationAxis(), QVector3D(0.0, 0.0, 1.0));
435 QCOMPARE(data2.opacity(), 1.0);
436 QCOMPARE(data2.brightness(), 1.0);
437 QCOMPARE(data2.saturation(), 1.0);
438
439 data2.setScale(QVector3D(0.5, 2.0, 3.0));
440 data2.translate(0.5, 2.0, 3.0);
441 data2.setRotationAngle(45.0);
442 data2.setRotationOrigin(QVector3D(1.0, 2.0, 3.0));
443 data2.setRotationAxis(QVector3D(1.0, 1.0, 0.0));
444 data2.setOpacity(0.1);
445 data2.setBrightness(0.3);
446 data2.setSaturation(0.4);
447
448 WindowPaintData data3(data2);
449 QCOMPARE(data3.xScale(), 0.5);
450 QCOMPARE(data3.yScale(), 2.0);
451 QCOMPARE(data3.zScale(), 3.0);
452 QCOMPARE(data3.xTranslation(), 0.5);
453 QCOMPARE(data3.yTranslation(), 2.0);
454 QCOMPARE(data3.zTranslation(), 3.0);
455 QCOMPARE(data3.translation(), QVector3D(0.5, 2.0, 3.0));
456 QCOMPARE(data3.rotationAngle(), 45.0);
457 QCOMPARE(data3.rotationOrigin(), QVector3D(1.0, 2.0, 3.0));
458 QCOMPARE(data3.rotationAxis(), QVector3D(1.0, 1.0, 0.0));
459 QCOMPARE(data3.opacity(), 0.1);
460 QCOMPARE(data3.brightness(), 0.3);
461 QCOMPARE(data3.saturation(), 0.4);
462 }
463
testOperatorMultiplyAssign()464 void TestWindowPaintData::testOperatorMultiplyAssign()
465 {
466 MockEffectWindow w;
467 WindowPaintData data(&w);
468 // without anything set, it's 1.0 on all axis
469 QCOMPARE(data.xScale(), 1.0);
470 QCOMPARE(data.yScale(), 1.0);
471 QCOMPARE(data.zScale(), 1.0);
472 // multiplying by a factor should set all components
473 data *= 2.0;
474 QCOMPARE(data.xScale(), 2.0);
475 QCOMPARE(data.yScale(), 2.0);
476 QCOMPARE(data.zScale(), 2.0);
477 // multiplying by a vector2D should set x and y components
478 data *= QVector2D(2.0, 3.0);
479 QCOMPARE(data.xScale(), 4.0);
480 QCOMPARE(data.yScale(), 6.0);
481 QCOMPARE(data.zScale(), 2.0);
482 // multiplying by a vector3d should set all components
483 data *= QVector3D(0.5, 1.5, 2.0);
484 QCOMPARE(data.xScale(), 2.0);
485 QCOMPARE(data.yScale(), 9.0);
486 QCOMPARE(data.zScale(), 4.0);
487 }
488
testOperatorPlus()489 void TestWindowPaintData::testOperatorPlus()
490 {
491 MockEffectWindow w;
492 WindowPaintData data(&w);
493 QCOMPARE(data.xTranslation(), 0.0);
494 QCOMPARE(data.yTranslation(), 0.0);
495 QCOMPARE(data.zTranslation(), 0.0);
496 QCOMPARE(data.translation(), QVector3D());
497 // test with point
498 data += QPoint(1, 2);
499 QCOMPARE(data.translation(), QVector3D(1.0, 2.0, 0.0));
500 // test with pointf
501 data += QPointF(0.5, 0.75);
502 QCOMPARE(data.translation(), QVector3D(1.5, 2.75, 0.0));
503 // test with QVector2D
504 data += QVector2D(0.25, 1.5);
505 QCOMPARE(data.translation(), QVector3D(1.75, 4.25, 0.0));
506 // test with QVector3D
507 data += QVector3D(1.0, 2.0, 3.5);
508 QCOMPARE(data.translation(), QVector3D(2.75, 6.25, 3.5));
509 }
510
testMultiplyBrightness()511 void TestWindowPaintData::testMultiplyBrightness()
512 {
513 MockEffectWindow w;
514 WindowPaintData data(&w);
515 QCOMPARE(0.2, data.multiplyBrightness(0.2));
516 QCOMPARE(0.2, data.brightness());
517 QCOMPARE(0.6, data.multiplyBrightness(3.0));
518 QCOMPARE(0.6, data.brightness());
519 // just for safety
520 QCOMPARE(1.0, data.opacity());
521 QCOMPARE(1.0, data.saturation());
522 }
523
testMultiplyOpacity()524 void TestWindowPaintData::testMultiplyOpacity()
525 {
526 MockEffectWindow w;
527 WindowPaintData data(&w);
528 QCOMPARE(0.2, data.multiplyOpacity(0.2));
529 QCOMPARE(0.2, data.opacity());
530 QCOMPARE(0.6, data.multiplyOpacity(3.0));
531 QCOMPARE(0.6, data.opacity());
532 // just for safety
533 QCOMPARE(1.0, data.brightness());
534 QCOMPARE(1.0, data.saturation());
535 }
536
testMultiplySaturation()537 void TestWindowPaintData::testMultiplySaturation()
538 {
539 MockEffectWindow w;
540 WindowPaintData data(&w);
541 QCOMPARE(0.2, data.multiplySaturation(0.2));
542 QCOMPARE(0.2, data.saturation());
543 QCOMPARE(0.6, data.multiplySaturation(3.0));
544 QCOMPARE(0.6, data.saturation());
545 // just for safety
546 QCOMPARE(1.0, data.brightness());
547 QCOMPARE(1.0, data.opacity());
548 }
549
550 QTEST_MAIN(TestWindowPaintData)
551 #include "test_window_paint_data.moc"
552