summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Edmundson <[email protected]>2025-05-24 21:55:24 +0300
committerDavid Edmundson <[email protected]>2025-05-29 21:06:53 +0300
commite9e025a085074ef9c0fca2953667ea722b66533c (patch)
treefcfcb68c0926d57be3ef797eafaa06bed42a8193
parent6a21e0e212732fb2b919f5dd18b1c48ef7285162 (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.cpp57
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow_p.h1
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;