Send SurfaceInterface::enter events after clients bind to outputs

The following order of events are legal:

Typically order is:
 - server announces a new output
 - client binds to a new output
 - server updates the surface to be on new output

But we can have events occur in the following order:

 - server announces a new output
 - server updates the surface to be on new output
 - client binds to a new output

At which point when we update the surface there is no ID to tell the
client which output the surface is on.

This patch watches for clients binding to output and updates
appropriately.
This commit is contained in:
David Edmundson 2021-01-12 11:10:50 +00:00
parent 6566c91e39
commit fbe8aff439
4 changed files with 19 additions and 1 deletions

View file

@ -337,6 +337,8 @@ void OutputInterface::Private::bind(wl_client *client, uint32_t version, uint32_
sendDone(r); sendDone(r);
c->flush(); c->flush();
emit q->bound(display->getConnection(client), r.resource);
} }
void OutputInterface::Private::unbind(wl_resource *resource) void OutputInterface::Private::unbind(wl_resource *resource)

View file

@ -148,6 +148,12 @@ Q_SIGNALS:
**/ **/
void dpmsModeRequested(KWaylandServer::OutputInterface::DpmsMode mode); void dpmsModeRequested(KWaylandServer::OutputInterface::DpmsMode mode);
/**
* Emitted when a client binds to a given output
* @internal
*/
void bound(ClientConnection *client, wl_resource *boundResource);
private: private:
class Private; class Private;
Private *d_func() const; Private *d_func() const;

View file

@ -832,6 +832,7 @@ void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &outputs)
d->send_leave(outputResource); d->send_leave(outputResource);
} }
disconnect(d->outputDestroyedConnections.take(*it)); disconnect(d->outputDestroyedConnections.take(*it));
disconnect(d->outputBoundConnections.take(*it));
} }
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) {
@ -849,8 +850,15 @@ void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &outputs)
if (outputs.removeOne(o)) { if (outputs.removeOne(o)) {
setOutputs(outputs); setOutputs(outputs);
}}); }});
Q_ASSERT(!d->outputBoundConnections.contains(o));
d->outputBoundConnections[o] = connect(o, &OutputInterface::bound, this, [this](ClientConnection *c, wl_resource *outputResource) {
if (c != client()) {
return;
}
d->send_enter(outputResource);
});
} }
// TODO: send enter when the client binds the OutputInterface another time
d->outputs = outputs; d->outputs = outputs;
for (auto child : d->current.children) { for (auto child : d->current.children) {

View file

@ -117,6 +117,8 @@ public:
LockedPointerV1Interface *lockedPointer = nullptr; LockedPointerV1Interface *lockedPointer = nullptr;
ConfinedPointerV1Interface *confinedPointer = nullptr; ConfinedPointerV1Interface *confinedPointer = nullptr;
QHash<OutputInterface*, QMetaObject::Connection> outputDestroyedConnections; QHash<OutputInterface*, QMetaObject::Connection> outputDestroyedConnections;
QHash<OutputInterface*, QMetaObject::Connection> outputBoundConnections;
QVector<IdleInhibitorV1Interface*> idleInhibitors; QVector<IdleInhibitorV1Interface*> idleInhibitors;
ViewportInterface *viewportExtension = nullptr; ViewportInterface *viewportExtension = nullptr;
SurfaceInterface *dataProxy = nullptr; SurfaceInterface *dataProxy = nullptr;