platforms/wayland: Delay setup until first configure
As per the xdg-shell specification, the compositor can only attach a wl_buffer to an xdg_surface once the compositor has sent an xdg_surface.configure event. Previously, there was a race condition in which WaylandOutput objects were added/enabled on creation, making it possible for the EglWaylandOutputs to be set up and for EglWaylandBackend to draw a frame (thereby attaching a buffer), all before the xdg_surface.configure configure event was received. Compositors other than kwin would then send an unconfigured buffer error and close the connection. This commit avoids the problem by not marking the WaylandBackend ready for use until all the output surfaces constructed at startup have received their initial configure event. (In practice, this takes one additional roundtrip.)
This commit is contained in:
parent
1bf901cfbf
commit
9be3513348
4 changed files with 32 additions and 7 deletions
|
@ -739,12 +739,11 @@ void WaylandBackend::createOutputs()
|
|||
});
|
||||
|
||||
logicalWidthSum += logicalWidth;
|
||||
m_outputs << waylandOutput;
|
||||
Q_EMIT outputAdded(waylandOutput);
|
||||
Q_EMIT outputEnabled(waylandOutput);
|
||||
|
||||
// The output will only actually be added when it receives its first
|
||||
// configure event, and buffers can start being attached
|
||||
m_pendingInitialOutputs++;
|
||||
}
|
||||
setReady(true);
|
||||
Q_EMIT screensQueried();
|
||||
}
|
||||
|
||||
void WaylandBackend::destroyOutputs()
|
||||
|
@ -852,6 +851,22 @@ Outputs WaylandBackend::enabledOutputs() const
|
|||
return m_outputs;
|
||||
}
|
||||
|
||||
void WaylandBackend::addConfiguredOutput(WaylandOutput *output)
|
||||
{
|
||||
m_outputs << output;
|
||||
Q_EMIT outputAdded(output);
|
||||
Q_EMIT outputEnabled(output);
|
||||
|
||||
m_pendingInitialOutputs--;
|
||||
if (m_pendingInitialOutputs == 0) {
|
||||
// Mark as ready once all the initial set of screens has arrived
|
||||
// (i.e, received their first configure and it is now safe to commit
|
||||
// buffers to them)
|
||||
setReady(true);
|
||||
Q_EMIT screensQueried();
|
||||
}
|
||||
}
|
||||
|
||||
DmaBufTexture *WaylandBackend::createDmaBufTexture(const QSize& size)
|
||||
{
|
||||
#if HAVE_GBM && HAVE_WAYLAND_EGL
|
||||
|
|
|
@ -200,6 +200,7 @@ public:
|
|||
QVector<WaylandOutput*> waylandOutputs() const {
|
||||
return m_outputs;
|
||||
}
|
||||
void addConfiguredOutput(WaylandOutput *output);
|
||||
void createDpmsFilter();
|
||||
void clearDpmsFilter();
|
||||
|
||||
|
@ -235,6 +236,7 @@ private:
|
|||
|
||||
QThread *m_connectionThread;
|
||||
QVector<WaylandOutput*> m_outputs;
|
||||
int m_pendingInitialOutputs = 0;
|
||||
|
||||
WaylandCursor *m_waylandCursor = nullptr;
|
||||
|
||||
|
|
|
@ -145,11 +145,18 @@ XdgShellOutput::~XdgShellOutput()
|
|||
void XdgShellOutput::handleConfigure(const QSize &size, XdgShellSurface::States states, quint32 serial)
|
||||
{
|
||||
Q_UNUSED(states);
|
||||
m_xdgShellSurface->ackConfigure(serial);
|
||||
if (size.width() > 0 && size.height() > 0) {
|
||||
setGeometry(geometry().topLeft(), size);
|
||||
Q_EMIT sizeChanged(size);
|
||||
if (m_hasBeenConfigured) {
|
||||
Q_EMIT sizeChanged(size);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_hasBeenConfigured) {
|
||||
m_hasBeenConfigured = true;
|
||||
backend()->addConfiguredOutput(this);
|
||||
}
|
||||
m_xdgShellSurface->ackConfigure(serial);
|
||||
}
|
||||
|
||||
void XdgShellOutput::updateWindowTitle()
|
||||
|
|
|
@ -110,6 +110,7 @@ private:
|
|||
int m_number;
|
||||
KWayland::Client::LockedPointer *m_pointerLock = nullptr;
|
||||
bool m_hasPointerLock = false;
|
||||
bool m_hasBeenConfigured = false;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue