diff --git a/autotests/libxrenderutils/blendpicture_test.cpp b/autotests/libxrenderutils/blendpicture_test.cpp index d00ad3df7..5cf3239f0 100644 --- a/autotests/libxrenderutils/blendpicture_test.cpp +++ b/autotests/libxrenderutils/blendpicture_test.cpp @@ -1,59 +1,61 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2016 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include #include #include +#include "../testutils.h" #include "../../libkwineffects/kwinxrenderutils.h" class BlendPictureTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void testDontCrashOnTeardown(); }; void BlendPictureTest::initTestCase() { KWin::XRenderUtils::init(QX11Info::connection(), QX11Info::appRootWindow()); } void BlendPictureTest::cleanupTestCase() { KWin::XRenderUtils::cleanup(); } void BlendPictureTest::testDontCrashOnTeardown() { // this test uses xrenderBlendPicture - the only idea is to trigger the creation // closing the application should not crash // see BUG 363251 const auto picture = KWin::xRenderBlendPicture(0.5); // and a second one const auto picture2 = KWin::xRenderBlendPicture(0.6); Q_UNUSED(picture) Q_UNUSED(picture2) } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(BlendPictureTest) #include "blendpicture_test.moc" diff --git a/autotests/tabbox/test_tabbox_clientmodel.cpp b/autotests/tabbox/test_tabbox_clientmodel.cpp index 72109a29d..f7b94a62f 100644 --- a/autotests/tabbox/test_tabbox_clientmodel.cpp +++ b/autotests/tabbox/test_tabbox_clientmodel.cpp @@ -1,92 +1,94 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2012 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "test_tabbox_clientmodel.h" #include "mock_tabboxhandler.h" #include "clientmodel.h" +#include "../testutils.h" #include #include using namespace KWin; void TestTabBoxClientModel::initTestCase() { qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestTabBoxClientModel::testLongestCaptionWithNullClient() { MockTabBoxHandler tabboxhandler; TabBox::ClientModel *clientModel = new TabBox::ClientModel(&tabboxhandler); clientModel->createClientList(); QCOMPARE(clientModel->longestCaption(), QString()); // add a window to the mock tabboxhandler.createMockWindow(QString("test"), 1); clientModel->createClientList(); QCOMPARE(clientModel->longestCaption(), QString("test")); // delete the one client in the list QModelIndex index = clientModel->index(0, 0); QVERIFY(index.isValid()); TabBox::TabBoxClient *client = static_cast(clientModel->data(index, TabBox::ClientModel::ClientRole).value()); client->close(); // internal model of ClientModel now contains a deleted pointer // longestCaption should behave just as if the window were not in the list QCOMPARE(clientModel->longestCaption(), QString()); } void TestTabBoxClientModel::testCreateClientListNoActiveClient() { MockTabBoxHandler tabboxhandler; tabboxhandler.setConfig(TabBox::TabBoxConfig()); TabBox::ClientModel *clientModel = new TabBox::ClientModel(&tabboxhandler); clientModel->createClientList(); QCOMPARE(clientModel->rowCount(), 0); // create two windows, rowCount() should go to two QWeakPointer client = tabboxhandler.createMockWindow(QString("test"), 1); tabboxhandler.createMockWindow(QString("test2"), 2); clientModel->createClientList(); QCOMPARE(clientModel->rowCount(), 2); // let's ensure there is no active client tabboxhandler.setActiveClient(QWeakPointer()); // now it should still have two members in the list clientModel->createClientList(); QCOMPARE(clientModel->rowCount(), 2); } void TestTabBoxClientModel::testCreateClientListActiveClientNotInFocusChain() { MockTabBoxHandler tabboxhandler; tabboxhandler.setConfig(TabBox::TabBoxConfig()); TabBox::ClientModel *clientModel = new TabBox::ClientModel(&tabboxhandler); // create two windows, rowCount() should go to two QWeakPointer client = tabboxhandler.createMockWindow(QString("test"), 1); client = tabboxhandler.createMockWindow(QString("test2"), 2); clientModel->createClientList(); QCOMPARE(clientModel->rowCount(), 2); // simulate that the active client is not in the focus chain // for that we use the closeWindow of the MockTabBoxHandler which // removes the Client from the Focus Chain but leaves the active window as it is QSharedPointer clientOwner = client.toStrongRef(); tabboxhandler.closeWindow(client.data()); clientModel->createClientList(); QCOMPARE(clientModel->rowCount(), 1); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestTabBoxClientModel) diff --git a/autotests/tabbox/test_tabbox_handler.cpp b/autotests/tabbox/test_tabbox_handler.cpp index b3ed194c3..83e92c4f9 100644 --- a/autotests/tabbox/test_tabbox_handler.cpp +++ b/autotests/tabbox/test_tabbox_handler.cpp @@ -1,61 +1,63 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2012 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "mock_tabboxhandler.h" #include "clientmodel.h" +#include "../testutils.h" #include #include using namespace KWin; class TestTabBoxHandler : public QObject { Q_OBJECT private slots: void initTestCase(); /** * Test to verify that update outline does not crash * if the ModelIndex for which the outline should be * shown is not valid. That is accessing the Pointer * to the Client returns an invalid QVariant. * BUG: 304620 **/ void testDontCrashUpdateOutlineNullClient(); }; void TestTabBoxHandler::initTestCase() { qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestTabBoxHandler::testDontCrashUpdateOutlineNullClient() { MockTabBoxHandler tabboxhandler; TabBox::TabBoxConfig config; config.setTabBoxMode(TabBox::TabBoxConfig::ClientTabBox); config.setShowTabBox(false); config.setHighlightWindows(false); tabboxhandler.setConfig(config); // now show the tabbox which will attempt to show the outline tabboxhandler.show(); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestTabBoxHandler) #include "test_tabbox_handler.moc" diff --git a/autotests/test_builtin_effectloader.cpp b/autotests/test_builtin_effectloader.cpp index 689cd2b58..0f3dab789 100644 --- a/autotests/test_builtin_effectloader.cpp +++ b/autotests/test_builtin_effectloader.cpp @@ -1,567 +1,569 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "../effectloader.h" #include "../effects/effect_builtins.h" #include "mock_effectshandler.h" #include "../scripting/scriptedeffect.h" // for mocking ScriptedEffect::create +#include "testutils.h" // KDE #include #include // Qt #include #include Q_DECLARE_METATYPE(KWin::CompositingType) Q_DECLARE_METATYPE(KWin::LoadEffectFlag) Q_DECLARE_METATYPE(KWin::LoadEffectFlags) Q_DECLARE_METATYPE(KWin::BuiltInEffect) Q_DECLARE_METATYPE(KWin::Effect*) Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") namespace KWin { ScriptedEffect *ScriptedEffect::create(const KPluginMetaData&) { return nullptr; } bool ScriptedEffect::supported() { return true; } } class TestBuiltInEffectLoader : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void testHasEffect_data(); void testHasEffect(); void testKnownEffects(); void testSupported_data(); void testSupported(); void testLoadEffect_data(); void testLoadEffect(); void testLoadBuiltInEffect_data(); void testLoadBuiltInEffect(); void testLoadAllEffects(); }; void TestBuiltInEffectLoader::initTestCase() { qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestBuiltInEffectLoader::testHasEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::newRow("blur") << QStringLiteral("blur") << true; QTest::newRow("with kwin4_effect_ prefix") << QStringLiteral("kwin4_effect_blur") << false; QTest::newRow("case sensitive") << QStringLiteral("BlUR") << true; QTest::newRow("Contrast") << QStringLiteral("contrast") << true; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << true; QTest::newRow("Cube") << QStringLiteral("cube") << true; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << true; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true; QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << true; QTest::newRow("FallApart") << QStringLiteral("fallapart") << true; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << true; QTest::newRow("Glide") << QStringLiteral("glide") << true; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true; QTest::newRow("Invert") << QStringLiteral("invert") << true; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << true; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << true; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true; QTest::newRow("Resize") << QStringLiteral("resize") << true; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true; QTest::newRow("Sheet") << QStringLiteral("sheet") << true; QTest::newRow("ShowFps") << QStringLiteral("showfps") << true; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true; QTest::newRow("Slide") << QStringLiteral("slide") << true; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << true; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true; QTest::newRow("Touchpoints") << QStringLiteral("touchpoints") << true; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true; QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << true; QTest::newRow("Zoom") << QStringLiteral("zoom") << true; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false; QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false; QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false; } void TestBuiltInEffectLoader::testHasEffect() { QFETCH(QString, name); QFETCH(bool, expected); KWin::BuiltInEffectLoader loader; QCOMPARE(loader.hasEffect(name), expected); } void TestBuiltInEffectLoader::testKnownEffects() { QStringList expectedEffects; expectedEffects << QStringLiteral("blur") << QStringLiteral("contrast") << QStringLiteral("coverswitch") << QStringLiteral("cube") << QStringLiteral("cubeslide") << QStringLiteral("desktopgrid") << QStringLiteral("diminactive") << QStringLiteral("dimscreen") << QStringLiteral("fallapart") << QStringLiteral("flipswitch") << QStringLiteral("glide") << QStringLiteral("highlightwindow") << QStringLiteral("invert") << QStringLiteral("kscreen") << QStringLiteral("lookingglass") << QStringLiteral("magiclamp") << QStringLiteral("magnifier") << QStringLiteral("minimizeanimation") << QStringLiteral("mouseclick") << QStringLiteral("mousemark") << QStringLiteral("presentwindows") << QStringLiteral("resize") << QStringLiteral("screenedge") << QStringLiteral("screenshot") << QStringLiteral("sheet") << QStringLiteral("showfps") << QStringLiteral("showpaint") << QStringLiteral("slide") << QStringLiteral("slideback") << QStringLiteral("slidingpopups") << QStringLiteral("snaphelper") << QStringLiteral("startupfeedback") << QStringLiteral("thumbnailaside") << QStringLiteral("touchpoints") << QStringLiteral("trackmouse") << QStringLiteral("windowgeometry") << QStringLiteral("wobblywindows") << QStringLiteral("zoom"); KWin::BuiltInEffectLoader loader; QStringList result = loader.listOfKnownEffects(); QCOMPARE(result.size(), expectedEffects.size()); qSort(result); for (int i = 0; i < expectedEffects.size(); ++i) { QCOMPARE(result.at(i), expectedEffects.at(i)); } } void TestBuiltInEffectLoader::testSupported_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); QTest::addColumn("animationsSupported"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("blur") << QStringLiteral("blur") << false << xc << true; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("blur-GL") << QStringLiteral("blur") << false << oc << true; QTest::newRow("Contrast") << QStringLiteral("contrast") << false << xc << true; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("Contrast-GL") << QStringLiteral("contrast") << false << oc << true; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false << xc << true; QTest::newRow("CoverSwitch-GL") << QStringLiteral("coverswitch") << true << oc << true; QTest::newRow("CoverSwitch-GL-no-anim") << QStringLiteral("coverswitch") << false << oc << false; QTest::newRow("Cube") << QStringLiteral("cube") << false << xc << true; QTest::newRow("Cube-GL") << QStringLiteral("cube") << true << oc << true; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false << xc << true; QTest::newRow("CubeSlide-GL") << QStringLiteral("cubeslide") << true << oc << true; QTest::newRow("CubeSlide-GL-no-anim") << QStringLiteral("cubeslide") << false << oc << false; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true << xc << true; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true << xc << true; QTest::newRow("DimScreen") << QStringLiteral("dimscreen") << true << xc << true; QTest::newRow("FallApart") << QStringLiteral("fallapart") << false << xc << true; QTest::newRow("FallApart-GL") << QStringLiteral("fallapart") << true << oc << true; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false << xc << true; QTest::newRow("FlipSwitch-GL") << QStringLiteral("flipswitch") << true << oc << true; QTest::newRow("FlipSwitch-GL-no-anim") << QStringLiteral("flipswitch") << false << oc << false; QTest::newRow("Glide") << QStringLiteral("glide") << false << xc << true; QTest::newRow("Glide-GL") << QStringLiteral("glide") << true << oc << true; QTest::newRow("Glide-GL-no-anim") << QStringLiteral("glide") << false << oc << false; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true << xc << true; QTest::newRow("Invert") << QStringLiteral("invert") << false << xc << true; QTest::newRow("Invert-GL") << QStringLiteral("invert") << true << oc << true; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true << xc << true; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false << xc << true; QTest::newRow("LookingGlass-GL") << QStringLiteral("lookingglass") << true << oc << true; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false << xc << true; QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc << true; QTest::newRow("MagicLamp-GL-no-anim") << QStringLiteral("magiclamp") << false << oc << false; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc << true; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc << true; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc << true; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc << true; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc << true; QTest::newRow("Resize") << QStringLiteral("resize") << true << xc << true; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc << true; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc << true; QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc << true; QTest::newRow("Sheet-GL") << QStringLiteral("sheet") << true << oc << true; QTest::newRow("Sheet-GL-no-anim") << QStringLiteral("sheet") << false << oc << false; QTest::newRow("ShowFps") << QStringLiteral("showfps") << true << xc << true; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc << true; QTest::newRow("Slide") << QStringLiteral("slide") << true << xc << true; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc << true; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc << true; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc << true; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc << true; QTest::newRow("StartupFeedback-GL") << QStringLiteral("startupfeedback") << true << oc << true; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true << xc << true; QTest::newRow("TouchPoints") << QStringLiteral("touchpoints") << true << xc << true; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true << xc << true; QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true << xc << true; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false << xc << true; QTest::newRow("WobblyWindows-GL") << QStringLiteral("wobblywindows") << true << oc << true; QTest::newRow("WobblyWindows-GL-no-anim") << QStringLiteral("wobblywindows") << false << oc << false; QTest::newRow("Zoom") << QStringLiteral("zoom") << true << xc << true; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false << xc << true; QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false << xc << true; QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false << xc << true; } void TestBuiltInEffectLoader::testSupported() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); QFETCH(bool, animationsSupported); MockEffectsHandler mockHandler(type); mockHandler.setAnimationsSupported(animationsSupported); QCOMPARE(mockHandler.animationsSupported(), animationsSupported); KWin::BuiltInEffectLoader loader; QCOMPARE(loader.isEffectSupported(name), expected); } void TestBuiltInEffectLoader::testLoadEffect_data() { QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; QTest::newRow("blur") << QStringLiteral("blur") << false << xc; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("blur-GL") << QStringLiteral("blur") << false << oc; QTest::newRow("Contrast") << QStringLiteral("contrast") << false << xc; // fails for GL as it does proper tests on what's supported and doesn't just check whether it's GL QTest::newRow("Contrast-GL") << QStringLiteral("contrast") << false << oc; QTest::newRow("CoverSwitch") << QStringLiteral("coverswitch") << false << xc; // TODO: needs GL mocking // QTest::newRow("CoverSwitch-GL") << QStringLiteral("coverswitch") << true << oc; QTest::newRow("Cube") << QStringLiteral("cube") << false << xc; // TODO: needs GL mocking // QTest::newRow("Cube-GL") << QStringLiteral("cube") << true << oc; QTest::newRow("CubeSlide") << QStringLiteral("cubeslide") << false << xc; QTest::newRow("CubeSlide-GL") << QStringLiteral("cubeslide") << true << oc; QTest::newRow("DesktopGrid") << QStringLiteral("desktopgrid") << true << xc; QTest::newRow("DimInactive") << QStringLiteral("diminactive") << true << xc; QTest::newRow("DimScreen") << QStringLiteral("dimScreen") << true << xc; QTest::newRow("FallApart") << QStringLiteral("fallapart") << false << xc; QTest::newRow("FallApart-GL") << QStringLiteral("fallapart") << true << oc; QTest::newRow("FlipSwitch") << QStringLiteral("flipswitch") << false << xc; QTest::newRow("FlipSwitch-GL") << QStringLiteral("flipswitch") << true << oc; QTest::newRow("Glide") << QStringLiteral("glide") << false << xc; QTest::newRow("Glide-GL") << QStringLiteral("glide") << true << oc; QTest::newRow("HighlightWindow") << QStringLiteral("highlightwindow") << true << xc; QTest::newRow("Invert") << QStringLiteral("invert") << false << xc; QTest::newRow("Invert-GL") << QStringLiteral("invert") << true << oc; QTest::newRow("Kscreen") << QStringLiteral("kscreen") << true << xc; QTest::newRow("LookingGlass") << QStringLiteral("lookingglass") << false << xc; QTest::newRow("LookingGlass-GL") << QStringLiteral("lookingglass") << true << oc; QTest::newRow("MagicLamp") << QStringLiteral("magiclamp") << false << xc; QTest::newRow("MagicLamp-GL") << QStringLiteral("magiclamp") << true << oc; QTest::newRow("Magnifier") << QStringLiteral("magnifier") << true << xc; QTest::newRow("MinimizeAnimation") << QStringLiteral("minimizeanimation") << true << xc; QTest::newRow("MouseClick") << QStringLiteral("mouseclick") << true << xc; QTest::newRow("MouseMark") << QStringLiteral("mousemark") << true << xc; QTest::newRow("PresentWindows") << QStringLiteral("presentwindows") << true << xc; QTest::newRow("Resize") << QStringLiteral("resize") << true << xc; QTest::newRow("ScreenEdge") << QStringLiteral("screenedge") << true << xc; QTest::newRow("ScreenShot") << QStringLiteral("screenshot") << true << xc; QTest::newRow("Sheet") << QStringLiteral("sheet") << false << xc; QTest::newRow("Sheet-GL") << QStringLiteral("sheet") << true << oc; // TODO: Accesses EffectFrame and crashes // QTest::newRow("ShowFps") << QStringLiteral("showfps") << true << xc; QTest::newRow("ShowPaint") << QStringLiteral("showpaint") << true << xc; QTest::newRow("Slide") << QStringLiteral("slide") << true << xc; QTest::newRow("SlideBack") << QStringLiteral("slideback") << true << xc; QTest::newRow("SlidingPopups") << QStringLiteral("slidingpopups") << true << xc; QTest::newRow("SnapHelper") << QStringLiteral("snaphelper") << true << xc; QTest::newRow("StartupFeedback") << QStringLiteral("startupfeedback") << false << xc; // Tries to load shader and makes our test abort // QTest::newRow("StartupFeedback-GL") << QStringLiteral("startupfeedback") << true << oc; QTest::newRow("ThumbnailAside") << QStringLiteral("thumbnailaside") << true << xc; QTest::newRow("Touchpoints") << QStringLiteral("touchpoints") << true << xc; QTest::newRow("TrackMouse") << QStringLiteral("trackmouse") << true << xc; // TODO: Accesses EffectFrame and crashes // QTest::newRow("WindowGeometry") << QStringLiteral("windowgeometry") << true << xc; QTest::newRow("WobblyWindows") << QStringLiteral("wobblywindows") << false << xc; QTest::newRow("WobblyWindows-GL") << QStringLiteral("wobblywindows") << true << oc; QTest::newRow("Zoom") << QStringLiteral("zoom") << true << xc; QTest::newRow("Non Existing") << QStringLiteral("InvalidName") << false << xc; QTest::newRow("Fade - Scripted") << QStringLiteral("fade") << false << xc; QTest::newRow("Fade - Scripted + kwin4_effect") << QStringLiteral("kwin4_effect_fade") << false << xc; } void TestBuiltInEffectLoader::testLoadEffect() { QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); MockEffectsHandler mockHandler(type); KWin::BuiltInEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::BuiltInEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(name), expected); // loading again should fail QVERIFY(!loader.loadEffect(name)); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } spy.clear(); QVERIFY(spy.isEmpty()); // now if we wait for the events being processed, the effect will get deleted and it should load again QTest::qWait(1); QCOMPARE(loader.loadEffect(name), expected); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } } void TestBuiltInEffectLoader::testLoadBuiltInEffect_data() { // TODO: this test cannot yet test the checkEnabledByDefault functionality as that requires // mocking enough of GL to get the blur effect to think it's supported and enabled by default QTest::addColumn("effect"); QTest::addColumn("name"); QTest::addColumn("expected"); QTest::addColumn("type"); QTest::addColumn("loadFlags"); const KWin::CompositingType xc = KWin::XRenderCompositing; const KWin::CompositingType oc = KWin::OpenGL2Compositing; const KWin::LoadEffectFlags checkDefault = KWin::LoadEffectFlag::Load | KWin::LoadEffectFlag::CheckDefaultFunction; const KWin::LoadEffectFlags forceFlags = KWin::LoadEffectFlag::Load; const KWin::LoadEffectFlags dontLoadFlags = KWin::LoadEffectFlags(); // enabled by default, but not supported QTest::newRow("blur") << KWin::BuiltInEffect::Blur << QStringLiteral("blur") << false << oc << checkDefault; // enabled by default QTest::newRow("HighlightWindow") << KWin::BuiltInEffect::HighlightWindow << QStringLiteral("highlightwindow") << true << xc << checkDefault; // supported but not enabled by default QTest::newRow("LookingGlass-GL") << KWin::BuiltInEffect::LookingGlass << QStringLiteral("lookingglass") << true << oc << checkDefault; // not enabled by default QTest::newRow("MouseClick") << KWin::BuiltInEffect::MouseClick << QStringLiteral("mouseclick") << true << xc << checkDefault; // Force an Effect which will load QTest::newRow("MouseClick-Force") << KWin::BuiltInEffect::MouseClick << QStringLiteral("mouseclick") << true << xc << forceFlags; // Force an Effect which is not supported QTest::newRow("LookingGlass-Force") << KWin::BuiltInEffect::LookingGlass << QStringLiteral("lookingglass") << false << xc << forceFlags; // Force the Effect as supported QTest::newRow("LookingGlass-Force-GL") << KWin::BuiltInEffect::LookingGlass << QStringLiteral("lookingglass") << true << oc << forceFlags; // Enforce no load of effect which is enabled by default QTest::newRow("HighlightWindow-DontLoad") << KWin::BuiltInEffect::HighlightWindow << QStringLiteral("highlightwindow") << false << xc << dontLoadFlags; // Enforce no load of effect which is not enabled by default, but enforced QTest::newRow("MouseClick-DontLoad") << KWin::BuiltInEffect::MouseClick << QStringLiteral("mouseclick") << false << xc << dontLoadFlags; } void TestBuiltInEffectLoader::testLoadBuiltInEffect() { QFETCH(KWin::BuiltInEffect, effect); QFETCH(QString, name); QFETCH(bool, expected); QFETCH(KWin::CompositingType, type); QFETCH(KWin::LoadEffectFlags, loadFlags); MockEffectsHandler mockHandler(type); KWin::BuiltInEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::BuiltInEffectLoader::effectLoaded, [&name](KWin::Effect *effect, const QString &effectName) { QCOMPARE(effectName, name); effect->deleteLater(); } ); // try to load the Effect QCOMPARE(loader.loadEffect(effect, loadFlags), expected); // loading again should fail QVERIFY(!loader.loadEffect(effect, loadFlags)); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } spy.clear(); QVERIFY(spy.isEmpty()); // now if we wait for the events being processed, the effect will get deleted and it should load again QTest::qWait(1); QCOMPARE(loader.loadEffect(effect, loadFlags), expected); // signal spy should have got the signal if it was expected QCOMPARE(spy.isEmpty(), !expected); if (!spy.isEmpty()) { QCOMPARE(spy.count(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), name); } } void TestBuiltInEffectLoader::testLoadAllEffects() { MockEffectsHandler mockHandler(KWin::XRenderCompositing); KWin::BuiltInEffectLoader loader; KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); // prepare the configuration to hard enable/disable the effects we want to load KConfigGroup plugins = config->group("Plugins"); plugins.writeEntry(QStringLiteral("desktopgridEnabled"), false); plugins.writeEntry(QStringLiteral("highlightwindowEnabled"), false); plugins.writeEntry(QStringLiteral("kscreenEnabled"), false); plugins.writeEntry(QStringLiteral("minimizeanimationEnabled"), false); plugins.writeEntry(QStringLiteral("presentwindowsEnabled"), false); plugins.writeEntry(QStringLiteral("screenedgeEnabled"), false); plugins.writeEntry(QStringLiteral("screenshotEnabled"), false); plugins.writeEntry(QStringLiteral("slideEnabled"), false); plugins.writeEntry(QStringLiteral("slidingpopupsEnabled"), false); plugins.writeEntry(QStringLiteral("startupfeedbackEnabled"), false); plugins.writeEntry(QStringLiteral("zoomEnabled"), false); // enable lookingglass as it's not supported plugins.writeEntry(QStringLiteral("lookingglassEnabled"), true); plugins.sync(); loader.setConfig(config); qRegisterMetaType(); QSignalSpy spy(&loader, SIGNAL(effectLoaded(KWin::Effect*,QString))); // connect to signal to ensure that we delete the Effect again as the Effect doesn't have a parent connect(&loader, &KWin::BuiltInEffectLoader::effectLoaded, [](KWin::Effect *effect) { effect->deleteLater(); } ); // the config is prepared so that no Effect gets loaded! loader.queryAndLoadAll(); // we need to wait some time because it's queued QVERIFY(!spy.wait(10)); // now let's prepare a config which has one effect explicitly enabled plugins.writeEntry(QStringLiteral("mouseclickEnabled"), true); plugins.sync(); loader.queryAndLoadAll(); // should load one effect in first go QVERIFY(spy.wait(10)); // and afterwards it should not load another one QVERIFY(!spy.wait(10)); QCOMPARE(spy.size(), 1); // if we caught a signal it should have the effect name we passed in QList arguments = spy.takeFirst(); QCOMPARE(arguments.count(), 2); QCOMPARE(arguments.at(1).toString(), QStringLiteral("mouseclick")); spy.clear(); // let's delete one of the default entries plugins.deleteEntry(QStringLiteral("kscreenEnabled")); plugins.sync(); QVERIFY(spy.isEmpty()); loader.queryAndLoadAll(); // let's use qWait as we need to wait for two signals to be emitted QTest::qWait(100); QCOMPARE(spy.size(), 2); QStringList loadedEffects; for (auto &list : spy) { QCOMPARE(list.size(), 2); loadedEffects << list.at(1).toString(); } qSort(loadedEffects); QCOMPARE(loadedEffects.at(0), QStringLiteral("kscreen")); QCOMPARE(loadedEffects.at(1), QStringLiteral("mouseclick")); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestBuiltInEffectLoader) #include "test_builtin_effectloader.moc" diff --git a/autotests/test_client_machine.cpp b/autotests/test_client_machine.cpp index cc37350c7..e86247370 100644 --- a/autotests/test_client_machine.cpp +++ b/autotests/test_client_machine.cpp @@ -1,155 +1,156 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2013 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "testutils.h" // KWin #include "../client_machine.h" #include "../xcbutils.h" // Qt #include #include // xcb #include // system #include #include #include #include Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") using namespace KWin; class TestClientMachine : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void hostName_data(); void hostName(); void emptyHostName(); private: void setClientMachineProperty(xcb_window_t window, const QByteArray &hostname); QByteArray m_hostName; QByteArray m_fqdn; }; void TestClientMachine::setClientMachineProperty(xcb_window_t window, const QByteArray &hostname) { xcb_change_property(connection(), XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_CLIENT_MACHINE, XCB_ATOM_STRING, 8, hostname.length(), hostname.constData()); } void TestClientMachine::initTestCase() { #ifdef HOST_NAME_MAX char hostnamebuf[HOST_NAME_MAX]; #else char hostnamebuf[256]; #endif if (gethostname(hostnamebuf, sizeof hostnamebuf) >= 0) { hostnamebuf[sizeof(hostnamebuf)-1] = 0; m_hostName = hostnamebuf; } addrinfo *res; addrinfo addressHints; memset(&addressHints, 0, sizeof(addressHints)); addressHints.ai_family = PF_UNSPEC; addressHints.ai_socktype = SOCK_STREAM; addressHints.ai_flags |= AI_CANONNAME; if (getaddrinfo(m_hostName.constData(), nullptr, &addressHints, &res) == 0) { if (res->ai_canonname) { m_fqdn = QByteArray(res->ai_canonname); } } freeaddrinfo(res); qApp->setProperty("x11RootWindow", QVariant::fromValue(QX11Info::appRootWindow())); qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestClientMachine::cleanupTestCase() { } void TestClientMachine::hostName_data() { QTest::addColumn("hostName"); QTest::addColumn("expectedHost"); QTest::addColumn("local"); QTest::newRow("empty") << QByteArray() << QByteArray("localhost") << true; QTest::newRow("localhost") << QByteArray("localhost") << QByteArray("localhost") << true; QTest::newRow("hostname") << m_hostName << m_hostName << true; QTest::newRow("HOSTNAME") << m_hostName.toUpper() << m_hostName.toUpper() << true; QByteArray cutted(m_hostName); cutted.remove(0, 1); QTest::newRow("ostname") << cutted << cutted << false; QByteArray domain("random.name.not.exist.tld"); QTest::newRow("domain") << domain << domain << false; QTest::newRow("fqdn") << m_fqdn << m_fqdn << true; QTest::newRow("FQDN") << m_fqdn.toUpper() << m_fqdn.toUpper() << true; cutted = m_fqdn; cutted.remove(0, 1); QTest::newRow("qdn") << cutted << cutted << false; } void TestClientMachine::hostName() { const QRect geometry(0, 0, 10, 10); const uint32_t values[] = { true }; Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values); QFETCH(QByteArray, hostName); QFETCH(bool, local); setClientMachineProperty(window, hostName); ClientMachine clientMachine; QSignalSpy spy(&clientMachine, SIGNAL(localhostChanged())); clientMachine.resolve(window, XCB_WINDOW_NONE); QTEST(clientMachine.hostName(), "expectedHost"); int i=0; while (clientMachine.isResolving() && i++ < 50) { // name is being resolved in an external thread, so let's wait a little bit QTest::qWait(250); } QCOMPARE(clientMachine.isLocal(), local); QCOMPARE(spy.isEmpty(), !local); } void TestClientMachine::emptyHostName() { const QRect geometry(0, 0, 10, 10); const uint32_t values[] = { true }; Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values); ClientMachine clientMachine; QSignalSpy spy(&clientMachine, SIGNAL(localhostChanged())); clientMachine.resolve(window, XCB_WINDOW_NONE); QCOMPARE(clientMachine.hostName(), ClientMachine::localhost()); QVERIFY(clientMachine.isLocal()); // should be local QCOMPARE(spy.isEmpty(), false); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestClientMachine) #include "test_client_machine.moc" diff --git a/autotests/test_screen_edges.cpp b/autotests/test_screen_edges.cpp index ec4a845c1..87017bd71 100644 --- a/autotests/test_screen_edges.cpp +++ b/autotests/test_screen_edges.cpp @@ -1,865 +1,867 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2014 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ // kwin #include "../atoms.h" #include "../cursor.h" #include "../input.h" #include "../main.h" #include "../screenedge.h" #include "../screens.h" #include "../utils.h" #include "../virtualdesktops.h" #include "../xcbutils.h" #include "mock_client.h" #include "mock_screens.h" #include "mock_workspace.h" +#include "testutils.h" // Frameworks #include // Qt #include // xcb #include Q_DECLARE_METATYPE(KWin::ElectricBorder) Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") namespace KWin { Atoms* atoms; int screen_number = 0; Cursor *Cursor::s_self = nullptr; static QPoint s_cursorPos = QPoint(); QPoint Cursor::pos() { return s_cursorPos; } void Cursor::setPos(const QPoint &pos) { s_cursorPos = pos; } void Cursor::setPos(int x, int y) { setPos(QPoint(x, y)); } void Cursor::startMousePolling() { } void Cursor::stopMousePolling() { } InputRedirection *InputRedirection::s_self = nullptr; void InputRedirection::registerShortcut(const QKeySequence &shortcut, QAction *action) { Q_UNUSED(shortcut) Q_UNUSED(action) } void InputRedirection::registerAxisShortcut(Qt::KeyboardModifiers modifiers, PointerAxisDirection axis, QAction *action) { Q_UNUSED(modifiers) Q_UNUSED(axis) Q_UNUSED(action) } void InputRedirection::registerShortcutForGlobalAccelTimestamp(QAction *action) { Q_UNUSED(action) } void updateXTime() { } class TestObject : public QObject { Q_OBJECT public Q_SLOTS: bool callback(ElectricBorder border); Q_SIGNALS: void gotCallback(KWin::ElectricBorder); }; bool TestObject::callback(KWin::ElectricBorder border) { emit gotCallback(border); return true; } } class TestScreenEdges : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); void testInit(); void testCreatingInitialEdges(); void testCallback(); void testCallbackWithCheck(); void testPushBack_data(); void testPushBack(); void testFullScreenBlocking(); void testClientEdge(); }; void TestScreenEdges::initTestCase() { qApp->setProperty("x11RootWindow", QVariant::fromValue(QX11Info::appRootWindow())); qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); KWin::atoms = new KWin::Atoms; qRegisterMetaType(); } void TestScreenEdges::cleanupTestCase() { delete KWin::atoms; } void TestScreenEdges::init() { using namespace KWin; new MockWorkspace; auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); Screens::create(); auto vd = VirtualDesktopManager::create(); vd->setConfig(config); vd->load(); auto s = ScreenEdges::create(); s->setConfig(config); } void TestScreenEdges::cleanup() { using namespace KWin; delete ScreenEdges::self(); delete VirtualDesktopManager::self(); delete Screens::self(); delete workspace(); } void TestScreenEdges::testInit() { using namespace KWin; auto s = ScreenEdges::self(); s->init(); QCOMPARE(s->isDesktopSwitching(), false); QCOMPARE(s->isDesktopSwitchingMovingClients(), false); QCOMPARE(s->timeThreshold(), 150); QCOMPARE(s->reActivationThreshold(), 350); QCOMPARE(s->cursorPushBackDistance(), QSize(1, 1)); QCOMPARE(s->actionTopLeft(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionTop(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionTopRight(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionRight(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionBottomRight(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionBottom(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionBottomLeft(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionLeft(), ElectricBorderAction::ElectricActionNone); QList edges = s->findChildren(QString(), Qt::FindDirectChildrenOnly); QCOMPARE(edges.size(), 8); for (auto e : edges) { QVERIFY(!e->isReserved()); QVERIFY(e->inherits("KWin::WindowBasedEdge")); QVERIFY(!e->inherits("KWin::AreaBasedEdge")); QVERIFY(!e->client()); QVERIFY(!e->isApproaching()); } Edge *te = edges.at(0); QVERIFY(te->isCorner()); QVERIFY(!te->isScreenEdge()); QVERIFY(te->isLeft()); QVERIFY(te->isTop()); QVERIFY(!te->isRight()); QVERIFY(!te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricTopLeft); te = edges.at(1); QVERIFY(te->isCorner()); QVERIFY(!te->isScreenEdge()); QVERIFY(te->isLeft()); QVERIFY(!te->isTop()); QVERIFY(!te->isRight()); QVERIFY(te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricBottomLeft); te = edges.at(2); QVERIFY(!te->isCorner()); QVERIFY(te->isScreenEdge()); QVERIFY(te->isLeft()); QVERIFY(!te->isTop()); QVERIFY(!te->isRight()); QVERIFY(!te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricLeft); te = edges.at(3); QVERIFY(te->isCorner()); QVERIFY(!te->isScreenEdge()); QVERIFY(!te->isLeft()); QVERIFY(te->isTop()); QVERIFY(te->isRight()); QVERIFY(!te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricTopRight); te = edges.at(4); QVERIFY(te->isCorner()); QVERIFY(!te->isScreenEdge()); QVERIFY(!te->isLeft()); QVERIFY(!te->isTop()); QVERIFY(te->isRight()); QVERIFY(te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricBottomRight); te = edges.at(5); QVERIFY(!te->isCorner()); QVERIFY(te->isScreenEdge()); QVERIFY(!te->isLeft()); QVERIFY(!te->isTop()); QVERIFY(te->isRight()); QVERIFY(!te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricRight); te = edges.at(6); QVERIFY(!te->isCorner()); QVERIFY(te->isScreenEdge()); QVERIFY(!te->isLeft()); QVERIFY(te->isTop()); QVERIFY(!te->isRight()); QVERIFY(!te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricTop); te = edges.at(7); QVERIFY(!te->isCorner()); QVERIFY(te->isScreenEdge()); QVERIFY(!te->isLeft()); QVERIFY(!te->isTop()); QVERIFY(!te->isRight()); QVERIFY(te->isBottom()); QCOMPARE(te->border(), ElectricBorder::ElectricBottom); // we shouldn't have any x windows, though QCOMPARE(s->windows().size(), 0); } void TestScreenEdges::testCreatingInitialEdges() { using namespace KWin; auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); config->group("Windows").writeEntry("ElectricBorders", 2/*ElectricAlways*/); config->sync(); auto s = ScreenEdges::self(); s->setConfig(config); s->init(); // we don't have multiple desktops, so it's returning false QCOMPARE(s->isDesktopSwitching(), true); QCOMPARE(s->isDesktopSwitchingMovingClients(), true); QCOMPARE(s->actionTopLeft(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionTop(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionTopRight(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionRight(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionBottomRight(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionBottom(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionBottomLeft(), ElectricBorderAction::ElectricActionNone); QCOMPARE(s->actionLeft(), ElectricBorderAction::ElectricActionNone); QEXPECT_FAIL("", "needs fixing", Continue); QCOMPARE(s->windows().size(), 0); // set some reasonable virtual desktops config->group("Desktops").writeEntry("Number", 4); config->sync(); auto vd = VirtualDesktopManager::self(); vd->setConfig(config); vd->load(); QCOMPARE(vd->count(), 4u); QCOMPARE(vd->grid().width(), 2); QCOMPARE(vd->grid().height(), 2); // approach windows for edges not created as screen too small s->updateLayout(); auto edgeWindows = s->windows(); #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) #if (QT_VERSION < QT_VERSION_CHECK(5, 6, 1)) if (!Xcb::Extensions::self()->isRandrAvailable()) { QEXPECT_FAIL("", "Broken on no xrandr systems in Qt 5.5", Abort); } #endif #endif QCOMPARE(edgeWindows.size(), 12); auto testWindowGeometry = [&](int index) { Xcb::WindowGeometry geo(edgeWindows[index]); return geo.rect(); }; QRect sg = screens()->geometry(); const int co = s->cornerOffset(); QList expectedGeometries{ QRect(0, 0, 1, 1), QRect(0, 0, co, co), QRect(0, sg.bottom(), 1, 1), QRect(0, sg.height() - co, co, co), QRect(0, co, 1, sg.height() - co*2), // QRect(0, co * 2 + 1, co, sg.height() - co*4), QRect(sg.right(), 0, 1, 1), QRect(sg.right() - co + 1, 0, co, co), QRect(sg.right(), sg.bottom(), 1, 1), QRect(sg.right() - co + 1, sg.bottom() - co + 1, co, co), QRect(sg.right(), co, 1, sg.height() - co*2), // QRect(sg.right() - co + 1, co * 2, co, sg.height() - co*4), QRect(co, 0, sg.width() - co * 2, 1), // QRect(co * 2, 0, sg.width() - co * 4, co), QRect(co, sg.bottom(), sg.width() - co * 2, 1), // QRect(co * 2, sg.height() - co, sg.width() - co * 4, co) }; for (int i = 0; i < 12; ++i) { QCOMPARE(testWindowGeometry(i), expectedGeometries.at(i)); } QList edges = s->findChildren(QString(), Qt::FindDirectChildrenOnly); QCOMPARE(edges.size(), 8); for (auto e : edges) { QVERIFY(e->isReserved()); } static_cast(screens())->setGeometries(QList{QRect{0, 0, 1024, 768}}); QSignalSpy changedSpy(screens(), SIGNAL(changed())); QVERIFY(changedSpy.isValid()); // first is before it's updated QVERIFY(changedSpy.wait()); // second is after it's updated QVERIFY(changedSpy.wait()); // let's update the layout and verify that we have edges s->recreateEdges(); edgeWindows = s->windows(); QCOMPARE(edgeWindows.size(), 16); sg = screens()->geometry(); expectedGeometries = QList{ QRect(0, 0, 1, 1), QRect(0, 0, co, co), QRect(0, sg.bottom(), 1, 1), QRect(0, sg.height() - co, co, co), QRect(0, co, 1, sg.height() - co*2), QRect(0, co * 2 + 1, co, sg.height() - co*4), QRect(sg.right(), 0, 1, 1), QRect(sg.right() - co + 1, 0, co, co), QRect(sg.right(), sg.bottom(), 1, 1), QRect(sg.right() - co + 1, sg.bottom() - co + 1, co, co), QRect(sg.right(), co, 1, sg.height() - co*2), QRect(sg.right() - co + 1, co * 2, co, sg.height() - co*4), QRect(co, 0, sg.width() - co * 2, 1), QRect(co * 2, 0, sg.width() - co * 4, co), QRect(co, sg.bottom(), sg.width() - co * 2, 1), QRect(co * 2, sg.height() - co, sg.width() - co * 4, co) }; for (int i = 0; i < 16; ++i) { QCOMPARE(testWindowGeometry(i), expectedGeometries.at(i)); } // disable desktop switching again config->group("Windows").writeEntry("ElectricBorders", 1/*ElectricMoveOnly*/); s->reconfigure(); QCOMPARE(s->isDesktopSwitching(), false); QCOMPARE(s->isDesktopSwitchingMovingClients(), true); QCOMPARE(s->windows().size(), 0); edges = s->findChildren(QString(), Qt::FindDirectChildrenOnly); QCOMPARE(edges.size(), 8); for (int i = 0; i < 8; ++i) { auto e = edges.at(i); QVERIFY(!e->isReserved()); QCOMPARE(e->approachGeometry(), expectedGeometries.at(i*2+1)); } } void TestScreenEdges::testCallback() { using namespace KWin; MockWorkspace ws; static_cast(screens())->setGeometries(QList{QRect{0, 0, 1024, 768}, QRect{200, 768, 1024, 768}}); QSignalSpy changedSpy(screens(), SIGNAL(changed())); QVERIFY(changedSpy.isValid()); // first is before it's updated QVERIFY(changedSpy.wait()); // second is after it's updated QVERIFY(changedSpy.wait()); auto s = ScreenEdges::self(); s->init(); TestObject callback; QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder))); QVERIFY(spy.isValid()); s->reserve(ElectricLeft, &callback, "callback"); s->reserve(ElectricTopLeft, &callback, "callback"); s->reserve(ElectricTop, &callback, "callback"); s->reserve(ElectricTopRight, &callback, "callback"); s->reserve(ElectricRight, &callback, "callback"); s->reserve(ElectricBottomRight, &callback, "callback"); s->reserve(ElectricBottom, &callback, "callback"); s->reserve(ElectricBottomLeft, &callback, "callback"); QList edges = s->findChildren(QString(), Qt::FindDirectChildrenOnly); QCOMPARE(edges.size(), 10); for (auto e: edges) { QVERIFY(e->isReserved()); } auto it = std::find_if(edges.constBegin(), edges.constEnd(), [](Edge *e) { return e->isScreenEdge() && e->isLeft() && e->approachGeometry().bottom() < 768; }); #if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) #if (QT_VERSION < QT_VERSION_CHECK(5, 6, 1)) if (!Xcb::Extensions::self()->isRandrAvailable()) { QEXPECT_FAIL("", "Broken on no xrandr systems in Qt 5.5", Abort); } #endif #endif QVERIFY(it != edges.constEnd()); xcb_enter_notify_event_t event; auto setPos = [&event] (const QPoint &pos) { Cursor::setPos(pos); event.root_x = pos.x(); event.root_y = pos.y(); event.event_x = pos.x(); event.event_y = pos.y(); }; event.root = XCB_WINDOW_NONE; event.child = XCB_WINDOW_NONE; event.event = (*it)->window(); event.same_screen_focus = 1; event.time = QDateTime::currentMSecsSinceEpoch(); setPos(QPoint(0, 50)); QVERIFY(s->isEntered(&event)); // doesn't trigger as the edge was not triggered yet QVERIFY(spy.isEmpty()); QCOMPARE(Cursor::pos(), QPoint(1, 50)); // test doesn't trigger due to too much offset QTest::qWait(160); setPos(QPoint(0, 100)); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); QCOMPARE(Cursor::pos(), QPoint(1, 100)); // doesn't trigger as we are waiting too long already QTest::qWait(200); setPos(QPoint(0, 101)); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); QCOMPARE(Cursor::pos(), QPoint(1, 101)); // doesn't activate as we are waiting too short QTest::qWait(50); setPos(QPoint(0, 100)); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); QCOMPARE(Cursor::pos(), QPoint(1, 100)); // and this one triggers QTest::qWait(110); setPos(QPoint(0, 101)); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(!spy.isEmpty()); QCOMPARE(Cursor::pos(), QPoint(1, 101)); // now let's try to trigger again QTest::qWait(351); setPos(QPoint(0, 100)); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QCOMPARE(spy.count(), 1); QCOMPARE(Cursor::pos(), QPoint(1, 100)); // it's still under the reactivation QTest::qWait(50); setPos(QPoint(0, 100)); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QCOMPARE(spy.count(), 1); QCOMPARE(Cursor::pos(), QPoint(1, 100)); // now it should trigger again QTest::qWait(250); setPos(QPoint(0, 100)); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QCOMPARE(spy.count(), 2); QCOMPARE(spy.first().first().value(), ElectricLeft); QCOMPARE(spy.last().first().value(), ElectricLeft); QCOMPARE(Cursor::pos(), QPoint(1, 100)); // let's disable pushback auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); config->group("Windows").writeEntry("ElectricBorderPushbackPixels", 0); config->sync(); s->setConfig(config); s->reconfigure(); // it should trigger directly QTest::qWait(350); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QCOMPARE(spy.count(), 3); QCOMPARE(spy.at(0).first().value(), ElectricLeft); QCOMPARE(spy.at(1).first().value(), ElectricLeft); QCOMPARE(spy.at(2).first().value(), ElectricLeft); QCOMPARE(Cursor::pos(), QPoint(0, 100)); // now let's unreserve again s->unreserve(ElectricTopLeft, &callback); s->unreserve(ElectricTop, &callback); s->unreserve(ElectricTopRight, &callback); s->unreserve(ElectricRight, &callback); s->unreserve(ElectricBottomRight, &callback); s->unreserve(ElectricBottom, &callback); s->unreserve(ElectricBottomLeft, &callback); s->unreserve(ElectricLeft, &callback); for (auto e: s->findChildren(QString(), Qt::FindDirectChildrenOnly)) { QVERIFY(!e->isReserved()); } } void TestScreenEdges::testCallbackWithCheck() { using namespace KWin; auto s = ScreenEdges::self(); s->init(); TestObject callback; QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder))); QVERIFY(spy.isValid()); s->reserve(ElectricLeft, &callback, "callback"); // check activating a different edge doesn't do anything s->check(QPoint(50, 0), QDateTime::currentDateTime(), true); QVERIFY(spy.isEmpty()); // try a direct activate without pushback Cursor::setPos(0, 50); s->check(QPoint(0, 50), QDateTime::currentDateTime(), true); QCOMPARE(spy.count(), 1); QEXPECT_FAIL("", "Argument says force no pushback, but it gets pushed back. Needs investigation", Continue); QCOMPARE(Cursor::pos(), QPoint(0, 50)); // use a different edge, this time with pushback s->reserve(KWin::ElectricRight, &callback, "callback"); Cursor::setPos(99, 50); s->check(QPoint(99, 50), QDateTime::currentDateTime()); QCOMPARE(spy.count(), 1); QCOMPARE(spy.last().first().value(), ElectricLeft); QCOMPARE(Cursor::pos(), QPoint(98, 50)); // and trigger it again QTest::qWait(160); Cursor::setPos(99, 50); s->check(QPoint(99, 50), QDateTime::currentDateTime()); QCOMPARE(spy.count(), 2); QCOMPARE(spy.last().first().value(), ElectricRight); QCOMPARE(Cursor::pos(), QPoint(98, 50)); } void TestScreenEdges::testPushBack_data() { QTest::addColumn("border"); QTest::addColumn("pushback"); QTest::addColumn("trigger"); QTest::addColumn("expected"); QTest::newRow("topleft-3") << KWin::ElectricTopLeft << 3 << QPoint(0, 0) << QPoint(3, 3); QTest::newRow("top-5") << KWin::ElectricTop << 5 << QPoint(50, 0) << QPoint(50, 5); QTest::newRow("toprigth-2") << KWin::ElectricTopRight << 2 << QPoint(99, 0) << QPoint(97, 2); QTest::newRow("right-10") << KWin::ElectricRight << 10 << QPoint(99, 50) << QPoint(89, 50); QTest::newRow("bottomright-5") << KWin::ElectricBottomRight << 5 << QPoint(99, 99) << QPoint(94, 94); QTest::newRow("bottom-10") << KWin::ElectricBottom << 10 << QPoint(50, 99) << QPoint(50, 89); QTest::newRow("bottomleft-3") << KWin::ElectricBottomLeft << 3 << QPoint(0, 99) << QPoint(3, 96); QTest::newRow("left-10") << KWin::ElectricLeft << 10 << QPoint(0, 50) << QPoint(10, 50); QTest::newRow("invalid") << KWin::ElectricLeft << 10 << QPoint(50, 0) << QPoint(50, 0); } void TestScreenEdges::testPushBack() { using namespace KWin; QFETCH(int, pushback); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); config->group("Windows").writeEntry("ElectricBorderPushbackPixels", pushback); config->sync(); // TODO: add screens auto s = ScreenEdges::self(); s->setConfig(config); s->init(); TestObject callback; QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder))); QVERIFY(spy.isValid()); QFETCH(ElectricBorder, border); s->reserve(border, &callback, "callback"); QFETCH(QPoint, trigger); Cursor::setPos(trigger); xcb_enter_notify_event_t event; event.root_x = trigger.x(); event.root_y = trigger.y(); event.event_x = trigger.x(); event.event_y = trigger.y(); event.root = XCB_WINDOW_NONE; event.child = XCB_WINDOW_NONE; event.event = s->windows().first(); event.same_screen_focus = 1; event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); QTEST(Cursor::pos(), "expected"); // do the same without the event, but the check method Cursor::setPos(trigger); s->check(trigger, QDateTime::currentDateTime()); QVERIFY(spy.isEmpty()); QTEST(Cursor::pos(), "expected"); } void TestScreenEdges::testFullScreenBlocking() { using namespace KWin; MockWorkspace ws; Client client(&ws); auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); config->group("Windows").writeEntry("ElectricBorderPushbackPixels", 1); config->sync(); auto s = ScreenEdges::self(); s->setConfig(config); s->init(); TestObject callback; QSignalSpy spy(&callback, SIGNAL(gotCallback(KWin::ElectricBorder))); QVERIFY(spy.isValid()); s->reserve(KWin::ElectricLeft, &callback, "callback"); s->reserve(KWin::ElectricBottomRight, &callback, "callback"); // currently there is no active client yet, so check blocking shouldn't do anything emit s->checkBlocking(); xcb_enter_notify_event_t event; Cursor::setPos(0, 50); event.root_x = 0; event.root_y = 50; event.event_x = 0; event.event_y = 50; event.root = XCB_WINDOW_NONE; event.child = XCB_WINDOW_NONE; event.event = s->windows().first(); event.same_screen_focus = 1; event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); QCOMPARE(Cursor::pos(), QPoint(1, 50)); client.setGeometry(screens()->geometry()); client.setActive(true); client.setFullScreen(true); ws.setActiveClient(&client); emit s->checkBlocking(); // the signal doesn't trigger for corners, let's go over all windows just to be sure that it doesn't call for corners for (auto e: s->findChildren()) { e->checkBlocking(); } // calling again should not trigger QTest::qWait(160); Cursor::setPos(0, 50); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); // and no pushback QCOMPARE(Cursor::pos(), QPoint(0, 50)); // let's make the client not fullscreen, which should trigger client.setFullScreen(false); emit s->checkBlocking(); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(!spy.isEmpty()); QCOMPARE(Cursor::pos(), QPoint(1, 50)); // let's make the client fullscreen again, but with a geometry not intersecting the left edge QTest::qWait(351); client.setFullScreen(true); client.setGeometry(client.geometry().translated(10, 0)); emit s->checkBlocking(); spy.clear(); Cursor::setPos(0, 50); event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); // and a pushback QCOMPARE(Cursor::pos(), QPoint(1, 50)); // just to be sure, let's set geometry back client.setGeometry(screens()->geometry()); emit s->checkBlocking(); Cursor::setPos(0, 50); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); // and no pushback QCOMPARE(Cursor::pos(), QPoint(0, 50)); // the corner should always trigger s->unreserve(KWin::ElectricLeft, &callback); event.event_x = 99; event.event_y = 99; event.root_x = 99; event.root_y = 99; event.event = s->windows().first(); event.time = QDateTime::currentMSecsSinceEpoch(); Cursor::setPos(99, 99); QVERIFY(s->isEntered(&event)); QVERIFY(spy.isEmpty()); // and pushback QCOMPARE(Cursor::pos(), QPoint(98, 98)); QTest::qWait(160); event.time = QDateTime::currentMSecsSinceEpoch(); Cursor::setPos(99, 99); QVERIFY(s->isEntered(&event)); QVERIFY(!spy.isEmpty()); } void TestScreenEdges::testClientEdge() { using namespace KWin; Client client(workspace()); client.setGeometry(QRect(10, 50, 10, 50)); auto s = ScreenEdges::self(); s->init(); s->reserve(&client, KWin::ElectricBottom); // let's set the client to be hidden client.setHiddenInternal(true); QPointer edge = s->findChildren().last(); s->reserve(&client, KWin::ElectricBottom); QCOMPARE(edge.data(), s->findChildren().last()); QCOMPARE(edge->isReserved(), true); //remove old reserves and resize to be in the middle of the screen s->reserve(&client, KWin::ElectricNone); client.setGeometry(QRect(2, 2, 20, 20)); // for none of the edges it should be able to be set for (int i = 0; i < ELECTRIC_COUNT; ++i) { client.setHiddenInternal(true); s->reserve(&client, static_cast(i)); QCOMPARE(client.isHiddenInternal(), false); } // now let's try to set it and activate it client.setGeometry(screens()->geometry()); client.setHiddenInternal(true); s->reserve(&client, KWin::ElectricLeft); QCOMPARE(client.isHiddenInternal(), true); xcb_enter_notify_event_t event; Cursor::setPos(0, 50); event.root_x = 0; event.root_y = 50; event.event_x = 0; event.event_y = 50; event.root = XCB_WINDOW_NONE; event.child = XCB_WINDOW_NONE; event.event = s->windows().first(); event.same_screen_focus = 1; event.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event)); // autohiding panels shall activate instantly QCOMPARE(client.isHiddenInternal(), false); QCOMPARE(Cursor::pos(), QPoint(1, 50)); // now let's reserve the client for each of the edges, in the end for the right one client.setHiddenInternal(true); s->reserve(&client, KWin::ElectricTop); s->reserve(&client, KWin::ElectricBottom); QCOMPARE(client.isHiddenInternal(), true); // corners shouldn't get reserved s->reserve(&client, KWin::ElectricTopLeft); QCOMPARE(client.isHiddenInternal(), false); client.setHiddenInternal(true); s->reserve(&client, KWin::ElectricTopRight); QCOMPARE(client.isHiddenInternal(), false); client.setHiddenInternal(true); s->reserve(&client, KWin::ElectricBottomRight); QCOMPARE(client.isHiddenInternal(), false); client.setHiddenInternal(true); s->reserve(&client, KWin::ElectricBottomLeft); QCOMPARE(client.isHiddenInternal(), false); // now finally reserve on right one client.setHiddenInternal(true); s->reserve(&client, KWin::ElectricRight); QCOMPARE(client.isHiddenInternal(), true); // now let's emulate the removal of a Client through Workspace emit workspace()->clientRemoved(&client); for (auto e : s->findChildren()) { QVERIFY(!e->client()); } QCOMPARE(client.isHiddenInternal(), true); // now let's try to trigger the client showing with the check method instead of enter notify s->reserve(&client, KWin::ElectricTop); QCOMPARE(client.isHiddenInternal(), true); Cursor::setPos(50, 0); s->check(QPoint(50, 0), QDateTime::currentDateTime()); QCOMPARE(client.isHiddenInternal(), false); QCOMPARE(Cursor::pos(), QPoint(50, 1)); // unreserve by setting to none edge s->reserve(&client, KWin::ElectricNone); // check on previous edge again, should fail client.setHiddenInternal(true); Cursor::setPos(50, 0); s->check(QPoint(50, 0), QDateTime::currentDateTime()); QCOMPARE(client.isHiddenInternal(), true); QCOMPARE(Cursor::pos(), QPoint(50, 0)); // set to windows can cover client.setGeometry(screens()->geometry()); client.setHiddenInternal(false); client.setKeepBelow(true); s->reserve(&client, KWin::ElectricLeft); QCOMPARE(client.keepBelow(), true); QCOMPARE(client.isHiddenInternal(), false); xcb_enter_notify_event_t event2; Cursor::setPos(0, 50); event2.root_x = 0; event2.root_y = 50; event2.event_x = 0; event2.event_y = 50; event2.root = XCB_WINDOW_NONE; event2.child = XCB_WINDOW_NONE; event2.event = s->windows().first(); event2.same_screen_focus = 1; event2.time = QDateTime::currentMSecsSinceEpoch(); QVERIFY(s->isEntered(&event2)); QCOMPARE(client.keepBelow(), false); QCOMPARE(client.isHiddenInternal(), false); QCOMPARE(Cursor::pos(), QPoint(1, 50)); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestScreenEdges) #include "test_screen_edges.moc" diff --git a/autotests/test_xcb_size_hints.cpp b/autotests/test_xcb_size_hints.cpp index 1c0009666..e759943a5 100644 --- a/autotests/test_xcb_size_hints.cpp +++ b/autotests/test_xcb_size_hints.cpp @@ -1,375 +1,376 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2015 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "testutils.h" // KWin #include "../xcbutils.h" // Qt #include #include #include // xcb #include #include using namespace KWin; using namespace KWin::Xcb; class TestXcbSizeHints : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void init(); void cleanup(); void testSizeHints_data(); void testSizeHints(); void testSizeHintsEmpty(); void testSizeHintsNotSet(); void geometryHintsBeforeInit(); void geometryHintsBeforeRead(); private: Window m_testWindow; }; void TestXcbSizeHints::initTestCase() { qApp->setProperty("x11RootWindow", QVariant::fromValue(QX11Info::appRootWindow())); qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestXcbSizeHints::init() { const uint32_t values[] = { true }; m_testWindow.create(QRect(0, 0, 10, 10), XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values); QVERIFY(m_testWindow.isValid()); } void TestXcbSizeHints::cleanup() { m_testWindow.reset(); } void TestXcbSizeHints::testSizeHints_data() { // set QTest::addColumn("userPos"); QTest::addColumn("userSize"); QTest::addColumn("minSize"); QTest::addColumn("maxSize"); QTest::addColumn("resizeInc"); QTest::addColumn("minAspect"); QTest::addColumn("maxAspect"); QTest::addColumn("baseSize"); QTest::addColumn("gravity"); // read for SizeHints QTest::addColumn("expectedFlags"); QTest::addColumn("expectedPad0"); QTest::addColumn("expectedPad1"); QTest::addColumn("expectedPad2"); QTest::addColumn("expectedPad3"); QTest::addColumn("expectedMinWidth"); QTest::addColumn("expectedMinHeight"); QTest::addColumn("expectedMaxWidth"); QTest::addColumn("expectedMaxHeight"); QTest::addColumn("expectedWidthInc"); QTest::addColumn("expectedHeightInc"); QTest::addColumn("expectedMinAspectNum"); QTest::addColumn("expectedMinAspectDen"); QTest::addColumn("expectedMaxAspectNum"); QTest::addColumn("expectedMaxAspectDen"); QTest::addColumn("expectedBaseWidth"); QTest::addColumn("expectedBaseHeight"); // read for GeometryHints QTest::addColumn("expectedMinSize"); QTest::addColumn("expectedMaxSize"); QTest::addColumn("expectedResizeIncrements"); QTest::addColumn("expectedMinAspect"); QTest::addColumn("expectedMaxAspect"); QTest::addColumn("expectedBaseSize"); QTest::addColumn("expectedGravity"); QTest::newRow("userPos") << QPoint(1, 2) << QSize() << QSize() << QSize() << QSize() << QSize() << QSize() << QSize() << 0 << 1 << 1 << 2 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(0, 0) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("userSize") << QPoint() << QSize(1, 2) << QSize() << QSize() << QSize() << QSize() << QSize() << QSize() << 0 << 2 << 0 << 0 << 1 << 2 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(0, 0) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("minSize") << QPoint() << QSize() << QSize(1, 2) << QSize() << QSize() << QSize() << QSize() << QSize() << 0 << 16 << 0 << 0 << 0 << 0 << 1 << 2 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(1, 2) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("maxSize") << QPoint() << QSize() << QSize() << QSize(1, 2) << QSize() << QSize() << QSize() << QSize() << 0 << 32 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 2 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(0, 0) << QSize(1, 2) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("maxSize0") << QPoint() << QSize() << QSize() << QSize(0, 0) << QSize() << QSize() << QSize() << QSize() << 0 << 32 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(0, 0) << QSize(1, 1) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("min/maxSize") << QPoint() << QSize() << QSize(1, 2) << QSize(3, 4) << QSize() << QSize() << QSize() << QSize() << 0 << 48 << 0 << 0 << 0 << 0 << 1 << 2 << 3 << 4 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(1, 2) << QSize(3, 4) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("resizeInc") << QPoint() << QSize() << QSize() << QSize() << QSize(1, 2) << QSize() << QSize() << QSize() << 0 << 64 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 2 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(0, 0) << QSize(INT_MAX, INT_MAX) << QSize(1, 2) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("resizeInc0") << QPoint() << QSize() << QSize() << QSize() << QSize(0, 0) << QSize() << QSize() << QSize() << 0 << 64 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(0, 0) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("aspect") << QPoint() << QSize() << QSize() << QSize() << QSize() << QSize(1, 2) << QSize(3, 4) << QSize() << 0 << 128 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 2 << 3 << 4 << 0 << 0 << QSize(0, 0) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, 2) << QSize(3, 4) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("aspectDivision0") << QPoint() << QSize() << QSize() << QSize() << QSize() << QSize(1, 0) << QSize(3, 0) << QSize() << 0 << 128 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 0 << 3 << 0 << 0 << 0 << QSize(0, 0) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, 1) << QSize(3, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("baseSize") << QPoint() << QSize() << QSize() << QSize() << QSize() << QSize() << QSize() << QSize(1, 2) << 0 << 256 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 1 << 2 << QSize(1, 2) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(1, 2) << qint32(XCB_GRAVITY_NORTH_WEST); QTest::newRow("gravity") << QPoint() << QSize() << QSize() << QSize() << QSize() << QSize() << QSize() << QSize() << qint32(XCB_GRAVITY_STATIC) << 512 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << QSize(0, 0) << QSize(INT_MAX, INT_MAX) << QSize(1, 1) << QSize(1, INT_MAX) << QSize(INT_MAX, 1) << QSize(0, 0) << qint32(XCB_GRAVITY_STATIC); QTest::newRow("all") << QPoint(1, 2) << QSize(3, 4) << QSize(5, 6) << QSize(7, 8) << QSize(9, 10) << QSize(11, 12) << QSize(13, 14) << QSize(15, 16) << 1 << 1011 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8 << 9 << 10 << 11 << 12 << 13 << 14 << 15 << 16 << QSize(5, 6) << QSize(7, 8) << QSize(9, 10) << QSize(11, 12) << QSize(13, 14) << QSize(15, 16) << qint32(XCB_GRAVITY_NORTH_WEST); } void TestXcbSizeHints::testSizeHints() { xcb_size_hints_t hints; memset(&hints, 0, sizeof(hints)); QFETCH(QPoint, userPos); if (!userPos.isNull()) { xcb_icccm_size_hints_set_position(&hints, 1, userPos.x(), userPos.y()); } QFETCH(QSize, userSize); if (userSize.isValid()) { xcb_icccm_size_hints_set_size(&hints, 1, userSize.width(), userSize.height()); } QFETCH(QSize, minSize); if (minSize.isValid()) { xcb_icccm_size_hints_set_min_size(&hints, minSize.width(), minSize.height()); } QFETCH(QSize, maxSize); if (maxSize.isValid()) { xcb_icccm_size_hints_set_max_size(&hints, maxSize.width(), maxSize.height()); } QFETCH(QSize, resizeInc); if (resizeInc.isValid()) { xcb_icccm_size_hints_set_resize_inc(&hints, resizeInc.width(), resizeInc.height()); } QFETCH(QSize, minAspect); QFETCH(QSize, maxAspect); if (minAspect.isValid() && maxAspect.isValid()) { xcb_icccm_size_hints_set_aspect(&hints, minAspect.width(), minAspect.height(), maxAspect.width(), maxAspect.height()); } QFETCH(QSize, baseSize); if (baseSize.isValid()) { xcb_icccm_size_hints_set_base_size(&hints, baseSize.width(), baseSize.height()); } QFETCH(qint32, gravity); if (gravity != 0) { xcb_icccm_size_hints_set_win_gravity(&hints, (xcb_gravity_t)gravity); } xcb_icccm_set_wm_normal_hints(QX11Info::connection(), m_testWindow, &hints); xcb_flush(QX11Info::connection()); GeometryHints geoHints; geoHints.init(m_testWindow); geoHints.read(); QCOMPARE(geoHints.hasAspect(), minAspect.isValid() && maxAspect.isValid()); QCOMPARE(geoHints.hasBaseSize(), baseSize.isValid()); QCOMPARE(geoHints.hasMaxSize(), maxSize.isValid()); QCOMPARE(geoHints.hasMinSize(), minSize.isValid()); QCOMPARE(geoHints.hasPosition(), !userPos.isNull()); QCOMPARE(geoHints.hasResizeIncrements(), resizeInc.isValid()); QCOMPARE(geoHints.hasSize(), userSize.isValid()); QCOMPARE(geoHints.hasWindowGravity(), gravity != 0); QTEST(geoHints.baseSize(), "expectedBaseSize"); QTEST(geoHints.maxAspect(), "expectedMaxAspect"); QTEST(geoHints.maxSize(), "expectedMaxSize"); QTEST(geoHints.minAspect(), "expectedMinAspect"); QTEST(geoHints.minSize(), "expectedMinSize"); QTEST(geoHints.resizeIncrements(), "expectedResizeIncrements"); QTEST(qint32(geoHints.windowGravity()), "expectedGravity"); auto sizeHints = geoHints.m_sizeHints; QVERIFY(sizeHints); QTEST(sizeHints->flags, "expectedFlags"); QTEST(sizeHints->pad[0], "expectedPad0"); QTEST(sizeHints->pad[1], "expectedPad1"); QTEST(sizeHints->pad[2], "expectedPad2"); QTEST(sizeHints->pad[3], "expectedPad3"); QTEST(sizeHints->minWidth, "expectedMinWidth"); QTEST(sizeHints->minHeight, "expectedMinHeight"); QTEST(sizeHints->maxWidth, "expectedMaxWidth"); QTEST(sizeHints->maxHeight, "expectedMaxHeight"); QTEST(sizeHints->widthInc, "expectedWidthInc"); QTEST(sizeHints->heightInc, "expectedHeightInc"); QTEST(sizeHints->minAspect[0], "expectedMinAspectNum"); QTEST(sizeHints->minAspect[1], "expectedMinAspectDen"); QTEST(sizeHints->maxAspect[0], "expectedMaxAspectNum"); QTEST(sizeHints->maxAspect[1], "expectedMaxAspectDen"); QTEST(sizeHints->baseWidth, "expectedBaseWidth"); QTEST(sizeHints->baseHeight, "expectedBaseHeight"); QCOMPARE(sizeHints->winGravity, gravity); // copy GeometryHints::NormalHints::SizeHints sizeHints2 = *sizeHints; QTEST(sizeHints2.flags, "expectedFlags"); QTEST(sizeHints2.pad[0], "expectedPad0"); QTEST(sizeHints2.pad[1], "expectedPad1"); QTEST(sizeHints2.pad[2], "expectedPad2"); QTEST(sizeHints2.pad[3], "expectedPad3"); QTEST(sizeHints2.minWidth, "expectedMinWidth"); QTEST(sizeHints2.minHeight, "expectedMinHeight"); QTEST(sizeHints2.maxWidth, "expectedMaxWidth"); QTEST(sizeHints2.maxHeight, "expectedMaxHeight"); QTEST(sizeHints2.widthInc, "expectedWidthInc"); QTEST(sizeHints2.heightInc, "expectedHeightInc"); QTEST(sizeHints2.minAspect[0], "expectedMinAspectNum"); QTEST(sizeHints2.minAspect[1], "expectedMinAspectDen"); QTEST(sizeHints2.maxAspect[0], "expectedMaxAspectNum"); QTEST(sizeHints2.maxAspect[1], "expectedMaxAspectDen"); QTEST(sizeHints2.baseWidth, "expectedBaseWidth"); QTEST(sizeHints2.baseHeight, "expectedBaseHeight"); QCOMPARE(sizeHints2.winGravity, gravity); } void TestXcbSizeHints::testSizeHintsEmpty() { xcb_size_hints_t xcbHints; memset(&xcbHints, 0, sizeof(xcbHints)); xcb_icccm_set_wm_normal_hints(QX11Info::connection(), m_testWindow, &xcbHints); xcb_flush(QX11Info::connection()); GeometryHints hints; hints.init(m_testWindow); hints.read(); QVERIFY(!hints.hasAspect()); QVERIFY(!hints.hasBaseSize()); QVERIFY(!hints.hasMaxSize()); QVERIFY(!hints.hasMinSize()); QVERIFY(!hints.hasPosition()); QVERIFY(!hints.hasResizeIncrements()); QVERIFY(!hints.hasSize()); QVERIFY(!hints.hasWindowGravity()); QCOMPARE(hints.baseSize(), QSize(0, 0)); QCOMPARE(hints.maxAspect(), QSize(INT_MAX, 1)); QCOMPARE(hints.maxSize(), QSize(INT_MAX, INT_MAX)); QCOMPARE(hints.minAspect(), QSize(1, INT_MAX)); QCOMPARE(hints.minSize(), QSize(0, 0)); QCOMPARE(hints.resizeIncrements(), QSize(1, 1)); QCOMPARE(hints.windowGravity(), XCB_GRAVITY_NORTH_WEST); auto sizeHints = hints.m_sizeHints; QVERIFY(sizeHints); QCOMPARE(sizeHints->flags, 0); QCOMPARE(sizeHints->pad[0], 0); QCOMPARE(sizeHints->pad[1], 0); QCOMPARE(sizeHints->pad[2], 0); QCOMPARE(sizeHints->pad[3], 0); QCOMPARE(sizeHints->minWidth, 0); QCOMPARE(sizeHints->minHeight, 0); QCOMPARE(sizeHints->maxWidth, 0); QCOMPARE(sizeHints->maxHeight, 0); QCOMPARE(sizeHints->widthInc, 0); QCOMPARE(sizeHints->heightInc, 0); QCOMPARE(sizeHints->minAspect[0], 0); QCOMPARE(sizeHints->minAspect[1], 0); QCOMPARE(sizeHints->maxAspect[0], 0); QCOMPARE(sizeHints->maxAspect[1], 0); QCOMPARE(sizeHints->baseWidth, 0); QCOMPARE(sizeHints->baseHeight, 0); QCOMPARE(sizeHints->winGravity, 0); } void TestXcbSizeHints::testSizeHintsNotSet() { GeometryHints hints; hints.init(m_testWindow); hints.read(); QVERIFY(!hints.m_sizeHints); QVERIFY(!hints.hasAspect()); QVERIFY(!hints.hasBaseSize()); QVERIFY(!hints.hasMaxSize()); QVERIFY(!hints.hasMinSize()); QVERIFY(!hints.hasPosition()); QVERIFY(!hints.hasResizeIncrements()); QVERIFY(!hints.hasSize()); QVERIFY(!hints.hasWindowGravity()); QCOMPARE(hints.baseSize(), QSize(0, 0)); QCOMPARE(hints.maxAspect(), QSize(INT_MAX, 1)); QCOMPARE(hints.maxSize(), QSize(INT_MAX, INT_MAX)); QCOMPARE(hints.minAspect(), QSize(1, INT_MAX)); QCOMPARE(hints.minSize(), QSize(0, 0)); QCOMPARE(hints.resizeIncrements(), QSize(1, 1)); QCOMPARE(hints.windowGravity(), XCB_GRAVITY_NORTH_WEST); } void TestXcbSizeHints::geometryHintsBeforeInit() { GeometryHints hints; QVERIFY(!hints.hasAspect()); QVERIFY(!hints.hasBaseSize()); QVERIFY(!hints.hasMaxSize()); QVERIFY(!hints.hasMinSize()); QVERIFY(!hints.hasPosition()); QVERIFY(!hints.hasResizeIncrements()); QVERIFY(!hints.hasSize()); QVERIFY(!hints.hasWindowGravity()); QCOMPARE(hints.baseSize(), QSize(0, 0)); QCOMPARE(hints.maxAspect(), QSize(INT_MAX, 1)); QCOMPARE(hints.maxSize(), QSize(INT_MAX, INT_MAX)); QCOMPARE(hints.minAspect(), QSize(1, INT_MAX)); QCOMPARE(hints.minSize(), QSize(0, 0)); QCOMPARE(hints.resizeIncrements(), QSize(1, 1)); QCOMPARE(hints.windowGravity(), XCB_GRAVITY_NORTH_WEST); } void TestXcbSizeHints::geometryHintsBeforeRead() { xcb_size_hints_t xcbHints; memset(&xcbHints, 0, sizeof(xcbHints)); xcb_icccm_size_hints_set_position(&xcbHints, 1, 1, 2); xcb_icccm_set_wm_normal_hints(QX11Info::connection(), m_testWindow, &xcbHints); xcb_flush(QX11Info::connection()); GeometryHints hints; hints.init(m_testWindow); QVERIFY(!hints.hasAspect()); QVERIFY(!hints.hasBaseSize()); QVERIFY(!hints.hasMaxSize()); QVERIFY(!hints.hasMinSize()); QVERIFY(!hints.hasPosition()); QVERIFY(!hints.hasResizeIncrements()); QVERIFY(!hints.hasSize()); QVERIFY(!hints.hasWindowGravity()); QCOMPARE(hints.baseSize(), QSize(0, 0)); QCOMPARE(hints.maxAspect(), QSize(INT_MAX, 1)); QCOMPARE(hints.maxSize(), QSize(INT_MAX, INT_MAX)); QCOMPARE(hints.minAspect(), QSize(1, INT_MAX)); QCOMPARE(hints.minSize(), QSize(0, 0)); QCOMPARE(hints.resizeIncrements(), QSize(1, 1)); QCOMPARE(hints.windowGravity(), XCB_GRAVITY_NORTH_WEST); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestXcbSizeHints) #include "test_xcb_size_hints.moc" diff --git a/autotests/test_xcb_window.cpp b/autotests/test_xcb_window.cpp index 8b1ec4a5b..339be675a 100644 --- a/autotests/test_xcb_window.cpp +++ b/autotests/test_xcb_window.cpp @@ -1,211 +1,212 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2013 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "testutils.h" // KWin #include "../xcbutils.h" // Qt #include #include // xcb #include using namespace KWin; class TestXcbWindow : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void defaultCtor(); void ctor(); void classCtor(); void create(); void mapUnmap(); void geometry(); void destroy(); void destroyNotManaged(); }; void TestXcbWindow::initTestCase() { qApp->setProperty("x11RootWindow", QVariant::fromValue(QX11Info::appRootWindow())); qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestXcbWindow::defaultCtor() { Xcb::Window window; QCOMPARE(window.isValid(), false); xcb_window_t wId = window; QCOMPARE(wId, noneWindow()); xcb_window_t nativeWindow = createWindow(); Xcb::Window window2(nativeWindow); QCOMPARE(window2.isValid(), true); wId = window2; QCOMPARE(wId, nativeWindow); } void TestXcbWindow::ctor() { const QRect geometry(0, 0, 10, 10); const uint32_t values[] = {true}; Xcb::Window window(geometry, XCB_CW_OVERRIDE_REDIRECT, values); QCOMPARE(window.isValid(), true); QVERIFY(window != XCB_WINDOW_NONE); Xcb::WindowGeometry windowGeometry(window); QCOMPARE(windowGeometry.isNull(), false); QCOMPARE(windowGeometry.rect(), geometry); } void TestXcbWindow::classCtor() { const QRect geometry(0, 0, 10, 10); const uint32_t values[] = {true}; Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values); QCOMPARE(window.isValid(), true); QVERIFY(window != XCB_WINDOW_NONE); Xcb::WindowGeometry windowGeometry(window); QCOMPARE(windowGeometry.isNull(), false); QCOMPARE(windowGeometry.rect(), geometry); Xcb::WindowAttributes attribs(window); QCOMPARE(attribs.isNull(), false); QVERIFY(attribs->_class == XCB_WINDOW_CLASS_INPUT_ONLY); } void TestXcbWindow::create() { Xcb::Window window; QCOMPARE(window.isValid(), false); xcb_window_t wId = window; QCOMPARE(wId, noneWindow()); const QRect geometry(0, 0, 10, 10); const uint32_t values[] = {true}; window.create(geometry, XCB_CW_OVERRIDE_REDIRECT, values); QCOMPARE(window.isValid(), true); QVERIFY(window != XCB_WINDOW_NONE); // and reset again window.reset(); QCOMPARE(window.isValid(), false); QVERIFY(window == XCB_WINDOW_NONE); } void TestXcbWindow::mapUnmap() { const QRect geometry(0, 0, 10, 10); const uint32_t values[] = {true}; Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values); Xcb::WindowAttributes attribs(window); QCOMPARE(attribs.isNull(), false); QVERIFY(attribs->map_state == XCB_MAP_STATE_UNMAPPED); window.map(); Xcb::WindowAttributes attribs2(window); QCOMPARE(attribs2.isNull(), false); QVERIFY(attribs2->map_state != XCB_MAP_STATE_UNMAPPED); window.unmap(); Xcb::WindowAttributes attribs3(window); QCOMPARE(attribs3.isNull(), false); QVERIFY(attribs3->map_state == XCB_MAP_STATE_UNMAPPED); // map, unmap shouldn't fail for an invalid window, it's just ignored window.reset(); window.map(); window.unmap(); } void TestXcbWindow::geometry() { const QRect geometry(0, 0, 10, 10); const uint32_t values[] = {true}; Xcb::Window window(geometry, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values); Xcb::WindowGeometry windowGeometry(window); QCOMPARE(windowGeometry.isNull(), false); QCOMPARE(windowGeometry.rect(), geometry); const QRect geometry2(10, 20, 100, 200); window.setGeometry(geometry2); Xcb::WindowGeometry windowGeometry2(window); QCOMPARE(windowGeometry2.isNull(), false); QCOMPARE(windowGeometry2.rect(), geometry2); // setting a geometry on an invalid window should be ignored window.reset(); window.setGeometry(geometry2); Xcb::WindowGeometry windowGeometry3(window); QCOMPARE(windowGeometry3.isNull(), true); } void TestXcbWindow::destroy() { const QRect geometry(0, 0, 10, 10); const uint32_t values[] = {true}; Xcb::Window window(geometry, XCB_CW_OVERRIDE_REDIRECT, values); QCOMPARE(window.isValid(), true); xcb_window_t wId = window; window.create(geometry, XCB_CW_OVERRIDE_REDIRECT, values); // wId should now be invalid xcb_generic_error_t *error = nullptr; ScopedCPointer attribs(xcb_get_window_attributes_reply( connection(), xcb_get_window_attributes(connection(), wId), &error)); QVERIFY(attribs.isNull()); QCOMPARE(error->error_code, uint8_t(3)); QCOMPARE(error->resource_id, wId); free(error); // test the same for the dtor { Xcb::Window scopedWindow(geometry, XCB_CW_OVERRIDE_REDIRECT, values); QVERIFY(scopedWindow.isValid()); wId = scopedWindow; } error = nullptr; ScopedCPointer attribs2(xcb_get_window_attributes_reply( connection(), xcb_get_window_attributes(connection(), wId), &error)); QVERIFY(attribs2.isNull()); QCOMPARE(error->error_code, uint8_t(3)); QCOMPARE(error->resource_id, wId); free(error); } void TestXcbWindow::destroyNotManaged() { Xcb::Window window; // just destroy the non-existing window window.reset(); // now let's add a window window.reset(createWindow(), false); xcb_window_t w = window; window.reset(); Xcb::WindowAttributes attribs(w); QVERIFY(attribs); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestXcbWindow) #include "test_xcb_window.moc" diff --git a/autotests/test_xcb_wrapper.cpp b/autotests/test_xcb_wrapper.cpp index 4c14cde43..a1e312c3f 100644 --- a/autotests/test_xcb_wrapper.cpp +++ b/autotests/test_xcb_wrapper.cpp @@ -1,529 +1,530 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2013 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #include "testutils.h" // KWin #include "../xcbutils.h" // Qt #include #include #include // xcb #include using namespace KWin; using namespace KWin::Xcb; class TestXcbWrapper : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase(); void init(); void cleanup(); void defaultCtor(); void normalCtor(); void copyCtorEmpty(); void copyCtorBeforeRetrieve(); void copyCtorAfterRetrieve(); void assignementEmpty(); void assignmentBeforeRetrieve(); void assignmentAfterRetrieve(); void discard(); void testQueryTree(); void testCurrentInput(); void testTransientFor(); void testPropertyByteArray(); void testPropertyBool(); void testAtom(); void testMotifEmpty(); void testMotif_data(); void testMotif(); private: void testEmpty(WindowGeometry &geometry); void testGeometry(WindowGeometry &geometry, const QRect &rect); Window m_testWindow; }; void TestXcbWrapper::initTestCase() { qApp->setProperty("x11RootWindow", QVariant::fromValue(QX11Info::appRootWindow())); qApp->setProperty("x11Connection", QVariant::fromValue(QX11Info::connection())); } void TestXcbWrapper::init() { const uint32_t values[] = { true }; m_testWindow.create(QRect(0, 0, 10, 10), XCB_WINDOW_CLASS_INPUT_ONLY, XCB_CW_OVERRIDE_REDIRECT, values); QVERIFY(m_testWindow.isValid()); } void TestXcbWrapper::cleanup() { m_testWindow.reset(); } void TestXcbWrapper::testEmpty(WindowGeometry &geometry) { QCOMPARE(geometry.window(), noneWindow()); QVERIFY(!geometry.data()); QCOMPARE(geometry.isNull(), true); QCOMPARE(geometry.rect(), QRect()); QVERIFY(!geometry); } void TestXcbWrapper::testGeometry(WindowGeometry &geometry, const QRect &rect) { QCOMPARE(geometry.window(), (xcb_window_t)m_testWindow); // now lets retrieve some data QCOMPARE(geometry.rect(), rect); QVERIFY(geometry.isRetrieved()); QCOMPARE(geometry.isNull(), false); QVERIFY(geometry); QVERIFY(geometry.data()); QCOMPARE(geometry.data()->x, int16_t(rect.x())); QCOMPARE(geometry.data()->y, int16_t(rect.y())); QCOMPARE(geometry.data()->width, uint16_t(rect.width())); QCOMPARE(geometry.data()->height, uint16_t(rect.height())); } void TestXcbWrapper::defaultCtor() { WindowGeometry geometry; testEmpty(geometry); QVERIFY(!geometry.isRetrieved()); } void TestXcbWrapper::normalCtor() { WindowGeometry geometry(m_testWindow); QVERIFY(!geometry.isRetrieved()); testGeometry(geometry, QRect(0, 0, 10, 10)); } void TestXcbWrapper::copyCtorEmpty() { WindowGeometry geometry; WindowGeometry other(geometry); testEmpty(geometry); QVERIFY(geometry.isRetrieved()); testEmpty(other); QVERIFY(!other.isRetrieved()); } void TestXcbWrapper::copyCtorBeforeRetrieve() { WindowGeometry geometry(m_testWindow); QVERIFY(!geometry.isRetrieved()); WindowGeometry other(geometry); testEmpty(geometry); QVERIFY(geometry.isRetrieved()); QVERIFY(!other.isRetrieved()); testGeometry(other, QRect(0, 0, 10, 10)); } void TestXcbWrapper::copyCtorAfterRetrieve() { WindowGeometry geometry(m_testWindow); QVERIFY(geometry); QVERIFY(geometry.isRetrieved()); QCOMPARE(geometry.rect(), QRect(0, 0, 10, 10)); WindowGeometry other(geometry); testEmpty(geometry); QVERIFY(geometry.isRetrieved()); QVERIFY(other.isRetrieved()); testGeometry(other, QRect(0, 0, 10, 10)); } void TestXcbWrapper::assignementEmpty() { WindowGeometry geometry; WindowGeometry other; testEmpty(geometry); testEmpty(other); other = geometry; QVERIFY(geometry.isRetrieved()); testEmpty(geometry); testEmpty(other); QVERIFY(!other.isRetrieved()); // test assignment to self geometry = geometry; other = other; testEmpty(geometry); testEmpty(other); } void TestXcbWrapper::assignmentBeforeRetrieve() { WindowGeometry geometry(m_testWindow); WindowGeometry other = geometry; QVERIFY(geometry.isRetrieved()); testEmpty(geometry); QVERIFY(!other.isRetrieved()); testGeometry(other, QRect(0, 0, 10, 10)); other = WindowGeometry(m_testWindow); QVERIFY(!other.isRetrieved()); QCOMPARE(other.window(), (xcb_window_t)m_testWindow); other = WindowGeometry(); testEmpty(geometry); // test assignment to self geometry = geometry; other = other; testEmpty(geometry); } void TestXcbWrapper::assignmentAfterRetrieve() { WindowGeometry geometry(m_testWindow); QVERIFY(geometry); QVERIFY(geometry.isRetrieved()); WindowGeometry other = geometry; testEmpty(geometry); QVERIFY(other.isRetrieved()); testGeometry(other, QRect(0, 0, 10, 10)); // test assignment to self geometry = geometry; other = other; testEmpty(geometry); testGeometry(other, QRect(0, 0, 10, 10)); // set to empty again other = WindowGeometry(); testEmpty(other); } void TestXcbWrapper::discard() { // discard of reply cannot be tested properly as we cannot check whether the reply has been discarded // therefore it's more or less just a test to ensure that it doesn't crash and the code paths // are taken. WindowGeometry *geometry = new WindowGeometry(); delete geometry; geometry = new WindowGeometry(m_testWindow); delete geometry; geometry = new WindowGeometry(m_testWindow); QVERIFY(geometry->data()); delete geometry; } void TestXcbWrapper::testQueryTree() { Tree tree(m_testWindow); // should have root as parent QCOMPARE(tree.parent(), static_cast(QX11Info::appRootWindow())); // shouldn't have any children QCOMPARE(tree->children_len, uint16_t(0)); QVERIFY(!tree.children()); // query for root Tree root(QX11Info::appRootWindow()); // shouldn't have a parent QCOMPARE(root.parent(), xcb_window_t(XCB_WINDOW_NONE)); QVERIFY(root->children_len > 0); xcb_window_t *children = root.children(); bool found = false; for (int i = 0; i < xcb_query_tree_children_length(root.data()); ++i) { if (children[i] == tree.window()) { found = true; break; } } QVERIFY(found); // query for not existing window Tree doesntExist(XCB_WINDOW_NONE); QCOMPARE(doesntExist.parent(), xcb_window_t(XCB_WINDOW_NONE)); QVERIFY(doesntExist.isNull()); QVERIFY(doesntExist.isRetrieved()); } void TestXcbWrapper::testCurrentInput() { xcb_connection_t *c = QX11Info::connection(); m_testWindow.map(); QX11Info::setAppTime(QX11Info::getTimestamp()); // let's set the input focus m_testWindow.focus(XCB_INPUT_FOCUS_PARENT, QX11Info::appTime()); xcb_flush(c); CurrentInput input; QCOMPARE(input.window(), (xcb_window_t)m_testWindow); // creating a copy should make the input object have no window any more CurrentInput input2(input); QCOMPARE(input2.window(), (xcb_window_t)m_testWindow); QCOMPARE(input.window(), xcb_window_t(XCB_WINDOW_NONE)); } void TestXcbWrapper::testTransientFor() { TransientFor transient(m_testWindow); QCOMPARE(transient.window(), (xcb_window_t)m_testWindow); // our m_testWindow doesn't have a transient for hint xcb_window_t compareWindow = XCB_WINDOW_NONE; QVERIFY(!transient.getTransientFor(&compareWindow)); QCOMPARE(compareWindow, xcb_window_t(XCB_WINDOW_NONE)); bool ok = true; QCOMPARE(transient.value(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, &ok), xcb_window_t(XCB_WINDOW_NONE)); QVERIFY(!ok); ok = true; QCOMPARE(transient.value(XCB_WINDOW_NONE, &ok), xcb_window_t(XCB_WINDOW_NONE)); QVERIFY(!ok); // Create a Window with a transient for hint Window transientWindow(createWindow()); xcb_window_t testWindowId = m_testWindow; transientWindow.changeProperty(XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, 1, &testWindowId); // let's get another transient object TransientFor realTransient(transientWindow); QVERIFY(realTransient.getTransientFor(&compareWindow)); QCOMPARE(compareWindow, (xcb_window_t)m_testWindow); ok = false; QCOMPARE(realTransient.value(32, XCB_ATOM_WINDOW, XCB_WINDOW_NONE, &ok), (xcb_window_t)m_testWindow); QVERIFY(ok); ok = false; QCOMPARE(realTransient.value(XCB_WINDOW_NONE, &ok), (xcb_window_t)m_testWindow); QVERIFY(ok); ok = false; QCOMPARE(realTransient.value(), (xcb_window_t)m_testWindow); QCOMPARE(realTransient.value(nullptr, &ok)[0], (xcb_window_t)m_testWindow); QVERIFY(ok); QCOMPARE(realTransient.value()[0], (xcb_window_t)m_testWindow); // test for a not existing window TransientFor doesntExist(XCB_WINDOW_NONE); QVERIFY(!doesntExist.getTransientFor(&compareWindow)); } void TestXcbWrapper::testPropertyByteArray() { Window testWindow(createWindow()); Property prop(false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 100000); QCOMPARE(prop.toByteArray(), QByteArray()); bool ok = true; QCOMPARE(prop.toByteArray(&ok), QByteArray()); QVERIFY(!ok); ok = true; QVERIFY(!prop.value()); QCOMPARE(prop.value("bar", &ok), "bar"); QVERIFY(!ok); QCOMPARE(QByteArray(StringProperty(testWindow, XCB_ATOM_WM_NAME)), QByteArray()); testWindow.changeProperty(XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 3, "foo"); prop = Property(false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 100000); QCOMPARE(prop.toByteArray(), QByteArrayLiteral("foo")); QCOMPARE(prop.toByteArray(&ok), QByteArrayLiteral("foo")); QVERIFY(ok); QCOMPARE(prop.value(nullptr, &ok), "foo"); QVERIFY(ok); QCOMPARE(QByteArray(StringProperty(testWindow, XCB_ATOM_WM_NAME)), QByteArrayLiteral("foo")); // verify incorrect format and type QCOMPARE(prop.toByteArray(32), QByteArray()); QCOMPARE(prop.toByteArray(8, XCB_ATOM_CARDINAL), QByteArray()); // verify empty property testWindow.changeProperty(XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, 0, nullptr); prop = Property(false, testWindow, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 100000); QCOMPARE(prop.toByteArray(), QByteArray()); QCOMPARE(prop.toByteArray(&ok), QByteArray()); //valid bytearray QVERIFY(ok); //The bytearray should be empty QVERIFY(prop.toByteArray().isEmpty()); //The bytearray should be not null QVERIFY(!prop.toByteArray().isNull()); QVERIFY(!prop.value()); QCOMPARE(QByteArray(StringProperty(testWindow, XCB_ATOM_WM_NAME)), QByteArray()); // verify non existing property Xcb::Atom invalid(QByteArrayLiteral("INVALID_ATOM")); prop = Property(false, testWindow, invalid, XCB_ATOM_STRING, 0, 100000); QCOMPARE(prop.toByteArray(), QByteArray()); QCOMPARE(prop.toByteArray(&ok), QByteArray()); //invalid bytearray QVERIFY(!ok); //The bytearray should be empty QVERIFY(prop.toByteArray().isEmpty()); //The bytearray should be not null QVERIFY(prop.toByteArray().isNull()); QVERIFY(!prop.value()); QCOMPARE(QByteArray(StringProperty(testWindow, XCB_ATOM_WM_NAME)), QByteArray()); } void TestXcbWrapper::testPropertyBool() { Window testWindow(createWindow()); Atom blockCompositing(QByteArrayLiteral("_KDE_NET_WM_BLOCK_COMPOSITING")); QVERIFY(blockCompositing != XCB_ATOM_NONE); NETWinInfo info(QX11Info::connection(), testWindow, QX11Info::appRootWindow(), NET::Properties(), NET::WM2BlockCompositing); Property prop(false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, 100000); bool ok = true; QVERIFY(!prop.toBool()); QVERIFY(!prop.toBool(&ok)); QVERIFY(!ok); info.setBlockingCompositing(true); xcb_flush(QX11Info::connection()); prop = Property(false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, 100000); QVERIFY(prop.toBool()); QVERIFY(prop.toBool(&ok)); QVERIFY(ok); // incorrect type and format QVERIFY(!prop.toBool(8)); QVERIFY(!prop.toBool(32, blockCompositing)); QVERIFY(!prop.toBool(32, blockCompositing, &ok)); QVERIFY(!ok); // incorrect value: uint32_t d[] = {1, 0}; testWindow.changeProperty(blockCompositing, XCB_ATOM_CARDINAL, 32, 2, d); prop = Property(false, testWindow, blockCompositing, XCB_ATOM_CARDINAL, 0, 100000); QVERIFY(!prop.toBool()); ok = true; QVERIFY(!prop.toBool(&ok)); QVERIFY(!ok); } void TestXcbWrapper::testAtom() { Atom atom(QByteArrayLiteral("WM_CLIENT_MACHINE")); QCOMPARE(atom.name(), QByteArrayLiteral("WM_CLIENT_MACHINE")); QVERIFY(atom == XCB_ATOM_WM_CLIENT_MACHINE); QVERIFY(atom.isValid()); // test the const paths const Atom &atom2(atom); QVERIFY(atom2.isValid()); QVERIFY(atom2 == XCB_ATOM_WM_CLIENT_MACHINE); QCOMPARE(atom2.name(), QByteArrayLiteral("WM_CLIENT_MACHINE")); //destroy before retrieved Atom atom3(QByteArrayLiteral("WM_CLIENT_MACHINE")); QCOMPARE(atom3.name(), QByteArrayLiteral("WM_CLIENT_MACHINE")); } void TestXcbWrapper::testMotifEmpty() { Atom atom(QByteArrayLiteral("_MOTIF_WM_HINTS")); MotifHints hints(atom); // pre init QCOMPARE(hints.hasDecoration(), false); QCOMPARE(hints.noBorder(), false); QCOMPARE(hints.resize(), true); QCOMPARE(hints.move(), true); QCOMPARE(hints.minimize(), true); QCOMPARE(hints.maximize(), true); QCOMPARE(hints.close(), true); // post init, pre read hints.init(m_testWindow); QCOMPARE(hints.hasDecoration(), false); QCOMPARE(hints.noBorder(), false); QCOMPARE(hints.resize(), true); QCOMPARE(hints.move(), true); QCOMPARE(hints.minimize(), true); QCOMPARE(hints.maximize(), true); QCOMPARE(hints.close(), true); // post read hints.read(); QCOMPARE(hints.hasDecoration(), false); QCOMPARE(hints.noBorder(), false); QCOMPARE(hints.resize(), true); QCOMPARE(hints.move(), true); QCOMPARE(hints.minimize(), true); QCOMPARE(hints.maximize(), true); QCOMPARE(hints.close(), true); } void TestXcbWrapper::testMotif_data() { QTest::addColumn("flags"); QTest::addColumn("funtions"); QTest::addColumn("decorations"); QTest::addColumn("expectedHasDecoration"); QTest::addColumn("expectedNoBorder"); QTest::addColumn("expectedResize"); QTest::addColumn("expectedMove"); QTest::addColumn("expectedMinimize"); QTest::addColumn("expectedMaximize"); QTest::addColumn("expectedClose"); QTest::newRow("none") << 0u << 0u << 0u << false << false << true << true << true << true << true; QTest::newRow("noborder") << 2u << 5u << 0u << true << true << true << true << true << true << true; QTest::newRow("border") << 2u << 5u << 1u << true << false << true << true << true << true << true; QTest::newRow("resize") << 1u << 2u << 1u << false << false << true << false << false << false << false; QTest::newRow("move") << 1u << 4u << 1u << false << false << false << true << false << false << false; QTest::newRow("minimize") << 1u << 8u << 1u << false << false << false << false << true << false << false; QTest::newRow("maximize") << 1u << 16u << 1u << false << false << false << false << false << true << false; QTest::newRow("close") << 1u << 32u << 1u << false << false << false << false << false << false << true; QTest::newRow("resize/all") << 1u << 3u << 1u << false << false << false << true << true << true << true; QTest::newRow("move/all") << 1u << 5u << 1u << false << false << true << false << true << true << true; QTest::newRow("minimize/all") << 1u << 9u << 1u << false << false << true << true << false << true << true; QTest::newRow("maximize/all") << 1u << 17u << 1u << false << false << true << true << true << false << true; QTest::newRow("close/all") << 1u << 33u << 1u << false << false << true << true << true << true << false; QTest::newRow("all") << 1u << 62u << 1u << false << false << true << true << true << true << true; QTest::newRow("all/all") << 1u << 63u << 1u << false << false << false << false << false << false << false; QTest::newRow("all/all/deco") << 3u << 63u << 1u << true << false << false << false << false << false << false; } void TestXcbWrapper::testMotif() { Atom atom(QByteArrayLiteral("_MOTIF_WM_HINTS")); QFETCH(quint32, flags); QFETCH(quint32, funtions); QFETCH(quint32, decorations); quint32 data[] = { flags, funtions, decorations, 0, 0 }; xcb_change_property(QX11Info::connection(), XCB_PROP_MODE_REPLACE, m_testWindow, atom, atom, 32, 5, data); xcb_flush(QX11Info::connection()); MotifHints hints(atom); hints.init(m_testWindow); hints.read(); QTEST(hints.hasDecoration(), "expectedHasDecoration"); QTEST(hints.noBorder(), "expectedNoBorder"); QTEST(hints.resize(), "expectedResize"); QTEST(hints.move(), "expectedMove"); QTEST(hints.minimize(), "expectedMinimize"); QTEST(hints.maximize(), "expectedMaximize"); QTEST(hints.close(), "expectedClose"); } +Q_CONSTRUCTOR_FUNCTION(forceXcb) QTEST_MAIN(TestXcbWrapper) #include "test_xcb_wrapper.moc" diff --git a/autotests/testutils.h b/autotests/testutils.h index 7fff8c49b..2b5e5450e 100644 --- a/autotests/testutils.h +++ b/autotests/testutils.h @@ -1,53 +1,59 @@ /******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2013 Martin Gräßlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ #ifndef TESTUTILS_H #define TESTUTILS_H // KWin #include // XCB #include +namespace { + static void forceXcb() { + qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("xcb")); + } +} + namespace KWin { /** * Wrapper to create an 0,0x10,10 input only window for testing purposes **/ static xcb_window_t createWindow() { xcb_window_t w = xcb_generate_id(connection()); const uint32_t values[] = { true }; xcb_create_window(connection(), 0, w, rootWindow(), 0, 0, 10, 10, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, XCB_CW_OVERRIDE_REDIRECT, values); return w; } /** * casts XCB_WINDOW_NONE to uint32_t. Needed to make QCOMPARE working. **/ static uint32_t noneWindow() { return XCB_WINDOW_NONE; } } // namespace #endif