1 /*
2  * SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5  */
6 #include "../src/decoratedclient.h"
7 #include "../src/decorationsettings.h"
8 #include "mockbridge.h"
9 #include "mockbutton.h"
10 #include "mockclient.h"
11 #include "mockdecoration.h"
12 #include "mocksettings.h"
13 #include <QSignalSpy>
14 #include <QStyleHints>
15 #include <QTest>
16 
17 Q_DECLARE_METATYPE(Qt::MouseButton)
18 
19 class DecorationButtonTest : public QObject
20 {
21     Q_OBJECT
22 private Q_SLOTS:
23     void testButton();
24     void testChecked();
25     void testEnabled();
26     void testPressIgnore_data();
27     void testPressIgnore();
28     void testReleaseIgnore_data();
29     void testReleaseIgnore();
30     void testHoverEnterIgnore_data();
31     void testHoverEnterIgnore();
32     void testHoverLeaveIgnore_data();
33     void testHoverLeaveIgnore();
34     void testHover();
35     void testMouseMove_data();
36     void testMouseMove();
37     void testClose();
38     void testMinimize();
39     void testQuickHelp();
40     void testKeepAbove();
41     void testKeepBelow();
42     void testShade();
43     void testMaximize();
44     void testOnAllDesktops();
45     void testMenu();
46     void testMenuDoubleClick();
47     void testMenuPressAndHold();
48     void testApplicationMenu();
49     void testContains_data();
50     void testContains();
51 };
52 
testButton()53 void DecorationButtonTest::testButton()
54 {
55     MockBridge bridge;
56     MockDecoration mockDecoration(&bridge);
57     // create a custom button and verify the base settings
58     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
59     QCOMPARE(button.decoration().data(), &mockDecoration);
60     const MockButton &constRef(button);
61     QCOMPARE(constRef.decoration().data(), &mockDecoration);
62     QCOMPARE(button.type(), KDecoration2::DecorationButtonType::Custom);
63     QCOMPARE(button.acceptedButtons(), Qt::MouseButtons(Qt::LeftButton));
64     QCOMPARE(button.isCheckable(), false);
65     QCOMPARE(button.isChecked(), false);
66     QCOMPARE(button.isEnabled(), true);
67     QCOMPARE(button.isHovered(), false);
68     QCOMPARE(button.isPressed(), false);
69     QCOMPARE(button.isVisible(), true);
70     QCOMPARE(button.size(), QSizeF(0, 0));
71     QCOMPARE(button.geometry(), QRectF());
72 
73     // test setting the geometry
74     QSignalSpy geometryChangedSpy(&button, &KDecoration2::DecorationButton::geometryChanged);
75     QVERIFY(geometryChangedSpy.isValid());
76     // setting to default geometry shouldn't change
77     button.setGeometry(QRectF());
78     QCOMPARE(button.geometry(), QRectF());
79     QCOMPARE(geometryChangedSpy.count(), 0);
80     // setting to a proper geometry should change
81     const QRectF testGeometry = QRectF(0, 0, 10, 20);
82     button.setGeometry(testGeometry);
83     QCOMPARE(button.geometry(), testGeometry);
84     QCOMPARE(button.size(), testGeometry.size());
85     QCOMPARE(geometryChangedSpy.count(), 1);
86     QCOMPARE(geometryChangedSpy.first().first().toRectF(), testGeometry);
87 
88     // test changing visibility
89     QSignalSpy visibilityChangedSpy(&button, &KDecoration2::DecorationButton::visibilityChanged);
90     QVERIFY(visibilityChangedSpy.isValid());
91     button.setVisible(true);
92     QCOMPARE(visibilityChangedSpy.count(), 0);
93     button.setVisible(false);
94     QCOMPARE(button.isVisible(), false);
95     QCOMPARE(visibilityChangedSpy.count(), 1);
96     QCOMPARE(visibilityChangedSpy.first().first().toBool(), false);
97 }
98 
testChecked()99 void DecorationButtonTest::testChecked()
100 {
101     MockBridge bridge;
102     MockDecoration mockDecoration(&bridge);
103     // create a custom button and verify the base settings
104     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
105     button.setGeometry(QRect(0, 0, 10, 10));
106 
107     // without being checkable it should not get checked
108     QSignalSpy checkedChangedSpy(&button, &KDecoration2::DecorationButton::checkedChanged);
109     QVERIFY(checkedChangedSpy.isValid());
110     button.setChecked(true);
111     QCOMPARE(button.isChecked(), false);
112     QCOMPARE(checkedChangedSpy.count(), 0);
113 
114     // now let's set the checkable state
115     QSignalSpy checkableChangedSpy(&button, &KDecoration2::DecorationButton::checkableChanged);
116     QVERIFY(checkableChangedSpy.isValid());
117     // setting to same should not emit
118     button.setCheckable(false);
119     QCOMPARE(checkableChangedSpy.count(), 0);
120     button.setCheckable(true);
121     QCOMPARE(button.isCheckable(), true);
122     QCOMPARE(checkableChangedSpy.count(), 1);
123     QCOMPARE(checkableChangedSpy.first().first().toBool(), true);
124 
125     // now it should be possible to check the button
126     button.setChecked(true);
127     QCOMPARE(button.isChecked(), true);
128     QCOMPARE(checkedChangedSpy.count(), 1);
129     // setting again should not change
130     button.setChecked(true);
131     QCOMPARE(button.isChecked(), true);
132     QCOMPARE(checkedChangedSpy.count(), 1);
133     // and disable
134     button.setChecked(false);
135     QCOMPARE(button.isChecked(), false);
136     QCOMPARE(checkedChangedSpy.count(), 2);
137     QCOMPARE(checkedChangedSpy.first().first().toBool(), true);
138     QCOMPARE(checkedChangedSpy.last().first().toBool(), false);
139 
140     // last but not least let's disable the checkable again, this should disable a checked button
141     button.setChecked(true);
142     QCOMPARE(button.isChecked(), true);
143     checkedChangedSpy.clear();
144     QCOMPARE(checkedChangedSpy.count(), 0);
145     button.setCheckable(false);
146     QCOMPARE(button.isCheckable(), false);
147     QCOMPARE(checkableChangedSpy.count(), 2);
148     QCOMPARE(checkableChangedSpy.last().first().toBool(), false);
149     QCOMPARE(button.isChecked(), false);
150     QCOMPARE(checkedChangedSpy.count(), 1);
151 }
152 
testEnabled()153 void DecorationButtonTest::testEnabled()
154 {
155     MockBridge bridge;
156     MockDecoration mockDecoration(&bridge);
157     // create a custom button and verify the base settings
158     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
159     button.setGeometry(QRect(0, 0, 10, 10));
160 
161     // enabling has influence on whether the button accepts events, so we need to fake events
162     QSignalSpy enabledChangedSpy(&button, &KDecoration2::DecorationButton::enabledChanged);
163     QVERIFY(enabledChangedSpy.isValid());
164     // setting to same shouldn't change
165     button.setEnabled(true);
166     QCOMPARE(enabledChangedSpy.count(), 0);
167     button.setEnabled(false);
168     QCOMPARE(button.isEnabled(), false);
169     QCOMPARE(enabledChangedSpy.count(), 1);
170     QCOMPARE(enabledChangedSpy.first().first().toBool(), false);
171 
172     // now let's send it a hover entered event
173     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
174     QVERIFY(hoveredChangedSpy.isValid());
175     QHoverEvent event(QEvent::HoverEnter, QPointF(1, 1), QPointF(-1, -1));
176     event.setAccepted(false);
177     button.event(&event);
178     QCOMPARE(event.isAccepted(), false);
179     QCOMPARE(hoveredChangedSpy.count(), 0);
180 
181     // if we enable the button again we should get a hovered changed signal
182     button.setEnabled(true);
183     QCOMPARE(enabledChangedSpy.count(), 2);
184     QCOMPARE(enabledChangedSpy.last().first().toBool(), true);
185     button.event(&event);
186     QCOMPARE(event.isAccepted(), true);
187     QCOMPARE(hoveredChangedSpy.count(), 1);
188     QCOMPARE(hoveredChangedSpy.first().first().toBool(), true);
189 
190     // if we disable the button now we get a hovered disabled signal
191     button.setEnabled(false);
192     QCOMPARE(hoveredChangedSpy.count(), 2);
193     QCOMPARE(hoveredChangedSpy.last().first().toBool(), false);
194 }
195 
testPressIgnore_data()196 void DecorationButtonTest::testPressIgnore_data()
197 {
198     QTest::addColumn<bool>("enabled");
199     QTest::addColumn<bool>("visible");
200     QTest::addColumn<QPoint>("clickPos");
201     QTest::addColumn<Qt::MouseButton>("mouseButton");
202     QTest::addColumn<bool>("expectedAccepted");
203 
204     QTest::newRow("all-disabled") << false << false << QPoint(0, 0) << Qt::LeftButton << false;
205     QTest::newRow("enabled") << true << false << QPoint(0, 0) << Qt::LeftButton << false;
206     QTest::newRow("visible") << false << true << QPoint(0, 0) << Qt::LeftButton << false;
207     QTest::newRow("outside") << true << true << QPoint(20, 20) << Qt::LeftButton << false;
208     QTest::newRow("wrong-button") << true << true << QPoint(0, 0) << Qt::RightButton << false;
209 }
210 
testPressIgnore()211 void DecorationButtonTest::testPressIgnore()
212 {
213     MockBridge bridge;
214     MockDecoration mockDecoration(&bridge);
215     // create a custom button and verify the base settings
216     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
217     button.setGeometry(QRect(0, 0, 10, 10));
218     button.setAcceptedButtons(Qt::LeftButton);
219     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
220     QVERIFY(pressedSpy.isValid());
221     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
222     QVERIFY(pressedChangedSpy.isValid());
223 
224     QFETCH(bool, enabled);
225     QFETCH(bool, visible);
226     button.setEnabled(enabled);
227     button.setVisible(visible);
228 
229     QFETCH(QPoint, clickPos);
230     QFETCH(Qt::MouseButton, mouseButton);
231     QMouseEvent pressEvent(QEvent::MouseButtonPress, clickPos, mouseButton, mouseButton, Qt::NoModifier);
232     pressEvent.setAccepted(false);
233     button.event(&pressEvent);
234     QTEST(pressEvent.isAccepted(), "expectedAccepted");
235     QCOMPARE(button.isPressed(), false);
236     QVERIFY(pressedSpy.isEmpty());
237     QVERIFY(pressedChangedSpy.isEmpty());
238 }
239 
testReleaseIgnore_data()240 void DecorationButtonTest::testReleaseIgnore_data()
241 {
242     QTest::addColumn<bool>("enabled");
243     QTest::addColumn<bool>("visible");
244     QTest::addColumn<QPoint>("clickPos");
245     QTest::addColumn<Qt::MouseButton>("mouseButton");
246     QTest::addColumn<bool>("expectedAccepted");
247     QTest::addColumn<bool>("expectedPressed");
248     QTest::addColumn<int>("expectedPressedChanged");
249 
250     QTest::newRow("all-disabled") << false << false << QPoint(0, 0) << Qt::LeftButton << false << false << 2;
251     QTest::newRow("enabled") << true << false << QPoint(0, 0) << Qt::LeftButton << false << false << 2;
252     QTest::newRow("visible") << false << true << QPoint(0, 0) << Qt::LeftButton << false << false << 2;
253     QTest::newRow("outside") << true << true << QPoint(20, 20) << Qt::LeftButton << true << false << 2;
254     QTest::newRow("wrong-button") << true << true << QPoint(0, 0) << Qt::RightButton << false << true << 1;
255 }
256 
testReleaseIgnore()257 void DecorationButtonTest::testReleaseIgnore()
258 {
259     MockBridge bridge;
260     MockDecoration mockDecoration(&bridge);
261     // create a custom button and verify the base settings
262     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
263     button.setGeometry(QRect(0, 0, 10, 10));
264     button.setAcceptedButtons(Qt::LeftButton);
265     button.setEnabled(true);
266     button.setVisible(true);
267     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
268     QVERIFY(pressedSpy.isValid());
269     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
270     QVERIFY(pressedChangedSpy.isValid());
271     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
272     QVERIFY(clickedSpy.isValid());
273 
274     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
275     pressEvent.setAccepted(false);
276     button.event(&pressEvent);
277     QCOMPARE(pressEvent.isAccepted(), true);
278     QCOMPARE(button.isPressed(), true);
279     QCOMPARE(pressedSpy.count(), 1);
280     QCOMPARE(pressedChangedSpy.count(), 1);
281     QCOMPARE(pressedChangedSpy.last().first().toBool(), true);
282 
283     QFETCH(bool, enabled);
284     QFETCH(bool, visible);
285     button.setEnabled(enabled);
286     button.setVisible(visible);
287 
288     QFETCH(QPoint, clickPos);
289     QFETCH(Qt::MouseButton, mouseButton);
290     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, clickPos, mouseButton, Qt::NoButton, Qt::NoModifier);
291     releaseEvent.setAccepted(false);
292     button.event(&releaseEvent);
293     QTEST(releaseEvent.isAccepted(), "expectedAccepted");
294     QTEST(button.isPressed(), "expectedPressed");
295     QCOMPARE(pressedSpy.count(), 1);
296     QTEST(pressedChangedSpy.count(), "expectedPressedChanged");
297     QCOMPARE(pressedChangedSpy.last().first().toBool(), button.isPressed());
298     QCOMPARE(clickedSpy.count(), 0);
299 }
300 
testHoverEnterIgnore_data()301 void DecorationButtonTest::testHoverEnterIgnore_data()
302 {
303     QTest::addColumn<bool>("enabled");
304     QTest::addColumn<bool>("visible");
305     QTest::addColumn<QPoint>("enterPos");
306 
307     QTest::newRow("all-disabled") << false << false << QPoint(0, 0);
308     QTest::newRow("enabled") << true << false << QPoint(0, 0);
309     QTest::newRow("visible") << false << true << QPoint(0, 0);
310     QTest::newRow("outside") << true << true << QPoint(20, 20);
311 }
312 
testHoverEnterIgnore()313 void DecorationButtonTest::testHoverEnterIgnore()
314 {
315     MockBridge bridge;
316     MockDecoration mockDecoration(&bridge);
317     // create a custom button and verify the base settings
318     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
319     button.setGeometry(QRect(0, 0, 10, 10));
320     QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered);
321     QVERIFY(pointerEnteredSpy.isValid());
322     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
323     QVERIFY(hoveredChangedSpy.isValid());
324 
325     QFETCH(bool, enabled);
326     QFETCH(bool, visible);
327     button.setEnabled(enabled);
328     button.setVisible(visible);
329 
330     QFETCH(QPoint, enterPos);
331     QHoverEvent enterEvent(QEvent::HoverEnter, enterPos, QPoint());
332     enterEvent.setAccepted(false);
333     button.event(&enterEvent);
334     QCOMPARE(enterEvent.isAccepted(), false);
335     QCOMPARE(button.isHovered(), false);
336     QCOMPARE(pointerEnteredSpy.count(), 0);
337     QCOMPARE(hoveredChangedSpy.count(), 0);
338 
339     // send a HoverLeft event should not be processed
340     button.setEnabled(true);
341     button.setVisible(true);
342     QHoverEvent leftEvent(QEvent::HoverLeave, QPoint(20, 20), enterPos);
343     leftEvent.setAccepted(false);
344     button.event(&leftEvent);
345     QCOMPARE(leftEvent.isAccepted(), false);
346 }
347 
testHoverLeaveIgnore_data()348 void DecorationButtonTest::testHoverLeaveIgnore_data()
349 {
350     QTest::addColumn<bool>("enabled");
351     QTest::addColumn<bool>("visible");
352     QTest::addColumn<QPoint>("leavePos");
353     QTest::addColumn<int>("expectedLeaveCount");
354     QTest::addColumn<int>("expectedHoverChangedCount");
355 
356     QTest::newRow("all-disabled") << false << false << QPoint(20, 20) << 1 << 2;
357     QTest::newRow("enabled") << true << false << QPoint(20, 20) << 1 << 2;
358     QTest::newRow("visible") << false << true << QPoint(20, 20) << 1 << 2;
359     QTest::newRow("inside") << true << true << QPoint(5, 5) << 0 << 1;
360 }
361 
testHoverLeaveIgnore()362 void DecorationButtonTest::testHoverLeaveIgnore()
363 {
364     MockBridge bridge;
365     MockDecoration mockDecoration(&bridge);
366     // create a custom button and verify the base settings
367     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
368     button.setGeometry(QRect(0, 0, 10, 10));
369     button.setEnabled(true);
370     button.setVisible(true);
371     QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered);
372     QVERIFY(pointerEnteredSpy.isValid());
373     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
374     QVERIFY(hoveredChangedSpy.isValid());
375     QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft);
376     QVERIFY(pointerLeavedSpy.isValid());
377 
378     QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint());
379     enterEvent.setAccepted(false);
380     button.event(&enterEvent);
381     QCOMPARE(enterEvent.isAccepted(), true);
382     QCOMPARE(button.isHovered(), true);
383     QCOMPARE(pointerEnteredSpy.count(), 1);
384     QCOMPARE(hoveredChangedSpy.count(), 1);
385     QCOMPARE(hoveredChangedSpy.last().first().toBool(), true);
386 
387     QFETCH(bool, enabled);
388     QFETCH(bool, visible);
389     button.setEnabled(enabled);
390     button.setVisible(visible);
391 
392     QFETCH(QPoint, leavePos);
393     QHoverEvent leftEvent(QEvent::HoverLeave, leavePos, QPoint(0, 0));
394     leftEvent.setAccepted(false);
395     button.event(&leftEvent);
396     QCOMPARE(leftEvent.isAccepted(), false);
397     QCOMPARE(pointerEnteredSpy.count(), 1);
398     QTEST(pointerLeavedSpy.count(), "expectedLeaveCount");
399     QTEST(hoveredChangedSpy.count(), "expectedHoverChangedCount");
400     QCOMPARE(hoveredChangedSpy.last().first().toBool(), button.isHovered());
401 }
402 
testHover()403 void DecorationButtonTest::testHover()
404 {
405     MockBridge bridge;
406     MockDecoration mockDecoration(&bridge);
407     // create a custom button and verify the base settings
408     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
409     button.setGeometry(QRectF(0, 0, 10, 10));
410     button.setEnabled(true);
411     button.setVisible(true);
412     QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered);
413     QVERIFY(pointerEnteredSpy.isValid());
414     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
415     QVERIFY(hoveredChangedSpy.isValid());
416     QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft);
417     QVERIFY(pointerLeavedSpy.isValid());
418 
419     QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint());
420     enterEvent.setAccepted(false);
421     button.event(&enterEvent);
422     QCOMPARE(enterEvent.isAccepted(), true);
423     QCOMPARE(button.isHovered(), true);
424     QCOMPARE(pointerEnteredSpy.count(), 1);
425     QCOMPARE(hoveredChangedSpy.count(), 1);
426     QCOMPARE(hoveredChangedSpy.last().first().toBool(), true);
427 
428     // send in a hovermove event - it's passed through, but not used
429     QHoverEvent moveEvent(QEvent::HoverMove, QPoint(5, 0), QPoint(0, 0));
430     moveEvent.setAccepted(false);
431     button.event(&moveEvent);
432     QCOMPARE(moveEvent.isAccepted(), false);
433 
434     QHoverEvent leftEvent(QEvent::HoverLeave, QPointF(10.1, 0.0), QPointF(0, 0));
435     leftEvent.setAccepted(false);
436     button.event(&leftEvent);
437     QCOMPARE(leftEvent.isAccepted(), true);
438     QCOMPARE(pointerEnteredSpy.count(), 1);
439     QCOMPARE(pointerLeavedSpy.count(), 1);
440     QCOMPARE(hoveredChangedSpy.count(), 2);
441     QCOMPARE(hoveredChangedSpy.last().first().toBool(), false);
442 }
443 
testMouseMove_data()444 void DecorationButtonTest::testMouseMove_data()
445 {
446     QTest::addColumn<bool>("enabled");
447     QTest::addColumn<bool>("visible");
448     QTest::addColumn<QPointF>("movePos");
449     QTest::addColumn<bool>("expectedAccepted");
450     QTest::addColumn<bool>("expectedHovered");
451     QTest::addColumn<int>("expectedChangedCount");
452 
453     QTest::newRow("outside") << true << true << QPointF(10.1, 10) << true << false << 2;
454     QTest::newRow("inside") << true << true << QPointF(5, 5) << false << true << 1;
455     QTest::newRow("disabled") << false << true << QPointF(10, 10) << false << false << 2;
456     QTest::newRow("invisible") << true << false << QPointF(10, 10) << false << false << 2;
457 }
458 
testMouseMove()459 void DecorationButtonTest::testMouseMove()
460 {
461     MockBridge bridge;
462     MockDecoration mockDecoration(&bridge);
463     // create a custom button and verify the base settings
464     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
465     button.setGeometry(QRectF(0, 0, 10, 10));
466     button.setEnabled(true);
467     button.setVisible(true);
468     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
469     QVERIFY(hoveredChangedSpy.isValid());
470     QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft);
471     QVERIFY(pointerLeavedSpy.isValid());
472 
473     QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint());
474     enterEvent.setAccepted(false);
475     button.event(&enterEvent);
476     QCOMPARE(enterEvent.isAccepted(), true);
477     QCOMPARE(button.isHovered(), true);
478     QCOMPARE(hoveredChangedSpy.count(), 1);
479     QCOMPARE(hoveredChangedSpy.last().first().toBool(), true);
480 
481     QFETCH(bool, enabled);
482     button.setEnabled(enabled);
483     QFETCH(bool, visible);
484     button.setVisible(visible);
485 
486     QFETCH(QPointF, movePos);
487     QMouseEvent mouseMoveEvent(QEvent::MouseMove, movePos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
488     mouseMoveEvent.setAccepted(false);
489     button.event(&mouseMoveEvent);
490     QTEST(mouseMoveEvent.isAccepted(), "expectedAccepted");
491     QTEST(button.isHovered(), "expectedHovered");
492     QTEST(hoveredChangedSpy.count(), "expectedChangedCount");
493     QCOMPARE(hoveredChangedSpy.last().first().toBool(), button.isHovered());
494 
495     // explicit further move event outside of button
496     QMouseEvent mouseMoveEvent2(QEvent::MouseMove, QPoint(50, 50), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
497     mouseMoveEvent2.setAccepted(false);
498     button.event(&mouseMoveEvent2);
499     QTEST(mouseMoveEvent2.isAccepted(), "expectedHovered");
500     QCOMPARE(button.isHovered(), false);
501 }
502 
testClose()503 void DecorationButtonTest::testClose()
504 {
505     MockBridge bridge;
506     MockDecoration mockDecoration(&bridge);
507     MockClient *client = bridge.lastCreatedClient();
508     MockButton button(KDecoration2::DecorationButtonType::Close, &mockDecoration);
509     button.setGeometry(QRect(0, 0, 10, 10));
510 
511     QCOMPARE(button.isEnabled(), false);
512     QCOMPARE(button.isCheckable(), false);
513     QCOMPARE(button.isChecked(), false);
514     QCOMPARE(button.isVisible(), true);
515     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
516 
517     // if the client is closeable the button should get enabled
518     QSignalSpy closeableChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::closeableChanged);
519     QVERIFY(closeableChangedSpy.isValid());
520     client->setCloseable(true);
521     QCOMPARE(button.isEnabled(), true);
522     QCOMPARE(closeableChangedSpy.count(), 1);
523     QCOMPARE(closeableChangedSpy.first().first().toBool(), true);
524 
525     // clicking the button should trigger a request for close
526     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
527     QVERIFY(clickedSpy.isValid());
528     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
529     QVERIFY(pressedSpy.isValid());
530     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
531     QVERIFY(releasedSpy.isValid());
532     QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested);
533     QVERIFY(closeRequestedSpy.isValid());
534     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
535     QVERIFY(pressedChangedSpy.isValid());
536 
537     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
538     pressEvent.setAccepted(false);
539     button.event(&pressEvent);
540     QCOMPARE(pressEvent.isAccepted(), true);
541     QCOMPARE(button.isPressed(), true);
542     QCOMPARE(clickedSpy.count(), 0);
543     QCOMPARE(pressedSpy.count(), 1);
544     QCOMPARE(releasedSpy.count(), 0);
545     QCOMPARE(closeRequestedSpy.count(), 0);
546     QCOMPARE(pressedChangedSpy.count(), 1);
547     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
548 
549     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
550     releaseEvent.setAccepted(false);
551     button.event(&releaseEvent);
552     QCOMPARE(releaseEvent.isAccepted(), true);
553     QCOMPARE(button.isPressed(), false);
554     QCOMPARE(clickedSpy.count(), 1);
555     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
556     QCOMPARE(pressedSpy.count(), 1);
557     QCOMPARE(releasedSpy.count(), 1);
558     QVERIFY(closeRequestedSpy.wait());
559     QCOMPARE(closeRequestedSpy.count(), 1);
560     QCOMPARE(pressedChangedSpy.count(), 2);
561     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
562 }
563 
testMinimize()564 void DecorationButtonTest::testMinimize()
565 {
566     MockBridge bridge;
567     MockDecoration mockDecoration(&bridge);
568     MockClient *client = bridge.lastCreatedClient();
569     MockButton button(KDecoration2::DecorationButtonType::Minimize, &mockDecoration);
570     button.setGeometry(QRect(0, 0, 10, 10));
571 
572     QCOMPARE(button.isEnabled(), false);
573     QCOMPARE(button.isCheckable(), false);
574     QCOMPARE(button.isChecked(), false);
575     QCOMPARE(button.isVisible(), true);
576     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
577 
578     // if the client is minimizeable the button should get enabled
579     QSignalSpy minimizableChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::minimizeableChanged);
580     QVERIFY(minimizableChangedSpy.isValid());
581     client->setMinimizable(true);
582     QCOMPARE(button.isEnabled(), true);
583     QCOMPARE(minimizableChangedSpy.count(), 1);
584     QCOMPARE(minimizableChangedSpy.first().first().toBool(), true);
585 
586     // clicking the button should trigger a request for minimize
587     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
588     QVERIFY(clickedSpy.isValid());
589     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
590     QVERIFY(pressedSpy.isValid());
591     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
592     QVERIFY(releasedSpy.isValid());
593     QSignalSpy minimizeRequestedSpy(client, &MockClient::minimizeRequested);
594     QVERIFY(minimizeRequestedSpy.isValid());
595     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
596     QVERIFY(pressedChangedSpy.isValid());
597 
598     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
599     pressEvent.setAccepted(false);
600     button.event(&pressEvent);
601     QCOMPARE(pressEvent.isAccepted(), true);
602     QCOMPARE(button.isPressed(), true);
603     QCOMPARE(clickedSpy.count(), 0);
604     QCOMPARE(pressedSpy.count(), 1);
605     QCOMPARE(releasedSpy.count(), 0);
606     QCOMPARE(minimizeRequestedSpy.count(), 0);
607     QCOMPARE(pressedChangedSpy.count(), 1);
608     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
609 
610     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
611     releaseEvent.setAccepted(false);
612     button.event(&releaseEvent);
613     QCOMPARE(releaseEvent.isAccepted(), true);
614     QCOMPARE(button.isPressed(), false);
615     QCOMPARE(clickedSpy.count(), 1);
616     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
617     QCOMPARE(pressedSpy.count(), 1);
618     QCOMPARE(releasedSpy.count(), 1);
619     QVERIFY(minimizeRequestedSpy.wait());
620     QCOMPARE(minimizeRequestedSpy.count(), 1);
621     QCOMPARE(pressedChangedSpy.count(), 2);
622     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
623 }
624 
testQuickHelp()625 void DecorationButtonTest::testQuickHelp()
626 {
627     MockBridge bridge;
628     MockDecoration mockDecoration(&bridge);
629     MockClient *client = bridge.lastCreatedClient();
630     MockButton button(KDecoration2::DecorationButtonType::ContextHelp, &mockDecoration);
631     button.setGeometry(QRect(0, 0, 10, 10));
632 
633     QCOMPARE(button.isEnabled(), true);
634     QCOMPARE(button.isCheckable(), false);
635     QCOMPARE(button.isChecked(), false);
636     QCOMPARE(button.isVisible(), false);
637     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
638 
639     // if the client provides quickhelp the button should get enabled
640     QSignalSpy providesContextHelpChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::providesContextHelpChanged);
641     QVERIFY(providesContextHelpChangedSpy.isValid());
642     client->setProvidesContextHelp(true);
643     QCOMPARE(button.isVisible(), true);
644     QCOMPARE(providesContextHelpChangedSpy.count(), 1);
645     QCOMPARE(providesContextHelpChangedSpy.first().first().toBool(), true);
646 
647     // clicking the button should trigger a request for minimize
648     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
649     QVERIFY(clickedSpy.isValid());
650     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
651     QVERIFY(pressedSpy.isValid());
652     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
653     QVERIFY(releasedSpy.isValid());
654     QSignalSpy quickhelpRequestedSpy(client, &MockClient::quickHelpRequested);
655     QVERIFY(quickhelpRequestedSpy.isValid());
656     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
657     QVERIFY(pressedChangedSpy.isValid());
658 
659     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
660     pressEvent.setAccepted(false);
661     button.event(&pressEvent);
662     QCOMPARE(pressEvent.isAccepted(), true);
663     QCOMPARE(button.isPressed(), true);
664     QCOMPARE(clickedSpy.count(), 0);
665     QCOMPARE(pressedSpy.count(), 1);
666     QCOMPARE(releasedSpy.count(), 0);
667     QCOMPARE(quickhelpRequestedSpy.count(), 0);
668     QCOMPARE(pressedChangedSpy.count(), 1);
669     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
670 
671     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
672     releaseEvent.setAccepted(false);
673     button.event(&releaseEvent);
674     QCOMPARE(releaseEvent.isAccepted(), true);
675     QCOMPARE(button.isPressed(), false);
676     QCOMPARE(clickedSpy.count(), 1);
677     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
678     QCOMPARE(pressedSpy.count(), 1);
679     QCOMPARE(releasedSpy.count(), 1);
680     QVERIFY(quickhelpRequestedSpy.wait());
681     QCOMPARE(quickhelpRequestedSpy.count(), 1);
682     QCOMPARE(pressedChangedSpy.count(), 2);
683     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
684 }
685 
testKeepAbove()686 void DecorationButtonTest::testKeepAbove()
687 {
688     MockBridge bridge;
689     MockDecoration mockDecoration(&bridge);
690     MockButton button(KDecoration2::DecorationButtonType::KeepAbove, &mockDecoration);
691     button.setGeometry(QRect(0, 0, 10, 10));
692 
693     QCOMPARE(button.isEnabled(), true);
694     QCOMPARE(button.isCheckable(), true);
695     QCOMPARE(button.isChecked(), false);
696     QCOMPARE(button.isVisible(), true);
697     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
698 
699     // clicking the button should trigger a request for keep above changed
700     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
701     QVERIFY(clickedSpy.isValid());
702     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
703     QVERIFY(pressedSpy.isValid());
704     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
705     QVERIFY(releasedSpy.isValid());
706     QSignalSpy keepAboveChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::keepAboveChanged);
707     QVERIFY(keepAboveChangedSpy.isValid());
708     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
709     QVERIFY(pressedChangedSpy.isValid());
710 
711     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
712     pressEvent.setAccepted(false);
713     button.event(&pressEvent);
714     QCOMPARE(pressEvent.isAccepted(), true);
715     QCOMPARE(button.isPressed(), true);
716     QCOMPARE(clickedSpy.count(), 0);
717     QCOMPARE(pressedSpy.count(), 1);
718     QCOMPARE(releasedSpy.count(), 0);
719     QCOMPARE(keepAboveChangedSpy.count(), 0);
720     QCOMPARE(pressedChangedSpy.count(), 1);
721     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
722 
723     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
724     releaseEvent.setAccepted(false);
725     button.event(&releaseEvent);
726     QCOMPARE(releaseEvent.isAccepted(), true);
727     QCOMPARE(button.isPressed(), false);
728     QCOMPARE(clickedSpy.count(), 1);
729     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
730     QCOMPARE(pressedSpy.count(), 1);
731     QCOMPARE(releasedSpy.count(), 1);
732     QVERIFY(keepAboveChangedSpy.wait());
733     QCOMPARE(keepAboveChangedSpy.count(), 1);
734     QCOMPARE(keepAboveChangedSpy.first().first().toBool(), true);
735     QCOMPARE(pressedChangedSpy.count(), 2);
736     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
737     QCOMPARE(button.isChecked(), true);
738 
739     // click once more should change again
740     button.event(&pressEvent);
741     button.event(&releaseEvent);
742     QVERIFY(keepAboveChangedSpy.wait());
743     QCOMPARE(keepAboveChangedSpy.count(), 2);
744     QCOMPARE(keepAboveChangedSpy.first().first().toBool(), true);
745     QCOMPARE(keepAboveChangedSpy.last().first().toBool(), false);
746     QCOMPARE(button.isChecked(), false);
747 }
748 
testKeepBelow()749 void DecorationButtonTest::testKeepBelow()
750 {
751     MockBridge bridge;
752     MockDecoration mockDecoration(&bridge);
753     MockButton button(KDecoration2::DecorationButtonType::KeepBelow, &mockDecoration);
754     button.setGeometry(QRect(0, 0, 10, 10));
755 
756     QCOMPARE(button.isEnabled(), true);
757     QCOMPARE(button.isCheckable(), true);
758     QCOMPARE(button.isChecked(), false);
759     QCOMPARE(button.isVisible(), true);
760     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
761 
762     // clicking the button should trigger a request for keep above changed
763     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
764     QVERIFY(clickedSpy.isValid());
765     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
766     QVERIFY(pressedSpy.isValid());
767     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
768     QVERIFY(releasedSpy.isValid());
769     QSignalSpy keepBelowChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::keepBelowChanged);
770     QVERIFY(keepBelowChangedSpy.isValid());
771     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
772     QVERIFY(pressedChangedSpy.isValid());
773 
774     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
775     pressEvent.setAccepted(false);
776     button.event(&pressEvent);
777     QCOMPARE(pressEvent.isAccepted(), true);
778     QCOMPARE(button.isPressed(), true);
779     QCOMPARE(clickedSpy.count(), 0);
780     QCOMPARE(pressedSpy.count(), 1);
781     QCOMPARE(releasedSpy.count(), 0);
782     QCOMPARE(keepBelowChangedSpy.count(), 0);
783     QCOMPARE(pressedChangedSpy.count(), 1);
784     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
785 
786     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
787     releaseEvent.setAccepted(false);
788     button.event(&releaseEvent);
789     QCOMPARE(releaseEvent.isAccepted(), true);
790     QCOMPARE(button.isPressed(), false);
791     QCOMPARE(clickedSpy.count(), 1);
792     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
793     QCOMPARE(pressedSpy.count(), 1);
794     QCOMPARE(releasedSpy.count(), 1);
795     QVERIFY(keepBelowChangedSpy.wait());
796     QCOMPARE(keepBelowChangedSpy.count(), 1);
797     QCOMPARE(keepBelowChangedSpy.first().first().toBool(), true);
798     QCOMPARE(pressedChangedSpy.count(), 2);
799     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
800     QCOMPARE(button.isChecked(), true);
801 
802     // click once more should change again
803     button.event(&pressEvent);
804     button.event(&releaseEvent);
805     QVERIFY(keepBelowChangedSpy.wait());
806     QCOMPARE(keepBelowChangedSpy.count(), 2);
807     QCOMPARE(keepBelowChangedSpy.first().first().toBool(), true);
808     QCOMPARE(keepBelowChangedSpy.last().first().toBool(), false);
809     QCOMPARE(button.isChecked(), false);
810 }
811 
testShade()812 void DecorationButtonTest::testShade()
813 {
814     MockBridge bridge;
815     MockDecoration mockDecoration(&bridge);
816     MockClient *client = bridge.lastCreatedClient();
817     MockButton button(KDecoration2::DecorationButtonType::Shade, &mockDecoration);
818     button.setGeometry(QRect(0, 0, 10, 10));
819 
820     QCOMPARE(button.isEnabled(), false);
821     QCOMPARE(button.isCheckable(), true);
822     QCOMPARE(button.isChecked(), false);
823     QCOMPARE(button.isVisible(), true);
824     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
825 
826     // if the client is shadeable the button should get enabled
827     QSignalSpy shadeableChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::shadeableChanged);
828     QVERIFY(shadeableChangedSpy.isValid());
829     client->setShadeable(true);
830     QCOMPARE(button.isEnabled(), true);
831     QCOMPARE(shadeableChangedSpy.count(), 1);
832     QCOMPARE(shadeableChangedSpy.first().first().toBool(), true);
833 
834     // clicking the button should trigger a request for keep above changed
835     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
836     QVERIFY(clickedSpy.isValid());
837     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
838     QVERIFY(pressedSpy.isValid());
839     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
840     QVERIFY(releasedSpy.isValid());
841     QSignalSpy shadedChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::shadedChanged);
842     QVERIFY(shadedChangedSpy.isValid());
843     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
844     QVERIFY(pressedChangedSpy.isValid());
845 
846     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
847     pressEvent.setAccepted(false);
848     button.event(&pressEvent);
849     QCOMPARE(pressEvent.isAccepted(), true);
850     QCOMPARE(button.isPressed(), true);
851     QCOMPARE(clickedSpy.count(), 0);
852     QCOMPARE(pressedSpy.count(), 1);
853     QCOMPARE(releasedSpy.count(), 0);
854     QCOMPARE(shadedChangedSpy.count(), 0);
855     QCOMPARE(pressedChangedSpy.count(), 1);
856     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
857 
858     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
859     releaseEvent.setAccepted(false);
860     button.event(&releaseEvent);
861     QCOMPARE(releaseEvent.isAccepted(), true);
862     QCOMPARE(button.isPressed(), false);
863     QCOMPARE(clickedSpy.count(), 1);
864     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
865     QCOMPARE(pressedSpy.count(), 1);
866     QCOMPARE(releasedSpy.count(), 1);
867     QVERIFY(shadedChangedSpy.wait());
868     QCOMPARE(shadedChangedSpy.count(), 1);
869     QCOMPARE(shadedChangedSpy.first().first().toBool(), true);
870     QCOMPARE(pressedChangedSpy.count(), 2);
871     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
872     QCOMPARE(button.isChecked(), true);
873 
874     // click once more should change again
875     button.event(&pressEvent);
876     button.event(&releaseEvent);
877     QVERIFY(shadedChangedSpy.wait());
878     QCOMPARE(shadedChangedSpy.count(), 2);
879     QCOMPARE(shadedChangedSpy.first().first().toBool(), true);
880     QCOMPARE(shadedChangedSpy.last().first().toBool(), false);
881     QCOMPARE(button.isChecked(), false);
882 }
883 
testMaximize()884 void DecorationButtonTest::testMaximize()
885 {
886     MockBridge bridge;
887     MockDecoration mockDecoration(&bridge);
888     MockClient *client = bridge.lastCreatedClient();
889     MockButton button(KDecoration2::DecorationButtonType::Maximize, &mockDecoration);
890     button.setGeometry(QRect(0, 0, 10, 10));
891 
892     QCOMPARE(button.isEnabled(), false);
893     QCOMPARE(button.isCheckable(), true);
894     QCOMPARE(button.isChecked(), false);
895     QCOMPARE(button.isVisible(), true);
896     QCOMPARE(button.acceptedButtons(), Qt::LeftButton | Qt::MiddleButton | Qt::RightButton);
897 
898     // if the client is maximizable the button should get enabled
899     QSignalSpy maximizableChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::maximizeableChanged);
900     QVERIFY(maximizableChangedSpy.isValid());
901     client->setMaximizable(true);
902     QCOMPARE(button.isEnabled(), true);
903     QCOMPARE(maximizableChangedSpy.count(), 1);
904     QCOMPARE(maximizableChangedSpy.first().first().toBool(), true);
905 
906     // clicking the button should trigger a request for keep above changed
907     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
908     QVERIFY(clickedSpy.isValid());
909     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
910     QVERIFY(pressedSpy.isValid());
911     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
912     QVERIFY(releasedSpy.isValid());
913     QSignalSpy maximizedChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::maximizedChanged);
914     QVERIFY(maximizedChangedSpy.isValid());
915     QSignalSpy maximizedVerticallyChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::maximizedVerticallyChanged);
916     QVERIFY(maximizedVerticallyChangedSpy.isValid());
917     QSignalSpy maximizedHorizontallyChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::maximizedHorizontallyChanged);
918     QVERIFY(maximizedHorizontallyChangedSpy.isValid());
919     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
920     QVERIFY(pressedChangedSpy.isValid());
921 
922     QMouseEvent leftPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
923     leftPressEvent.setAccepted(false);
924     button.event(&leftPressEvent);
925     QCOMPARE(leftPressEvent.isAccepted(), true);
926     QCOMPARE(button.isPressed(), true);
927     QCOMPARE(clickedSpy.count(), 0);
928     QCOMPARE(pressedSpy.count(), 1);
929     QCOMPARE(releasedSpy.count(), 0);
930     QCOMPARE(maximizedChangedSpy.count(), 0);
931     QCOMPARE(pressedChangedSpy.count(), 1);
932     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
933 
934     QMouseEvent leftReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
935     leftReleaseEvent.setAccepted(false);
936     button.event(&leftReleaseEvent);
937     QCOMPARE(leftReleaseEvent.isAccepted(), true);
938     QCOMPARE(button.isPressed(), false);
939     QCOMPARE(clickedSpy.count(), 1);
940     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
941     QCOMPARE(pressedSpy.count(), 1);
942     QCOMPARE(releasedSpy.count(), 1);
943     QVERIFY(maximizedChangedSpy.wait());
944     QCOMPARE(maximizedChangedSpy.count(), 1);
945     QCOMPARE(maximizedChangedSpy.first().first().toBool(), true);
946     QCOMPARE(pressedChangedSpy.count(), 2);
947     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
948     QCOMPARE(button.isChecked(), true);
949 
950     // clicking again should set to restored
951     button.event(&leftPressEvent);
952     button.event(&leftReleaseEvent);
953     QVERIFY(maximizedChangedSpy.wait());
954     QCOMPARE(maximizedChangedSpy.count(), 2);
955     QCOMPARE(maximizedChangedSpy.first().first().toBool(), true);
956     QCOMPARE(maximizedChangedSpy.last().first().toBool(), false);
957     QCOMPARE(button.isChecked(), false);
958 
959     // test the other buttons
960     QMouseEvent rightPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::RightButton, Qt::RightButton, Qt::NoModifier);
961     rightPressEvent.setAccepted(false);
962     button.event(&rightPressEvent);
963     QCOMPARE(rightPressEvent.isAccepted(), true);
964     QCOMPARE(button.isPressed(), true);
965 
966     QMouseEvent middlePressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::MiddleButton, Qt::MiddleButton, Qt::NoModifier);
967     middlePressEvent.setAccepted(false);
968     button.event(&middlePressEvent);
969     QCOMPARE(middlePressEvent.isAccepted(), true);
970     QCOMPARE(button.isPressed(), true);
971 
972     QMouseEvent middleReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::MiddleButton, Qt::NoButton, Qt::NoModifier);
973     middleReleaseEvent.setAccepted(false);
974     button.event(&middleReleaseEvent);
975     QCOMPARE(middleReleaseEvent.isAccepted(), true);
976     QVERIFY(maximizedHorizontallyChangedSpy.wait());
977     QCOMPARE(button.isPressed(), true);
978     QCOMPARE(clickedSpy.count(), 3);
979     QCOMPARE(button.isChecked(), false);
980     QCOMPARE(client->isMaximizedHorizontally(), true);
981     QCOMPARE(client->isMaximizedVertically(), false);
982 
983     QMouseEvent rightReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::RightButton, Qt::NoButton, Qt::NoModifier);
984     rightReleaseEvent.setAccepted(false);
985     button.event(&rightReleaseEvent);
986     QCOMPARE(rightReleaseEvent.isAccepted(), true);
987     QVERIFY(maximizedVerticallyChangedSpy.wait());
988     QCOMPARE(button.isPressed(), false);
989     QCOMPARE(clickedSpy.count(), 4);
990     QCOMPARE(client->isMaximizedHorizontally(), true);
991     QCOMPARE(client->isMaximizedVertically(), true);
992     QCOMPARE(button.isChecked(), true);
993 }
994 
testOnAllDesktops()995 void DecorationButtonTest::testOnAllDesktops()
996 {
997     MockBridge bridge;
998     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
999     MockDecoration mockDecoration(&bridge);
1000     mockDecoration.setSettings(decoSettings);
1001     MockButton button(KDecoration2::DecorationButtonType::OnAllDesktops, &mockDecoration);
1002     button.setGeometry(QRect(0, 0, 10, 10));
1003 
1004     QCOMPARE(button.isEnabled(), true);
1005     QCOMPARE(button.isCheckable(), true);
1006     QCOMPARE(button.isChecked(), false);
1007     QCOMPARE(button.isVisible(), false);
1008     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
1009     QCOMPARE(mockDecoration.client().data()->isOnAllDesktops(), false);
1010 
1011     MockSettings *settings = bridge.lastCreatedSettings();
1012     QVERIFY(settings);
1013 
1014     QSignalSpy onAllDesktopsAvailableChangedSpy(decoSettings.data(), &KDecoration2::DecorationSettings::onAllDesktopsAvailableChanged);
1015     QVERIFY(onAllDesktopsAvailableChangedSpy.isValid());
1016     QSignalSpy visibleChangedSpy(&button, &KDecoration2::DecorationButton::visibilityChanged);
1017     QVERIFY(visibleChangedSpy.isValid());
1018 
1019     settings->setOnAllDesktopsAvailabe(true);
1020     QCOMPARE(onAllDesktopsAvailableChangedSpy.count(), 1);
1021     QCOMPARE(onAllDesktopsAvailableChangedSpy.last().first().toBool(), true);
1022     QCOMPARE(visibleChangedSpy.count(), 1);
1023     QCOMPARE(visibleChangedSpy.last().first().toBool(), true);
1024 
1025     // clicking the button should trigger a request for on all desktops
1026     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1027     QVERIFY(clickedSpy.isValid());
1028     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
1029     QVERIFY(pressedSpy.isValid());
1030     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
1031     QVERIFY(releasedSpy.isValid());
1032     QSignalSpy onAllDesktopsChangedSpy(mockDecoration.client().data(), &KDecoration2::DecoratedClient::onAllDesktopsChanged);
1033     QVERIFY(onAllDesktopsChangedSpy.isValid());
1034     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
1035     QVERIFY(pressedChangedSpy.isValid());
1036 
1037     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1038     pressEvent.setAccepted(false);
1039     button.event(&pressEvent);
1040     QCOMPARE(pressEvent.isAccepted(), true);
1041     QCOMPARE(button.isPressed(), true);
1042     QCOMPARE(clickedSpy.count(), 0);
1043     QCOMPARE(pressedSpy.count(), 1);
1044     QCOMPARE(releasedSpy.count(), 0);
1045     QCOMPARE(onAllDesktopsChangedSpy.count(), 0);
1046     QCOMPARE(pressedChangedSpy.count(), 1);
1047     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
1048 
1049     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1050     releaseEvent.setAccepted(false);
1051     button.event(&releaseEvent);
1052     QCOMPARE(releaseEvent.isAccepted(), true);
1053     QCOMPARE(button.isPressed(), false);
1054     QCOMPARE(clickedSpy.count(), 1);
1055     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
1056     QCOMPARE(pressedSpy.count(), 1);
1057     QCOMPARE(releasedSpy.count(), 1);
1058     QVERIFY(onAllDesktopsChangedSpy.wait());
1059     QCOMPARE(onAllDesktopsChangedSpy.count(), 1);
1060     QCOMPARE(onAllDesktopsChangedSpy.first().first().toBool(), true);
1061     QCOMPARE(pressedChangedSpy.count(), 2);
1062     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
1063     QCOMPARE(button.isChecked(), true);
1064 }
1065 
testMenu()1066 void DecorationButtonTest::testMenu()
1067 {
1068     MockBridge bridge;
1069     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1070     MockDecoration mockDecoration(&bridge);
1071     mockDecoration.setSettings(decoSettings);
1072     MockClient *client = bridge.lastCreatedClient();
1073     MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration);
1074     button.setGeometry(QRect(0, 0, 10, 10));
1075 
1076     QCOMPARE(button.isEnabled(), true);
1077     QCOMPARE(button.isCheckable(), false);
1078     QCOMPARE(button.isChecked(), false);
1079     QCOMPARE(button.isVisible(), true);
1080     QCOMPARE(button.acceptedButtons(), Qt::LeftButton | Qt::RightButton);
1081 
1082     // clicking the button should trigger a request for menu button
1083     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1084     QVERIFY(clickedSpy.isValid());
1085     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
1086     QVERIFY(pressedSpy.isValid());
1087     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
1088     QVERIFY(releasedSpy.isValid());
1089     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
1090     QVERIFY(pressedChangedSpy.isValid());
1091     QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested);
1092     QVERIFY(menuRequestedSpy.isValid());
1093 
1094     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1095     pressEvent.setAccepted(false);
1096     button.event(&pressEvent);
1097     QCOMPARE(pressEvent.isAccepted(), true);
1098     QCOMPARE(button.isPressed(), true);
1099     QCOMPARE(clickedSpy.count(), 0);
1100     QCOMPARE(pressedSpy.count(), 1);
1101     QCOMPARE(releasedSpy.count(), 0);
1102     QCOMPARE(menuRequestedSpy.count(), 0);
1103     QCOMPARE(pressedChangedSpy.count(), 1);
1104     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
1105 
1106     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1107     releaseEvent.setAccepted(false);
1108     button.event(&releaseEvent);
1109     QCOMPARE(releaseEvent.isAccepted(), true);
1110     QCOMPARE(button.isPressed(), false);
1111     QCOMPARE(clickedSpy.count(), 1);
1112     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
1113     QCOMPARE(pressedSpy.count(), 1);
1114     QCOMPARE(releasedSpy.count(), 1);
1115     QVERIFY(menuRequestedSpy.wait());
1116     QCOMPARE(menuRequestedSpy.count(), 1);
1117     QCOMPARE(pressedChangedSpy.count(), 2);
1118     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
1119 }
1120 
testMenuDoubleClick()1121 void DecorationButtonTest::testMenuDoubleClick()
1122 {
1123     MockBridge bridge;
1124     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1125     MockDecoration mockDecoration(&bridge);
1126     mockDecoration.setSettings(decoSettings);
1127     MockClient *client = bridge.lastCreatedClient();
1128     MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration);
1129     button.setGeometry(QRect(0, 0, 10, 10));
1130 
1131     MockSettings *settings = bridge.lastCreatedSettings();
1132     QVERIFY(settings);
1133     QSignalSpy closeOnDoubleClickOnMenuChangedSpy(decoSettings.data(), &KDecoration2::DecorationSettings::closeOnDoubleClickOnMenuChanged);
1134     QVERIFY(closeOnDoubleClickOnMenuChangedSpy.isValid());
1135     settings->setCloseOnDoubleClickOnMenu(true);
1136     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 1);
1137     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), true);
1138 
1139     // button used a queued connection, so we need to run event loop
1140     QCoreApplication::processEvents();
1141 
1142     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1143     QVERIFY(clickedSpy.isValid());
1144     QSignalSpy doubleClickedSpy(&button, &KDecoration2::DecorationButton::doubleClicked);
1145     QVERIFY(doubleClickedSpy.isValid());
1146     QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested);
1147     QVERIFY(closeRequestedSpy.isValid());
1148     QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested);
1149     QVERIFY(menuRequestedSpy.isValid());
1150 
1151     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1152     pressEvent.setAccepted(false);
1153     button.event(&pressEvent);
1154     QCOMPARE(pressEvent.isAccepted(), true);
1155     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1156     releaseEvent.setAccepted(false);
1157     button.event(&releaseEvent);
1158     QCOMPARE(releaseEvent.isAccepted(), true);
1159     // should not have emitted a clicked
1160     QCOMPARE(clickedSpy.count(), 0);
1161     QCOMPARE(doubleClickedSpy.count(), 0);
1162 
1163     // another press should trigger the double click event
1164     pressEvent.setAccepted(false);
1165     button.event(&pressEvent);
1166     QCOMPARE(pressEvent.isAccepted(), true);
1167     QVERIFY(closeRequestedSpy.wait());
1168     QCOMPARE(doubleClickedSpy.count(), 1);
1169     QCOMPARE(closeRequestedSpy.count(), 1);
1170     QCOMPARE(menuRequestedSpy.count(), 0);
1171 
1172     releaseEvent.setAccepted(false);
1173     button.event(&releaseEvent);
1174     QCOMPARE(releaseEvent.isAccepted(), true);
1175     QCOMPARE(clickedSpy.count(), 0);
1176     // run events
1177     QCoreApplication::processEvents();
1178     QCOMPARE(closeRequestedSpy.count(), 1);
1179     QCOMPARE(menuRequestedSpy.count(), 0);
1180 
1181     // a double click of right button shouldn't trigger the double click event
1182     QMouseEvent rightPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::RightButton, Qt::RightButton, Qt::NoModifier);
1183     rightPressEvent.setAccepted(false);
1184     button.event(&rightPressEvent);
1185     QCOMPARE(rightPressEvent.isAccepted(), true);
1186     QMouseEvent rightReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::RightButton, Qt::NoButton, Qt::NoModifier);
1187     rightReleaseEvent.setAccepted(false);
1188     button.event(&rightReleaseEvent);
1189     QCOMPARE(rightReleaseEvent.isAccepted(), true);
1190     QCOMPARE(clickedSpy.count(), 1);
1191     QVERIFY(menuRequestedSpy.wait());
1192     QCOMPARE(menuRequestedSpy.count(), 1);
1193     // second click
1194     rightPressEvent.setAccepted(false);
1195     button.event(&rightPressEvent);
1196     QCOMPARE(rightPressEvent.isAccepted(), true);
1197     rightReleaseEvent.setAccepted(false);
1198     button.event(&rightReleaseEvent);
1199     QCOMPARE(rightReleaseEvent.isAccepted(), true);
1200     QCOMPARE(clickedSpy.count(), 2);
1201     QVERIFY(menuRequestedSpy.wait());
1202     QCOMPARE(menuRequestedSpy.count(), 2);
1203 }
1204 
testMenuPressAndHold()1205 void DecorationButtonTest::testMenuPressAndHold()
1206 {
1207     MockBridge bridge;
1208     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1209     MockDecoration mockDecoration(&bridge);
1210     mockDecoration.setSettings(decoSettings);
1211     MockClient *client = bridge.lastCreatedClient();
1212     MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration);
1213     button.setGeometry(QRect(0, 0, 10, 10));
1214 
1215     MockSettings *settings = bridge.lastCreatedSettings();
1216     QVERIFY(settings);
1217     QSignalSpy closeOnDoubleClickOnMenuChangedSpy(decoSettings.data(), &KDecoration2::DecorationSettings::closeOnDoubleClickOnMenuChanged);
1218     QVERIFY(closeOnDoubleClickOnMenuChangedSpy.isValid());
1219     settings->setCloseOnDoubleClickOnMenu(true);
1220     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 1);
1221     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), true);
1222 
1223     // button used a queued connection, so we need to run event loop
1224     QCoreApplication::processEvents();
1225 
1226     QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested);
1227     QVERIFY(menuRequestedSpy.isValid());
1228     QSignalSpy doubleClickedSpy(&button, &KDecoration2::DecorationButton::doubleClicked);
1229     QVERIFY(doubleClickedSpy.isValid());
1230     QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested);
1231     QVERIFY(closeRequestedSpy.isValid());
1232     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1233     QVERIFY(clickedSpy.isValid());
1234 
1235     // send a press event
1236     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1237     pressEvent.setAccepted(false);
1238     button.event(&pressEvent);
1239     QCOMPARE(pressEvent.isAccepted(), true);
1240     QCOMPARE(clickedSpy.count(), 0);
1241 
1242     // and wait
1243     QVERIFY(menuRequestedSpy.wait());
1244     QCOMPARE(menuRequestedSpy.count(), 1);
1245     QCOMPARE(clickedSpy.count(), 1);
1246 
1247     // send release event
1248     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1249     releaseEvent.setAccepted(false);
1250     button.event(&releaseEvent);
1251     QCOMPARE(releaseEvent.isAccepted(), true);
1252     QCOMPARE(clickedSpy.count(), 1);
1253 
1254     QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 5);
1255 
1256     // and it shouldn't be a double click
1257     pressEvent.setAccepted(false);
1258     button.event(&pressEvent);
1259     QCOMPARE(pressEvent.isAccepted(), true);
1260 
1261     // while waiting we disable click and hold
1262     settings->setCloseOnDoubleClickOnMenu(false);
1263     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 2);
1264     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), false);
1265     // button used a queued connection, so we need to run event loop
1266     QCoreApplication::processEvents();
1267     // and releasing should emit the menu signal
1268     releaseEvent.setAccepted(false);
1269     button.event(&releaseEvent);
1270     QCOMPARE(releaseEvent.isAccepted(), true);
1271     QCOMPARE(clickedSpy.count(), 2);
1272     QVERIFY(menuRequestedSpy.wait());
1273     QCOMPARE(menuRequestedSpy.count(), 2);
1274     // never got a dobule click
1275     QCOMPARE(closeRequestedSpy.count(), 0);
1276 }
1277 
testApplicationMenu()1278 void DecorationButtonTest::testApplicationMenu()
1279 {
1280     MockBridge bridge;
1281     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1282     MockDecoration mockDecoration(&bridge);
1283     mockDecoration.setSettings(decoSettings);
1284     MockClient *client = bridge.lastCreatedClient();
1285     MockButton button(KDecoration2::DecorationButtonType::ApplicationMenu, &mockDecoration);
1286     button.setGeometry(QRect(0, 0, 10, 10));
1287 
1288     QCOMPARE(button.isEnabled(), true);
1289     QCOMPARE(button.isCheckable(), true);
1290     QCOMPARE(button.isChecked(), false);
1291     QCOMPARE(button.isVisible(), true);
1292     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
1293 
1294     // clicking the button should trigger a request for application menu
1295     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1296     QVERIFY(clickedSpy.isValid());
1297     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
1298     QVERIFY(pressedSpy.isValid());
1299     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
1300     QVERIFY(releasedSpy.isValid());
1301     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
1302     QVERIFY(pressedChangedSpy.isValid());
1303     QSignalSpy applicationMenuRequestedSpy(client, &MockClient::applicationMenuRequested);
1304     QVERIFY(applicationMenuRequestedSpy.isValid());
1305 
1306     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1307     pressEvent.setAccepted(false);
1308     button.event(&pressEvent);
1309     QCOMPARE(pressEvent.isAccepted(), true);
1310     QCOMPARE(button.isPressed(), true);
1311     QCOMPARE(clickedSpy.count(), 0);
1312     QCOMPARE(pressedSpy.count(), 1);
1313     QCOMPARE(releasedSpy.count(), 0);
1314     QCOMPARE(applicationMenuRequestedSpy.count(), 0);
1315     QCOMPARE(pressedChangedSpy.count(), 1);
1316     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
1317 
1318     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1319     releaseEvent.setAccepted(false);
1320     button.event(&releaseEvent);
1321     QCOMPARE(releaseEvent.isAccepted(), true);
1322     QCOMPARE(button.isPressed(), false);
1323     QCOMPARE(clickedSpy.count(), 1);
1324     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
1325     QCOMPARE(pressedSpy.count(), 1);
1326     QCOMPARE(releasedSpy.count(), 1);
1327     QVERIFY(applicationMenuRequestedSpy.wait());
1328     QCOMPARE(applicationMenuRequestedSpy.count(), 1);
1329     QCOMPARE(pressedChangedSpy.count(), 2);
1330     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
1331 }
1332 
testContains_data()1333 void DecorationButtonTest::testContains_data()
1334 {
1335     QTest::addColumn<QPointF>("pos");
1336     QTest::addColumn<bool>("contains");
1337 
1338     // Button geometry: QRectF(0, 0, 10, 10).
1339     QTest::newRow("on left edge") << QPointF(0, 5) << true;
1340     QTest::newRow("on top edge") << QPointF(5, 0) << true;
1341     QTest::newRow("on right edge") << QPointF(9, 5) << true;
1342     QTest::newRow("on bottom edge") << QPointF(5, 9) << true;
1343     QTest::newRow("inside") << QPointF(5, 5) << true;
1344     QTest::newRow("outside 1") << QPointF(-1, 5) << false;
1345     QTest::newRow("outside 2") << QPointF(5, -1) << false;
1346     QTest::newRow("outside 3") << QPointF(10, 5) << false;
1347     QTest::newRow("outside 4") << QPointF(5, 10) << false;
1348 }
1349 
testContains()1350 void DecorationButtonTest::testContains()
1351 {
1352     MockBridge bridge;
1353     MockDecoration mockDecoration(&bridge);
1354 
1355     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
1356     button.setGeometry(QRectF(0, 0, 10, 10));
1357     button.setEnabled(true);
1358     button.setVisible(true);
1359 
1360     QFETCH(QPointF, pos);
1361     QTEST(button.contains(pos), "contains");
1362 }
1363 
1364 QTEST_MAIN(DecorationButtonTest)
1365 #include "decorationbuttontest.moc"
1366