From 88a0246a46c30e08e9730d16cf8739773447d058 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 24 Sep 2018 13:04:51 +0200 Subject: Client: Don't attach buffers to unexposed windows QBackingStore::flush is sometimes called with an unxeposed window, in that case, don't attach the buffer to the wl_surface immediately, as that causes protocol errors with xdg_shell. Flushed buffers are instead stored until we get the first configure event. [ChangeLog][QPA plugin][xdg-shell] Fixed a bug where buffers were sometimes attached and committed before the first configure event, causing protocol errors. Fixes: QTBUG-71345 Change-Id: If9409d97bd25f6b13940c56141920a664c349c8e Reviewed-by: Paul Olav Tvete Reviewed-by: David Edmundson --- src/client/qwaylandshmbackingstore.cpp | 3 +-- src/client/qwaylandwindow.cpp | 22 ++++++++++++++++++++++ src/client/qwaylandwindow_p.h | 4 ++++ 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'src/client') diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp index ecb03c0d6..3fe2ce80c 100644 --- a/src/client/qwaylandshmbackingstore.cpp +++ b/src/client/qwaylandshmbackingstore.cpp @@ -234,8 +234,7 @@ void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, cons mFrontBuffer = mBackBuffer; QMargins margins = windowDecorationMargins(); - - waylandWindow()->commit(mFrontBuffer, region.translated(margins.left(), margins.top())); + waylandWindow()->safeCommit(mFrontBuffer, region.translated(margins.left(), margins.top())); } void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &) diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 52bee6ae3..1801c2a4b 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -248,6 +248,7 @@ void QWaylandWindow::reset(bool sendDestroyEvent) } mMask = QRegion(); + mQueuedBuffer = nullptr; } QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface) @@ -566,8 +567,29 @@ void QWaylandWindow::damage(const QRect &rect) damage(rect.x(), rect.y(), rect.width(), rect.height()); } +void QWaylandWindow::safeCommit(QWaylandBuffer *buffer, const QRegion &damage) +{ + if (isExposed()) { + commit(buffer, damage); + } else { + mQueuedBuffer = buffer; + mQueuedBufferDamage = damage; + } +} + +void QWaylandWindow::handleExpose(const QRegion ®ion) +{ + QWindowSystemInterface::handleExposeEvent(window(), region); + if (mQueuedBuffer) { + commit(mQueuedBuffer, mQueuedBufferDamage); + mQueuedBuffer = nullptr; + mQueuedBufferDamage = QRegion(); + } +} + void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage) { + Q_ASSERT(isExposed()); if (buffer->committed()) { qCDebug(lcWaylandBackingstore) << "Buffer already committed, ignoring."; return; diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index d11ed871b..ad24b7358 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -116,6 +116,8 @@ public: using QtWayland::wl_surface::damage; void damage(const QRect &rect); + void safeCommit(QWaylandBuffer *buffer, const QRegion &damage); + void handleExpose(const QRegion ®ion); void commit(QWaylandBuffer *buffer, const QRegion &damage); void waitForFrameSync(); @@ -231,6 +233,8 @@ protected: Qt::WindowStates mLastReportedWindowStates = Qt::WindowNoState; QWaylandShmBackingStore *mBackingStore = nullptr; + QWaylandBuffer *mQueuedBuffer = nullptr; + QRegion mQueuedBufferDamage; private slots: void handleScreenRemoved(QScreen *qScreen); -- cgit v1.2.3