diff options
author | David Edmundson <[email protected]> | 2025-05-24 21:55:24 +0300 |
---|---|---|
committer | David Edmundson <[email protected]> | 2025-05-29 21:06:53 +0300 |
commit | e9e025a085074ef9c0fca2953667ea722b66533c (patch) | |
tree | fcfcb68c0926d57be3ef797eafaa06bed42a8193 | |
parent | 6a21e0e212732fb2b919f5dd18b1c48ef7285162 (diff) |
wayland: Move to synchronous expose events
Move to synchronous delivery for expose events.
One twist with this the expose event from geometry events. This event
normally comes from the display server, but in our case is synthesised
by the backend. This needs to be deferred, but we can do that
internally.
The move to synchronous events allows us to drop an old workaround for
renders finishing after a window is hidden.
The mInResizeFromApplyConfigure guard in geometry changes existed as all
configure events trigger their own expose event and we didn't want two.
Not the sending is deferred it's implicity handled by the
mLastExposeGeometry check.
Task-number: QTBUG-137021
Change-Id: I8758c083e4d44a04606ae72f1019f2bc577f51f6
Reviewed-by: Vlad Zahorodnii <[email protected]>
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindow.cpp | 57 | ||||
-rw-r--r-- | src/plugins/platforms/wayland/qwaylandwindow_p.h | 1 |
2 files changed, 28 insertions, 30 deletions
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 49b4431ac98..f14ddb78d56 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -98,15 +98,6 @@ void QWaylandWindow::ensureSize() void QWaylandWindow::initWindow() { - /** - * Cleanup window state just before showing. - * This is necessary because a render could still have been running and commit - * after the window was last hidden and the last null was attached - * - * When we port to synchronous delivery it should be possible to drop this - */ - mSurface->attach(nullptr, 0, 0); - mSurface->commit(); resetFrameCallback(); if (window()->type() == Qt::Desktop) @@ -510,9 +501,22 @@ void QWaylandWindow::setGeometry(const QRect &r) QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window(), geometry()); mSentInitialResize = true; } + + // Wayland has no concept of areas being exposed or not, only the entire window, when our geometry changes, we need to flag the new area as exposed + // On other platforms (X11) the expose event would be received deferred from the X server + // we want our behaviour to match, and only run after control has returned to the event loop + QMetaObject::invokeMethod(this, &QWaylandWindow::synthesizeExposeOnGeometryChange, Qt::QueuedConnection); +} + +void QWaylandWindow::synthesizeExposeOnGeometryChange() +{ + if (!isExposed()) + return; QRect exposeGeometry(QPoint(), geometry().size()); - if (isExposed() && !mInResizeFromApplyConfigure && exposeGeometry != mLastExposeGeometry) - sendExposeEvent(exposeGeometry); + if (exposeGeometry == mLastExposeGeometry) + return; + + sendExposeEvent(exposeGeometry); } void QWaylandWindow::updateInputRegion() @@ -598,22 +602,20 @@ void QWaylandWindow::sendExposeEvent(const QRect &rect) if (sQtTestMode) { mExposeEventNeedsAttachedBuffer = true; - QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), rect); - /** - * If an expose is not handled by application code, explicitly attach a buffer - * This primarily is a workaround for Qt unit tests using QWindow directly and - * wanting focus. - */ - if (mExposeEventNeedsAttachedBuffer && !rect.isNull()) { - auto buffer = new QWaylandShmBuffer(mDisplay, rect.size(), QImage::Format_ARGB32); - buffer->image()->fill(Qt::transparent); - buffer->setDeleteOnRelease(true); - attach(buffer, 0, 0); - } - } else { - QWindowSystemInterface::handleExposeEvent(window(), rect); } + QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), rect); + /** + * If an expose is not handled by application code, explicitly attach a buffer + * This primarily is a workaround for Qt unit tests using QWindow directly and + * wanting focus. + */ + if (mExposeEventNeedsAttachedBuffer && !rect.isNull()) { + auto buffer = new QWaylandShmBuffer(mDisplay, rect.size(), QImage::Format_ARGB32); + buffer->image()->fill(Qt::transparent); + buffer->setDeleteOnRelease(true); + attach(buffer, 0, 0); + } } QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const @@ -637,10 +639,6 @@ void QWaylandWindow::setVisible(bool visible) setGeometry(windowGeometry()); initWindow(); updateExposure(); - // Don't flush the events here, or else the newly visible window may start drawing, but since - // there was no frame before it will be stuck at the waitForFrameSync() in - // QWaylandShmBackingStore::beginPaint(). - if (mShellSurface) mShellSurface->requestActivateOnShow(); } else { @@ -729,7 +727,6 @@ void QWaylandWindow::applyConfigure() mWaitingToApplyConfigure = false; QRect exposeGeometry(QPoint(), geometry().size()); sendExposeEvent(exposeGeometry); - QWindowSystemInterface::flushWindowSystemEvents(); } void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 2c5117a0db4..800cc817a09 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -363,6 +363,7 @@ protected: private: void setGeometry_helper(const QRect &rect); + void synthesizeExposeOnGeometryChange(); void initWindow(); bool shouldCreateShellSurface() const; bool shouldCreateSubSurface() const; |