From 9b564c4069c599bf9269608d19dfa3084e37e6c1 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Sat, 26 Aug 2017 11:53:09 +0100 Subject: [PATCH] Update SurfaceInterface outputs when an output global gets destroyed Summary: As per existing TODO. A new signal is added on Global to emit so we can process the result whist we still have a valid object. The name is overly explicit to try and logically separate it from QObject::destroyed(). Test Plan: Updated existing unit test. Reviewers: #plasma, graesslin Reviewed By: #plasma, graesslin Subscribers: graesslin, anthonyfieroni, plasma-devel, #frameworks Tags: #frameworks, #plasma_on_wayland Differential Revision: https://phabricator.kde.org/D7531 --- .../autotests/client/test_wayland_surface.cpp | 10 +++++----- src/wayland/server/global.cpp | 1 + src/wayland/server/global.h | 8 ++++++++ src/wayland/surface_interface.cpp | 12 +++++++++--- src/wayland/surface_interface_p.h | 1 + 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/wayland/autotests/client/test_wayland_surface.cpp b/src/wayland/autotests/client/test_wayland_surface.cpp index 2b79dac7f6..0f79c7b921 100644 --- a/src/wayland/autotests/client/test_wayland_surface.cpp +++ b/src/wayland/autotests/client/test_wayland_surface.cpp @@ -1077,11 +1077,11 @@ void TestWaylandSurface::testOutput() QCOMPARE(enteredSpy.count(), 2); QCOMPARE(leftSpy.count(), 1); - //test the client handles a misbehaving server that removes a display before updating clients - m_display->removeOutput(serverOutput); - QCOMPARE(leftSpy.count(), 1); - QVERIFY(s->outputs().isEmpty()); - + //delete output client is on. + //client should get an exit and be left on no outputs (which is allowed) + serverOutput->deleteLater(); + QVERIFY(leftSpy.wait()); + QCOMPARE(serverSurface->outputs(), QVector()); } QTEST_GUILESS_MAIN(TestWaylandSurface) diff --git a/src/wayland/server/global.cpp b/src/wayland/server/global.cpp index ac929633cc..6c765cdca4 100644 --- a/src/wayland/server/global.cpp +++ b/src/wayland/server/global.cpp @@ -70,6 +70,7 @@ void Global::destroy() if (!d->global) { return; } + emit aboutToDestroyGlobal(); wl_global_destroy(d->global); d->global = nullptr; } diff --git a/src/wayland/server/global.h b/src/wayland/server/global.h index 6883a98a15..e13d6ba225 100644 --- a/src/wayland/server/global.h +++ b/src/wayland/server/global.h @@ -90,6 +90,14 @@ public: **/ operator wl_global*() const; +Q_SIGNALS: + /** + * This signal is emitted when the client is in the process of removing the wl_global. + * At the time the signal is emitted the global is still valid and allows to perform + * cleanup tasks. + */ + void aboutToDestroyGlobal(); + protected: class Private; explicit Global(Private *d, QObject *parent = nullptr); diff --git a/src/wayland/surface_interface.cpp b/src/wayland/surface_interface.cpp index faac902881..37179a643c 100644 --- a/src/wayland/surface_interface.cpp +++ b/src/wayland/surface_interface.cpp @@ -793,19 +793,25 @@ void SurfaceInterface::setOutputs(const QVector &outputs) for (wl_resource *r : resources) { wl_surface_send_leave(d->resource, r); } + disconnect(d->outputDestroyedConnections.take(*it)); } - // TODO: send leave when OutputInterface gets destroyed - QVector addedOutputsOutputs = outputs; for (auto it = d->outputs.constBegin(), end = d->outputs.constEnd(); it != end; ++it) { const auto o = *it; addedOutputsOutputs.removeOne(o); } for (auto it = addedOutputsOutputs.constBegin(), end = addedOutputsOutputs.constEnd(); it != end; ++it) { - const auto resources = (*it)->clientResources(client()); + const auto o = *it; + const auto resources = o->clientResources(client()); for (wl_resource *r : resources) { wl_surface_send_enter(d->resource, r); } + d->outputDestroyedConnections[o] = connect(o, &Global::aboutToDestroyGlobal, this, [this, o] { + Q_D(); + auto outputs = d->outputs; + if (outputs.removeOne(o)) { + setOutputs(outputs); + }}); } // TODO: send enter when the client binds the OutputInterface another time diff --git a/src/wayland/surface_interface_p.h b/src/wayland/surface_interface_p.h index 484e2f7d26..30c39dbf45 100644 --- a/src/wayland/surface_interface_p.h +++ b/src/wayland/surface_interface_p.h @@ -97,6 +97,7 @@ public: QPointer lockedPointer; QPointer confinedPointer; + QHash outputDestroyedConnections; private: QMetaObject::Connection constrainsOneShotConnection;