File indexing completed on 2024-05-12 05:38:23

0001 /*
0002     SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include <QObject>
0008 
0009 #include <QDir>
0010 #include <QScreen>
0011 #include <QSignalSpy>
0012 #include <QStandardPaths>
0013 #include <QTemporaryDir>
0014 #include <QTest>
0015 #include <plasmaactivities/controller.h>
0016 #include <qtestcase.h>
0017 
0018 #include "../desktopview.h"
0019 #include "../panelview.h"
0020 #include "../screenpool.h"
0021 #include "../shellcorona.h"
0022 #include "mockcompositor.h"
0023 #include "xdgoutputv1.h"
0024 
0025 using namespace MockCompositor;
0026 
0027 class ShellTest : public QObject, DefaultCompositor
0028 {
0029     Q_OBJECT
0030 
0031     QScreen *insertScreen(const QRect &geometry, const QString &name);
0032     void setScreenOrder(const QStringList &order, bool expectOrderChanged);
0033 
0034 private Q_SLOTS:
0035     void initTestCase();
0036     void cleanupTestCase();
0037     void cleanup();
0038 
0039     void testScreenInsertion();
0040     void testPanelInsertion();
0041     void testSecondScreenInsertion();
0042     void testRedundantScreenInsertion();
0043     void testScreenRemovalRecyclingViews();
0044     void testMoveOutOfRedundant();
0045     void testScreenRemoval();
0046     void testReorderScreens_data();
0047     void testReorderScreens();
0048     void testReorderContainments();
0049 
0050 private:
0051     ShellCorona *m_corona;
0052 };
0053 
0054 QScreen *ShellTest::insertScreen(const QRect &geometry, const QString &name)
0055 {
0056     QScreen *result = nullptr;
0057 
0058     auto doTest = [=, this](QScreen *&res) {
0059         int oldAppNumScreens = qApp->screens().size();
0060         int oldCoronaNumScreens = m_corona->numScreens();
0061 
0062         // Fake screen?
0063         if (qApp->screens().size() == 1 && qApp->screens()[0]->name().isEmpty()) {
0064             QCOMPARE(m_corona->numScreens(), 0);
0065             oldAppNumScreens = 0;
0066         }
0067 
0068         // QSignalSpy coronaAddedSpy(m_corona, SIGNAL(screenAdded(int)));
0069         QSignalSpy appAddedSpy(qGuiApp, SIGNAL(screenAdded(QScreen *)));
0070         //  QSignalSpy orderChangeSpy(m_corona->m_screenPool, &ScreenPool::screenOrderChanged);
0071 
0072         // Add a new output
0073         exec([=, this] {
0074             OutputData data;
0075             data.mode.resolution = {geometry.width(), geometry.height()};
0076             data.position = {geometry.x(), geometry.y()};
0077             data.physicalSize = data.mode.physicalSizeForDpi(96);
0078             data.connector = name;
0079             // NOTE: assumes that when a screen is added it will already have the final geometry
0080             add<Output>(data);
0081         });
0082 
0083         //  coronaAddedSpy.wait();
0084         QTRY_COMPARE(appAddedSpy.size(), 1);
0085         //   QTRY_COMPARE(orderChangeSpy.size(), 1);
0086         QCOMPARE(m_corona->numScreens(), oldCoronaNumScreens); // Corona has *not* been notified yer as setScreenOrder has not been called
0087         QCOMPARE(m_corona->m_desktopViewForScreen.count(), oldCoronaNumScreens);
0088         QCOMPARE(qApp->screens().size(), oldAppNumScreens + 1);
0089         //     QCOMPARE(coronaAddedSpy.size(), 1);
0090         //     result.first = coronaAddedSpy.takeFirst().at(0).value<int>();
0091         res = appAddedSpy.takeFirst().at(0).value<QScreen *>();
0092         QCOMPARE(res->name(), name);
0093         QCOMPARE(res->geometry(), geometry);
0094         /*    auto *cont = m_corona->m_desktopViewForScreen[result.first]->containment();
0095             QCOMPARE(cont->screen(), result.first);
0096             QCOMPARE(m_corona->containmentForScreen(result.first, m_corona->m_activityController->currentActivity(), QString()), cont);*/
0097     };
0098     doTest(result);
0099     return result;
0100 }
0101 
0102 void ShellTest::setScreenOrder(const QStringList &order, bool expectOrderChanged)
0103 {
0104     QSignalSpy coronaScreenOrderSpy(m_corona, &ShellCorona::screenOrderChanged);
0105 
0106     exec([=, this] {
0107         outputOrder()->setList(order);
0108     });
0109 
0110     if (expectOrderChanged) {
0111         coronaScreenOrderSpy.wait();
0112         Q_ASSERT(coronaScreenOrderSpy.count() == 1);
0113         QCOMPARE(coronaScreenOrderSpy.count(), 1);
0114         auto order = coronaScreenOrderSpy.takeFirst().at(0).value<QList<QScreen *>>();
0115         QCOMPARE(m_corona->m_desktopViewForScreen.size(), order.size());
0116     } else {
0117         coronaScreenOrderSpy.wait(250);
0118         Q_ASSERT(coronaScreenOrderSpy.count() == 0);
0119         QCOMPARE(coronaScreenOrderSpy.count(), 0);
0120     }
0121 
0122     QCOMPARE(m_corona->m_desktopViewForScreen.size(), m_corona->m_screenPool->screenOrder().size());
0123 
0124     for (int i = 0; i < m_corona->m_screenPool->screenOrder().size(); ++i) {
0125         QVERIFY(m_corona->m_desktopViewForScreen.contains(i));
0126         QCOMPARE(m_corona->m_desktopViewForScreen[i]->containment()->screen(), i);
0127         QCOMPARE(m_corona->m_desktopViewForScreen[i]->screenToFollow(), m_corona->m_screenPool->screenOrder()[i]);
0128     }
0129 }
0130 
0131 void ShellTest::initTestCase()
0132 {
0133     QStandardPaths::setTestModeEnabled(true);
0134     qRegisterMetaType<QScreen *>();
0135 
0136     KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("ScreenConnectors"));
0137     cg.deleteGroup();
0138     cg.sync();
0139 
0140     qApp->setProperty("org.kde.KActivities.core.disableAutostart", true);
0141     m_corona = new ShellCorona();
0142     m_corona->setShell("org.kde.plasma.nano");
0143     m_corona->init();
0144 
0145     QTRY_COMPARE(QGuiApplication::screens().size(), 1);
0146     QCOMPARE(m_corona->screenPool()->screenOrder().size(), 1);
0147     QCOMPARE(QGuiApplication::screens().first()->name(), QStringLiteral("WL-1"));
0148     QCOMPARE(QGuiApplication::primaryScreen(), QGuiApplication::screens().first());
0149     QCOMPARE(QGuiApplication::primaryScreen(), m_corona->screenPool()->primaryScreen());
0150     QCOMPARE(m_corona->screenPool()->idForScreen(m_corona->screenPool()->primaryScreen()), 0);
0151     QCOMPARE(m_corona->screenPool()->screenForId(0)->name(), QStringLiteral("WL-1"));
0152 }
0153 
0154 void ShellTest::cleanupTestCase()
0155 {
0156     exec([this] {
0157         outputOrder()->setList({"WL-1"});
0158     });
0159     QCOMPOSITOR_COMPARE(getAll<Output>().size(), 1); // Only the default output should be left
0160     QTRY_COMPARE(QGuiApplication::screens().size(), 1);
0161     // m_corona->deleteLater();
0162     m_corona->unload();
0163     QCOMPARE(m_corona->m_desktopViewForScreen.count(), 0);
0164 
0165     QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage()));
0166 
0167     KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("ScreenConnectors"));
0168     cg.deleteGroup();
0169     cg.sync();
0170     delete m_corona;
0171 }
0172 
0173 void ShellTest::cleanup()
0174 {
0175     const int oldNumScreens = qApp->screens().size();
0176     const int oldCoronaNumScreens = m_corona->numScreens();
0177     QVERIFY(oldCoronaNumScreens <= oldNumScreens);
0178     QSignalSpy coronaRemovedSpy(m_corona, SIGNAL(screenRemoved(int)));
0179 
0180     exec([=, this] {
0181         for (int i = oldNumScreens - 1; i >= 0; --i) {
0182             remove(output(i));
0183         }
0184     });
0185     setScreenOrder({}, true);
0186 
0187     QTRY_COMPARE(coronaRemovedSpy.size(), oldCoronaNumScreens);
0188 
0189     // Cleanup all the containments that were created
0190     for (auto *c : m_corona->containments()) {
0191         if (c->containmentType() == Plasma::Containment::Panel || c->screen() != 0) {
0192             c->destroy();
0193         }
0194     }
0195     m_corona->m_waitingPanels.clear();
0196 
0197     QCOMPARE(m_corona->m_panelViews.size(), 0);
0198     QCOMPARE(m_corona->numScreens(), 0);
0199     QCOMPARE(qApp->screens().size(), 1);
0200     QCOMPARE(qApp->screens()[0]->name(), QString());
0201     insertScreen(QRect(0, 0, 1920, 1080), QStringLiteral("WL-1"));
0202     QCOMPARE(qApp->screens().size(), 1);
0203     QSignalSpy coronaScreenOrderSpy(m_corona, &ShellCorona::screenOrderChanged);
0204     setScreenOrder({"WL-1"}, true);
0205 }
0206 
0207 void ShellTest::testScreenInsertion()
0208 {
0209     const auto geom = QRect(1920, 0, 1920, 1080);
0210     const auto name = QStringLiteral("DP-1");
0211     auto result = insertScreen(geom, name);
0212     setScreenOrder({"WL-1", "DP-1"}, true);
0213     QCOMPARE(result->geometry(), geom);
0214     QCOMPARE(qApp->screens().size(), 2);
0215     QCOMPARE(qApp->screens()[0]->geometry(), m_corona->m_desktopViewForScreen[0]->geometry());
0216     QCOMPARE(qApp->screens()[1]->geometry(), m_corona->m_desktopViewForScreen[1]->geometry());
0217     QCOMPARE(qApp->screens()[1]->name(), name);
0218 }
0219 
0220 void ShellTest::testPanelInsertion()
0221 {
0222     QCOMPARE(m_corona->m_panelViews.size(), 0);
0223     auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.panel"));
0224     // If the panel fails to load (on ci plasma-desktop isn't here) we want the "failed" containment to be of panel type anyways
0225     QCOMPARE(m_corona->m_panelViews.size(), 1);
0226     QVERIFY(m_corona->m_panelViews.contains(panelCont));
0227     QCOMPARE(panelCont->screen(), 0);
0228     QCOMPARE(m_corona->m_panelViews[panelCont]->screen(), qApp->primaryScreen());
0229 }
0230 
0231 void ShellTest::testSecondScreenInsertion()
0232 {
0233     auto geom1 = QRect(1920, 0, 1920, 1080);
0234     auto name1 = QStringLiteral("DP-1");
0235     auto result1 = insertScreen(geom1, name1);
0236 
0237     auto geom2 = QRect(3840, 0, 1920, 1080);
0238     auto name2 = QStringLiteral("DP-2");
0239     auto result2 = insertScreen(geom2, name2);
0240 
0241     setScreenOrder({"WL-1", "DP-1", "DP-2"}, true);
0242 
0243     QCOMPARE(qApp->screens().size(), 3);
0244     QCOMPARE(result1->geometry(), geom1);
0245     QCOMPARE(result1->name(), name1);
0246 
0247     QCOMPARE(result2->geometry(), geom2);
0248     QCOMPARE(result2->name(), name2);
0249 }
0250 
0251 void ShellTest::testRedundantScreenInsertion()
0252 {
0253     QCOMPARE(m_corona->m_desktopViewForScreen.size(), 1);
0254     auto *view0 = m_corona->m_desktopViewForScreen[0];
0255     QCOMPARE(view0->screen()->name(), QStringLiteral("WL-1"));
0256 
0257     auto *cont0 = m_corona->m_desktopViewForScreen[0]->containment();
0258     QCOMPARE(cont0->screen(), 0);
0259     auto *oldScreen0 = view0->screen();
0260 
0261     const auto geom = QRect(0, 0, 1920, 1080);
0262     const auto name = QStringLiteral("DP-1");
0263     auto result = insertScreen(geom, name);
0264     // false as we do not expect to be notified for screenorderchanged
0265     setScreenOrder({"WL-1", "DP-1"}, false);
0266     QCOMPARE(result->geometry(), geom);
0267     QCOMPARE(qApp->screens().size(), 2);
0268     // m_desktopViewForScreen did *not* get a view for the new screen
0269     QCOMPARE(m_corona->m_desktopViewForScreen.size(), 1);
0270     // associations of old things didn't change
0271     QCOMPARE(view0->containment(), cont0);
0272     QCOMPARE(cont0->screen(), 0);
0273     QCOMPARE(view0->screen(), oldScreen0);
0274 }
0275 
0276 void ShellTest::testMoveOutOfRedundant()
0277 {
0278     testRedundantScreenInsertion();
0279 
0280     QSignalSpy coronaAddedSpy(m_corona, SIGNAL(screenAdded(int)));
0281 
0282     exec([this] {
0283         auto *out = output(1);
0284         auto *xdgOut = xdgOutput(out);
0285         out->m_data.mode.resolution = {1280, 2048};
0286         xdgOut->sendLogicalSize(QSize(1280, 2048));
0287         out->sendDone();
0288         outputOrder()->setList({"WL-1", "DP-1"});
0289     });
0290 
0291     coronaAddedSpy.wait();
0292     QCOMPARE(coronaAddedSpy.size(), 1);
0293     const int screen = coronaAddedSpy.takeFirst().at(0).value<int>();
0294     QCOMPARE(screen, 1);
0295 }
0296 
0297 void ShellTest::testScreenRemoval()
0298 {
0299     // Create 2 new screens
0300     testSecondScreenInsertion();
0301 
0302     Plasma::Containment *cont0 = m_corona->containmentForScreen(0, m_corona->m_activityController->currentActivity(), QString());
0303     QVERIFY(cont0);
0304     QCOMPARE(cont0->screen(), 0);
0305     Plasma::Containment *cont1 = m_corona->containmentForScreen(1, m_corona->m_activityController->currentActivity(), QString());
0306     QVERIFY(cont1);
0307     QCOMPARE(cont1->screen(), 1);
0308     Plasma::Containment *cont2 = m_corona->containmentForScreen(2, m_corona->m_activityController->currentActivity(), QString());
0309     QVERIFY(cont2);
0310     QCOMPARE(cont2->screen(), 2);
0311 
0312     QCOMPARE(m_corona->m_panelViews.size(), 0);
0313     auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.plasma.panel"));
0314     m_corona->m_panelViews[panelCont]->setScreenToFollow(m_corona->m_screenPool->screenForId(2));
0315     QCOMPARE(panelCont->screen(), 2);
0316     QCOMPARE(m_corona->m_panelViews[panelCont]->screen(), m_corona->m_screenPool->screenForId(2));
0317     QCOMPARE(m_corona->m_panelViews.size(), 1);
0318 
0319     QSignalSpy removedSpy(m_corona, SIGNAL(screenRemoved(int)));
0320 
0321     // Remove outputs
0322     exec([this] {
0323         remove(output(2));
0324         remove(output(1));
0325     });
0326 
0327     QTRY_COMPARE(removedSpy.size(), 2);
0328 
0329     setScreenOrder({"WL-1"}, true);
0330 
0331     QCOMPARE(m_corona->numScreens(), 1);
0332     QCOMPARE(qApp->screens().size(), 1);
0333 
0334     // the removed screens are what corona calls 1 and 2, 0 remains
0335     QCOMPARE(removedSpy.takeFirst().at(0).value<int>(), 2);
0336     QCOMPARE(removedSpy.takeFirst().at(0).value<int>(), 1);
0337     QCOMPARE(m_corona->m_desktopViewForScreen.count(), 1);
0338     // The only view remained is the one which was primary already
0339     QCOMPARE(cont0, m_corona->m_desktopViewForScreen[0]->containment());
0340     QCOMPARE(qApp->screens()[0]->geometry(), m_corona->m_desktopViewForScreen[0]->geometry());
0341 
0342     // Has the panelview been removed?
0343     QCOMPARE(m_corona->m_panelViews.size(), 0);
0344 
0345     bool cont1Found = false;
0346     bool cont2Found = false;
0347     // Search for the other two containments, should have screen() -1 and lastScreen 1 and 2
0348     for (auto *cont : m_corona->containments()) {
0349         if (cont == cont1) {
0350             cont1Found = true;
0351             QCOMPARE(cont->screen(), -1);
0352             QCOMPARE(cont->lastScreen(), 1);
0353         } else if (cont == cont2) {
0354             cont2Found = true;
0355             QCOMPARE(cont->screen(), -1);
0356             QCOMPARE(cont->lastScreen(), 2);
0357         }
0358     }
0359     QVERIFY(cont1Found);
0360     QVERIFY(cont2Found);
0361 }
0362 
0363 void ShellTest::testScreenRemovalRecyclingViews()
0364 {
0365     // Create 2 new screens
0366     testSecondScreenInsertion();
0367 
0368     Plasma::Containment *cont0 = m_corona->containmentForScreen(0, m_corona->m_activityController->currentActivity(), QString());
0369     QVERIFY(cont0);
0370     QCOMPARE(cont0->screen(), 0);
0371     Plasma::Containment *cont1 = m_corona->containmentForScreen(1, m_corona->m_activityController->currentActivity(), QString());
0372     QVERIFY(cont1);
0373     QCOMPARE(cont1->screen(), 1);
0374     Plasma::Containment *cont2 = m_corona->containmentForScreen(2, m_corona->m_activityController->currentActivity(), QString());
0375     QVERIFY(cont2);
0376     QCOMPARE(cont2->screen(), 2);
0377 
0378     auto *view0 = m_corona->m_desktopViewForScreen[0];
0379     auto screen0 = view0->screenToFollow();
0380     auto *view1 = m_corona->m_desktopViewForScreen[1];
0381     auto screen1 = view1->screenToFollow();
0382     auto *view2 = m_corona->m_desktopViewForScreen[2];
0383     auto screen2 = view2->screenToFollow();
0384 
0385     QSignalSpy view2DeletedSpy(view2, &DesktopView::destroyed);
0386     QSignalSpy screen1DeletedSpy(screen1, &DesktopView::destroyed);
0387 
0388     // Create a panel on screen 1
0389     QCOMPARE(m_corona->m_panelViews.size(), 0);
0390     auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.plasma.panel"));
0391     QCOMPARE(m_corona->m_panelViews.size(), 1);
0392     auto panelView = m_corona->m_panelViews[panelCont];
0393     panelView->setScreenToFollow(m_corona->m_screenPool->screenForId(1));
0394     QCOMPARE(panelCont->screen(), 1);
0395     QCOMPARE(panelView->screen(), m_corona->m_screenPool->screenForId(1));
0396     QCOMPARE(m_corona->m_panelViews.size(), 1);
0397 
0398     QSignalSpy removedSpy(m_corona, SIGNAL(screenRemoved(int)));
0399 
0400     // Remove output
0401     exec([this] {
0402         remove(output(1));
0403     });
0404 
0405     QTRY_COMPARE(removedSpy.size(), 1);
0406 
0407     setScreenOrder({"WL-1", "DP-2"}, true);
0408 
0409     QTRY_COMPARE(view2DeletedSpy.count(), 1);
0410     QTRY_COMPARE(screen1DeletedSpy.count(), 1);
0411 
0412     QCOMPARE(m_corona->numScreens(), 2);
0413     QCOMPARE(qApp->screens().size(), 2);
0414     // the removed screens are what corona calls 1 and 2, 0 remains
0415     QCOMPARE(removedSpy.takeFirst().at(0).value<int>(), 2);
0416     QCOMPARE(m_corona->m_desktopViewForScreen.count(), 2);
0417 
0418     // Views for cont0 and cont1 remained, cont1 reassigned screen
0419     QCOMPARE(cont0, m_corona->m_desktopViewForScreen[0]->containment());
0420     QCOMPARE(cont1, m_corona->m_desktopViewForScreen[1]->containment());
0421     QCOMPARE(view0, m_corona->m_desktopViewForScreen[0]);
0422     QCOMPARE(view1, m_corona->m_desktopViewForScreen[1]);
0423     QCOMPARE(view0->screenToFollow(), screen0);
0424     QCOMPARE(view1->screenToFollow(), screen2);
0425 
0426     // The panel remained, moved to screen2
0427     QCOMPARE(m_corona->m_panelViews.size(), 1);
0428     QCOMPARE(panelView->screenToFollow(), screen2);
0429 
0430     // Add DP-1 again, test that a view with cont2 inside is created
0431     insertScreen(QRect(1920, 0, 1920, 1080), QStringLiteral("DP-1"));
0432 
0433     setScreenOrder({"WL-1", "DP-2", "DP-1"}, true);
0434 
0435     auto *newView2 = m_corona->m_desktopViewForScreen[2];
0436     QCOMPARE(m_corona->m_desktopViewForScreen.size(), 3);
0437     QCOMPARE(newView2->containment(), cont2);
0438 }
0439 
0440 void ShellTest::testReorderScreens_data()
0441 {
0442     QTest::addColumn<QList<QRect>>("geometries");
0443     QTest::addColumn<QStringList>("orderBefore");
0444     QTest::addColumn<QStringList>("orderAfter");
0445 
0446     QTest::newRow("twoScreens") << QList<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}}) << QStringList({"WL-1", "DP-1"}) << QStringList({"DP-1", "WL-1"});
0447     QTest::newRow("3screensReorder0_1") << QList<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}, {3840, 0, 1920, 1080}})
0448                                         << QStringList({"WL-1", "DP-1", "DP-2"}) << QStringList({"DP-1", "WL-1", "DP-2"});
0449     QTest::newRow("3screensReorder2_3") << QList<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}, {3840, 0, 1920, 1080}})
0450                                         << QStringList({"WL-1", "DP-1", "DP-2"}) << QStringList({"DP-1", "WL-1", "DP-2"});
0451     QTest::newRow("3screensShuffled") << QList<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}, {3840, 0, 1920, 1080}})
0452                                       << QStringList({"WL-1", "DP-1", "DP-2"}) << QStringList({"DP-2", "DP-1", "WL-1"});
0453 }
0454 
0455 void ShellTest::testReorderScreens()
0456 {
0457     QFETCH(QList<QRect>, geometries);
0458     QFETCH(QStringList, orderBefore);
0459     QFETCH(QStringList, orderAfter);
0460 
0461     QVERIFY(orderBefore.size() > 0);
0462     QCOMPARE(orderBefore.size(), geometries.size());
0463     QCOMPARE(orderBefore.size(), orderAfter.size());
0464     // At the beginning of the test there is always a default one
0465     QCOMPARE(orderBefore.first(), QStringLiteral("WL-1"));
0466 
0467     QHash<int, int> remapIndexes;
0468 
0469     for (int i = 0; i < orderBefore.size(); ++i) {
0470         const QString conn = orderBefore[i];
0471         remapIndexes[i] = orderAfter.indexOf(conn);
0472         // Verify that we have same connectors in orderBefore and orderAfter
0473         QVERIFY(remapIndexes[i] >= 0);
0474         if (conn != QStringLiteral("WL-1")) {
0475             insertScreen(geometries[i], conn);
0476         }
0477     }
0478     setScreenOrder(orderBefore, true);
0479 
0480     QList<DesktopView *> desktopViews;
0481     QList<PanelView *> panelViews;
0482     QList<Plasma::Containment *> desktopContainments;
0483     QList<Plasma::Containment *> panelContainments;
0484     QList<QScreen *> screens;
0485 
0486     for (int i = 0; i < orderBefore.size(); ++i) {
0487         auto *view = m_corona->m_desktopViewForScreen[i];
0488         desktopViews.append(view);
0489         desktopContainments.append(view->containment());
0490         screens.append(view->screenToFollow());
0491 
0492         QCOMPARE(view->screen()->name(), orderBefore[i]);
0493         QCOMPARE(view->containment()->screen(), i);
0494     }
0495 
0496     // Add a panel for each screen
0497     for (int i = 0; i < screens.size(); ++i) {
0498         QScreen *s = screens[i];
0499         auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.plasma.panel"));
0500         // If the panel fails to load (on ci plasma-desktop isn't here) we want the "failed" containment to be of panel type anyways
0501         QVERIFY(m_corona->m_panelViews.contains(panelCont));
0502         QCOMPARE(panelCont->screen(), 0);
0503         m_corona->m_panelViews[panelCont]->setScreenToFollow(s);
0504         QCOMPARE(panelCont->screen(), i);
0505         panelViews.append(m_corona->m_panelViews[panelCont]);
0506         panelContainments.append(panelCont);
0507     }
0508 
0509     QSignalSpy coronaScreenOrderSpy(m_corona, &ShellCorona::screenOrderChanged);
0510     setScreenOrder(orderAfter, true);
0511 
0512     QTRY_COMPARE(coronaScreenOrderSpy.count(), 1);
0513     QList<QScreen *> qScreenOrderFormSignal = coronaScreenOrderSpy.takeFirst().at(0).value<QList<QScreen *>>();
0514 
0515     QCOMPARE(qScreenOrderFormSignal.size(), orderAfter.size());
0516     for (int i = 0; i < qScreenOrderFormSignal.size(); ++i) {
0517         QCOMPARE(qScreenOrderFormSignal[i]->name(), orderAfter[i]);
0518     }
0519 
0520     for (int i = 0; i < orderAfter.size(); ++i) {
0521         auto *view = m_corona->m_desktopViewForScreen[i];
0522         view->screenToFollow();
0523     }
0524 
0525     QList<DesktopView *> desktopViewsAfter;
0526     QList<PanelView *> panelViewsAfter;
0527     panelViewsAfter.resize(orderAfter.size());
0528     QList<Plasma::Containment *> desktopContainmentsAfter;
0529     QList<Plasma::Containment *> panelContainmentsAfter;
0530     panelContainmentsAfter.resize(orderAfter.size());
0531     QList<QScreen *> screensAfter;
0532 
0533     for (int i = 0; i < orderAfter.size(); ++i) {
0534         auto *view = m_corona->m_desktopViewForScreen[i];
0535         desktopViewsAfter.append(view);
0536         desktopContainmentsAfter.append(view->containment());
0537         screensAfter.append(view->screenToFollow());
0538 
0539         QCOMPARE(view->screenToFollow(), qScreenOrderFormSignal[i]);
0540         QCOMPARE(view->screen()->name(), orderAfter[i]);
0541         QCOMPARE(view->containment()->screen(), i);
0542     }
0543 
0544     {
0545         QSet<int> allScreenIds;
0546         for (int i = 0; i < orderAfter.size(); ++i) {
0547             allScreenIds.insert(i);
0548         }
0549         for (PanelView *v : m_corona->m_panelViews) {
0550             Plasma::Containment *cont = v->containment();
0551             QVERIFY(cont->screen() >= 0);
0552             QVERIFY(allScreenIds.contains(cont->screen()));
0553             panelViewsAfter[cont->screen()] = v;
0554             panelContainmentsAfter[cont->screen()] = cont;
0555             allScreenIds.remove(cont->screen());
0556         }
0557     }
0558 
0559     for (int i = 0; i < orderAfter.size(); ++i) {
0560         QCOMPARE(desktopViews[i], desktopViewsAfter[i]);
0561         QCOMPARE(panelViews[i], panelViewsAfter[i]);
0562         QCOMPARE(desktopContainments[i], desktopContainmentsAfter[i]);
0563         QCOMPARE(panelContainments[i], panelContainmentsAfter[i]);
0564         QCOMPARE(screens[i], screensAfter[remapIndexes[i]]);
0565 
0566         QCOMPARE(desktopViewsAfter[i]->screenToFollow(), screensAfter[i]);
0567         QCOMPARE(desktopViewsAfter[i]->screenToFollow(), screens[remapIndexes[i]]);
0568         QCOMPARE(panelViewsAfter[i]->screenToFollow(), screensAfter[i]);
0569         QCOMPARE(panelViewsAfter[i]->screenToFollow(), screens[remapIndexes[i]]);
0570     }
0571 }
0572 
0573 void ShellTest::testReorderContainments()
0574 {
0575     // this tests assigning different screens to containments without the actual order changing
0576     testSecondScreenInsertion();
0577     testPanelInsertion();
0578 
0579     QList<DesktopView *> desktopViews;
0580     QList<Plasma::Containment *> desktopContainments;
0581     QList<QScreen *> screens = m_corona->m_screenPool->screenOrder().toVector();
0582     QCOMPARE(screens.size(), 3);
0583 
0584     for (int i = 0; i < screens.size(); ++i) {
0585         auto *view = m_corona->m_desktopViewForScreen[i];
0586         desktopViews.append(view);
0587         desktopContainments.append(view->containment());
0588 
0589         QCOMPARE(view->screen(), screens[i]);
0590         QCOMPARE(view->containment()->screen(), i);
0591     }
0592     QCOMPARE(desktopViews.size(), 3);
0593     /*Disable the test on panels for now, as the fake containment we create here would be og NoContainment type
0594     QCOMPARE(m_corona->m_panelViews.size(), 1);
0595     auto *panelView = m_corona->m_panelViews.values().first();
0596     auto panelContainment = panelView->containment();
0597     QCOMPARE(panelView->screen(), screens[0]);
0598     QCOMPARE(panelContainment->screen(), 0);
0599 
0600     // Move panel to screen 1
0601     m_corona->setScreenForContainment(panelContainment, 1);
0602     QCOMPARE(panelView->screen(), screens[1]);
0603     QCOMPARE(panelContainment->screen(), 1);
0604     */
0605 
0606     // Move containment at screen 0 to 1
0607     QCOMPARE(desktopContainments[0]->screen(), 0);
0608     QCOMPARE(desktopContainments[1]->screen(), 1);
0609     m_corona->setScreenForContainment(desktopContainments[0], 1);
0610 
0611     QCOMPARE(desktopContainments[0]->screen(), 1);
0612     QCOMPARE(desktopContainments[1]->screen(), 0);
0613     QCOMPARE(desktopViews[0]->screenToFollow(), screens[1]);
0614     QCOMPARE(desktopViews[1]->screenToFollow(), screens[0]);
0615 }
0616 
0617 QCOMPOSITOR_TEST_MAIN(ShellTest)
0618 
0619 #include "shelltest.moc"