diff --git a/autotests/integration/shell_client_test.cpp b/autotests/integration/shell_client_test.cpp index c5b41db0ec..6c60737aad 100644 --- a/autotests/integration/shell_client_test.cpp +++ b/autotests/integration/shell_client_test.cpp @@ -49,6 +49,7 @@ private Q_SLOTS: void testMapUnmapMap_data(); void testMapUnmapMap(); void testDesktopPresenceChanged(); + void testTransientPositionAfterRemap(); }; void TestShellClient::initTestCase() @@ -199,5 +200,40 @@ void TestShellClient::testDesktopPresenceChanged() QCOMPARE(desktopPresenceChangedEffectsSpy.first().at(2).toInt(), 2); } +void TestShellClient::testTransientPositionAfterRemap() +{ + // this test simulates the situation that a transient window gets reused and the parent window + // moved between the two usages + QScopedPointer surface(Test::createSurface()); + QScopedPointer shellSurface(Test::createShellSurface(surface.data())); + auto c = Test::renderAndWaitForShown(surface.data(), QSize(100, 50), Qt::blue); + QVERIFY(c); + + // create the Transient window + QScopedPointer transientSurface(Test::createSurface()); + QScopedPointer transientShellSurface(Test::createShellSurface(transientSurface.data())); + transientShellSurface->setTransient(surface.data(), QPoint(5, 10)); + auto transient = Test::renderAndWaitForShown(transientSurface.data(), QSize(50, 40), Qt::blue); + QVERIFY(transient); + QCOMPARE(transient->geometry(), QRect(c->geometry().topLeft() + QPoint(5, 10), QSize(50, 40))); + + // unmap the transient + QSignalSpy windowHiddenSpy(transient, &ShellClient::windowHidden); + QVERIFY(windowHiddenSpy.isValid()); + transientSurface->attachBuffer(Buffer::Ptr()); + transientSurface->commit(Surface::CommitFlag::None); + QVERIFY(windowHiddenSpy.wait()); + + // now move the parent surface + c->setGeometry(c->geometry().translated(5, 10)); + + // now map the transient again + QSignalSpy windowShownSpy(transient, &ShellClient::windowShown); + QVERIFY(windowShownSpy.isValid()); + Test::render(transientSurface.data(), QSize(50, 40), Qt::blue); + QVERIFY(windowShownSpy.wait()); + QCOMPARE(transient->geometry(), QRect(c->geometry().topLeft() + QPoint(5, 10), QSize(50, 40))); +} + WAYLANDTEST_MAIN(TestShellClient) #include "shell_client_test.moc" diff --git a/workspace.cpp b/workspace.cpp index 42c15c678f..c62d073147 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -398,6 +398,11 @@ void Workspace::init() connect(c, &ShellClient::windowShown, this, [this, c] { updateClientLayer(c); + // TODO: when else should we send the client through placement? + if (c->hasTransientPlacementHint()) { + QRect area = clientArea(PlacementArea, Screens::self()->current(), c->desktop()); + Placement::self()->place(c, area); + } x_stacking_dirty = true; updateStackingOrder(true); updateClientArea();