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 <vlad.zahorodnii@kde.org>
This commit is contained in:
parent
6a21e0e212
commit
e9e025a085
@ -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)
|
||||
|
@ -363,6 +363,7 @@ protected:
|
||||
|
||||
private:
|
||||
void setGeometry_helper(const QRect &rect);
|
||||
void synthesizeExposeOnGeometryChange();
|
||||
void initWindow();
|
||||
bool shouldCreateShellSurface() const;
|
||||
bool shouldCreateSubSurface() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user