diff --git a/autotests/client/test_wayland_windowmanagement.cpp b/autotests/client/test_wayland_windowmanagement.cpp --- a/autotests/client/test_wayland_windowmanagement.cpp +++ b/autotests/client/test_wayland_windowmanagement.cpp @@ -48,6 +48,7 @@ void testServerDelete(); void testActiveWindowOnUnmapped(); void testDeleteActiveWindow(); + void testCreateAfterUnmap(); void cleanup(); @@ -309,5 +310,35 @@ QVERIFY(!m_windowManagement->activeWindow()); } +void TestWindowManagement::testCreateAfterUnmap() +{ + // this test verifies that we don't get a protocol error on client side when creating an already unmapped window. + QSignalSpy windowSpy(m_windowManagement, &KWayland::Client::PlasmaWindowManagement::windowCreated); + QVERIFY(windowSpy.isValid()); + // create and unmap in one go + // client will first handle the create, the unmap will be sent once the server side is bound + auto serverWindow = m_windowManagementInterface->createWindow(this); + serverWindow->unmap(); + QCOMPARE(m_windowManagementInterface->children().count(), 0); + QVERIFY(windowSpy.wait()); + QCOMPARE(windowSpy.count(), 1); + auto window = windowSpy.first().first().value(); + QVERIFY(window); + // now this is not yet on the server, on the server it will be after next roundtrip + // which we can trigger by waiting for destroy of the newly created window. + // why destroy? Because we will get the unmap which triggers a destroy + QSignalSpy clientDestroyedSpy(window, &QObject::destroyed); + QVERIFY(clientDestroyedSpy.isValid()); + QVERIFY(clientDestroyedSpy.wait()); + // the server side created a helper PlasmaWindowInterface with PlasmaWindowManagementInterface as parent + // it emitted unmapped so we can be sure it will be destroyed directly + QCOMPARE(m_windowManagementInterface->children().count(), 1); + auto helperWindow = qobject_cast(m_windowManagementInterface->children().first()); + QVERIFY(helperWindow); + QSignalSpy helperDestroyedSpy(helperWindow, &QObject::destroyed); + QVERIFY(helperDestroyedSpy.isValid()); + QVERIFY(helperDestroyedSpy.wait()); +} + QTEST_GUILESS_MAIN(TestWindowManagement) #include "test_wayland_windowmanagement.moc" diff --git a/src/server/plasmawindowmanagement_interface.cpp b/src/server/plasmawindowmanagement_interface.cpp --- a/src/server/plasmawindowmanagement_interface.cpp +++ b/src/server/plasmawindowmanagement_interface.cpp @@ -169,13 +169,10 @@ } ); if (it == p->windows.constEnd()) { - ClientConnection *c = p->q->display()->getConnection(client); - wl_resource *r = c->createResource(&org_kde_plasma_window_interface, wl_resource_get_version(resource), id); - if (!r) { - return; - } - org_kde_plasma_window_send_unmapped(r); - wl_resource_destroy(r); + // create a temp window just for the resource and directly send an unmapped + PlasmaWindowInterface *window = new PlasmaWindowInterface(p->q, p->q); + window->d->createResource(resource, id); + window->unmap(); return; } (*it)->d->createResource(resource, id);