client: Cache exposed state and unify sending events
Right now we are sending an expose event on every configure event because exposure may have changed. This causes an overhead. The mechanism for sending expose events is also scattered, there are a lot of properties that affect exposure, having everyone track the full state gets messy. This is cleanup work to then be able to land viewport clipping and synchronous event delivery. Change-Id: I192b908cdb6f6adda7d0e33f83961861e09504e8 Reviewed-by: Vlad Zahorodnii <vlad.zahorodnii@kde.org>
This commit is contained in:
parent
18355d9d37
commit
e705040909
@ -406,8 +406,6 @@ bool QWaylandXdgSurface::handleExpose(const QRegion ®ion)
|
||||
|
||||
void QWaylandXdgSurface::applyConfigure()
|
||||
{
|
||||
bool wasExposed = isExposed();
|
||||
|
||||
// It is a redundant ack_configure, so skipped.
|
||||
if (m_pendingConfigureSerial == m_appliedConfigureSerial)
|
||||
return;
|
||||
@ -421,8 +419,7 @@ void QWaylandXdgSurface::applyConfigure()
|
||||
m_configured = true;
|
||||
ack_configure(m_appliedConfigureSerial);
|
||||
|
||||
if (!wasExposed && isExposed())
|
||||
m_window->sendRecursiveExposeEvent();
|
||||
window()->updateExposure();
|
||||
}
|
||||
|
||||
bool QWaylandXdgSurface::wantsDecorations() const
|
||||
|
@ -326,7 +326,7 @@ void QWaylandWindow::reset()
|
||||
mCanResize = true;
|
||||
mResizeDirty = false;
|
||||
mScale = std::nullopt;
|
||||
|
||||
mExposed = false;
|
||||
mOpaqueArea = QRegion();
|
||||
mMask = QRegion();
|
||||
|
||||
@ -544,11 +544,12 @@ void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, cons
|
||||
|
||||
void QWaylandWindow::sendExposeEvent(const QRect &rect)
|
||||
{
|
||||
if (!(mShellSurface && mShellSurface->handleExpose(rect)))
|
||||
if (!(mShellSurface && mShellSurface->handleExpose(rect))) {
|
||||
QWindowSystemInterface::handleExposeEvent(window(), rect);
|
||||
mLastExposeGeometry = rect;
|
||||
}
|
||||
else
|
||||
qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending";
|
||||
mLastExposeGeometry = rect;
|
||||
}
|
||||
|
||||
QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
|
||||
@ -572,6 +573,7 @@ void QWaylandWindow::setVisible(bool visible)
|
||||
initWindow();
|
||||
|
||||
setGeometry(windowGeometry());
|
||||
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().
|
||||
@ -579,6 +581,8 @@ void QWaylandWindow::setVisible(bool visible)
|
||||
if (mShellSurface)
|
||||
mShellSurface->requestActivateOnShow();
|
||||
} else {
|
||||
// make sure isExposed is false during the next event dispatch
|
||||
mExposed = false;
|
||||
sendExposeEvent(QRect());
|
||||
reset();
|
||||
}
|
||||
@ -654,6 +658,8 @@ void QWaylandWindow::doApplyConfigure()
|
||||
mShellSurface->applyConfigure();
|
||||
|
||||
mWaitingToApplyConfigure = false;
|
||||
|
||||
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||
}
|
||||
|
||||
void QWaylandWindow::doApplyConfigureFromOtherThread()
|
||||
@ -662,7 +668,6 @@ void QWaylandWindow::doApplyConfigureFromOtherThread()
|
||||
if (!mCanResize || !mWaitingToApplyConfigure)
|
||||
return;
|
||||
doApplyConfigure();
|
||||
sendRecursiveExposeEvent();
|
||||
}
|
||||
|
||||
void QWaylandWindow::setCanResize(bool canResize)
|
||||
@ -678,13 +683,11 @@ void QWaylandWindow::setCanResize(bool canResize)
|
||||
bool inGuiThread = QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed();
|
||||
if (inGuiThread) {
|
||||
doApplyConfigure();
|
||||
sendRecursiveExposeEvent();
|
||||
} else {
|
||||
QMetaObject::invokeMethod(this, &QWaylandWindow::doApplyConfigureFromOtherThread, Qt::QueuedConnection);
|
||||
}
|
||||
} else if (mResizeDirty) {
|
||||
mResizeDirty = false;
|
||||
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -697,23 +700,9 @@ void QWaylandWindow::applyConfigure()
|
||||
doApplyConfigure();
|
||||
|
||||
lock.unlock();
|
||||
sendRecursiveExposeEvent();
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
}
|
||||
|
||||
void QWaylandWindow::sendRecursiveExposeEvent()
|
||||
{
|
||||
if (!isExposed())
|
||||
sendExposeEvent(QRect());
|
||||
else
|
||||
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||
|
||||
for (QWaylandSubSurface *subSurface : std::as_const(mChildren)) {
|
||||
auto subWindow = subSurface->window();
|
||||
subWindow->sendRecursiveExposeEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
|
||||
{
|
||||
QReadLocker locker(&mSurfaceLock);
|
||||
@ -843,8 +832,8 @@ void QWaylandWindow::doHandleFrameCallback()
|
||||
mWaitingForUpdateDelivery.storeRelease(false);
|
||||
bool wasExposed = isExposed();
|
||||
mFrameCallbackTimedOut = false;
|
||||
if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
|
||||
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||
// Did setting mFrameCallbackTimedOut make the window exposed?
|
||||
updateExposure();
|
||||
if (wasExposed && hasPendingUpdateRequest())
|
||||
deliverUpdateRequest();
|
||||
|
||||
@ -861,7 +850,7 @@ bool QWaylandWindow::waitForFrameSync(int timeout)
|
||||
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
||||
mFrameCallbackTimedOut = true;
|
||||
mWaitingForUpdate = false;
|
||||
sendExposeEvent(QRect());
|
||||
updateExposure();
|
||||
}
|
||||
|
||||
return !mWaitingForFrameCallback;
|
||||
@ -1517,7 +1506,7 @@ void QWaylandWindow::requestActivateWindow()
|
||||
mShellSurface->requestActivate();
|
||||
}
|
||||
|
||||
bool QWaylandWindow::isExposed() const
|
||||
bool QWaylandWindow::calculateExposure() const
|
||||
{
|
||||
if (!window()->isVisible())
|
||||
return false;
|
||||
@ -1534,6 +1523,30 @@ bool QWaylandWindow::isExposed() const
|
||||
return !(shouldCreateShellSurface() || shouldCreateSubSurface());
|
||||
}
|
||||
|
||||
void QWaylandWindow::updateExposure()
|
||||
{
|
||||
bool exposed = calculateExposure();
|
||||
if (exposed == mExposed)
|
||||
return;
|
||||
|
||||
mExposed = exposed;
|
||||
|
||||
if (!exposed)
|
||||
sendExposeEvent(QRect());
|
||||
else
|
||||
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||
|
||||
for (QWaylandSubSurface *subSurface : std::as_const(mChildren)) {
|
||||
auto subWindow = subSurface->window();
|
||||
subWindow->updateExposure();
|
||||
}
|
||||
}
|
||||
|
||||
bool QWaylandWindow::isExposed() const
|
||||
{
|
||||
return mExposed;
|
||||
}
|
||||
|
||||
bool QWaylandWindow::isActive() const
|
||||
{
|
||||
return mDisplay->isWindowActivated(this);
|
||||
@ -1647,7 +1660,7 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
|
||||
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
||||
mFrameCallbackTimedOut = true;
|
||||
mWaitingForUpdate = false;
|
||||
sendExposeEvent(QRect());
|
||||
updateExposure();
|
||||
}
|
||||
|
||||
void QWaylandWindow::requestUpdate()
|
||||
|
@ -232,7 +232,10 @@ public:
|
||||
void endFrame();
|
||||
|
||||
void closeChildPopups();
|
||||
void sendRecursiveExposeEvent();
|
||||
|
||||
// should be invoked whenever a property that potentially affects
|
||||
// exposure changes
|
||||
void updateExposure();
|
||||
|
||||
virtual void reinit();
|
||||
void reset();
|
||||
@ -249,6 +252,9 @@ Q_SIGNALS:
|
||||
protected:
|
||||
virtual void doHandleFrameCallback();
|
||||
virtual QRect defaultGeometry() const;
|
||||
|
||||
// this should be called directly for buffer size changes only
|
||||
// use updateExposure for anything affecting the on/off state
|
||||
void sendExposeEvent(const QRect &rect);
|
||||
|
||||
QWaylandDisplay *mDisplay = nullptr;
|
||||
@ -299,6 +305,7 @@ protected:
|
||||
|
||||
// True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
|
||||
bool mWaitingForUpdate = false;
|
||||
bool mExposed = false;
|
||||
|
||||
QRecursiveMutex mResizeLock;
|
||||
bool mWaitingToApplyConfigure = false;
|
||||
@ -349,6 +356,7 @@ private:
|
||||
bool isOpaque() const;
|
||||
void updateInputRegion();
|
||||
void updateViewport();
|
||||
bool calculateExposure() const;
|
||||
|
||||
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
||||
void handleScreensChanged();
|
||||
|
Loading…
x
Reference in New Issue
Block a user