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
This commit is contained in:
David Edmundson 2017-08-26 11:53:09 +01:00
parent ec8887ad27
commit 9b564c4069
5 changed files with 24 additions and 8 deletions

View file

@ -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<OutputInterface*>());
}
QTEST_GUILESS_MAIN(TestWaylandSurface)

View file

@ -70,6 +70,7 @@ void Global::destroy()
if (!d->global) {
return;
}
emit aboutToDestroyGlobal();
wl_global_destroy(d->global);
d->global = nullptr;
}

View file

@ -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);

View file

@ -793,19 +793,25 @@ void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &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<OutputInterface *> 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

View file

@ -97,6 +97,7 @@ public:
QPointer<LockedPointerInterface> lockedPointer;
QPointer<ConfinedPointerInterface> confinedPointer;
QHash<OutputInterface*, QMetaObject::Connection> outputDestroyedConnections;
private:
QMetaObject::Connection constrainsOneShotConnection;