From 223b01f9e7ce8ea907c9d96fdcb2c08c2623ca00 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 13 May 2023 14:25:53 +0300 Subject: [PATCH] wayland: Reevaluate layer shell window layer Currently, if the layer shell surface's layer changes, the Window's layer is not synchronized with it. --- .../integration/layershellv1window_test.cpp | 53 +++++++++++++++++++ src/layershellv1integration.cpp | 2 + 2 files changed, 55 insertions(+) diff --git a/autotests/integration/layershellv1window_test.cpp b/autotests/integration/layershellv1window_test.cpp index 61e6c28ef7..6791725f12 100644 --- a/autotests/integration/layershellv1window_test.cpp +++ b/autotests/integration/layershellv1window_test.cpp @@ -41,6 +41,7 @@ private Q_SLOTS: void testMargins(); void testLayer_data(); void testLayer(); + void testChangeLayer(); void testPlacementArea_data(); void testPlacementArea(); void testFill_data(); @@ -296,6 +297,58 @@ void LayerShellV1WindowTest::testLayer() QVERIFY(Test::waitForWindowClosed(window)); } +void LayerShellV1WindowTest::testChangeLayer() +{ + // This test verifies that set_layer requests are handled properly after the surface has + // been mapped on the screen. + + // Create layer shell surfaces. + std::unique_ptr surface1(Test::createSurface()); + std::unique_ptr shellSurface1(Test::createLayerSurfaceV1(surface1.get(), QStringLiteral("test"))); + shellSurface1->set_layer(Test::LayerShellV1::layer_bottom); + shellSurface1->set_size(200, 100); + surface1->commit(KWayland::Client::Surface::CommitFlag::None); + + std::unique_ptr surface2(Test::createSurface()); + std::unique_ptr shellSurface2(Test::createLayerSurfaceV1(surface2.get(), QStringLiteral("test"))); + shellSurface2->set_layer(Test::LayerShellV1::layer_bottom); + shellSurface2->set_size(200, 100); + surface2->commit(KWayland::Client::Surface::CommitFlag::None); + + // Wait for the compositor to position the surfaces. + QSignalSpy configureRequestedSpy1(shellSurface1.get(), &Test::LayerSurfaceV1::configureRequested); + QSignalSpy configureRequestedSpy2(shellSurface2.get(), &Test::LayerSurfaceV1::configureRequested); + QVERIFY(configureRequestedSpy2.wait()); + const QSize requestedSize1 = configureRequestedSpy1.last().at(1).toSize(); + const QSize requestedSize2 = configureRequestedSpy2.last().at(1).toSize(); + + // Map the layer surfaces. + shellSurface1->ack_configure(configureRequestedSpy1.last().at(0).toUInt()); + Window *window1 = Test::renderAndWaitForShown(surface1.get(), requestedSize1, Qt::red); + QVERIFY(window1); + shellSurface2->ack_configure(configureRequestedSpy2.last().at(0).toUInt()); + Window *window2 = Test::renderAndWaitForShown(surface2.get(), requestedSize2, Qt::red); + QVERIFY(window2); + + // The first layer shell window is stacked below the second one. + QCOMPARE(workspace()->stackingOrder(), (QList{window1, window2})); + + // Move the first layer shell window to the top layer. + QSignalSpy stackingOrderChangedSpy(workspace(), &Workspace::stackingOrderChanged); + shellSurface1->set_layer(Test::LayerShellV1::layer_top); + surface1->commit(KWayland::Client::Surface::CommitFlag::None); + QVERIFY(stackingOrderChangedSpy.wait()); + + // The first layer shell window should be on top now. + QCOMPARE(workspace()->stackingOrder(), (QList{window2, window1})); + + // Destroy the window. + shellSurface1.reset(); + QVERIFY(Test::waitForWindowClosed(window1)); + shellSurface2.reset(); + QVERIFY(Test::waitForWindowClosed(window2)); +} + void LayerShellV1WindowTest::testPlacementArea_data() { QTest::addColumn("anchor"); diff --git a/src/layershellv1integration.cpp b/src/layershellv1integration.cpp index 12f3b02b56..3d9f02a326 100644 --- a/src/layershellv1integration.cpp +++ b/src/layershellv1integration.cpp @@ -148,6 +148,8 @@ static void rearrangeLayer(const QList &windows, QRect *wo geometry.setBottom(window->virtualKeyboardGeometry().top()); } + window->updateLayer(); + if (geometry.isValid()) { window->moveResize(geometry); } else {