File indexing completed on 2024-05-12 17:10:21
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 <kactivities/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 = [=](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([=] { 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 0087 QCOMPARE(m_corona->numScreens(), oldCoronaNumScreens); // Corona has *not* been notified yer as setScreenOrder has not been called 0088 QCOMPARE(m_corona->m_desktopViewForScreen.count(), oldCoronaNumScreens); 0089 QCOMPARE(qApp->screens().size(), oldAppNumScreens + 1); 0090 // QCOMPARE(coronaAddedSpy.size(), 1); 0091 // result.first = coronaAddedSpy.takeFirst().at(0).value<int>(); 0092 res = appAddedSpy.takeFirst().at(0).value<QScreen *>(); 0093 QCOMPARE(res->name(), name); 0094 QCOMPARE(res->geometry(), geometry); 0095 /* auto *cont = m_corona->m_desktopViewForScreen[result.first]->containment(); 0096 QCOMPARE(cont->screen(), result.first); 0097 QCOMPARE(m_corona->containmentForScreen(result.first, m_corona->m_activityController->currentActivity(), QString()), cont);*/ 0098 }; 0099 doTest(result); 0100 return result; 0101 } 0102 0103 void ShellTest::setScreenOrder(const QStringList &order, bool expectOrderChanged) 0104 { 0105 QSignalSpy coronaScreenOrderSpy(m_corona, &ShellCorona::screenOrderChanged); 0106 0107 exec([=] { 0108 outputOrder()->setList(order); 0109 }); 0110 0111 if (expectOrderChanged) { 0112 coronaScreenOrderSpy.wait(); 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 QCOMPARE(coronaScreenOrderSpy.count(), 0); 0119 } 0120 0121 QCOMPARE(m_corona->m_desktopViewForScreen.size(), m_corona->m_screenPool->screenOrder().size()); 0122 0123 for (int i = 0; i < m_corona->m_screenPool->screenOrder().size(); ++i) { 0124 QVERIFY(m_corona->m_desktopViewForScreen.contains(i)); 0125 QCOMPARE(m_corona->m_desktopViewForScreen[i]->containment()->screen(), i); 0126 QCOMPARE(m_corona->m_desktopViewForScreen[i]->screenToFollow(), m_corona->m_screenPool->screenOrder()[i]); 0127 } 0128 } 0129 0130 void ShellTest::initTestCase() 0131 { 0132 QStandardPaths::setTestModeEnabled(true); 0133 qRegisterMetaType<QScreen *>(); 0134 0135 KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("ScreenConnectors")); 0136 cg.deleteGroup(); 0137 cg.sync(); 0138 0139 qApp->setProperty("org.kde.KActivities.core.disableAutostart", true); 0140 m_corona = new ShellCorona(); 0141 m_corona->setShell("org.kde.plasma.desktop"); 0142 m_corona->init(); 0143 0144 QTRY_COMPARE(QGuiApplication::screens().size(), 1); 0145 QCOMPARE(m_corona->screenPool()->screenOrder().size(), 1); 0146 QCOMPARE(QGuiApplication::screens().first()->name(), QStringLiteral("WL-1")); 0147 QCOMPARE(QGuiApplication::primaryScreen(), QGuiApplication::screens().first()); 0148 QCOMPARE(QGuiApplication::primaryScreen(), m_corona->screenPool()->primaryScreen()); 0149 QCOMPARE(m_corona->screenPool()->idForScreen(m_corona->screenPool()->primaryScreen()), 0); 0150 QCOMPARE(m_corona->screenPool()->screenForId(0)->name(), QStringLiteral("WL-1")); 0151 } 0152 0153 void ShellTest::cleanupTestCase() 0154 { 0155 exec([=] { 0156 outputOrder()->setList({"WL-1"}); 0157 }); 0158 QCOMPOSITOR_COMPARE(getAll<Output>().size(), 1); // Only the default output should be left 0159 QTRY_COMPARE(QGuiApplication::screens().size(), 1); 0160 // m_corona->deleteLater(); 0161 m_corona->unload(); 0162 QCOMPARE(m_corona->m_desktopViewForScreen.count(), 0); 0163 0164 QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); 0165 0166 KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("ScreenConnectors")); 0167 cg.deleteGroup(); 0168 cg.sync(); 0169 delete m_corona; 0170 } 0171 0172 void ShellTest::cleanup() 0173 { 0174 const int oldNumScreens = qApp->screens().size(); 0175 const int oldCoronaNumScreens = m_corona->numScreens(); 0176 QVERIFY(oldCoronaNumScreens <= oldNumScreens); 0177 QSignalSpy coronaRemovedSpy(m_corona, SIGNAL(screenRemoved(int))); 0178 0179 exec([=] { 0180 for (int i = oldNumScreens - 1; i >= 0; --i) { 0181 remove(output(i)); 0182 } 0183 }); 0184 setScreenOrder({""}, true); 0185 0186 QTRY_COMPARE(coronaRemovedSpy.size(), oldCoronaNumScreens); 0187 0188 // Cleanup all the containments that were created 0189 for (auto *c : m_corona->containments()) { 0190 if (c->containmentType() == Plasma::Types::PanelContainment || c->screen() != 0) { 0191 c->destroy(); 0192 } 0193 } 0194 m_corona->m_waitingPanels.clear(); 0195 0196 QCOMPARE(m_corona->m_panelViews.size(), 0); 0197 QCOMPARE(m_corona->numScreens(), 0); 0198 QCOMPARE(qApp->screens().size(), 1); 0199 QCOMPARE(qApp->screens()[0]->name(), QString()); 0200 insertScreen(QRect(0, 0, 1920, 1080), QStringLiteral("WL-1")); 0201 QCOMPARE(qApp->screens().size(), 1); 0202 QSignalSpy coronaScreenOrderSpy(m_corona, &ShellCorona::screenOrderChanged); 0203 setScreenOrder({"WL-1"}, true); 0204 } 0205 0206 void ShellTest::testScreenInsertion() 0207 { 0208 const auto geom = QRect(1920, 0, 1920, 1080); 0209 const auto name = QStringLiteral("DP-1"); 0210 auto result = insertScreen(geom, name); 0211 setScreenOrder({"WL-1", "DP-1"}, true); 0212 QCOMPARE(result->geometry(), geom); 0213 QCOMPARE(qApp->screens().size(), 2); 0214 QCOMPARE(qApp->screens()[0]->geometry(), m_corona->m_desktopViewForScreen[0]->geometry()); 0215 QCOMPARE(qApp->screens()[1]->geometry(), m_corona->m_desktopViewForScreen[1]->geometry()); 0216 QCOMPARE(qApp->screens()[1]->name(), name); 0217 } 0218 0219 void ShellTest::testPanelInsertion() 0220 { 0221 QCOMPARE(m_corona->m_panelViews.size(), 0); 0222 auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.plasma.panel")); 0223 // If the panel fails to load (on ci plasma-desktop isn't here) we want the "failed" containment to be of panel type anyways 0224 panelCont->setContainmentType(Plasma::Types::PanelContainment); 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([=] { 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 QCOMPARE(cont0->screen(), 0); 0304 Plasma::Containment *cont1 = m_corona->containmentForScreen(1, m_corona->m_activityController->currentActivity(), QString()); 0305 QCOMPARE(cont1->screen(), 1); 0306 Plasma::Containment *cont2 = m_corona->containmentForScreen(2, m_corona->m_activityController->currentActivity(), QString()); 0307 QCOMPARE(cont2->screen(), 2); 0308 0309 QCOMPARE(m_corona->m_panelViews.size(), 0); 0310 auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.plasma.panel")); 0311 panelCont->setContainmentType(Plasma::Types::PanelContainment); 0312 m_corona->m_panelViews[panelCont]->setScreenToFollow(m_corona->m_screenPool->screenForId(2)); 0313 QCOMPARE(panelCont->screen(), 2); 0314 QCOMPARE(m_corona->m_panelViews[panelCont]->screen(), m_corona->m_screenPool->screenForId(2)); 0315 QCOMPARE(m_corona->m_panelViews.size(), 1); 0316 0317 QSignalSpy removedSpy(m_corona, SIGNAL(screenRemoved(int))); 0318 0319 // Remove outputs 0320 exec([=] { 0321 remove(output(2)); 0322 remove(output(1)); 0323 }); 0324 0325 QTRY_COMPARE(removedSpy.size(), 2); 0326 0327 setScreenOrder({"WL-1"}, true); 0328 0329 QCOMPARE(m_corona->numScreens(), 1); 0330 QCOMPARE(qApp->screens().size(), 1); 0331 0332 // the removed screens are what corona calls 1 and 2, 0 remains 0333 QCOMPARE(removedSpy.takeFirst().at(0).value<int>(), 2); 0334 QCOMPARE(removedSpy.takeFirst().at(0).value<int>(), 1); 0335 QCOMPARE(m_corona->m_desktopViewForScreen.count(), 1); 0336 // The only view remained is the one which was primary already 0337 QCOMPARE(cont0, m_corona->m_desktopViewForScreen[0]->containment()); 0338 QCOMPARE(qApp->screens()[0]->geometry(), m_corona->m_desktopViewForScreen[0]->geometry()); 0339 0340 // Has the panelview been removed? 0341 QCOMPARE(m_corona->m_panelViews.size(), 0); 0342 0343 bool cont1Found = false; 0344 bool cont2Found = false; 0345 // Search for the other two containments, should have screen() -1 and lastScreen 1 and 2 0346 for (auto *cont : m_corona->containments()) { 0347 if (cont == cont1) { 0348 cont1Found = true; 0349 QCOMPARE(cont->screen(), -1); 0350 QCOMPARE(cont->lastScreen(), 1); 0351 } else if (cont == cont2) { 0352 cont2Found = true; 0353 QCOMPARE(cont->screen(), -1); 0354 QCOMPARE(cont->lastScreen(), 2); 0355 } 0356 } 0357 QVERIFY(cont1Found); 0358 QVERIFY(cont2Found); 0359 } 0360 0361 void ShellTest::testScreenRemovalRecyclingViews() 0362 { 0363 // Create 2 new screens 0364 testSecondScreenInsertion(); 0365 0366 Plasma::Containment *cont0 = m_corona->containmentForScreen(0, m_corona->m_activityController->currentActivity(), QString()); 0367 QCOMPARE(cont0->screen(), 0); 0368 Plasma::Containment *cont1 = m_corona->containmentForScreen(1, m_corona->m_activityController->currentActivity(), QString()); 0369 QCOMPARE(cont1->screen(), 1); 0370 Plasma::Containment *cont2 = m_corona->containmentForScreen(2, m_corona->m_activityController->currentActivity(), QString()); 0371 QCOMPARE(cont2->screen(), 2); 0372 0373 auto *view0 = m_corona->m_desktopViewForScreen[0]; 0374 auto screen0 = view0->screenToFollow(); 0375 auto *view1 = m_corona->m_desktopViewForScreen[1]; 0376 auto screen1 = view1->screenToFollow(); 0377 auto *view2 = m_corona->m_desktopViewForScreen[2]; 0378 auto screen2 = view2->screenToFollow(); 0379 0380 QSignalSpy view2DeletedSpy(view2, &DesktopView::destroyed); 0381 QSignalSpy screen1DeletedSpy(screen1, &DesktopView::destroyed); 0382 0383 // Create a panel on screen 1 0384 QCOMPARE(m_corona->m_panelViews.size(), 0); 0385 auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.plasma.panel")); 0386 panelCont->setContainmentType(Plasma::Types::PanelContainment); 0387 QCOMPARE(m_corona->m_panelViews.size(), 1); 0388 auto panelView = m_corona->m_panelViews[panelCont]; 0389 panelView->setScreenToFollow(m_corona->m_screenPool->screenForId(1)); 0390 QCOMPARE(panelCont->screen(), 1); 0391 QCOMPARE(panelView->screen(), m_corona->m_screenPool->screenForId(1)); 0392 QCOMPARE(m_corona->m_panelViews.size(), 1); 0393 0394 QSignalSpy removedSpy(m_corona, SIGNAL(screenRemoved(int))); 0395 0396 // Remove output 0397 exec([=] { 0398 remove(output(1)); 0399 }); 0400 0401 QTRY_COMPARE(removedSpy.size(), 1); 0402 0403 setScreenOrder({"WL-1", "DP-2"}, true); 0404 0405 QTRY_COMPARE(view2DeletedSpy.count(), 1); 0406 QTRY_COMPARE(screen1DeletedSpy.count(), 1); 0407 0408 QCOMPARE(m_corona->numScreens(), 2); 0409 QCOMPARE(qApp->screens().size(), 2); 0410 // the removed screens are what corona calls 1 and 2, 0 remains 0411 QCOMPARE(removedSpy.takeFirst().at(0).value<int>(), 2); 0412 QCOMPARE(m_corona->m_desktopViewForScreen.count(), 2); 0413 0414 // Views for cont0 and cont1 remained, cont1 reassigned screen 0415 QCOMPARE(cont0, m_corona->m_desktopViewForScreen[0]->containment()); 0416 QCOMPARE(cont1, m_corona->m_desktopViewForScreen[1]->containment()); 0417 QCOMPARE(view0, m_corona->m_desktopViewForScreen[0]); 0418 QCOMPARE(view1, m_corona->m_desktopViewForScreen[1]); 0419 QCOMPARE(view0->screenToFollow(), screen0); 0420 QCOMPARE(view1->screenToFollow(), screen2); 0421 0422 // The panel remained, moved to screen2 0423 QCOMPARE(m_corona->m_panelViews.size(), 1); 0424 QCOMPARE(panelView->screenToFollow(), screen2); 0425 0426 // Add DP-1 again, test that a view with cont2 inside is created 0427 insertScreen(QRect(1920, 0, 1920, 1080), QStringLiteral("DP-1")); 0428 0429 setScreenOrder({"WL-1", "DP-2", "DP-1"}, true); 0430 0431 auto *newView2 = m_corona->m_desktopViewForScreen[2]; 0432 QCOMPARE(m_corona->m_desktopViewForScreen.size(), 3); 0433 QCOMPARE(newView2->containment(), cont2); 0434 } 0435 0436 void ShellTest::testReorderScreens_data() 0437 { 0438 QTest::addColumn<QVector<QRect>>("geometries"); 0439 QTest::addColumn<QStringList>("orderBefore"); 0440 QTest::addColumn<QStringList>("orderAfter"); 0441 0442 QTest::newRow("twoScreens") << QVector<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}}) << QStringList({"WL-1", "DP-1"}) 0443 << QStringList({"DP-1", "WL-1"}); 0444 QTest::newRow("3screensReorder0_1") << QVector<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}, {3840, 0, 1920, 1080}}) 0445 << QStringList({"WL-1", "DP-1", "DP-2"}) << QStringList({"DP-1", "WL-1", "DP-2"}); 0446 QTest::newRow("3screensReorder2_3") << QVector<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}, {3840, 0, 1920, 1080}}) 0447 << QStringList({"WL-1", "DP-1", "DP-2"}) << QStringList({"DP-1", "WL-1", "DP-2"}); 0448 QTest::newRow("3screensShuffled") << QVector<QRect>({{0, 0, 1920, 1080}, {1920, 0, 1920, 1080}, {3840, 0, 1920, 1080}}) 0449 << QStringList({"WL-1", "DP-1", "DP-2"}) << QStringList({"DP-2", "DP-1", "WL-1"}); 0450 } 0451 0452 void ShellTest::testReorderScreens() 0453 { 0454 QFETCH(QVector<QRect>, geometries); 0455 QFETCH(QStringList, orderBefore); 0456 QFETCH(QStringList, orderAfter); 0457 0458 QVERIFY(orderBefore.size() > 0); 0459 QCOMPARE(orderBefore.size(), geometries.size()); 0460 QCOMPARE(orderBefore.size(), orderAfter.size()); 0461 // At the beginning of the test there is always a default one 0462 QCOMPARE(orderBefore.first(), QStringLiteral("WL-1")); 0463 0464 QHash<int, int> remapIndexes; 0465 0466 for (int i = 0; i < orderBefore.size(); ++i) { 0467 const QString conn = orderBefore[i]; 0468 remapIndexes[i] = orderAfter.indexOf(conn); 0469 // Verify that we have same connectors in orderBefore and orderAfter 0470 QVERIFY(remapIndexes[i] >= 0); 0471 if (conn != QStringLiteral("WL-1")) { 0472 insertScreen(geometries[i], conn); 0473 } 0474 } 0475 setScreenOrder(orderBefore, true); 0476 0477 QVector<DesktopView *> desktopViews; 0478 QVector<PanelView *> panelViews; 0479 QVector<Plasma::Containment *> desktopContainments; 0480 QVector<Plasma::Containment *> panelContainments; 0481 QVector<QScreen *> screens; 0482 0483 for (int i = 0; i < orderBefore.size(); ++i) { 0484 auto *view = m_corona->m_desktopViewForScreen[i]; 0485 desktopViews.append(view); 0486 desktopContainments.append(view->containment()); 0487 screens.append(view->screenToFollow()); 0488 0489 QCOMPARE(view->screen()->name(), orderBefore[i]); 0490 QCOMPARE(view->containment()->screen(), i); 0491 } 0492 0493 // Add a panel for each screen 0494 for (int i = 0; i < screens.size(); ++i) { 0495 QScreen *s = screens[i]; 0496 auto panelCont = m_corona->addPanel(QStringLiteral("org.kde.plasma.panel")); 0497 // If the panel fails to load (on ci plasma-desktop isn't here) we want the "failed" containment to be of panel type anyways 0498 panelCont->setContainmentType(Plasma::Types::PanelContainment); 0499 QVERIFY(m_corona->m_panelViews.contains(panelCont)); 0500 QCOMPARE(panelCont->screen(), 0); 0501 m_corona->m_panelViews[panelCont]->setScreenToFollow(s); 0502 QCOMPARE(panelCont->screen(), i); 0503 panelViews.append(m_corona->m_panelViews[panelCont]); 0504 panelContainments.append(panelCont); 0505 } 0506 0507 QSignalSpy coronaScreenOrderSpy(m_corona, &ShellCorona::screenOrderChanged); 0508 setScreenOrder(orderAfter, true); 0509 0510 QTRY_COMPARE(coronaScreenOrderSpy.count(), 1); 0511 QList<QScreen *> qScreenOrderFormSignal = coronaScreenOrderSpy.takeFirst().at(0).value<QList<QScreen *>>(); 0512 0513 QCOMPARE(qScreenOrderFormSignal.size(), orderAfter.size()); 0514 for (int i = 0; i < qScreenOrderFormSignal.size(); ++i) { 0515 QCOMPARE(qScreenOrderFormSignal[i]->name(), orderAfter[i]); 0516 } 0517 0518 for (int i = 0; i < orderAfter.size(); ++i) { 0519 auto *view = m_corona->m_desktopViewForScreen[i]; 0520 view->screenToFollow(); 0521 } 0522 0523 QVector<DesktopView *> desktopViewsAfter; 0524 QVector<PanelView *> panelViewsAfter; 0525 panelViewsAfter.resize(orderAfter.size()); 0526 QVector<Plasma::Containment *> desktopContainmentsAfter; 0527 QVector<Plasma::Containment *> panelContainmentsAfter; 0528 panelContainmentsAfter.resize(orderAfter.size()); 0529 QVector<QScreen *> screensAfter; 0530 0531 for (int i = 0; i < orderAfter.size(); ++i) { 0532 auto *view = m_corona->m_desktopViewForScreen[i]; 0533 desktopViewsAfter.append(view); 0534 desktopContainmentsAfter.append(view->containment()); 0535 screensAfter.append(view->screenToFollow()); 0536 0537 QCOMPARE(view->screenToFollow(), qScreenOrderFormSignal[i]); 0538 QCOMPARE(view->screen()->name(), orderAfter[i]); 0539 QCOMPARE(view->containment()->screen(), i); 0540 } 0541 0542 { 0543 QSet<int> allScreenIds; 0544 for (int i = 0; i < orderAfter.size(); ++i) { 0545 allScreenIds.insert(i); 0546 } 0547 for (PanelView *v : m_corona->m_panelViews) { 0548 Plasma::Containment *cont = v->containment(); 0549 QVERIFY(cont->screen() >= 0); 0550 QVERIFY(allScreenIds.contains(cont->screen())); 0551 panelViewsAfter[cont->screen()] = v; 0552 panelContainmentsAfter[cont->screen()] = cont; 0553 allScreenIds.remove(cont->screen()); 0554 } 0555 } 0556 0557 for (int i = 0; i < orderAfter.size(); ++i) { 0558 QCOMPARE(desktopViews[i], desktopViewsAfter[i]); 0559 QCOMPARE(panelViews[i], panelViewsAfter[i]); 0560 QCOMPARE(desktopContainments[i], desktopContainmentsAfter[i]); 0561 QCOMPARE(panelContainments[i], panelContainmentsAfter[i]); 0562 QCOMPARE(screens[i], screensAfter[remapIndexes[i]]); 0563 0564 QCOMPARE(desktopViewsAfter[i]->screenToFollow(), screensAfter[i]); 0565 QCOMPARE(desktopViewsAfter[i]->screenToFollow(), screens[remapIndexes[i]]); 0566 QCOMPARE(panelViewsAfter[i]->screenToFollow(), screensAfter[i]); 0567 QCOMPARE(panelViewsAfter[i]->screenToFollow(), screens[remapIndexes[i]]); 0568 } 0569 } 0570 0571 void ShellTest::testReorderContainments() 0572 { 0573 // this tests assigning different screens to containments without the actual order changing 0574 testSecondScreenInsertion(); 0575 testPanelInsertion(); 0576 0577 QVector<DesktopView *> desktopViews; 0578 QVector<Plasma::Containment *> desktopContainments; 0579 QVector<QScreen *> screens = m_corona->m_screenPool->screenOrder().toVector(); 0580 QCOMPARE(screens.size(), 3); 0581 0582 for (int i = 0; i < screens.size(); ++i) { 0583 auto *view = m_corona->m_desktopViewForScreen[i]; 0584 desktopViews.append(view); 0585 desktopContainments.append(view->containment()); 0586 0587 QCOMPARE(view->screen(), screens[i]); 0588 QCOMPARE(view->containment()->screen(), i); 0589 } 0590 QCOMPARE(desktopViews.size(), 3); 0591 QCOMPARE(m_corona->m_panelViews.size(), 1); 0592 auto *panelView = m_corona->m_panelViews.values().first(); 0593 auto panelContainment = panelView->containment(); 0594 QCOMPARE(panelView->screen(), screens[0]); 0595 QCOMPARE(panelContainment->screen(), 0); 0596 0597 // Move panel to screen 1 0598 m_corona->setScreenForContainment(panelContainment, 1); 0599 QCOMPARE(panelView->screen(), screens[1]); 0600 QCOMPARE(panelContainment->screen(), 1); 0601 0602 // Move containment at screen 0 to 1 0603 QCOMPARE(desktopContainments[0]->screen(), 0); 0604 QCOMPARE(desktopContainments[1]->screen(), 1); 0605 m_corona->setScreenForContainment(desktopContainments[0], 1); 0606 0607 QCOMPARE(desktopContainments[0]->screen(), 1); 0608 QCOMPARE(desktopContainments[1]->screen(), 0); 0609 QCOMPARE(desktopViews[0]->screenToFollow(), screens[1]); 0610 QCOMPARE(desktopViews[1]->screenToFollow(), screens[0]); 0611 } 0612 0613 QCOMPOSITOR_TEST_MAIN(ShellTest) 0614 0615 #include "shelltest.moc"