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