File indexing completed on 2024-11-10 04:56:03
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2019 David Edmundson <davidedmundson@kde.org> 0006 SPDX-FileCopyrightText: 2019 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0007 SPDX-FileCopyrightText: 2023 Natalie Clarius <natalie_clarius@yahoo.de> 0008 0009 SPDX-License-Identifier: GPL-2.0-or-later 0010 */ 0011 #include "kwin_wayland_test.h" 0012 0013 #include "core/output.h" 0014 #include "placement.h" 0015 #include "pointer_input.h" 0016 #include "wayland_server.h" 0017 #include "window.h" 0018 #include "workspace.h" 0019 0020 #include <KWayland/Client/compositor.h> 0021 #include <KWayland/Client/shm_pool.h> 0022 #include <KWayland/Client/surface.h> 0023 0024 using namespace KWin; 0025 0026 static const QString s_socketName = QStringLiteral("wayland_test_kwin_placement-0"); 0027 0028 struct PlaceWindowResult 0029 { 0030 QSizeF initiallyConfiguredSize; 0031 Test::XdgToplevel::States initiallyConfiguredStates; 0032 QRectF finalGeometry; 0033 }; 0034 0035 class TestPlacement : public QObject 0036 { 0037 Q_OBJECT 0038 0039 private Q_SLOTS: 0040 void init(); 0041 void cleanup(); 0042 void initTestCase(); 0043 0044 void testPlaceSmart(); 0045 void testPlaceMaximized(); 0046 void testPlaceMaximizedLeavesFullscreen(); 0047 void testPlaceCentered(); 0048 void testPlaceUnderMouse(); 0049 void testPlaceZeroCornered(); 0050 void testPlaceRandom(); 0051 void testFullscreen(); 0052 void testCascadeIfCovering(); 0053 void testCascadeIfCoveringIgnoreNonCovering(); 0054 void testCascadeIfCoveringIgnoreOutOfArea(); 0055 void testCascadeIfCoveringIgnoreAlreadyCovered(); 0056 0057 private: 0058 void setPlacementPolicy(PlacementPolicy policy); 0059 /* 0060 * Create a window and return relevant results for testing 0061 * defaultSize is the buffer size to use if the compositor returns an empty size in the first configure 0062 * event. 0063 */ 0064 std::pair<PlaceWindowResult, std::unique_ptr<KWayland::Client::Surface>> createAndPlaceWindow(const QSize &defaultSize); 0065 }; 0066 0067 void TestPlacement::init() 0068 { 0069 QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::LayerShellV1)); 0070 0071 workspace()->setActiveOutput(QPoint(640, 512)); 0072 KWin::input()->pointer()->warp(QPoint(640, 512)); 0073 } 0074 0075 void TestPlacement::cleanup() 0076 { 0077 Test::destroyWaylandConnection(); 0078 } 0079 0080 void TestPlacement::initTestCase() 0081 { 0082 qRegisterMetaType<KWin::Window *>(); 0083 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0084 QVERIFY(waylandServer()->init(s_socketName)); 0085 Test::setOutputConfig({ 0086 QRect(0, 0, 1280, 1024), 0087 QRect(1280, 0, 1280, 1024), 0088 }); 0089 0090 kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); 0091 0092 kwinApp()->start(); 0093 QVERIFY(applicationStartedSpy.wait()); 0094 const auto outputs = workspace()->outputs(); 0095 QCOMPARE(outputs.count(), 2); 0096 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024)); 0097 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024)); 0098 } 0099 0100 void TestPlacement::setPlacementPolicy(PlacementPolicy policy) 0101 { 0102 auto group = kwinApp()->config()->group(QStringLiteral("Windows")); 0103 group.writeEntry("Placement", Placement::policyToString(policy)); 0104 group.sync(); 0105 Workspace::self()->slotReconfigure(); 0106 } 0107 0108 std::pair<PlaceWindowResult, std::unique_ptr<KWayland::Client::Surface>> TestPlacement::createAndPlaceWindow(const QSize &defaultSize) 0109 { 0110 PlaceWindowResult rc; 0111 0112 // create a new window 0113 std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface(); 0114 auto shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly, surface.get()); 0115 0116 QSignalSpy toplevelConfigureRequestedSpy(shellSurface, &Test::XdgToplevel::configureRequested); 0117 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested); 0118 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0119 surfaceConfigureRequestedSpy.wait(); 0120 0121 rc.initiallyConfiguredSize = toplevelConfigureRequestedSpy[0][0].toSize(); 0122 rc.initiallyConfiguredStates = toplevelConfigureRequestedSpy[0][1].value<Test::XdgToplevel::States>(); 0123 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy[0][0].toUInt()); 0124 0125 QSizeF size = rc.initiallyConfiguredSize; 0126 0127 if (size.isEmpty()) { 0128 size = defaultSize; 0129 } 0130 0131 auto window = Test::renderAndWaitForShown(surface.get(), size.toSize(), Qt::red); 0132 0133 rc.finalGeometry = window->frameGeometry(); 0134 return {rc, std::move(surface)}; 0135 } 0136 0137 void TestPlacement::testPlaceSmart() 0138 { 0139 const auto outputs = workspace()->outputs(); 0140 const QList<QRect> desiredGeometries{ 0141 QRect(0, 0, 600, 500), 0142 QRect(600, 0, 600, 500), 0143 QRect(0, 500, 600, 500), 0144 QRect(600, 500, 600, 500), 0145 QRect(680, 524, 600, 500), 0146 QRect(680, 0, 600, 500), 0147 QRect(0, 524, 600, 500), 0148 QRect(0, 0, 600, 500), 0149 }; 0150 0151 setPlacementPolicy(PlacementSmart); 0152 0153 std::vector<std::unique_ptr<KWayland::Client::Surface>> surfaces; 0154 0155 for (const QRect &desiredGeometry : desiredGeometries) { 0156 auto [windowPlacement, surface] = createAndPlaceWindow(QSize(600, 500)); 0157 surfaces.push_back(std::move(surface)); 0158 0159 // smart placement shouldn't define a size on windows 0160 QCOMPARE(windowPlacement.initiallyConfiguredSize, QSize(0, 0)); 0161 QCOMPARE(windowPlacement.finalGeometry.size(), QSize(600, 500)); 0162 0163 QVERIFY(outputs[0]->geometry().contains(windowPlacement.finalGeometry.toRect())); 0164 0165 QCOMPARE(windowPlacement.finalGeometry.toRect(), desiredGeometry); 0166 } 0167 } 0168 0169 void TestPlacement::testPlaceMaximized() 0170 { 0171 setPlacementPolicy(PlacementMaximizing); 0172 0173 // add a top panel 0174 std::unique_ptr<KWayland::Client::Surface> panelSurface{Test::createSurface()}; 0175 std::unique_ptr<Test::LayerSurfaceV1> panelShellSurface{Test::createLayerSurfaceV1(panelSurface.get(), QStringLiteral("dock"))}; 0176 panelShellSurface->set_size(1280, 20); 0177 panelShellSurface->set_anchor(Test::LayerSurfaceV1::anchor_top); 0178 panelShellSurface->set_exclusive_zone(20); 0179 panelSurface->commit(KWayland::Client::Surface::CommitFlag::None); 0180 QSignalSpy panelConfigureRequestedSpy(panelShellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0181 QVERIFY(panelConfigureRequestedSpy.wait()); 0182 Test::renderAndWaitForShown(panelSurface.get(), panelConfigureRequestedSpy.last().at(1).toSize(), Qt::blue); 0183 0184 std::vector<std::unique_ptr<KWayland::Client::Surface>> surfaces; 0185 0186 // all windows should be initially maximized with an initial configure size sent 0187 for (int i = 0; i < 4; i++) { 0188 auto [windowPlacement, surface] = createAndPlaceWindow(QSize(600, 500)); 0189 QVERIFY(windowPlacement.initiallyConfiguredStates & Test::XdgToplevel::State::Maximized); 0190 QCOMPARE(windowPlacement.initiallyConfiguredSize, QSize(1280, 1024 - 20)); 0191 QCOMPARE(windowPlacement.finalGeometry, QRect(0, 20, 1280, 1024 - 20)); // under the panel 0192 surfaces.push_back(std::move(surface)); 0193 } 0194 } 0195 0196 void TestPlacement::testPlaceMaximizedLeavesFullscreen() 0197 { 0198 setPlacementPolicy(PlacementMaximizing); 0199 0200 // add a top panel 0201 std::unique_ptr<KWayland::Client::Surface> panelSurface{Test::createSurface()}; 0202 std::unique_ptr<Test::LayerSurfaceV1> panelShellSurface{Test::createLayerSurfaceV1(panelSurface.get(), QStringLiteral("dock"))}; 0203 panelShellSurface->set_size(1280, 20); 0204 panelShellSurface->set_anchor(Test::LayerSurfaceV1::anchor_top); 0205 panelShellSurface->set_exclusive_zone(20); 0206 panelSurface->commit(KWayland::Client::Surface::CommitFlag::None); 0207 QSignalSpy panelConfigureRequestedSpy(panelShellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0208 QVERIFY(panelConfigureRequestedSpy.wait()); 0209 Test::renderAndWaitForShown(panelSurface.get(), panelConfigureRequestedSpy.last().at(1).toSize(), Qt::blue); 0210 0211 std::vector<std::unique_ptr<KWayland::Client::Surface>> surfaces; 0212 0213 // all windows should be initially fullscreen with an initial configure size sent, despite the policy 0214 for (int i = 0; i < 4; i++) { 0215 std::unique_ptr<KWayland::Client::Surface> surface = Test::createSurface(); 0216 auto shellSurface = Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly, surface.get()); 0217 shellSurface->set_fullscreen(nullptr); 0218 QSignalSpy toplevelConfigureRequestedSpy(shellSurface, &Test::XdgToplevel::configureRequested); 0219 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested); 0220 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0221 QVERIFY(surfaceConfigureRequestedSpy.wait()); 0222 0223 auto initiallyConfiguredSize = toplevelConfigureRequestedSpy[0][0].toSize(); 0224 auto initiallyConfiguredStates = toplevelConfigureRequestedSpy[0][1].value<Test::XdgToplevel::States>(); 0225 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy[0][0].toUInt()); 0226 0227 auto window = Test::renderAndWaitForShown(surface.get(), initiallyConfiguredSize, Qt::red); 0228 0229 QVERIFY(initiallyConfiguredStates & Test::XdgToplevel::State::Fullscreen); 0230 QCOMPARE(initiallyConfiguredSize, QSize(1280, 1024)); 0231 QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024)); 0232 0233 surfaces.push_back(std::move(surface)); 0234 } 0235 } 0236 0237 void TestPlacement::testPlaceCentered() 0238 { 0239 // This test verifies that Centered placement policy works. 0240 0241 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0242 group.writeEntry("Placement", Placement::policyToString(PlacementCentered)); 0243 group.sync(); 0244 workspace()->slotReconfigure(); 0245 0246 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0247 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0248 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::red); 0249 QVERIFY(window); 0250 QCOMPARE(window->frameGeometry(), QRect(590, 487, 100, 50)); 0251 0252 shellSurface.reset(); 0253 QVERIFY(Test::waitForWindowClosed(window)); 0254 } 0255 0256 void TestPlacement::testPlaceUnderMouse() 0257 { 0258 // This test verifies that Under Mouse placement policy works. 0259 0260 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0261 group.writeEntry("Placement", Placement::policyToString(PlacementUnderMouse)); 0262 group.sync(); 0263 workspace()->slotReconfigure(); 0264 0265 KWin::input()->pointer()->warp(QPoint(200, 300)); 0266 QCOMPARE(KWin::Cursors::self()->mouse()->pos(), QPoint(200, 300)); 0267 0268 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0269 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0270 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::red); 0271 QVERIFY(window); 0272 QCOMPARE(window->frameGeometry(), QRect(150, 275, 100, 50)); 0273 0274 shellSurface.reset(); 0275 QVERIFY(Test::waitForWindowClosed(window)); 0276 } 0277 0278 void TestPlacement::testPlaceZeroCornered() 0279 { 0280 // This test verifies that the Zero-Cornered placement policy works. 0281 0282 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0283 group.writeEntry("Placement", Placement::policyToString(PlacementZeroCornered)); 0284 group.sync(); 0285 workspace()->slotReconfigure(); 0286 0287 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0288 std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get())); 0289 Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::red); 0290 QVERIFY(window1); 0291 QCOMPARE(window1->pos(), QPoint(0, 0)); 0292 QCOMPARE(window1->size(), QSize(100, 50)); 0293 0294 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0295 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get())); 0296 Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue); 0297 QVERIFY(window2); 0298 QCOMPARE(window2->pos(), window1->pos() + workspace()->cascadeOffset(window2)); 0299 QCOMPARE(window2->size(), QSize(100, 50)); 0300 0301 std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface()); 0302 std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get())); 0303 Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::green); 0304 QVERIFY(window3); 0305 QCOMPARE(window3->pos(), window2->pos() + workspace()->cascadeOffset(window3)); 0306 QCOMPARE(window3->size(), QSize(100, 50)); 0307 0308 shellSurface3.reset(); 0309 QVERIFY(Test::waitForWindowClosed(window3)); 0310 shellSurface2.reset(); 0311 QVERIFY(Test::waitForWindowClosed(window2)); 0312 shellSurface1.reset(); 0313 QVERIFY(Test::waitForWindowClosed(window1)); 0314 } 0315 0316 void TestPlacement::testPlaceRandom() 0317 { 0318 // This test verifies that Random placement policy works. 0319 0320 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0321 group.writeEntry("Placement", Placement::policyToString(PlacementRandom)); 0322 group.sync(); 0323 workspace()->slotReconfigure(); 0324 0325 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0326 std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get())); 0327 Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::red); 0328 QVERIFY(window1); 0329 QCOMPARE(window1->size(), QSize(100, 50)); 0330 0331 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0332 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get())); 0333 Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue); 0334 QVERIFY(window2); 0335 QVERIFY(window2->pos() != window1->pos()); 0336 QCOMPARE(window2->size(), QSize(100, 50)); 0337 0338 std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface()); 0339 std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get())); 0340 Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::green); 0341 QVERIFY(window3); 0342 QVERIFY(window3->pos() != window1->pos()); 0343 QVERIFY(window3->pos() != window2->pos()); 0344 QCOMPARE(window3->size(), QSize(100, 50)); 0345 0346 shellSurface3.reset(); 0347 QVERIFY(Test::waitForWindowClosed(window3)); 0348 shellSurface2.reset(); 0349 QVERIFY(Test::waitForWindowClosed(window2)); 0350 shellSurface1.reset(); 0351 QVERIFY(Test::waitForWindowClosed(window1)); 0352 } 0353 0354 void TestPlacement::testFullscreen() 0355 { 0356 const QList<Output *> outputs = workspace()->outputs(); 0357 0358 setPlacementPolicy(PlacementSmart); 0359 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0360 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0361 0362 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::red); 0363 QVERIFY(window); 0364 window->sendToOutput(outputs[0]); 0365 0366 // Wait for the configure event with the activated state. 0367 QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested); 0368 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested); 0369 QVERIFY(surfaceConfigureRequestedSpy.wait()); 0370 0371 window->setFullScreen(true); 0372 0373 QSignalSpy geometryChangedSpy(window, &Window::frameGeometryChanged); 0374 QVERIFY(surfaceConfigureRequestedSpy.wait()); 0375 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>()); 0376 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().at(0).toSize(), Qt::red); 0377 QVERIFY(geometryChangedSpy.wait()); 0378 QCOMPARE(window->frameGeometry(), outputs[0]->geometry()); 0379 0380 // this doesn't require a round trip, so should be immediate 0381 window->sendToOutput(outputs[1]); 0382 QCOMPARE(window->frameGeometry(), outputs[1]->geometry()); 0383 QCOMPARE(geometryChangedSpy.count(), 2); 0384 } 0385 0386 void TestPlacement::testCascadeIfCovering() 0387 { 0388 // This test verifies that the cascade-if-covering adjustment works for the Centered placement 0389 // policy. 0390 0391 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0392 group.writeEntry("Placement", Placement::policyToString(PlacementCentered)); 0393 group.sync(); 0394 workspace()->slotReconfigure(); 0395 0396 // window should be in center 0397 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0398 std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get())); 0399 Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::red); 0400 QVERIFY(window1); 0401 QCOMPARE(window1->pos(), QPoint(590, 487)); 0402 QCOMPARE(window1->size(), QSize(100, 50)); 0403 0404 // window should be cascaded to avoid overlapping window 1 0405 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0406 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get())); 0407 Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(100, 50), Qt::blue); 0408 QVERIFY(window2); 0409 QCOMPARE(window2->pos(), window1->pos() + workspace()->cascadeOffset(window2)); 0410 QCOMPARE(window2->size(), QSize(100, 50)); 0411 0412 // window should be cascaded to avoid overlapping window 1 and 2 0413 std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface()); 0414 std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get())); 0415 Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::green); 0416 QVERIFY(window3); 0417 QCOMPARE(window3->pos(), window2->pos() + workspace()->cascadeOffset(window3)); 0418 QCOMPARE(window3->size(), QSize(100, 50)); 0419 0420 shellSurface3.reset(); 0421 QVERIFY(Test::waitForWindowClosed(window3)); 0422 shellSurface2.reset(); 0423 QVERIFY(Test::waitForWindowClosed(window2)); 0424 shellSurface1.reset(); 0425 QVERIFY(Test::waitForWindowClosed(window1)); 0426 } 0427 0428 void TestPlacement::testCascadeIfCoveringIgnoreNonCovering() 0429 { 0430 // This test verifies that the cascade-if-covering adjustment doesn't take effect when the 0431 // other window wouldn't be fully covered. 0432 0433 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0434 group.writeEntry("Placement", Placement::policyToString(PlacementCentered)); 0435 group.sync(); 0436 workspace()->slotReconfigure(); 0437 0438 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0439 std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get())); 0440 Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::red); 0441 QVERIFY(window1); 0442 0443 // window should not be cascaded since it wouldn't fully overlap 0444 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0445 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get())); 0446 Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(50, 50), Qt::blue); 0447 QVERIFY(window2); 0448 QCOMPARE(window2->pos(), QPoint(615, 487)); 0449 QCOMPARE(window2->size(), QSize(50, 50)); 0450 0451 shellSurface2.reset(); 0452 QVERIFY(Test::waitForWindowClosed(window2)); 0453 shellSurface1.reset(); 0454 QVERIFY(Test::waitForWindowClosed(window1)); 0455 } 0456 0457 void TestPlacement::testCascadeIfCoveringIgnoreOutOfArea() 0458 { 0459 // This test verifies that the cascade-if-covering adjustment doesn't take effect when there is 0460 // not enough space on the placement area to cascade. 0461 0462 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0463 group.writeEntry("Placement", Placement::policyToString(PlacementCentered)); 0464 group.sync(); 0465 workspace()->slotReconfigure(); 0466 0467 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0468 std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get())); 0469 Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::red); 0470 QVERIFY(window1); 0471 0472 // window should not be cascaded since it would be out of bounds of work area 0473 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0474 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get())); 0475 Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(1280, 1024), Qt::blue); 0476 QVERIFY(window2); 0477 QCOMPARE(window2->pos(), QPoint(0, 0)); 0478 QCOMPARE(window2->size(), QSize(1280, 1024)); 0479 0480 shellSurface2.reset(); 0481 QVERIFY(Test::waitForWindowClosed(window2)); 0482 shellSurface1.reset(); 0483 QVERIFY(Test::waitForWindowClosed(window1)); 0484 } 0485 0486 void TestPlacement::testCascadeIfCoveringIgnoreAlreadyCovered() 0487 { 0488 // This test verifies that the cascade-if-covering adjustment doesn't take effect when the 0489 // other window is already fully covered by other windows anyway. 0490 0491 KConfigGroup group = kwinApp()->config()->group(QStringLiteral("Windows")); 0492 group.writeEntry("Placement", Placement::policyToString(PlacementCentered)); 0493 group.sync(); 0494 workspace()->slotReconfigure(); 0495 0496 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0497 std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get())); 0498 Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(100, 50), Qt::red); 0499 QVERIFY(window1); 0500 0501 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0502 std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get())); 0503 Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(1280, 1024), Qt::blue); 0504 QVERIFY(window2); 0505 0506 // window should not be cascaded since the small window is already fully covered by the 0507 // large window anyway 0508 std::unique_ptr<KWayland::Client::Surface> surface3(Test::createSurface()); 0509 std::unique_ptr<Test::XdgToplevel> shellSurface3(Test::createXdgToplevelSurface(surface3.get())); 0510 Window *window3 = Test::renderAndWaitForShown(surface3.get(), QSize(100, 50), Qt::green); 0511 QVERIFY(window3); 0512 QCOMPARE(window3->pos(), QPoint(590, 487)); 0513 QCOMPARE(window3->size(), QSize(100, 50)); 0514 0515 shellSurface3.reset(); 0516 QVERIFY(Test::waitForWindowClosed(window3)); 0517 shellSurface2.reset(); 0518 QVERIFY(Test::waitForWindowClosed(window2)); 0519 shellSurface1.reset(); 0520 QVERIFY(Test::waitForWindowClosed(window1)); 0521 } 0522 0523 WAYLANDTEST_MAIN(TestPlacement) 0524 #include "placement_test.moc"