Commit 151a910f authored by Martin Flöser's avatar Martin Flöser
Browse files

[server] Properly handle the case that a PlasmaWindow is unmapped before client bound it

Summary:
So far we directly destroyed the resource on the server side. But this
causes a wayland error when the client tries to cleanup. This results in
the client being destroyed. A problem which brings down plasmashell
regularly when short living windows are shown. This happens e.g. in
Dolphin with the adress auto complete.

This change addresses the problem by creating a temporary
PlasmaWindowInterface for the already unmapped window. It doesn't get
added to the list of known windows and it's only purpose is to properly
handle the unmap and the destroy of the just created resource.

Reviewers: #plasma

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D1734
parent 92c379d4
......@@ -48,6 +48,7 @@ private Q_SLOTS:
void testServerDelete();
void testActiveWindowOnUnmapped();
void testDeleteActiveWindow();
void testCreateAfterUnmap();
void cleanup();
......@@ -309,5 +310,35 @@ void TestWindowManagement::testDeleteActiveWindow()
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<KWayland::Client::PlasmaWindow*>();
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<KWayland::Server::PlasmaWindowInterface*>(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"
......@@ -169,13 +169,10 @@ void PlasmaWindowManagementInterface::Private::getWindowCallback(wl_client *clie
}
);
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);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment