File indexing completed on 2024-11-10 04:56:01
0001 /* 0002 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kwin_wayland_test.h" 0008 0009 #include "core/output.h" 0010 #include "main.h" 0011 #include "pointer_input.h" 0012 #include "screenedge.h" 0013 #include "wayland_server.h" 0014 #include "window.h" 0015 #include "workspace.h" 0016 0017 #include <KWayland/Client/output.h> 0018 #include <KWayland/Client/surface.h> 0019 0020 Q_DECLARE_METATYPE(QMargins) 0021 Q_DECLARE_METATYPE(KWin::Layer) 0022 0023 namespace KWin 0024 { 0025 0026 static const QString s_socketName = QStringLiteral("wayland_test_kwin_layershellv1window-0"); 0027 0028 class LayerShellV1WindowTest : public QObject 0029 { 0030 Q_OBJECT 0031 0032 private Q_SLOTS: 0033 void initTestCase(); 0034 void init(); 0035 void cleanup(); 0036 void testOutput_data(); 0037 void testOutput(); 0038 void testAnchor_data(); 0039 void testAnchor(); 0040 void testMargins_data(); 0041 void testMargins(); 0042 void testLayer_data(); 0043 void testLayer(); 0044 void testChangeLayer(); 0045 void testPlacementArea_data(); 0046 void testPlacementArea(); 0047 void testFill_data(); 0048 void testFill(); 0049 void testStack(); 0050 void testKeyboardInteractivityNone(); 0051 void testKeyboardInteractivityOnDemand(); 0052 void testActivate_data(); 0053 void testActivate(); 0054 void testUnmap(); 0055 void testScreenEdge_data(); 0056 void testScreenEdge(); 0057 }; 0058 0059 void LayerShellV1WindowTest::initTestCase() 0060 { 0061 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0062 QVERIFY(waylandServer()->init(s_socketName)); 0063 Test::setOutputConfig({ 0064 QRect(0, 0, 1280, 1024), 0065 QRect(1280, 0, 1280, 1024), 0066 }); 0067 0068 kwinApp()->start(); 0069 QVERIFY(applicationStartedSpy.wait()); 0070 const auto outputs = workspace()->outputs(); 0071 QCOMPARE(outputs.count(), 2); 0072 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024)); 0073 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024)); 0074 } 0075 0076 void LayerShellV1WindowTest::init() 0077 { 0078 QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::LayerShellV1 | Test::AdditionalWaylandInterface::ScreenEdgeV1)); 0079 0080 workspace()->setActiveOutput(QPoint(640, 512)); 0081 input()->pointer()->warp(QPoint(640, 512)); 0082 } 0083 0084 void LayerShellV1WindowTest::cleanup() 0085 { 0086 Test::destroyWaylandConnection(); 0087 } 0088 0089 void LayerShellV1WindowTest::testOutput_data() 0090 { 0091 QTest::addColumn<int>("screenId"); 0092 0093 QTest::addRow("first output") << 0; 0094 QTest::addRow("second output") << 1; 0095 } 0096 0097 void LayerShellV1WindowTest::testOutput() 0098 { 0099 // Fetch the wl_output object. 0100 QFETCH(int, screenId); 0101 KWayland::Client::Output *output = Test::waylandOutputs().value(screenId); 0102 QVERIFY(output); 0103 0104 // Create a layer shell surface. 0105 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0106 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"), output)); 0107 0108 // Set the initial state of the layer surface. 0109 shellSurface->set_size(280, 124); 0110 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0111 0112 // Wait for the compositor to position the surface. 0113 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0114 QVERIFY(configureRequestedSpy.wait()); 0115 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0116 0117 // Map the layer surface. 0118 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0119 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0120 QVERIFY(window); 0121 0122 // Verify that the window is on the requested screen. 0123 QVERIFY(output->geometry().contains(window->frameGeometry().toRect())); 0124 0125 // Destroy the window. 0126 shellSurface.reset(); 0127 QVERIFY(Test::waitForWindowClosed(window)); 0128 } 0129 0130 void LayerShellV1WindowTest::testAnchor_data() 0131 { 0132 QTest::addColumn<int>("anchor"); 0133 QTest::addColumn<QRectF>("expectedGeometry"); 0134 0135 QTest::addRow("left") << int(Test::LayerSurfaceV1::anchor_left) 0136 << QRectF(0, 450, 280, 124); 0137 0138 QTest::addRow("top left") << (Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) 0139 << QRectF(0, 0, 280, 124); 0140 0141 QTest::addRow("top") << int(Test::LayerSurfaceV1::anchor_top) 0142 << QRectF(500, 0, 280, 124); 0143 0144 QTest::addRow("top right") << (Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) 0145 << QRectF(1000, 0, 280, 124); 0146 0147 QTest::addRow("right") << int(Test::LayerSurfaceV1::anchor_right) 0148 << QRectF(1000, 450, 280, 124); 0149 0150 QTest::addRow("bottom right") << (Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) 0151 << QRectF(1000, 900, 280, 124); 0152 0153 QTest::addRow("bottom") << int(Test::LayerSurfaceV1::anchor_bottom) 0154 << QRectF(500, 900, 280, 124); 0155 0156 QTest::addRow("bottom left") << (Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) 0157 << QRectF(0, 900, 280, 124); 0158 } 0159 0160 void LayerShellV1WindowTest::testAnchor() 0161 { 0162 // Create a layer shell surface. 0163 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0164 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0165 0166 // Set the initial state of the layer surface. 0167 QFETCH(int, anchor); 0168 shellSurface->set_anchor(anchor); 0169 shellSurface->set_size(280, 124); 0170 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0171 0172 // Wait for the compositor to position the surface. 0173 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0174 QVERIFY(configureRequestedSpy.wait()); 0175 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0176 QCOMPARE(requestedSize, QSize(280, 124)); 0177 0178 // Map the layer surface. 0179 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0180 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(280, 124), Qt::red); 0181 QVERIFY(window); 0182 0183 // Verify that the window is placed at expected location. 0184 QTEST(window->frameGeometry(), "expectedGeometry"); 0185 0186 // Destroy the window. 0187 shellSurface.reset(); 0188 QVERIFY(Test::waitForWindowClosed(window)); 0189 } 0190 0191 void LayerShellV1WindowTest::testMargins_data() 0192 { 0193 QTest::addColumn<int>("anchor"); 0194 QTest::addColumn<QMargins>("margins"); 0195 QTest::addColumn<QRectF>("expectedGeometry"); 0196 0197 QTest::addRow("left") << int(Test::LayerSurfaceV1::anchor_left) 0198 << QMargins(100, 0, 0, 0) 0199 << QRectF(100, 450, 280, 124); 0200 0201 QTest::addRow("top left") << (Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) 0202 << QMargins(100, 200, 0, 0) 0203 << QRectF(100, 200, 280, 124); 0204 0205 QTest::addRow("top") << int(Test::LayerSurfaceV1::anchor_top) 0206 << QMargins(0, 200, 0, 0) 0207 << QRectF(500, 200, 280, 124); 0208 0209 QTest::addRow("top right") << (Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) 0210 << QMargins(0, 200, 300, 0) 0211 << QRectF(700, 200, 280, 124); 0212 0213 QTest::addRow("right") << int(Test::LayerSurfaceV1::anchor_right) 0214 << QMargins(0, 0, 300, 0) 0215 << QRectF(700, 450, 280, 124); 0216 0217 QTest::addRow("bottom right") << (Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) 0218 << QMargins(0, 0, 300, 400) 0219 << QRectF(700, 500, 280, 124); 0220 0221 QTest::addRow("bottom") << int(Test::LayerSurfaceV1::anchor_bottom) 0222 << QMargins(0, 0, 0, 400) 0223 << QRectF(500, 500, 280, 124); 0224 0225 QTest::addRow("bottom left") << (Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) 0226 << QMargins(100, 0, 0, 400) 0227 << QRectF(100, 500, 280, 124); 0228 } 0229 0230 void LayerShellV1WindowTest::testMargins() 0231 { 0232 // Create a layer shell surface. 0233 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0234 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0235 0236 // Set the initial state of the layer surface. 0237 QFETCH(QMargins, margins); 0238 QFETCH(int, anchor); 0239 shellSurface->set_anchor(anchor); 0240 shellSurface->set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); 0241 shellSurface->set_size(280, 124); 0242 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0243 0244 // Wait for the compositor to position the surface. 0245 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0246 QVERIFY(configureRequestedSpy.wait()); 0247 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0248 0249 // Map the layer surface. 0250 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0251 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0252 QVERIFY(window); 0253 0254 // Verify that the window is placed at expected location. 0255 QTEST(window->frameGeometry(), "expectedGeometry"); 0256 0257 // Destroy the window. 0258 shellSurface.reset(); 0259 QVERIFY(Test::waitForWindowClosed(window)); 0260 } 0261 0262 void LayerShellV1WindowTest::testLayer_data() 0263 { 0264 QTest::addColumn<int>("protocolLayer"); 0265 QTest::addColumn<Layer>("compositorLayer"); 0266 0267 QTest::addRow("overlay") << int(Test::LayerShellV1::layer_overlay) << OverlayLayer; 0268 QTest::addRow("top") << int(Test::LayerShellV1::layer_top) << AboveLayer; 0269 QTest::addRow("bottom") << int(Test::LayerShellV1::layer_bottom) << BelowLayer; 0270 QTest::addRow("background") << int(Test::LayerShellV1::layer_background) << DesktopLayer; 0271 } 0272 0273 void LayerShellV1WindowTest::testLayer() 0274 { 0275 // Create a layer shell surface. 0276 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0277 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0278 0279 // Set the initial state of the layer surface. 0280 QFETCH(int, protocolLayer); 0281 shellSurface->set_layer(protocolLayer); 0282 shellSurface->set_size(280, 124); 0283 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0284 0285 // Wait for the compositor to position the surface. 0286 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0287 QVERIFY(configureRequestedSpy.wait()); 0288 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0289 0290 // Map the layer surface. 0291 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0292 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0293 QVERIFY(window); 0294 0295 // Verify that the window is placed at expected location. 0296 QTEST(window->layer(), "compositorLayer"); 0297 0298 // Destroy the window. 0299 shellSurface.reset(); 0300 QVERIFY(Test::waitForWindowClosed(window)); 0301 } 0302 0303 void LayerShellV1WindowTest::testChangeLayer() 0304 { 0305 // This test verifies that set_layer requests are handled properly after the surface has 0306 // been mapped on the screen. 0307 0308 // Create layer shell surfaces. 0309 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0310 std::unique_ptr<Test::LayerSurfaceV1> shellSurface1(Test::createLayerSurfaceV1(surface1.get(), QStringLiteral("test"))); 0311 shellSurface1->set_layer(Test::LayerShellV1::layer_bottom); 0312 shellSurface1->set_size(200, 100); 0313 surface1->commit(KWayland::Client::Surface::CommitFlag::None); 0314 0315 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0316 std::unique_ptr<Test::LayerSurfaceV1> shellSurface2(Test::createLayerSurfaceV1(surface2.get(), QStringLiteral("test"))); 0317 shellSurface2->set_layer(Test::LayerShellV1::layer_bottom); 0318 shellSurface2->set_size(200, 100); 0319 surface2->commit(KWayland::Client::Surface::CommitFlag::None); 0320 0321 // Wait for the compositor to position the surfaces. 0322 QSignalSpy configureRequestedSpy1(shellSurface1.get(), &Test::LayerSurfaceV1::configureRequested); 0323 QSignalSpy configureRequestedSpy2(shellSurface2.get(), &Test::LayerSurfaceV1::configureRequested); 0324 QVERIFY(configureRequestedSpy2.wait()); 0325 const QSize requestedSize1 = configureRequestedSpy1.last().at(1).toSize(); 0326 const QSize requestedSize2 = configureRequestedSpy2.last().at(1).toSize(); 0327 0328 // Map the layer surfaces. 0329 shellSurface1->ack_configure(configureRequestedSpy1.last().at(0).toUInt()); 0330 Window *window1 = Test::renderAndWaitForShown(surface1.get(), requestedSize1, Qt::red); 0331 QVERIFY(window1); 0332 shellSurface2->ack_configure(configureRequestedSpy2.last().at(0).toUInt()); 0333 Window *window2 = Test::renderAndWaitForShown(surface2.get(), requestedSize2, Qt::red); 0334 QVERIFY(window2); 0335 0336 // The first layer shell window is stacked below the second one. 0337 QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window1, window2})); 0338 0339 // Move the first layer shell window to the top layer. 0340 QSignalSpy stackingOrderChangedSpy(workspace(), &Workspace::stackingOrderChanged); 0341 shellSurface1->set_layer(Test::LayerShellV1::layer_top); 0342 surface1->commit(KWayland::Client::Surface::CommitFlag::None); 0343 QVERIFY(stackingOrderChangedSpy.wait()); 0344 0345 // The first layer shell window should be on top now. 0346 QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window2, window1})); 0347 0348 // Destroy the window. 0349 shellSurface1.reset(); 0350 QVERIFY(Test::waitForWindowClosed(window1)); 0351 shellSurface2.reset(); 0352 QVERIFY(Test::waitForWindowClosed(window2)); 0353 } 0354 0355 void LayerShellV1WindowTest::testPlacementArea_data() 0356 { 0357 QTest::addColumn<int>("anchor"); 0358 QTest::addColumn<QMargins>("margins"); 0359 QTest::addColumn<int>("exclusiveZone"); 0360 QTest::addColumn<int>("exclusiveEdge"); 0361 QTest::addColumn<QRectF>("placementArea"); 0362 0363 QTest::addRow("left") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(300, 0, 980, 1024); 0364 QTest::addRow("top") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 300, 1280, 724); 0365 QTest::addRow("right") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 980, 1024); 0366 QTest::addRow("bottom") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 724); 0367 0368 QTest::addRow("top | left") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024); 0369 QTest::addRow("top | right") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024); 0370 QTest::addRow("bottom | left") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024); 0371 QTest::addRow("bottom | right") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << 0 << QRectF(0, 0, 1280, 1024); 0372 0373 QTest::addRow("left, negative margin") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(-5, 0, 0, 0) << 300 << 0 << QRectF(295, 0, 985, 1024); 0374 QTest::addRow("top, negative margin") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, -5, 0, 0) << 300 << 0 << QRectF(0, 295, 1280, 729); 0375 QTest::addRow("right, negative margin") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, -5, 0) << 300 << 0 << QRectF(0, 0, 985, 1024); 0376 QTest::addRow("bottom, negative margin") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, -5) << 300 << 0 << QRectF(0, 0, 1280, 729); 0377 0378 QTest::addRow("left, positive margin") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(5, 0, 0, 0) << 300 << 0 << QRectF(305, 0, 975, 1024); 0379 QTest::addRow("top, positive margin") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 5, 0, 0) << 300 << 0 << QRectF(0, 305, 1280, 719); 0380 QTest::addRow("right, positive margin") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 5, 0) << 300 << 0 << QRectF(0, 0, 975, 1024); 0381 QTest::addRow("bottom, positive margin") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 5) << 300 << 0 << QRectF(0, 0, 1280, 719); 0382 0383 QTest::addRow("left + left exclusive edge") << int(Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_left) << QRectF(300, 0, 980, 1024); 0384 QTest::addRow("top + top exclusive edge") << int(Test::LayerSurfaceV1::anchor_top) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_top) << QRectF(0, 300, 1280, 724); 0385 QTest::addRow("right + right exclusive edge") << int(Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_right) << QRectF(0, 0, 980, 1024); 0386 QTest::addRow("bottom + bottom exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_bottom) << QRectF(0, 0, 1280, 724); 0387 0388 QTest::addRow("top | left + top exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_top) << QRectF(0, 300, 1280, 724); 0389 QTest::addRow("top | left + left exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_left) << QRectF(300, 0, 980, 1024); 0390 QTest::addRow("top | right + top exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_top) << QRectF(0, 300, 1280, 724); 0391 QTest::addRow("top | right + right exclusive edge") << int(Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_right) << QRectF(0, 0, 980, 1024); 0392 QTest::addRow("bottom | left + bottom exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_bottom) << QRectF(0, 0, 1280, 724); 0393 QTest::addRow("bottom | left + left exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_left) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_left) << QRectF(300, 0, 980, 1024); 0394 QTest::addRow("bottom | right + bottom exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_bottom) << QRectF(0, 0, 1280, 724); 0395 QTest::addRow("bottom | right + right exclusive edge") << int(Test::LayerSurfaceV1::anchor_bottom | Test::LayerSurfaceV1::anchor_right) << QMargins(0, 0, 0, 0) << 300 << int(Test::LayerSurfaceV1::anchor_right) << QRectF(0, 0, 980, 1024); 0396 } 0397 0398 void LayerShellV1WindowTest::testPlacementArea() 0399 { 0400 // Create a layer shell surface. 0401 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0402 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0403 0404 // Set the initial state of the layer surface. 0405 QFETCH(int, anchor); 0406 QFETCH(QMargins, margins); 0407 QFETCH(int, exclusiveZone); 0408 QFETCH(int, exclusiveEdge); 0409 shellSurface->set_anchor(anchor); 0410 shellSurface->set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); 0411 shellSurface->set_exclusive_zone(exclusiveZone); 0412 shellSurface->set_exclusive_edge(exclusiveEdge); 0413 shellSurface->set_size(280, 124); 0414 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0415 0416 // Wait for the compositor to position the surface. 0417 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0418 QVERIFY(configureRequestedSpy.wait()); 0419 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0420 0421 // Map the layer surface. 0422 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0423 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0424 QVERIFY(window); 0425 0426 // Verify that the work area has been adjusted. 0427 QTEST(workspace()->clientArea(PlacementArea, window), "placementArea"); 0428 0429 // Destroy the window. 0430 shellSurface.reset(); 0431 QVERIFY(Test::waitForWindowClosed(window)); 0432 } 0433 0434 void LayerShellV1WindowTest::testFill_data() 0435 { 0436 QTest::addColumn<int>("anchor"); 0437 QTest::addColumn<QSize>("desiredSize"); 0438 QTest::addColumn<QRectF>("expectedGeometry"); 0439 0440 QTest::addRow("horizontal") << (Test::LayerSurfaceV1::anchor_left | Test::LayerSurfaceV1::anchor_right) 0441 << QSize(0, 124) 0442 << QRectF(0, 450, 1280, 124); 0443 0444 QTest::addRow("vertical") << (Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_bottom) 0445 << QSize(280, 0) 0446 << QRectF(500, 0, 280, 1024); 0447 0448 QTest::addRow("all") << (Test::LayerSurfaceV1::anchor_left | Test::LayerSurfaceV1::anchor_top | Test::LayerSurfaceV1::anchor_right | Test::LayerSurfaceV1::anchor_bottom) 0449 << QSize(0, 0) 0450 << QRectF(0, 0, 1280, 1024); 0451 } 0452 0453 void LayerShellV1WindowTest::testFill() 0454 { 0455 // Create a layer shell surface. 0456 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0457 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0458 0459 // Set the initial state of the layer surface. 0460 QFETCH(int, anchor); 0461 QFETCH(QSize, desiredSize); 0462 shellSurface->set_anchor(anchor); 0463 shellSurface->set_size(desiredSize.width(), desiredSize.height()); 0464 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0465 0466 // Wait for the compositor to position the surface. 0467 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0468 QVERIFY(configureRequestedSpy.wait()); 0469 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0470 0471 // Map the layer surface. 0472 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0473 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0474 QVERIFY(window); 0475 0476 // Verify that the window is placed at expected location. 0477 QTEST(window->frameGeometry(), "expectedGeometry"); 0478 0479 // Destroy the window. 0480 shellSurface.reset(); 0481 QVERIFY(Test::waitForWindowClosed(window)); 0482 } 0483 0484 void LayerShellV1WindowTest::testStack() 0485 { 0486 // Create a layer shell surface. 0487 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0488 std::unique_ptr<Test::LayerSurfaceV1> shellSurface1(Test::createLayerSurfaceV1(surface1.get(), QStringLiteral("test"))); 0489 0490 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0491 std::unique_ptr<Test::LayerSurfaceV1> shellSurface2(Test::createLayerSurfaceV1(surface2.get(), QStringLiteral("test"))); 0492 0493 // Set the initial state of the layer surface. 0494 shellSurface1->set_anchor(Test::LayerSurfaceV1::anchor_left); 0495 shellSurface1->set_size(80, 124); 0496 shellSurface1->set_exclusive_zone(80); 0497 surface1->commit(KWayland::Client::Surface::CommitFlag::None); 0498 0499 shellSurface2->set_anchor(Test::LayerSurfaceV1::anchor_left); 0500 shellSurface2->set_size(200, 124); 0501 shellSurface2->set_exclusive_zone(200); 0502 surface2->commit(KWayland::Client::Surface::CommitFlag::None); 0503 0504 // Wait for the compositor to position the surfaces. 0505 QSignalSpy configureRequestedSpy1(shellSurface1.get(), &Test::LayerSurfaceV1::configureRequested); 0506 QSignalSpy configureRequestedSpy2(shellSurface2.get(), &Test::LayerSurfaceV1::configureRequested); 0507 QVERIFY(configureRequestedSpy2.wait()); 0508 const QSize requestedSize1 = configureRequestedSpy1.last().at(1).toSize(); 0509 const QSize requestedSize2 = configureRequestedSpy2.last().at(1).toSize(); 0510 0511 // Map the layer surface. 0512 shellSurface1->ack_configure(configureRequestedSpy1.last().at(0).toUInt()); 0513 Window *window1 = Test::renderAndWaitForShown(surface1.get(), requestedSize1, Qt::red); 0514 QVERIFY(window1); 0515 0516 shellSurface2->ack_configure(configureRequestedSpy2.last().at(0).toUInt()); 0517 Window *window2 = Test::renderAndWaitForShown(surface2.get(), requestedSize2, Qt::red); 0518 QVERIFY(window2); 0519 0520 // Check that the second layer surface is placed next to the first. 0521 QCOMPARE(window1->frameGeometry(), QRect(0, 450, 80, 124)); 0522 QCOMPARE(window2->frameGeometry(), QRect(80, 450, 200, 124)); 0523 0524 // Check that the work area has been adjusted accordingly. 0525 QCOMPARE(workspace()->clientArea(PlacementArea, window1), QRect(280, 0, 1000, 1024)); 0526 QCOMPARE(workspace()->clientArea(PlacementArea, window2), QRect(280, 0, 1000, 1024)); 0527 0528 // Destroy the window. 0529 shellSurface1.reset(); 0530 QVERIFY(Test::waitForWindowClosed(window1)); 0531 shellSurface2.reset(); 0532 QVERIFY(Test::waitForWindowClosed(window2)); 0533 } 0534 0535 void LayerShellV1WindowTest::testKeyboardInteractivityNone() 0536 { 0537 // Create a layer shell surface. 0538 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0539 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0540 0541 // Set the initial state of the layer surface. 0542 shellSurface->set_keyboard_interactivity(0); 0543 shellSurface->set_size(100, 50); 0544 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0545 0546 // Wait for the compositor to position the surface. 0547 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0548 QVERIFY(configureRequestedSpy.wait()); 0549 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0550 0551 // Map the layer surface. 0552 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0553 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0554 QVERIFY(window); 0555 QVERIFY(!window->isActive()); 0556 0557 // Try to activate the surface. 0558 workspace()->activateWindow(window); 0559 QVERIFY(!window->isActive()); 0560 0561 // Destroy the window. 0562 shellSurface.reset(); 0563 QVERIFY(Test::waitForWindowClosed(window)); 0564 } 0565 0566 void LayerShellV1WindowTest::testKeyboardInteractivityOnDemand() 0567 { 0568 // Create a layer shell surface. 0569 std::unique_ptr<KWayland::Client::Surface> surface1(Test::createSurface()); 0570 std::unique_ptr<Test::LayerSurfaceV1> shellSurface1(Test::createLayerSurfaceV1(surface1.get(), QStringLiteral("test"))); 0571 shellSurface1->set_keyboard_interactivity(1); 0572 shellSurface1->set_size(280, 124); 0573 surface1->commit(KWayland::Client::Surface::CommitFlag::None); 0574 0575 QSignalSpy configureRequestedSpy1(shellSurface1.get(), &Test::LayerSurfaceV1::configureRequested); 0576 QVERIFY(configureRequestedSpy1.wait()); 0577 const QSize requestedSize1 = configureRequestedSpy1.last().at(1).toSize(); 0578 shellSurface1->ack_configure(configureRequestedSpy1.last().at(0).toUInt()); 0579 Window *window1 = Test::renderAndWaitForShown(surface1.get(), requestedSize1, Qt::red); 0580 QVERIFY(window1); 0581 QVERIFY(window1->isActive()); 0582 0583 // Create the second layer shell surface. 0584 std::unique_ptr<KWayland::Client::Surface> surface2(Test::createSurface()); 0585 std::unique_ptr<Test::LayerSurfaceV1> shellSurface2(Test::createLayerSurfaceV1(surface2.get(), QStringLiteral("test"))); 0586 shellSurface2->set_keyboard_interactivity(1); 0587 shellSurface2->set_size(280, 124); 0588 surface2->commit(KWayland::Client::Surface::CommitFlag::None); 0589 0590 QSignalSpy configureRequestedSpy2(shellSurface2.get(), &Test::LayerSurfaceV1::configureRequested); 0591 QVERIFY(configureRequestedSpy2.wait()); 0592 const QSize requestedSize2 = configureRequestedSpy2.last().at(1).toSize(); 0593 shellSurface2->ack_configure(configureRequestedSpy2.last().at(0).toUInt()); 0594 Window *window2 = Test::renderAndWaitForShown(surface2.get(), requestedSize2, Qt::red); 0595 QVERIFY(window2); 0596 QVERIFY(window2->isActive()); 0597 QVERIFY(!window1->isActive()); 0598 0599 // Activate the first surface. 0600 workspace()->activateWindow(window1); 0601 QVERIFY(window1->isActive()); 0602 QVERIFY(!window2->isActive()); 0603 0604 // Destroy the window. 0605 shellSurface1.reset(); 0606 QVERIFY(Test::waitForWindowClosed(window1)); 0607 shellSurface2.reset(); 0608 QVERIFY(Test::waitForWindowClosed(window2)); 0609 } 0610 0611 void LayerShellV1WindowTest::testActivate_data() 0612 { 0613 QTest::addColumn<int>("layer"); 0614 QTest::addColumn<bool>("active"); 0615 0616 QTest::addRow("overlay") << int(Test::LayerShellV1::layer_overlay) << true; 0617 QTest::addRow("top") << int(Test::LayerShellV1::layer_top) << true; 0618 QTest::addRow("bottom") << int(Test::LayerShellV1::layer_bottom) << false; 0619 QTest::addRow("background") << int(Test::LayerShellV1::layer_background) << false; 0620 } 0621 0622 void LayerShellV1WindowTest::testActivate() 0623 { 0624 // Create a layer shell surface. 0625 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0626 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0627 0628 // Set the initial state of the layer surface. 0629 QFETCH(int, layer); 0630 shellSurface->set_layer(layer); 0631 shellSurface->set_size(280, 124); 0632 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0633 0634 // Wait for the compositor to position the surface. 0635 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0636 QVERIFY(configureRequestedSpy.wait()); 0637 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0638 0639 // Map the layer surface. 0640 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0641 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0642 QVERIFY(window); 0643 QVERIFY(!window->isActive()); 0644 0645 // Try to activate the layer surface. 0646 shellSurface->set_keyboard_interactivity(1); 0647 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0648 0649 QSignalSpy activeChangedSpy(window, &Window::activeChanged); 0650 QTEST(activeChangedSpy.wait(1000), "active"); 0651 0652 // Destroy the window. 0653 shellSurface.reset(); 0654 QVERIFY(Test::waitForWindowClosed(window)); 0655 } 0656 0657 void LayerShellV1WindowTest::testUnmap() 0658 { 0659 // Create a layer shell surface. 0660 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0661 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0662 0663 // Set the initial state of the layer surface. 0664 shellSurface->set_size(280, 124); 0665 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0666 0667 // Wait for the compositor to position the surface. 0668 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0669 QVERIFY(configureRequestedSpy.wait()); 0670 0671 // Map the layer surface. 0672 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0673 Window *window = Test::renderAndWaitForShown(surface.get(), QSize(280, 124), Qt::red); 0674 QVERIFY(window); 0675 0676 // Unmap the layer surface. 0677 surface->attachBuffer(KWayland::Client::Buffer::Ptr()); 0678 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0679 QVERIFY(Test::waitForWindowClosed(window)); 0680 0681 // Notify the compositor that we want to map the layer surface. 0682 shellSurface->set_size(280, 124); 0683 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0684 0685 // Wait for the configure event. 0686 QVERIFY(configureRequestedSpy.wait()); 0687 0688 // Map the layer surface back. 0689 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0690 window = Test::renderAndWaitForShown(surface.get(), QSize(280, 124), Qt::red); 0691 QVERIFY(window); 0692 0693 // Destroy the window. 0694 shellSurface.reset(); 0695 QVERIFY(Test::waitForWindowClosed(window)); 0696 } 0697 0698 void LayerShellV1WindowTest::testScreenEdge_data() 0699 { 0700 QTest::addColumn<QMargins>("margins"); 0701 0702 QTest::addRow("normal") << QMargins(0, 0, 0, 0); 0703 QTest::addRow("with margin") << QMargins(0, 0, 0, 10); 0704 } 0705 0706 void LayerShellV1WindowTest::testScreenEdge() 0707 { 0708 auto config = kwinApp()->config(); 0709 config->group(QStringLiteral("Windows")).writeEntry("ElectricBorderDelay", 75); 0710 config->sync(); 0711 workspace()->slotReconfigure(); 0712 0713 // Create a layer shell surface. 0714 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0715 std::unique_ptr<Test::LayerSurfaceV1> shellSurface(Test::createLayerSurfaceV1(surface.get(), QStringLiteral("test"))); 0716 std::unique_ptr<Test::AutoHideScreenEdgeV1> screenEdge(Test::createAutoHideScreenEdgeV1(surface.get(), Test::ScreenEdgeManagerV1::border_bottom)); 0717 0718 // Set the initial state of the layer surface. 0719 QFETCH(QMargins, margins); 0720 shellSurface->set_layer(Test::LayerShellV1::layer_top); 0721 shellSurface->set_anchor(Test::LayerSurfaceV1::anchor_bottom); 0722 shellSurface->set_size(100, 50); 0723 shellSurface->set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); 0724 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0725 0726 // Wait for the compositor to position the surface. 0727 QSignalSpy configureRequestedSpy(shellSurface.get(), &Test::LayerSurfaceV1::configureRequested); 0728 QVERIFY(configureRequestedSpy.wait()); 0729 const QSize requestedSize = configureRequestedSpy.last().at(1).toSize(); 0730 0731 // Map the layer surface. 0732 shellSurface->ack_configure(configureRequestedSpy.last().at(0).toUInt()); 0733 Window *window = Test::renderAndWaitForShown(surface.get(), requestedSize, Qt::red); 0734 QVERIFY(window); 0735 QVERIFY(!window->isActive()); 0736 0737 QSignalSpy windowShowSpy(window, &Window::windowShown); 0738 QSignalSpy windowHiddenSpy(window, &Window::windowHidden); 0739 quint32 timestamp = 0; 0740 0741 // The layer surface will be hidden and shown when the screen edge is activated or deactivated. 0742 { 0743 screenEdge->activate(); 0744 QVERIFY(windowHiddenSpy.wait()); 0745 QVERIFY(!window->isShown()); 0746 0747 screenEdge->deactivate(); 0748 QVERIFY(windowShowSpy.wait()); 0749 QVERIFY(window->isShown()); 0750 } 0751 0752 // The layer surface will be shown when the screen edge is triggered. 0753 { 0754 screenEdge->activate(); 0755 QVERIFY(windowHiddenSpy.wait()); 0756 QVERIFY(!window->isShown()); 0757 0758 Test::pointerMotion(QPointF(640, 1023), timestamp); 0759 timestamp += 160; 0760 Test::pointerMotion(QPointF(640, 1023), timestamp); 0761 timestamp += 160; 0762 Test::pointerMotion(QPointF(640, 512), timestamp); 0763 QVERIFY(windowShowSpy.wait()); 0764 QVERIFY(window->isShown()); 0765 } 0766 0767 // The approaching state will be reset if the window is shown manually. 0768 { 0769 QSignalSpy approachingSpy(workspace()->screenEdges(), &ScreenEdges::approaching); 0770 screenEdge->activate(); 0771 QVERIFY(windowHiddenSpy.wait()); 0772 QVERIFY(!window->isShown()); 0773 0774 Test::pointerMotion(QPointF(640, 1020), timestamp++); 0775 QVERIFY(approachingSpy.last().at(1).toReal() == 0.0); 0776 Test::pointerMotion(QPointF(640, 1021), timestamp++); 0777 QVERIFY(approachingSpy.last().at(1).toReal() != 0.0); 0778 0779 screenEdge->deactivate(); 0780 QVERIFY(windowShowSpy.wait()); 0781 QVERIFY(window->isShown()); 0782 QVERIFY(approachingSpy.last().at(1).toReal() == 0.0); 0783 0784 Test::pointerMotion(QPointF(640, 512), timestamp++); 0785 } 0786 0787 // The layer surface will be shown when the screen edge is destroyed. 0788 { 0789 screenEdge->activate(); 0790 QVERIFY(windowHiddenSpy.wait()); 0791 QVERIFY(!window->isShown()); 0792 0793 screenEdge.reset(); 0794 QVERIFY(windowShowSpy.wait()); 0795 QVERIFY(window->isShown()); 0796 } 0797 } 0798 0799 } // namespace KWin 0800 0801 WAYLANDTEST_MAIN(KWin::LayerShellV1WindowTest) 0802 #include "layershellv1window_test.moc"