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:
parent
ec8887ad27
commit
9b564c4069
5 changed files with 24 additions and 8 deletions
|
@ -1077,11 +1077,11 @@ void TestWaylandSurface::testOutput()
|
||||||
QCOMPARE(enteredSpy.count(), 2);
|
QCOMPARE(enteredSpy.count(), 2);
|
||||||
QCOMPARE(leftSpy.count(), 1);
|
QCOMPARE(leftSpy.count(), 1);
|
||||||
|
|
||||||
//test the client handles a misbehaving server that removes a display before updating clients
|
//delete output client is on.
|
||||||
m_display->removeOutput(serverOutput);
|
//client should get an exit and be left on no outputs (which is allowed)
|
||||||
QCOMPARE(leftSpy.count(), 1);
|
serverOutput->deleteLater();
|
||||||
QVERIFY(s->outputs().isEmpty());
|
QVERIFY(leftSpy.wait());
|
||||||
|
QCOMPARE(serverSurface->outputs(), QVector<OutputInterface*>());
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TestWaylandSurface)
|
QTEST_GUILESS_MAIN(TestWaylandSurface)
|
||||||
|
|
|
@ -70,6 +70,7 @@ void Global::destroy()
|
||||||
if (!d->global) {
|
if (!d->global) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
emit aboutToDestroyGlobal();
|
||||||
wl_global_destroy(d->global);
|
wl_global_destroy(d->global);
|
||||||
d->global = nullptr;
|
d->global = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,14 @@ public:
|
||||||
**/
|
**/
|
||||||
operator wl_global*() const;
|
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:
|
protected:
|
||||||
class Private;
|
class Private;
|
||||||
explicit Global(Private *d, QObject *parent = nullptr);
|
explicit Global(Private *d, QObject *parent = nullptr);
|
||||||
|
|
|
@ -793,19 +793,25 @@ void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &outputs)
|
||||||
for (wl_resource *r : resources) {
|
for (wl_resource *r : resources) {
|
||||||
wl_surface_send_leave(d->resource, r);
|
wl_surface_send_leave(d->resource, r);
|
||||||
}
|
}
|
||||||
|
disconnect(d->outputDestroyedConnections.take(*it));
|
||||||
}
|
}
|
||||||
// TODO: send leave when OutputInterface gets destroyed
|
|
||||||
|
|
||||||
QVector<OutputInterface *> addedOutputsOutputs = outputs;
|
QVector<OutputInterface *> addedOutputsOutputs = outputs;
|
||||||
for (auto it = d->outputs.constBegin(), end = d->outputs.constEnd(); it != end; ++it) {
|
for (auto it = d->outputs.constBegin(), end = d->outputs.constEnd(); it != end; ++it) {
|
||||||
const auto o = *it;
|
const auto o = *it;
|
||||||
addedOutputsOutputs.removeOne(o);
|
addedOutputsOutputs.removeOne(o);
|
||||||
}
|
}
|
||||||
for (auto it = addedOutputsOutputs.constBegin(), end = addedOutputsOutputs.constEnd(); it != end; ++it) {
|
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) {
|
for (wl_resource *r : resources) {
|
||||||
wl_surface_send_enter(d->resource, r);
|
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
|
// TODO: send enter when the client binds the OutputInterface another time
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,7 @@ public:
|
||||||
|
|
||||||
QPointer<LockedPointerInterface> lockedPointer;
|
QPointer<LockedPointerInterface> lockedPointer;
|
||||||
QPointer<ConfinedPointerInterface> confinedPointer;
|
QPointer<ConfinedPointerInterface> confinedPointer;
|
||||||
|
QHash<OutputInterface*, QMetaObject::Connection> outputDestroyedConnections;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMetaObject::Connection constrainsOneShotConnection;
|
QMetaObject::Connection constrainsOneShotConnection;
|
||||||
|
|
Loading…
Reference in a new issue