File indexing completed on 2024-04-28 16:44:32

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005  */
0006 #include "../src/decoratedclient.h"
0007 #include "../src/decorationsettings.h"
0008 #include "mockbridge.h"
0009 #include "mockbutton.h"
0010 #include "mockclient.h"
0011 #include "mockdecoration.h"
0012 #include "mocksettings.h"
0013 #include <QSignalSpy>
0014 #include <QStyleHints>
0015 #include <QTest>
0016 
0017 Q_DECLARE_METATYPE(Qt::MouseButton)
0018 
0019 class DecorationButtonTest : public QObject
0020 {
0021     Q_OBJECT
0022 private Q_SLOTS:
0023     void testButton();
0024     void testChecked();
0025     void testEnabled();
0026     void testPressIgnore_data();
0027     void testPressIgnore();
0028     void testReleaseIgnore_data();
0029     void testReleaseIgnore();
0030     void testHoverEnterIgnore_data();
0031     void testHoverEnterIgnore();
0032     void testHoverLeaveIgnore_data();
0033     void testHoverLeaveIgnore();
0034     void testHover();
0035     void testMouseMove_data();
0036     void testMouseMove();
0037     void testClose();
0038     void testMinimize();
0039     void testQuickHelp();
0040     void testKeepAbove();
0041     void testKeepBelow();
0042     void testShade();
0043     void testMaximize();
0044     void testOnAllDesktops();
0045     void testMenu();
0046     void testMenuDoubleClick();
0047     void testMenuPressAndHold();
0048     void testApplicationMenu();
0049     void testContains_data();
0050     void testContains();
0051 };
0052 
0053 void DecorationButtonTest::testButton()
0054 {
0055     MockBridge bridge;
0056     MockDecoration mockDecoration(&bridge);
0057     // create a custom button and verify the base settings
0058     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0059     QCOMPARE(button.decoration().data(), &mockDecoration);
0060     const MockButton &constRef(button);
0061     QCOMPARE(constRef.decoration().data(), &mockDecoration);
0062     QCOMPARE(button.type(), KDecoration2::DecorationButtonType::Custom);
0063     QCOMPARE(button.acceptedButtons(), Qt::MouseButtons(Qt::LeftButton));
0064     QCOMPARE(button.isCheckable(), false);
0065     QCOMPARE(button.isChecked(), false);
0066     QCOMPARE(button.isEnabled(), true);
0067     QCOMPARE(button.isHovered(), false);
0068     QCOMPARE(button.isPressed(), false);
0069     QCOMPARE(button.isVisible(), true);
0070     QCOMPARE(button.size(), QSizeF(0, 0));
0071     QCOMPARE(button.geometry(), QRectF());
0072 
0073     // test setting the geometry
0074     QSignalSpy geometryChangedSpy(&button, &KDecoration2::DecorationButton::geometryChanged);
0075     QVERIFY(geometryChangedSpy.isValid());
0076     // setting to default geometry shouldn't change
0077     button.setGeometry(QRectF());
0078     QCOMPARE(button.geometry(), QRectF());
0079     QCOMPARE(geometryChangedSpy.count(), 0);
0080     // setting to a proper geometry should change
0081     const QRectF testGeometry = QRectF(0, 0, 10, 20);
0082     button.setGeometry(testGeometry);
0083     QCOMPARE(button.geometry(), testGeometry);
0084     QCOMPARE(button.size(), testGeometry.size());
0085     QCOMPARE(geometryChangedSpy.count(), 1);
0086     QCOMPARE(geometryChangedSpy.first().first().toRectF(), testGeometry);
0087 
0088     // test changing visibility
0089     QSignalSpy visibilityChangedSpy(&button, &KDecoration2::DecorationButton::visibilityChanged);
0090     QVERIFY(visibilityChangedSpy.isValid());
0091     button.setVisible(true);
0092     QCOMPARE(visibilityChangedSpy.count(), 0);
0093     button.setVisible(false);
0094     QCOMPARE(button.isVisible(), false);
0095     QCOMPARE(visibilityChangedSpy.count(), 1);
0096     QCOMPARE(visibilityChangedSpy.first().first().toBool(), false);
0097 }
0098 
0099 void DecorationButtonTest::testChecked()
0100 {
0101     MockBridge bridge;
0102     MockDecoration mockDecoration(&bridge);
0103     // create a custom button and verify the base settings
0104     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0105     button.setGeometry(QRect(0, 0, 10, 10));
0106 
0107     // without being checkable it should not get checked
0108     QSignalSpy checkedChangedSpy(&button, &KDecoration2::DecorationButton::checkedChanged);
0109     QVERIFY(checkedChangedSpy.isValid());
0110     button.setChecked(true);
0111     QCOMPARE(button.isChecked(), false);
0112     QCOMPARE(checkedChangedSpy.count(), 0);
0113 
0114     // now let's set the checkable state
0115     QSignalSpy checkableChangedSpy(&button, &KDecoration2::DecorationButton::checkableChanged);
0116     QVERIFY(checkableChangedSpy.isValid());
0117     // setting to same should not emit
0118     button.setCheckable(false);
0119     QCOMPARE(checkableChangedSpy.count(), 0);
0120     button.setCheckable(true);
0121     QCOMPARE(button.isCheckable(), true);
0122     QCOMPARE(checkableChangedSpy.count(), 1);
0123     QCOMPARE(checkableChangedSpy.first().first().toBool(), true);
0124 
0125     // now it should be possible to check the button
0126     button.setChecked(true);
0127     QCOMPARE(button.isChecked(), true);
0128     QCOMPARE(checkedChangedSpy.count(), 1);
0129     // setting again should not change
0130     button.setChecked(true);
0131     QCOMPARE(button.isChecked(), true);
0132     QCOMPARE(checkedChangedSpy.count(), 1);
0133     // and disable
0134     button.setChecked(false);
0135     QCOMPARE(button.isChecked(), false);
0136     QCOMPARE(checkedChangedSpy.count(), 2);
0137     QCOMPARE(checkedChangedSpy.first().first().toBool(), true);
0138     QCOMPARE(checkedChangedSpy.last().first().toBool(), false);
0139 
0140     // last but not least let's disable the checkable again, this should disable a checked button
0141     button.setChecked(true);
0142     QCOMPARE(button.isChecked(), true);
0143     checkedChangedSpy.clear();
0144     QCOMPARE(checkedChangedSpy.count(), 0);
0145     button.setCheckable(false);
0146     QCOMPARE(button.isCheckable(), false);
0147     QCOMPARE(checkableChangedSpy.count(), 2);
0148     QCOMPARE(checkableChangedSpy.last().first().toBool(), false);
0149     QCOMPARE(button.isChecked(), false);
0150     QCOMPARE(checkedChangedSpy.count(), 1);
0151 }
0152 
0153 void DecorationButtonTest::testEnabled()
0154 {
0155     MockBridge bridge;
0156     MockDecoration mockDecoration(&bridge);
0157     // create a custom button and verify the base settings
0158     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0159     button.setGeometry(QRect(0, 0, 10, 10));
0160 
0161     // enabling has influence on whether the button accepts events, so we need to fake events
0162     QSignalSpy enabledChangedSpy(&button, &KDecoration2::DecorationButton::enabledChanged);
0163     QVERIFY(enabledChangedSpy.isValid());
0164     // setting to same shouldn't change
0165     button.setEnabled(true);
0166     QCOMPARE(enabledChangedSpy.count(), 0);
0167     button.setEnabled(false);
0168     QCOMPARE(button.isEnabled(), false);
0169     QCOMPARE(enabledChangedSpy.count(), 1);
0170     QCOMPARE(enabledChangedSpy.first().first().toBool(), false);
0171 
0172     // now let's send it a hover entered event
0173     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
0174     QVERIFY(hoveredChangedSpy.isValid());
0175     QHoverEvent event(QEvent::HoverEnter, QPointF(1, 1), QPointF(-1, -1));
0176     event.setAccepted(false);
0177     button.event(&event);
0178     QCOMPARE(event.isAccepted(), false);
0179     QCOMPARE(hoveredChangedSpy.count(), 0);
0180 
0181     // if we enable the button again we should get a hovered changed signal
0182     button.setEnabled(true);
0183     QCOMPARE(enabledChangedSpy.count(), 2);
0184     QCOMPARE(enabledChangedSpy.last().first().toBool(), true);
0185     button.event(&event);
0186     QCOMPARE(event.isAccepted(), true);
0187     QCOMPARE(hoveredChangedSpy.count(), 1);
0188     QCOMPARE(hoveredChangedSpy.first().first().toBool(), true);
0189 
0190     // if we disable the button now we get a hovered disabled signal
0191     button.setEnabled(false);
0192     QCOMPARE(hoveredChangedSpy.count(), 2);
0193     QCOMPARE(hoveredChangedSpy.last().first().toBool(), false);
0194 }
0195 
0196 void DecorationButtonTest::testPressIgnore_data()
0197 {
0198     QTest::addColumn<bool>("enabled");
0199     QTest::addColumn<bool>("visible");
0200     QTest::addColumn<QPoint>("clickPos");
0201     QTest::addColumn<Qt::MouseButton>("mouseButton");
0202     QTest::addColumn<bool>("expectedAccepted");
0203 
0204     QTest::newRow("all-disabled") << false << false << QPoint(0, 0) << Qt::LeftButton << false;
0205     QTest::newRow("enabled") << true << false << QPoint(0, 0) << Qt::LeftButton << false;
0206     QTest::newRow("visible") << false << true << QPoint(0, 0) << Qt::LeftButton << false;
0207     QTest::newRow("outside") << true << true << QPoint(20, 20) << Qt::LeftButton << false;
0208     QTest::newRow("wrong-button") << true << true << QPoint(0, 0) << Qt::RightButton << false;
0209 }
0210 
0211 void DecorationButtonTest::testPressIgnore()
0212 {
0213     MockBridge bridge;
0214     MockDecoration mockDecoration(&bridge);
0215     // create a custom button and verify the base settings
0216     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0217     button.setGeometry(QRect(0, 0, 10, 10));
0218     button.setAcceptedButtons(Qt::LeftButton);
0219     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0220     QVERIFY(pressedSpy.isValid());
0221     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0222     QVERIFY(pressedChangedSpy.isValid());
0223 
0224     QFETCH(bool, enabled);
0225     QFETCH(bool, visible);
0226     button.setEnabled(enabled);
0227     button.setVisible(visible);
0228 
0229     QFETCH(QPoint, clickPos);
0230     QFETCH(Qt::MouseButton, mouseButton);
0231     QMouseEvent pressEvent(QEvent::MouseButtonPress, clickPos, mouseButton, mouseButton, Qt::NoModifier);
0232     pressEvent.setAccepted(false);
0233     button.event(&pressEvent);
0234     QTEST(pressEvent.isAccepted(), "expectedAccepted");
0235     QCOMPARE(button.isPressed(), false);
0236     QVERIFY(pressedSpy.isEmpty());
0237     QVERIFY(pressedChangedSpy.isEmpty());
0238 }
0239 
0240 void DecorationButtonTest::testReleaseIgnore_data()
0241 {
0242     QTest::addColumn<bool>("enabled");
0243     QTest::addColumn<bool>("visible");
0244     QTest::addColumn<QPoint>("clickPos");
0245     QTest::addColumn<Qt::MouseButton>("mouseButton");
0246     QTest::addColumn<bool>("expectedAccepted");
0247     QTest::addColumn<bool>("expectedPressed");
0248     QTest::addColumn<int>("expectedPressedChanged");
0249 
0250     QTest::newRow("all-disabled") << false << false << QPoint(0, 0) << Qt::LeftButton << false << false << 2;
0251     QTest::newRow("enabled") << true << false << QPoint(0, 0) << Qt::LeftButton << false << false << 2;
0252     QTest::newRow("visible") << false << true << QPoint(0, 0) << Qt::LeftButton << false << false << 2;
0253     QTest::newRow("outside") << true << true << QPoint(20, 20) << Qt::LeftButton << true << false << 2;
0254     QTest::newRow("wrong-button") << true << true << QPoint(0, 0) << Qt::RightButton << false << true << 1;
0255 }
0256 
0257 void DecorationButtonTest::testReleaseIgnore()
0258 {
0259     MockBridge bridge;
0260     MockDecoration mockDecoration(&bridge);
0261     // create a custom button and verify the base settings
0262     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0263     button.setGeometry(QRect(0, 0, 10, 10));
0264     button.setAcceptedButtons(Qt::LeftButton);
0265     button.setEnabled(true);
0266     button.setVisible(true);
0267     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0268     QVERIFY(pressedSpy.isValid());
0269     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0270     QVERIFY(pressedChangedSpy.isValid());
0271     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0272     QVERIFY(clickedSpy.isValid());
0273 
0274     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0275     pressEvent.setAccepted(false);
0276     button.event(&pressEvent);
0277     QCOMPARE(pressEvent.isAccepted(), true);
0278     QCOMPARE(button.isPressed(), true);
0279     QCOMPARE(pressedSpy.count(), 1);
0280     QCOMPARE(pressedChangedSpy.count(), 1);
0281     QCOMPARE(pressedChangedSpy.last().first().toBool(), true);
0282 
0283     QFETCH(bool, enabled);
0284     QFETCH(bool, visible);
0285     button.setEnabled(enabled);
0286     button.setVisible(visible);
0287 
0288     QFETCH(QPoint, clickPos);
0289     QFETCH(Qt::MouseButton, mouseButton);
0290     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, clickPos, mouseButton, Qt::NoButton, Qt::NoModifier);
0291     releaseEvent.setAccepted(false);
0292     button.event(&releaseEvent);
0293     QTEST(releaseEvent.isAccepted(), "expectedAccepted");
0294     QTEST(button.isPressed(), "expectedPressed");
0295     QCOMPARE(pressedSpy.count(), 1);
0296     QFETCH(int, expectedPressedChanged);
0297     QCOMPARE(pressedChangedSpy.count(), expectedPressedChanged);
0298     QCOMPARE(pressedChangedSpy.last().first().toBool(), button.isPressed());
0299     QCOMPARE(clickedSpy.count(), 0);
0300 }
0301 
0302 void DecorationButtonTest::testHoverEnterIgnore_data()
0303 {
0304     QTest::addColumn<bool>("enabled");
0305     QTest::addColumn<bool>("visible");
0306     QTest::addColumn<QPoint>("enterPos");
0307 
0308     QTest::newRow("all-disabled") << false << false << QPoint(0, 0);
0309     QTest::newRow("enabled") << true << false << QPoint(0, 0);
0310     QTest::newRow("visible") << false << true << QPoint(0, 0);
0311     QTest::newRow("outside") << true << true << QPoint(20, 20);
0312 }
0313 
0314 void DecorationButtonTest::testHoverEnterIgnore()
0315 {
0316     MockBridge bridge;
0317     MockDecoration mockDecoration(&bridge);
0318     // create a custom button and verify the base settings
0319     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0320     button.setGeometry(QRect(0, 0, 10, 10));
0321     QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered);
0322     QVERIFY(pointerEnteredSpy.isValid());
0323     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
0324     QVERIFY(hoveredChangedSpy.isValid());
0325 
0326     QFETCH(bool, enabled);
0327     QFETCH(bool, visible);
0328     button.setEnabled(enabled);
0329     button.setVisible(visible);
0330 
0331     QFETCH(QPoint, enterPos);
0332     QHoverEvent enterEvent(QEvent::HoverEnter, enterPos, QPoint());
0333     enterEvent.setAccepted(false);
0334     button.event(&enterEvent);
0335     QCOMPARE(enterEvent.isAccepted(), false);
0336     QCOMPARE(button.isHovered(), false);
0337     QCOMPARE(pointerEnteredSpy.count(), 0);
0338     QCOMPARE(hoveredChangedSpy.count(), 0);
0339 
0340     // send a HoverLeft event should not be processed
0341     button.setEnabled(true);
0342     button.setVisible(true);
0343     QHoverEvent leftEvent(QEvent::HoverLeave, QPoint(20, 20), enterPos);
0344     leftEvent.setAccepted(false);
0345     button.event(&leftEvent);
0346     QCOMPARE(leftEvent.isAccepted(), false);
0347 }
0348 
0349 void DecorationButtonTest::testHoverLeaveIgnore_data()
0350 {
0351     QTest::addColumn<bool>("enabled");
0352     QTest::addColumn<bool>("visible");
0353     QTest::addColumn<QPoint>("leavePos");
0354     QTest::addColumn<int>("expectedLeaveCount");
0355     QTest::addColumn<int>("expectedHoverChangedCount");
0356 
0357     QTest::newRow("all-disabled") << false << false << QPoint(20, 20) << 1 << 2;
0358     QTest::newRow("enabled") << true << false << QPoint(20, 20) << 1 << 2;
0359     QTest::newRow("visible") << false << true << QPoint(20, 20) << 1 << 2;
0360     QTest::newRow("inside") << true << true << QPoint(5, 5) << 0 << 1;
0361 }
0362 
0363 void DecorationButtonTest::testHoverLeaveIgnore()
0364 {
0365     MockBridge bridge;
0366     MockDecoration mockDecoration(&bridge);
0367     // create a custom button and verify the base settings
0368     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0369     button.setGeometry(QRect(0, 0, 10, 10));
0370     button.setEnabled(true);
0371     button.setVisible(true);
0372     QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered);
0373     QVERIFY(pointerEnteredSpy.isValid());
0374     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
0375     QVERIFY(hoveredChangedSpy.isValid());
0376     QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft);
0377     QVERIFY(pointerLeavedSpy.isValid());
0378 
0379     QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint());
0380     enterEvent.setAccepted(false);
0381     button.event(&enterEvent);
0382     QCOMPARE(enterEvent.isAccepted(), true);
0383     QCOMPARE(button.isHovered(), true);
0384     QCOMPARE(pointerEnteredSpy.count(), 1);
0385     QCOMPARE(hoveredChangedSpy.count(), 1);
0386     QCOMPARE(hoveredChangedSpy.last().first().toBool(), true);
0387 
0388     QFETCH(bool, enabled);
0389     QFETCH(bool, visible);
0390     button.setEnabled(enabled);
0391     button.setVisible(visible);
0392 
0393     QFETCH(QPoint, leavePos);
0394     QHoverEvent leftEvent(QEvent::HoverLeave, leavePos, QPoint(0, 0));
0395     leftEvent.setAccepted(false);
0396     button.event(&leftEvent);
0397     QCOMPARE(leftEvent.isAccepted(), false);
0398     QCOMPARE(pointerEnteredSpy.count(), 1);
0399     QFETCH(int, expectedLeaveCount);
0400     QFETCH(int, expectedHoverChangedCount);
0401     QCOMPARE(pointerLeavedSpy.count(), expectedLeaveCount);
0402     QCOMPARE(hoveredChangedSpy.count(), expectedHoverChangedCount);
0403     QCOMPARE(hoveredChangedSpy.last().first().toBool(), button.isHovered());
0404 }
0405 
0406 void DecorationButtonTest::testHover()
0407 {
0408     MockBridge bridge;
0409     MockDecoration mockDecoration(&bridge);
0410     // create a custom button and verify the base settings
0411     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0412     button.setGeometry(QRectF(0, 0, 10, 10));
0413     button.setEnabled(true);
0414     button.setVisible(true);
0415     QSignalSpy pointerEnteredSpy(&button, &KDecoration2::DecorationButton::pointerEntered);
0416     QVERIFY(pointerEnteredSpy.isValid());
0417     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
0418     QVERIFY(hoveredChangedSpy.isValid());
0419     QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft);
0420     QVERIFY(pointerLeavedSpy.isValid());
0421 
0422     QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint());
0423     enterEvent.setAccepted(false);
0424     button.event(&enterEvent);
0425     QCOMPARE(enterEvent.isAccepted(), true);
0426     QCOMPARE(button.isHovered(), true);
0427     QCOMPARE(pointerEnteredSpy.count(), 1);
0428     QCOMPARE(hoveredChangedSpy.count(), 1);
0429     QCOMPARE(hoveredChangedSpy.last().first().toBool(), true);
0430 
0431     // send in a hovermove event - it's passed through, but not used
0432     QHoverEvent moveEvent(QEvent::HoverMove, QPoint(5, 0), QPoint(0, 0));
0433     moveEvent.setAccepted(false);
0434     button.event(&moveEvent);
0435     QCOMPARE(moveEvent.isAccepted(), false);
0436 
0437     QHoverEvent leftEvent(QEvent::HoverLeave, QPointF(10.1, 0.0), QPointF(0, 0));
0438     leftEvent.setAccepted(false);
0439     button.event(&leftEvent);
0440     QCOMPARE(leftEvent.isAccepted(), true);
0441     QCOMPARE(pointerEnteredSpy.count(), 1);
0442     QCOMPARE(pointerLeavedSpy.count(), 1);
0443     QCOMPARE(hoveredChangedSpy.count(), 2);
0444     QCOMPARE(hoveredChangedSpy.last().first().toBool(), false);
0445 }
0446 
0447 void DecorationButtonTest::testMouseMove_data()
0448 {
0449     QTest::addColumn<bool>("enabled");
0450     QTest::addColumn<bool>("visible");
0451     QTest::addColumn<QPointF>("movePos");
0452     QTest::addColumn<bool>("expectedAccepted");
0453     QTest::addColumn<bool>("expectedHovered");
0454     QTest::addColumn<int>("expectedChangedCount");
0455 
0456     QTest::newRow("outside") << true << true << QPointF(10.1, 10) << true << false << 2;
0457     QTest::newRow("inside") << true << true << QPointF(5, 5) << false << true << 1;
0458     QTest::newRow("disabled") << false << true << QPointF(10, 10) << false << false << 2;
0459     QTest::newRow("invisible") << true << false << QPointF(10, 10) << false << false << 2;
0460 }
0461 
0462 void DecorationButtonTest::testMouseMove()
0463 {
0464     MockBridge bridge;
0465     MockDecoration mockDecoration(&bridge);
0466     // create a custom button and verify the base settings
0467     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
0468     button.setGeometry(QRectF(0, 0, 10, 10));
0469     button.setEnabled(true);
0470     button.setVisible(true);
0471     QSignalSpy hoveredChangedSpy(&button, &KDecoration2::DecorationButton::hoveredChanged);
0472     QVERIFY(hoveredChangedSpy.isValid());
0473     QSignalSpy pointerLeavedSpy(&button, &KDecoration2::DecorationButton::pointerLeft);
0474     QVERIFY(pointerLeavedSpy.isValid());
0475 
0476     QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(0, 0), QPoint());
0477     enterEvent.setAccepted(false);
0478     button.event(&enterEvent);
0479     QCOMPARE(enterEvent.isAccepted(), true);
0480     QCOMPARE(button.isHovered(), true);
0481     QCOMPARE(hoveredChangedSpy.count(), 1);
0482     QCOMPARE(hoveredChangedSpy.last().first().toBool(), true);
0483 
0484     QFETCH(bool, enabled);
0485     button.setEnabled(enabled);
0486     QFETCH(bool, visible);
0487     button.setVisible(visible);
0488 
0489     QFETCH(QPointF, movePos);
0490     QMouseEvent mouseMoveEvent(QEvent::MouseMove, movePos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0491     mouseMoveEvent.setAccepted(false);
0492     button.event(&mouseMoveEvent);
0493     QTEST(mouseMoveEvent.isAccepted(), "expectedAccepted");
0494     QTEST(button.isHovered(), "expectedHovered");
0495     QFETCH(int, expectedChangedCount);
0496     QCOMPARE(hoveredChangedSpy.count(), expectedChangedCount);
0497     QCOMPARE(hoveredChangedSpy.last().first().toBool(), button.isHovered());
0498 
0499     // explicit further move event outside of button
0500     QMouseEvent mouseMoveEvent2(QEvent::MouseMove, QPoint(50, 50), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0501     mouseMoveEvent2.setAccepted(false);
0502     button.event(&mouseMoveEvent2);
0503     QTEST(mouseMoveEvent2.isAccepted(), "expectedHovered");
0504     QCOMPARE(button.isHovered(), false);
0505 }
0506 
0507 void DecorationButtonTest::testClose()
0508 {
0509     MockBridge bridge;
0510     MockDecoration mockDecoration(&bridge);
0511     MockClient *client = bridge.lastCreatedClient();
0512     MockButton button(KDecoration2::DecorationButtonType::Close, &mockDecoration);
0513     button.setGeometry(QRect(0, 0, 10, 10));
0514 
0515     QCOMPARE(button.isEnabled(), false);
0516     QCOMPARE(button.isCheckable(), false);
0517     QCOMPARE(button.isChecked(), false);
0518     QCOMPARE(button.isVisible(), true);
0519     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
0520 
0521     // if the client is closeable the button should get enabled
0522     QSignalSpy closeableChangedSpy(mockDecoration.client().toStrongRef().data(), &KDecoration2::DecoratedClient::closeableChanged);
0523     QVERIFY(closeableChangedSpy.isValid());
0524     client->setCloseable(true);
0525     QCOMPARE(button.isEnabled(), true);
0526     QCOMPARE(closeableChangedSpy.count(), 1);
0527     QCOMPARE(closeableChangedSpy.first().first().toBool(), true);
0528 
0529     // clicking the button should trigger a request for close
0530     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0531     QVERIFY(clickedSpy.isValid());
0532     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0533     QVERIFY(pressedSpy.isValid());
0534     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
0535     QVERIFY(releasedSpy.isValid());
0536     QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested);
0537     QVERIFY(closeRequestedSpy.isValid());
0538     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0539     QVERIFY(pressedChangedSpy.isValid());
0540 
0541     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0542     pressEvent.setAccepted(false);
0543     button.event(&pressEvent);
0544     QCOMPARE(pressEvent.isAccepted(), true);
0545     QCOMPARE(button.isPressed(), true);
0546     QCOMPARE(clickedSpy.count(), 0);
0547     QCOMPARE(pressedSpy.count(), 1);
0548     QCOMPARE(releasedSpy.count(), 0);
0549     QCOMPARE(closeRequestedSpy.count(), 0);
0550     QCOMPARE(pressedChangedSpy.count(), 1);
0551     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
0552 
0553     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
0554     releaseEvent.setAccepted(false);
0555     button.event(&releaseEvent);
0556     QCOMPARE(releaseEvent.isAccepted(), true);
0557     QCOMPARE(button.isPressed(), false);
0558     QCOMPARE(clickedSpy.count(), 1);
0559     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
0560     QCOMPARE(pressedSpy.count(), 1);
0561     QCOMPARE(releasedSpy.count(), 1);
0562     QVERIFY(closeRequestedSpy.wait());
0563     QCOMPARE(closeRequestedSpy.count(), 1);
0564     QCOMPARE(pressedChangedSpy.count(), 2);
0565     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
0566 }
0567 
0568 void DecorationButtonTest::testMinimize()
0569 {
0570     MockBridge bridge;
0571     MockDecoration mockDecoration(&bridge);
0572     MockClient *client = bridge.lastCreatedClient();
0573     MockButton button(KDecoration2::DecorationButtonType::Minimize, &mockDecoration);
0574     button.setGeometry(QRect(0, 0, 10, 10));
0575 
0576     QCOMPARE(button.isEnabled(), false);
0577     QCOMPARE(button.isCheckable(), false);
0578     QCOMPARE(button.isChecked(), false);
0579     QCOMPARE(button.isVisible(), true);
0580     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
0581 
0582     // if the client is minimizeable the button should get enabled
0583     QSignalSpy minimizableChangedSpy(mockDecoration.client().toStrongRef().data(), &KDecoration2::DecoratedClient::minimizeableChanged);
0584     QVERIFY(minimizableChangedSpy.isValid());
0585     client->setMinimizable(true);
0586     QCOMPARE(button.isEnabled(), true);
0587     QCOMPARE(minimizableChangedSpy.count(), 1);
0588     QCOMPARE(minimizableChangedSpy.first().first().toBool(), true);
0589 
0590     // clicking the button should trigger a request for minimize
0591     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0592     QVERIFY(clickedSpy.isValid());
0593     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0594     QVERIFY(pressedSpy.isValid());
0595     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
0596     QVERIFY(releasedSpy.isValid());
0597     QSignalSpy minimizeRequestedSpy(client, &MockClient::minimizeRequested);
0598     QVERIFY(minimizeRequestedSpy.isValid());
0599     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0600     QVERIFY(pressedChangedSpy.isValid());
0601 
0602     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0603     pressEvent.setAccepted(false);
0604     button.event(&pressEvent);
0605     QCOMPARE(pressEvent.isAccepted(), true);
0606     QCOMPARE(button.isPressed(), true);
0607     QCOMPARE(clickedSpy.count(), 0);
0608     QCOMPARE(pressedSpy.count(), 1);
0609     QCOMPARE(releasedSpy.count(), 0);
0610     QCOMPARE(minimizeRequestedSpy.count(), 0);
0611     QCOMPARE(pressedChangedSpy.count(), 1);
0612     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
0613 
0614     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
0615     releaseEvent.setAccepted(false);
0616     button.event(&releaseEvent);
0617     QCOMPARE(releaseEvent.isAccepted(), true);
0618     QCOMPARE(button.isPressed(), false);
0619     QCOMPARE(clickedSpy.count(), 1);
0620     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
0621     QCOMPARE(pressedSpy.count(), 1);
0622     QCOMPARE(releasedSpy.count(), 1);
0623     QVERIFY(minimizeRequestedSpy.wait());
0624     QCOMPARE(minimizeRequestedSpy.count(), 1);
0625     QCOMPARE(pressedChangedSpy.count(), 2);
0626     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
0627 }
0628 
0629 void DecorationButtonTest::testQuickHelp()
0630 {
0631     MockBridge bridge;
0632     MockDecoration mockDecoration(&bridge);
0633     MockClient *client = bridge.lastCreatedClient();
0634     MockButton button(KDecoration2::DecorationButtonType::ContextHelp, &mockDecoration);
0635     button.setGeometry(QRect(0, 0, 10, 10));
0636 
0637     QCOMPARE(button.isEnabled(), true);
0638     QCOMPARE(button.isCheckable(), false);
0639     QCOMPARE(button.isChecked(), false);
0640     QCOMPARE(button.isVisible(), false);
0641     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
0642 
0643     // if the client provides quickhelp the button should get enabled
0644     QSignalSpy providesContextHelpChangedSpy(mockDecoration.client().toStrongRef().data(), &KDecoration2::DecoratedClient::providesContextHelpChanged);
0645     QVERIFY(providesContextHelpChangedSpy.isValid());
0646     client->setProvidesContextHelp(true);
0647     QCOMPARE(button.isVisible(), true);
0648     QCOMPARE(providesContextHelpChangedSpy.count(), 1);
0649     QCOMPARE(providesContextHelpChangedSpy.first().first().toBool(), true);
0650 
0651     // clicking the button should trigger a request for minimize
0652     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0653     QVERIFY(clickedSpy.isValid());
0654     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0655     QVERIFY(pressedSpy.isValid());
0656     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
0657     QVERIFY(releasedSpy.isValid());
0658     QSignalSpy quickhelpRequestedSpy(client, &MockClient::quickHelpRequested);
0659     QVERIFY(quickhelpRequestedSpy.isValid());
0660     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0661     QVERIFY(pressedChangedSpy.isValid());
0662 
0663     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0664     pressEvent.setAccepted(false);
0665     button.event(&pressEvent);
0666     QCOMPARE(pressEvent.isAccepted(), true);
0667     QCOMPARE(button.isPressed(), true);
0668     QCOMPARE(clickedSpy.count(), 0);
0669     QCOMPARE(pressedSpy.count(), 1);
0670     QCOMPARE(releasedSpy.count(), 0);
0671     QCOMPARE(quickhelpRequestedSpy.count(), 0);
0672     QCOMPARE(pressedChangedSpy.count(), 1);
0673     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
0674 
0675     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
0676     releaseEvent.setAccepted(false);
0677     button.event(&releaseEvent);
0678     QCOMPARE(releaseEvent.isAccepted(), true);
0679     QCOMPARE(button.isPressed(), false);
0680     QCOMPARE(clickedSpy.count(), 1);
0681     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
0682     QCOMPARE(pressedSpy.count(), 1);
0683     QCOMPARE(releasedSpy.count(), 1);
0684     QVERIFY(quickhelpRequestedSpy.wait());
0685     QCOMPARE(quickhelpRequestedSpy.count(), 1);
0686     QCOMPARE(pressedChangedSpy.count(), 2);
0687     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
0688 }
0689 
0690 void DecorationButtonTest::testKeepAbove()
0691 {
0692     MockBridge bridge;
0693     MockDecoration mockDecoration(&bridge);
0694     MockButton button(KDecoration2::DecorationButtonType::KeepAbove, &mockDecoration);
0695     button.setGeometry(QRect(0, 0, 10, 10));
0696 
0697     QCOMPARE(button.isEnabled(), true);
0698     QCOMPARE(button.isCheckable(), true);
0699     QCOMPARE(button.isChecked(), false);
0700     QCOMPARE(button.isVisible(), true);
0701     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
0702 
0703     // clicking the button should trigger a request for keep above changed
0704     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0705     QVERIFY(clickedSpy.isValid());
0706     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0707     QVERIFY(pressedSpy.isValid());
0708     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
0709     QVERIFY(releasedSpy.isValid());
0710     QSignalSpy keepAboveChangedSpy(mockDecoration.client().toStrongRef().data(), &KDecoration2::DecoratedClient::keepAboveChanged);
0711     QVERIFY(keepAboveChangedSpy.isValid());
0712     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0713     QVERIFY(pressedChangedSpy.isValid());
0714 
0715     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0716     pressEvent.setAccepted(false);
0717     button.event(&pressEvent);
0718     QCOMPARE(pressEvent.isAccepted(), true);
0719     QCOMPARE(button.isPressed(), true);
0720     QCOMPARE(clickedSpy.count(), 0);
0721     QCOMPARE(pressedSpy.count(), 1);
0722     QCOMPARE(releasedSpy.count(), 0);
0723     QCOMPARE(keepAboveChangedSpy.count(), 0);
0724     QCOMPARE(pressedChangedSpy.count(), 1);
0725     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
0726 
0727     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
0728     releaseEvent.setAccepted(false);
0729     button.event(&releaseEvent);
0730     QCOMPARE(releaseEvent.isAccepted(), true);
0731     QCOMPARE(button.isPressed(), false);
0732     QCOMPARE(clickedSpy.count(), 1);
0733     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
0734     QCOMPARE(pressedSpy.count(), 1);
0735     QCOMPARE(releasedSpy.count(), 1);
0736     QVERIFY(keepAboveChangedSpy.wait());
0737     QCOMPARE(keepAboveChangedSpy.count(), 1);
0738     QCOMPARE(keepAboveChangedSpy.first().first().toBool(), true);
0739     QCOMPARE(pressedChangedSpy.count(), 2);
0740     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
0741     QCOMPARE(button.isChecked(), true);
0742 
0743     // click once more should change again
0744     button.event(&pressEvent);
0745     button.event(&releaseEvent);
0746     QVERIFY(keepAboveChangedSpy.wait());
0747     QCOMPARE(keepAboveChangedSpy.count(), 2);
0748     QCOMPARE(keepAboveChangedSpy.first().first().toBool(), true);
0749     QCOMPARE(keepAboveChangedSpy.last().first().toBool(), false);
0750     QCOMPARE(button.isChecked(), false);
0751 }
0752 
0753 void DecorationButtonTest::testKeepBelow()
0754 {
0755     MockBridge bridge;
0756     MockDecoration mockDecoration(&bridge);
0757     MockButton button(KDecoration2::DecorationButtonType::KeepBelow, &mockDecoration);
0758     button.setGeometry(QRect(0, 0, 10, 10));
0759 
0760     QCOMPARE(button.isEnabled(), true);
0761     QCOMPARE(button.isCheckable(), true);
0762     QCOMPARE(button.isChecked(), false);
0763     QCOMPARE(button.isVisible(), true);
0764     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
0765 
0766     // clicking the button should trigger a request for keep above changed
0767     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0768     QVERIFY(clickedSpy.isValid());
0769     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0770     QVERIFY(pressedSpy.isValid());
0771     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
0772     QVERIFY(releasedSpy.isValid());
0773     QSignalSpy keepBelowChangedSpy(mockDecoration.client().toStrongRef().data(), &KDecoration2::DecoratedClient::keepBelowChanged);
0774     QVERIFY(keepBelowChangedSpy.isValid());
0775     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0776     QVERIFY(pressedChangedSpy.isValid());
0777 
0778     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0779     pressEvent.setAccepted(false);
0780     button.event(&pressEvent);
0781     QCOMPARE(pressEvent.isAccepted(), true);
0782     QCOMPARE(button.isPressed(), true);
0783     QCOMPARE(clickedSpy.count(), 0);
0784     QCOMPARE(pressedSpy.count(), 1);
0785     QCOMPARE(releasedSpy.count(), 0);
0786     QCOMPARE(keepBelowChangedSpy.count(), 0);
0787     QCOMPARE(pressedChangedSpy.count(), 1);
0788     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
0789 
0790     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
0791     releaseEvent.setAccepted(false);
0792     button.event(&releaseEvent);
0793     QCOMPARE(releaseEvent.isAccepted(), true);
0794     QCOMPARE(button.isPressed(), false);
0795     QCOMPARE(clickedSpy.count(), 1);
0796     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
0797     QCOMPARE(pressedSpy.count(), 1);
0798     QCOMPARE(releasedSpy.count(), 1);
0799     QVERIFY(keepBelowChangedSpy.wait());
0800     QCOMPARE(keepBelowChangedSpy.count(), 1);
0801     QCOMPARE(keepBelowChangedSpy.first().first().toBool(), true);
0802     QCOMPARE(pressedChangedSpy.count(), 2);
0803     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
0804     QCOMPARE(button.isChecked(), true);
0805 
0806     // click once more should change again
0807     button.event(&pressEvent);
0808     button.event(&releaseEvent);
0809     QVERIFY(keepBelowChangedSpy.wait());
0810     QCOMPARE(keepBelowChangedSpy.count(), 2);
0811     QCOMPARE(keepBelowChangedSpy.first().first().toBool(), true);
0812     QCOMPARE(keepBelowChangedSpy.last().first().toBool(), false);
0813     QCOMPARE(button.isChecked(), false);
0814 }
0815 
0816 void DecorationButtonTest::testShade()
0817 {
0818     MockBridge bridge;
0819     MockDecoration mockDecoration(&bridge);
0820     MockClient *client = bridge.lastCreatedClient();
0821     MockButton button(KDecoration2::DecorationButtonType::Shade, &mockDecoration);
0822     button.setGeometry(QRect(0, 0, 10, 10));
0823 
0824     QCOMPARE(button.isEnabled(), false);
0825     QCOMPARE(button.isCheckable(), true);
0826     QCOMPARE(button.isChecked(), false);
0827     QCOMPARE(button.isVisible(), true);
0828     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
0829 
0830     // if the client is shadeable the button should get enabled
0831     const auto decoClient = mockDecoration.client();
0832     QSignalSpy shadeableChangedSpy(decoClient.toStrongRef().data(), &KDecoration2::DecoratedClient::shadeableChanged);
0833     QVERIFY(shadeableChangedSpy.isValid());
0834     client->setShadeable(true);
0835     QCOMPARE(button.isEnabled(), true);
0836     QCOMPARE(shadeableChangedSpy.count(), 1);
0837     QCOMPARE(shadeableChangedSpy.first().first().toBool(), true);
0838 
0839     // clicking the button should trigger a request for keep above changed
0840     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0841     QVERIFY(clickedSpy.isValid());
0842     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0843     QVERIFY(pressedSpy.isValid());
0844     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
0845     QVERIFY(releasedSpy.isValid());
0846     QSignalSpy shadedChangedSpy(decoClient.toStrongRef().data(), &KDecoration2::DecoratedClient::shadedChanged);
0847     QVERIFY(shadedChangedSpy.isValid());
0848     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0849     QVERIFY(pressedChangedSpy.isValid());
0850 
0851     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0852     pressEvent.setAccepted(false);
0853     button.event(&pressEvent);
0854     QCOMPARE(pressEvent.isAccepted(), true);
0855     QCOMPARE(button.isPressed(), true);
0856     QCOMPARE(clickedSpy.count(), 0);
0857     QCOMPARE(pressedSpy.count(), 1);
0858     QCOMPARE(releasedSpy.count(), 0);
0859     QCOMPARE(shadedChangedSpy.count(), 0);
0860     QCOMPARE(pressedChangedSpy.count(), 1);
0861     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
0862 
0863     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
0864     releaseEvent.setAccepted(false);
0865     button.event(&releaseEvent);
0866     QCOMPARE(releaseEvent.isAccepted(), true);
0867     QCOMPARE(button.isPressed(), false);
0868     QCOMPARE(clickedSpy.count(), 1);
0869     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
0870     QCOMPARE(pressedSpy.count(), 1);
0871     QCOMPARE(releasedSpy.count(), 1);
0872     QVERIFY(shadedChangedSpy.wait());
0873     QCOMPARE(shadedChangedSpy.count(), 1);
0874     QCOMPARE(shadedChangedSpy.first().first().toBool(), true);
0875     QCOMPARE(pressedChangedSpy.count(), 2);
0876     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
0877     QCOMPARE(button.isChecked(), true);
0878 
0879     // click once more should change again
0880     button.event(&pressEvent);
0881     button.event(&releaseEvent);
0882     QVERIFY(shadedChangedSpy.wait());
0883     QCOMPARE(shadedChangedSpy.count(), 2);
0884     QCOMPARE(shadedChangedSpy.first().first().toBool(), true);
0885     QCOMPARE(shadedChangedSpy.last().first().toBool(), false);
0886     QCOMPARE(button.isChecked(), false);
0887 }
0888 
0889 void DecorationButtonTest::testMaximize()
0890 {
0891     MockBridge bridge;
0892     MockDecoration mockDecoration(&bridge);
0893     MockClient *client = bridge.lastCreatedClient();
0894     MockButton button(KDecoration2::DecorationButtonType::Maximize, &mockDecoration);
0895     button.setGeometry(QRect(0, 0, 10, 10));
0896 
0897     QCOMPARE(button.isEnabled(), false);
0898     QCOMPARE(button.isCheckable(), true);
0899     QCOMPARE(button.isChecked(), false);
0900     QCOMPARE(button.isVisible(), true);
0901     QCOMPARE(button.acceptedButtons(), Qt::LeftButton | Qt::MiddleButton | Qt::RightButton);
0902 
0903     // if the client is maximizable the button should get enabled
0904     const auto decoClient = mockDecoration.client().toStrongRef();
0905     QSignalSpy maximizableChangedSpy(decoClient.data(), &KDecoration2::DecoratedClient::maximizeableChanged);
0906     QVERIFY(maximizableChangedSpy.isValid());
0907     client->setMaximizable(true);
0908     QCOMPARE(button.isEnabled(), true);
0909     QCOMPARE(maximizableChangedSpy.count(), 1);
0910     QCOMPARE(maximizableChangedSpy.first().first().toBool(), true);
0911 
0912     // clicking the button should trigger a request for keep above changed
0913     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
0914     QVERIFY(clickedSpy.isValid());
0915     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
0916     QVERIFY(pressedSpy.isValid());
0917     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
0918     QVERIFY(releasedSpy.isValid());
0919     QSignalSpy maximizedChangedSpy(decoClient.data(), &KDecoration2::DecoratedClient::maximizedChanged);
0920     QVERIFY(maximizedChangedSpy.isValid());
0921     QSignalSpy maximizedVerticallyChangedSpy(decoClient.data(), &KDecoration2::DecoratedClient::maximizedVerticallyChanged);
0922     QVERIFY(maximizedVerticallyChangedSpy.isValid());
0923     QSignalSpy maximizedHorizontallyChangedSpy(decoClient.data(), &KDecoration2::DecoratedClient::maximizedHorizontallyChanged);
0924     QVERIFY(maximizedHorizontallyChangedSpy.isValid());
0925     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
0926     QVERIFY(pressedChangedSpy.isValid());
0927 
0928     QMouseEvent leftPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
0929     leftPressEvent.setAccepted(false);
0930     button.event(&leftPressEvent);
0931     QCOMPARE(leftPressEvent.isAccepted(), true);
0932     QCOMPARE(button.isPressed(), true);
0933     QCOMPARE(clickedSpy.count(), 0);
0934     QCOMPARE(pressedSpy.count(), 1);
0935     QCOMPARE(releasedSpy.count(), 0);
0936     QCOMPARE(maximizedChangedSpy.count(), 0);
0937     QCOMPARE(pressedChangedSpy.count(), 1);
0938     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
0939 
0940     QMouseEvent leftReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
0941     leftReleaseEvent.setAccepted(false);
0942     button.event(&leftReleaseEvent);
0943     QCOMPARE(leftReleaseEvent.isAccepted(), true);
0944     QCOMPARE(button.isPressed(), false);
0945     QCOMPARE(clickedSpy.count(), 1);
0946     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
0947     QCOMPARE(pressedSpy.count(), 1);
0948     QCOMPARE(releasedSpy.count(), 1);
0949     QVERIFY(maximizedChangedSpy.wait());
0950     QCOMPARE(maximizedChangedSpy.count(), 1);
0951     QCOMPARE(maximizedChangedSpy.first().first().toBool(), true);
0952     QCOMPARE(pressedChangedSpy.count(), 2);
0953     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
0954     QCOMPARE(button.isChecked(), true);
0955 
0956     // clicking again should set to restored
0957     button.event(&leftPressEvent);
0958     button.event(&leftReleaseEvent);
0959     QVERIFY(maximizedChangedSpy.wait());
0960     QCOMPARE(maximizedChangedSpy.count(), 2);
0961     QCOMPARE(maximizedChangedSpy.first().first().toBool(), true);
0962     QCOMPARE(maximizedChangedSpy.last().first().toBool(), false);
0963     QCOMPARE(button.isChecked(), false);
0964 
0965     // test the other buttons
0966     QMouseEvent rightPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::RightButton, Qt::RightButton, Qt::NoModifier);
0967     rightPressEvent.setAccepted(false);
0968     button.event(&rightPressEvent);
0969     QCOMPARE(rightPressEvent.isAccepted(), true);
0970     QCOMPARE(button.isPressed(), true);
0971 
0972     QMouseEvent middlePressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::MiddleButton, Qt::MiddleButton, Qt::NoModifier);
0973     middlePressEvent.setAccepted(false);
0974     button.event(&middlePressEvent);
0975     QCOMPARE(middlePressEvent.isAccepted(), true);
0976     QCOMPARE(button.isPressed(), true);
0977 
0978     QMouseEvent middleReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::MiddleButton, Qt::NoButton, Qt::NoModifier);
0979     middleReleaseEvent.setAccepted(false);
0980     button.event(&middleReleaseEvent);
0981     QCOMPARE(middleReleaseEvent.isAccepted(), true);
0982     QVERIFY(maximizedHorizontallyChangedSpy.wait());
0983     QCOMPARE(button.isPressed(), true);
0984     QCOMPARE(clickedSpy.count(), 3);
0985     QCOMPARE(button.isChecked(), false);
0986     QCOMPARE(client->isMaximizedHorizontally(), true);
0987     QCOMPARE(client->isMaximizedVertically(), false);
0988 
0989     QMouseEvent rightReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::RightButton, Qt::NoButton, Qt::NoModifier);
0990     rightReleaseEvent.setAccepted(false);
0991     button.event(&rightReleaseEvent);
0992     QCOMPARE(rightReleaseEvent.isAccepted(), true);
0993     QVERIFY(maximizedVerticallyChangedSpy.wait());
0994     QCOMPARE(button.isPressed(), false);
0995     QCOMPARE(clickedSpy.count(), 4);
0996     QCOMPARE(client->isMaximizedHorizontally(), true);
0997     QCOMPARE(client->isMaximizedVertically(), true);
0998     QCOMPARE(button.isChecked(), true);
0999 }
1000 
1001 void DecorationButtonTest::testOnAllDesktops()
1002 {
1003     MockBridge bridge;
1004     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1005     MockDecoration mockDecoration(&bridge);
1006     mockDecoration.setSettings(decoSettings);
1007     MockButton button(KDecoration2::DecorationButtonType::OnAllDesktops, &mockDecoration);
1008     button.setGeometry(QRect(0, 0, 10, 10));
1009 
1010     QCOMPARE(button.isEnabled(), true);
1011     QCOMPARE(button.isCheckable(), true);
1012     QCOMPARE(button.isChecked(), false);
1013     QCOMPARE(button.isVisible(), false);
1014     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
1015     const auto decoClient = mockDecoration.client().toStrongRef();
1016     QCOMPARE(decoClient.data()->isOnAllDesktops(), false);
1017 
1018     MockSettings *settings = bridge.lastCreatedSettings();
1019     QVERIFY(settings);
1020 
1021     QSignalSpy onAllDesktopsAvailableChangedSpy(decoSettings.data(), &KDecoration2::DecorationSettings::onAllDesktopsAvailableChanged);
1022     QVERIFY(onAllDesktopsAvailableChangedSpy.isValid());
1023     QSignalSpy visibleChangedSpy(&button, &KDecoration2::DecorationButton::visibilityChanged);
1024     QVERIFY(visibleChangedSpy.isValid());
1025 
1026     settings->setOnAllDesktopsAvailabe(true);
1027     QCOMPARE(onAllDesktopsAvailableChangedSpy.count(), 1);
1028     QCOMPARE(onAllDesktopsAvailableChangedSpy.last().first().toBool(), true);
1029     QCOMPARE(visibleChangedSpy.count(), 1);
1030     QCOMPARE(visibleChangedSpy.last().first().toBool(), true);
1031 
1032     // clicking the button should trigger a request for on all desktops
1033     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1034     QVERIFY(clickedSpy.isValid());
1035     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
1036     QVERIFY(pressedSpy.isValid());
1037     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
1038     QVERIFY(releasedSpy.isValid());
1039     QSignalSpy onAllDesktopsChangedSpy(decoClient.data(), &KDecoration2::DecoratedClient::onAllDesktopsChanged);
1040     QVERIFY(onAllDesktopsChangedSpy.isValid());
1041     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
1042     QVERIFY(pressedChangedSpy.isValid());
1043 
1044     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1045     pressEvent.setAccepted(false);
1046     button.event(&pressEvent);
1047     QCOMPARE(pressEvent.isAccepted(), true);
1048     QCOMPARE(button.isPressed(), true);
1049     QCOMPARE(clickedSpy.count(), 0);
1050     QCOMPARE(pressedSpy.count(), 1);
1051     QCOMPARE(releasedSpy.count(), 0);
1052     QCOMPARE(onAllDesktopsChangedSpy.count(), 0);
1053     QCOMPARE(pressedChangedSpy.count(), 1);
1054     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
1055 
1056     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1057     releaseEvent.setAccepted(false);
1058     button.event(&releaseEvent);
1059     QCOMPARE(releaseEvent.isAccepted(), true);
1060     QCOMPARE(button.isPressed(), false);
1061     QCOMPARE(clickedSpy.count(), 1);
1062     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
1063     QCOMPARE(pressedSpy.count(), 1);
1064     QCOMPARE(releasedSpy.count(), 1);
1065     QVERIFY(onAllDesktopsChangedSpy.wait());
1066     QCOMPARE(onAllDesktopsChangedSpy.count(), 1);
1067     QCOMPARE(onAllDesktopsChangedSpy.first().first().toBool(), true);
1068     QCOMPARE(pressedChangedSpy.count(), 2);
1069     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
1070     QCOMPARE(button.isChecked(), true);
1071 }
1072 
1073 void DecorationButtonTest::testMenu()
1074 {
1075     MockBridge bridge;
1076     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1077     MockDecoration mockDecoration(&bridge);
1078     mockDecoration.setSettings(decoSettings);
1079     MockClient *client = bridge.lastCreatedClient();
1080     MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration);
1081     button.setGeometry(QRect(0, 0, 10, 10));
1082 
1083     QCOMPARE(button.isEnabled(), true);
1084     QCOMPARE(button.isCheckable(), false);
1085     QCOMPARE(button.isChecked(), false);
1086     QCOMPARE(button.isVisible(), true);
1087     QCOMPARE(button.acceptedButtons(), Qt::LeftButton | Qt::RightButton);
1088 
1089     // clicking the button should trigger a request for menu button
1090     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1091     QVERIFY(clickedSpy.isValid());
1092     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
1093     QVERIFY(pressedSpy.isValid());
1094     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
1095     QVERIFY(releasedSpy.isValid());
1096     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
1097     QVERIFY(pressedChangedSpy.isValid());
1098     QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested);
1099     QVERIFY(menuRequestedSpy.isValid());
1100 
1101     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1102     pressEvent.setAccepted(false);
1103     button.event(&pressEvent);
1104     QCOMPARE(pressEvent.isAccepted(), true);
1105     QCOMPARE(button.isPressed(), true);
1106     QCOMPARE(clickedSpy.count(), 0);
1107     QCOMPARE(pressedSpy.count(), 1);
1108     QCOMPARE(releasedSpy.count(), 0);
1109     QCOMPARE(menuRequestedSpy.count(), 0);
1110     QCOMPARE(pressedChangedSpy.count(), 1);
1111     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
1112 
1113     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1114     releaseEvent.setAccepted(false);
1115     button.event(&releaseEvent);
1116     QCOMPARE(releaseEvent.isAccepted(), true);
1117     QCOMPARE(button.isPressed(), false);
1118     QCOMPARE(clickedSpy.count(), 1);
1119     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
1120     QCOMPARE(pressedSpy.count(), 1);
1121     QCOMPARE(releasedSpy.count(), 1);
1122     QVERIFY(menuRequestedSpy.wait());
1123     QCOMPARE(menuRequestedSpy.count(), 1);
1124     QCOMPARE(pressedChangedSpy.count(), 2);
1125     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
1126 }
1127 
1128 void DecorationButtonTest::testMenuDoubleClick()
1129 {
1130     MockBridge bridge;
1131     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1132     MockDecoration mockDecoration(&bridge);
1133     mockDecoration.setSettings(decoSettings);
1134     MockClient *client = bridge.lastCreatedClient();
1135     MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration);
1136     button.setGeometry(QRect(0, 0, 10, 10));
1137 
1138     MockSettings *settings = bridge.lastCreatedSettings();
1139     QVERIFY(settings);
1140     QSignalSpy closeOnDoubleClickOnMenuChangedSpy(decoSettings.data(), &KDecoration2::DecorationSettings::closeOnDoubleClickOnMenuChanged);
1141     QVERIFY(closeOnDoubleClickOnMenuChangedSpy.isValid());
1142     settings->setCloseOnDoubleClickOnMenu(true);
1143     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 1);
1144     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), true);
1145 
1146     // button used a queued connection, so we need to run event loop
1147     QCoreApplication::processEvents();
1148 
1149     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1150     QVERIFY(clickedSpy.isValid());
1151     QSignalSpy doubleClickedSpy(&button, &KDecoration2::DecorationButton::doubleClicked);
1152     QVERIFY(doubleClickedSpy.isValid());
1153     QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested);
1154     QVERIFY(closeRequestedSpy.isValid());
1155     QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested);
1156     QVERIFY(menuRequestedSpy.isValid());
1157 
1158     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1159     pressEvent.setAccepted(false);
1160     button.event(&pressEvent);
1161     QCOMPARE(pressEvent.isAccepted(), true);
1162     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1163     releaseEvent.setAccepted(false);
1164     button.event(&releaseEvent);
1165     QCOMPARE(releaseEvent.isAccepted(), true);
1166     // should not have emitted a clicked
1167     QCOMPARE(clickedSpy.count(), 0);
1168     QCOMPARE(doubleClickedSpy.count(), 0);
1169 
1170     // another press should trigger the double click event
1171     pressEvent.setAccepted(false);
1172     button.event(&pressEvent);
1173     QCOMPARE(pressEvent.isAccepted(), true);
1174     QVERIFY(closeRequestedSpy.wait());
1175     QCOMPARE(doubleClickedSpy.count(), 1);
1176     QCOMPARE(closeRequestedSpy.count(), 1);
1177     QCOMPARE(menuRequestedSpy.count(), 0);
1178 
1179     releaseEvent.setAccepted(false);
1180     button.event(&releaseEvent);
1181     QCOMPARE(releaseEvent.isAccepted(), true);
1182     QCOMPARE(clickedSpy.count(), 0);
1183     // run events
1184     QCoreApplication::processEvents();
1185     QCOMPARE(closeRequestedSpy.count(), 1);
1186     QCOMPARE(menuRequestedSpy.count(), 0);
1187 
1188     // a double click of right button shouldn't trigger the double click event
1189     QMouseEvent rightPressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::RightButton, Qt::RightButton, Qt::NoModifier);
1190     rightPressEvent.setAccepted(false);
1191     button.event(&rightPressEvent);
1192     QCOMPARE(rightPressEvent.isAccepted(), true);
1193     QMouseEvent rightReleaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::RightButton, Qt::NoButton, Qt::NoModifier);
1194     rightReleaseEvent.setAccepted(false);
1195     button.event(&rightReleaseEvent);
1196     QCOMPARE(rightReleaseEvent.isAccepted(), true);
1197     QCOMPARE(clickedSpy.count(), 1);
1198     QVERIFY(menuRequestedSpy.wait());
1199     QCOMPARE(menuRequestedSpy.count(), 1);
1200     // second click
1201     rightPressEvent.setAccepted(false);
1202     button.event(&rightPressEvent);
1203     QCOMPARE(rightPressEvent.isAccepted(), true);
1204     rightReleaseEvent.setAccepted(false);
1205     button.event(&rightReleaseEvent);
1206     QCOMPARE(rightReleaseEvent.isAccepted(), true);
1207     QCOMPARE(clickedSpy.count(), 2);
1208     QVERIFY(menuRequestedSpy.wait());
1209     QCOMPARE(menuRequestedSpy.count(), 2);
1210 }
1211 
1212 void DecorationButtonTest::testMenuPressAndHold()
1213 {
1214     MockBridge bridge;
1215     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1216     MockDecoration mockDecoration(&bridge);
1217     mockDecoration.setSettings(decoSettings);
1218     MockClient *client = bridge.lastCreatedClient();
1219     MockButton button(KDecoration2::DecorationButtonType::Menu, &mockDecoration);
1220     button.setGeometry(QRect(0, 0, 10, 10));
1221 
1222     MockSettings *settings = bridge.lastCreatedSettings();
1223     QVERIFY(settings);
1224     QSignalSpy closeOnDoubleClickOnMenuChangedSpy(decoSettings.data(), &KDecoration2::DecorationSettings::closeOnDoubleClickOnMenuChanged);
1225     QVERIFY(closeOnDoubleClickOnMenuChangedSpy.isValid());
1226     settings->setCloseOnDoubleClickOnMenu(true);
1227     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 1);
1228     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), true);
1229 
1230     // button used a queued connection, so we need to run event loop
1231     QCoreApplication::processEvents();
1232 
1233     QSignalSpy menuRequestedSpy(client, &MockClient::menuRequested);
1234     QVERIFY(menuRequestedSpy.isValid());
1235     QSignalSpy doubleClickedSpy(&button, &KDecoration2::DecorationButton::doubleClicked);
1236     QVERIFY(doubleClickedSpy.isValid());
1237     QSignalSpy closeRequestedSpy(client, &MockClient::closeRequested);
1238     QVERIFY(closeRequestedSpy.isValid());
1239     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1240     QVERIFY(clickedSpy.isValid());
1241 
1242     // send a press event
1243     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1244     pressEvent.setAccepted(false);
1245     button.event(&pressEvent);
1246     QCOMPARE(pressEvent.isAccepted(), true);
1247     QCOMPARE(clickedSpy.count(), 0);
1248 
1249     // and wait
1250     QVERIFY(menuRequestedSpy.wait());
1251     QCOMPARE(menuRequestedSpy.count(), 1);
1252     QCOMPARE(clickedSpy.count(), 1);
1253 
1254     // send release event
1255     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1256     releaseEvent.setAccepted(false);
1257     button.event(&releaseEvent);
1258     QCOMPARE(releaseEvent.isAccepted(), true);
1259     QCOMPARE(clickedSpy.count(), 1);
1260 
1261     QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 5);
1262 
1263     // and it shouldn't be a double click
1264     pressEvent.setAccepted(false);
1265     button.event(&pressEvent);
1266     QCOMPARE(pressEvent.isAccepted(), true);
1267 
1268     // while waiting we disable click and hold
1269     settings->setCloseOnDoubleClickOnMenu(false);
1270     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.count(), 2);
1271     QCOMPARE(closeOnDoubleClickOnMenuChangedSpy.last().first().toBool(), false);
1272     // button used a queued connection, so we need to run event loop
1273     QCoreApplication::processEvents();
1274     // and releasing should emit the menu signal
1275     releaseEvent.setAccepted(false);
1276     button.event(&releaseEvent);
1277     QCOMPARE(releaseEvent.isAccepted(), true);
1278     QCOMPARE(clickedSpy.count(), 2);
1279     QVERIFY(menuRequestedSpy.wait());
1280     QCOMPARE(menuRequestedSpy.count(), 2);
1281     // never got a dobule click
1282     QCOMPARE(closeRequestedSpy.count(), 0);
1283 }
1284 
1285 void DecorationButtonTest::testApplicationMenu()
1286 {
1287     MockBridge bridge;
1288     auto decoSettings = QSharedPointer<KDecoration2::DecorationSettings>::create(&bridge);
1289     MockDecoration mockDecoration(&bridge);
1290     mockDecoration.setSettings(decoSettings);
1291     MockClient *client = bridge.lastCreatedClient();
1292     MockButton button(KDecoration2::DecorationButtonType::ApplicationMenu, &mockDecoration);
1293     button.setGeometry(QRect(0, 0, 10, 10));
1294 
1295     QCOMPARE(button.isEnabled(), true);
1296     QCOMPARE(button.isCheckable(), true);
1297     QCOMPARE(button.isChecked(), false);
1298     QCOMPARE(button.isVisible(), true);
1299     QCOMPARE(button.acceptedButtons(), Qt::LeftButton);
1300 
1301     // clicking the button should trigger a request for application menu
1302     QSignalSpy clickedSpy(&button, &KDecoration2::DecorationButton::clicked);
1303     QVERIFY(clickedSpy.isValid());
1304     QSignalSpy pressedSpy(&button, &KDecoration2::DecorationButton::pressed);
1305     QVERIFY(pressedSpy.isValid());
1306     QSignalSpy releasedSpy(&button, &KDecoration2::DecorationButton::released);
1307     QVERIFY(releasedSpy.isValid());
1308     QSignalSpy pressedChangedSpy(&button, &KDecoration2::DecorationButton::pressedChanged);
1309     QVERIFY(pressedChangedSpy.isValid());
1310     QSignalSpy applicationMenuRequestedSpy(client, &MockClient::applicationMenuRequested);
1311     QVERIFY(applicationMenuRequestedSpy.isValid());
1312 
1313     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPointF(5, 5), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
1314     pressEvent.setAccepted(false);
1315     button.event(&pressEvent);
1316     QCOMPARE(pressEvent.isAccepted(), true);
1317     QCOMPARE(button.isPressed(), true);
1318     QCOMPARE(clickedSpy.count(), 0);
1319     QCOMPARE(pressedSpy.count(), 1);
1320     QCOMPARE(releasedSpy.count(), 0);
1321     QCOMPARE(applicationMenuRequestedSpy.count(), 0);
1322     QCOMPARE(pressedChangedSpy.count(), 1);
1323     QCOMPARE(pressedChangedSpy.first().first().toBool(), true);
1324 
1325     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPointF(5, 5), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
1326     releaseEvent.setAccepted(false);
1327     button.event(&releaseEvent);
1328     QCOMPARE(releaseEvent.isAccepted(), true);
1329     QCOMPARE(button.isPressed(), false);
1330     QCOMPARE(clickedSpy.count(), 1);
1331     QCOMPARE(clickedSpy.first().first().value<Qt::MouseButton>(), Qt::LeftButton);
1332     QCOMPARE(pressedSpy.count(), 1);
1333     QCOMPARE(releasedSpy.count(), 1);
1334     QVERIFY(applicationMenuRequestedSpy.wait());
1335     QCOMPARE(applicationMenuRequestedSpy.count(), 1);
1336     QCOMPARE(pressedChangedSpy.count(), 2);
1337     QCOMPARE(pressedChangedSpy.last().first().toBool(), false);
1338 }
1339 
1340 void DecorationButtonTest::testContains_data()
1341 {
1342     QTest::addColumn<QPointF>("pos");
1343     QTest::addColumn<bool>("contains");
1344 
1345     // Button geometry: QRectF(0, 0, 10, 10).
1346     QTest::newRow("on left edge") << QPointF(0, 5) << true;
1347     QTest::newRow("on top edge") << QPointF(5, 0) << true;
1348     QTest::newRow("on right edge") << QPointF(9, 5) << true;
1349     QTest::newRow("on bottom edge") << QPointF(5, 9) << true;
1350     QTest::newRow("inside") << QPointF(5, 5) << true;
1351     QTest::newRow("outside 1") << QPointF(-1, 5) << false;
1352     QTest::newRow("outside 2") << QPointF(5, -1) << false;
1353     QTest::newRow("outside 3") << QPointF(10, 5) << false;
1354     QTest::newRow("outside 4") << QPointF(5, 10) << false;
1355 }
1356 
1357 void DecorationButtonTest::testContains()
1358 {
1359     MockBridge bridge;
1360     MockDecoration mockDecoration(&bridge);
1361 
1362     MockButton button(KDecoration2::DecorationButtonType::Custom, &mockDecoration);
1363     button.setGeometry(QRectF(0, 0, 10, 10));
1364     button.setEnabled(true);
1365     button.setVisible(true);
1366 
1367     QFETCH(QPointF, pos);
1368     QTEST(button.contains(pos), "contains");
1369 }
1370 
1371 QTEST_MAIN(DecorationButtonTest)
1372 #include "decorationbuttontest.moc"