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()
|
void QWaylandXdgSurface::applyConfigure()
|
||||||
{
|
{
|
||||||
bool wasExposed = isExposed();
|
|
||||||
|
|
||||||
// It is a redundant ack_configure, so skipped.
|
// It is a redundant ack_configure, so skipped.
|
||||||
if (m_pendingConfigureSerial == m_appliedConfigureSerial)
|
if (m_pendingConfigureSerial == m_appliedConfigureSerial)
|
||||||
return;
|
return;
|
||||||
@ -421,8 +419,7 @@ void QWaylandXdgSurface::applyConfigure()
|
|||||||
m_configured = true;
|
m_configured = true;
|
||||||
ack_configure(m_appliedConfigureSerial);
|
ack_configure(m_appliedConfigureSerial);
|
||||||
|
|
||||||
if (!wasExposed && isExposed())
|
window()->updateExposure();
|
||||||
m_window->sendRecursiveExposeEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWaylandXdgSurface::wantsDecorations() const
|
bool QWaylandXdgSurface::wantsDecorations() const
|
||||||
|
@ -326,7 +326,7 @@ void QWaylandWindow::reset()
|
|||||||
mCanResize = true;
|
mCanResize = true;
|
||||||
mResizeDirty = false;
|
mResizeDirty = false;
|
||||||
mScale = std::nullopt;
|
mScale = std::nullopt;
|
||||||
|
mExposed = false;
|
||||||
mOpaqueArea = QRegion();
|
mOpaqueArea = QRegion();
|
||||||
mMask = QRegion();
|
mMask = QRegion();
|
||||||
|
|
||||||
@ -544,11 +544,12 @@ void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, cons
|
|||||||
|
|
||||||
void QWaylandWindow::sendExposeEvent(const QRect &rect)
|
void QWaylandWindow::sendExposeEvent(const QRect &rect)
|
||||||
{
|
{
|
||||||
if (!(mShellSurface && mShellSurface->handleExpose(rect)))
|
if (!(mShellSurface && mShellSurface->handleExpose(rect))) {
|
||||||
QWindowSystemInterface::handleExposeEvent(window(), rect);
|
QWindowSystemInterface::handleExposeEvent(window(), rect);
|
||||||
|
mLastExposeGeometry = rect;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending";
|
qCDebug(lcQpaWayland) << "sendExposeEvent: intercepted by shell extension, not sending";
|
||||||
mLastExposeGeometry = rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
|
QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const
|
||||||
@ -572,6 +573,7 @@ void QWaylandWindow::setVisible(bool visible)
|
|||||||
initWindow();
|
initWindow();
|
||||||
|
|
||||||
setGeometry(windowGeometry());
|
setGeometry(windowGeometry());
|
||||||
|
updateExposure();
|
||||||
// Don't flush the events here, or else the newly visible window may start drawing, but since
|
// 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
|
// there was no frame before it will be stuck at the waitForFrameSync() in
|
||||||
// QWaylandShmBackingStore::beginPaint().
|
// QWaylandShmBackingStore::beginPaint().
|
||||||
@ -579,6 +581,8 @@ void QWaylandWindow::setVisible(bool visible)
|
|||||||
if (mShellSurface)
|
if (mShellSurface)
|
||||||
mShellSurface->requestActivateOnShow();
|
mShellSurface->requestActivateOnShow();
|
||||||
} else {
|
} else {
|
||||||
|
// make sure isExposed is false during the next event dispatch
|
||||||
|
mExposed = false;
|
||||||
sendExposeEvent(QRect());
|
sendExposeEvent(QRect());
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
@ -654,6 +658,8 @@ void QWaylandWindow::doApplyConfigure()
|
|||||||
mShellSurface->applyConfigure();
|
mShellSurface->applyConfigure();
|
||||||
|
|
||||||
mWaitingToApplyConfigure = false;
|
mWaitingToApplyConfigure = false;
|
||||||
|
|
||||||
|
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandWindow::doApplyConfigureFromOtherThread()
|
void QWaylandWindow::doApplyConfigureFromOtherThread()
|
||||||
@ -662,7 +668,6 @@ void QWaylandWindow::doApplyConfigureFromOtherThread()
|
|||||||
if (!mCanResize || !mWaitingToApplyConfigure)
|
if (!mCanResize || !mWaitingToApplyConfigure)
|
||||||
return;
|
return;
|
||||||
doApplyConfigure();
|
doApplyConfigure();
|
||||||
sendRecursiveExposeEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandWindow::setCanResize(bool canResize)
|
void QWaylandWindow::setCanResize(bool canResize)
|
||||||
@ -678,13 +683,11 @@ void QWaylandWindow::setCanResize(bool canResize)
|
|||||||
bool inGuiThread = QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed();
|
bool inGuiThread = QThread::currentThreadId() == QThreadData::get2(thread())->threadId.loadRelaxed();
|
||||||
if (inGuiThread) {
|
if (inGuiThread) {
|
||||||
doApplyConfigure();
|
doApplyConfigure();
|
||||||
sendRecursiveExposeEvent();
|
|
||||||
} else {
|
} else {
|
||||||
QMetaObject::invokeMethod(this, &QWaylandWindow::doApplyConfigureFromOtherThread, Qt::QueuedConnection);
|
QMetaObject::invokeMethod(this, &QWaylandWindow::doApplyConfigureFromOtherThread, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
} else if (mResizeDirty) {
|
} else if (mResizeDirty) {
|
||||||
mResizeDirty = false;
|
mResizeDirty = false;
|
||||||
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -697,23 +700,9 @@ void QWaylandWindow::applyConfigure()
|
|||||||
doApplyConfigure();
|
doApplyConfigure();
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
sendRecursiveExposeEvent();
|
|
||||||
QWindowSystemInterface::flushWindowSystemEvents();
|
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)
|
void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y)
|
||||||
{
|
{
|
||||||
QReadLocker locker(&mSurfaceLock);
|
QReadLocker locker(&mSurfaceLock);
|
||||||
@ -843,8 +832,8 @@ void QWaylandWindow::doHandleFrameCallback()
|
|||||||
mWaitingForUpdateDelivery.storeRelease(false);
|
mWaitingForUpdateDelivery.storeRelease(false);
|
||||||
bool wasExposed = isExposed();
|
bool wasExposed = isExposed();
|
||||||
mFrameCallbackTimedOut = false;
|
mFrameCallbackTimedOut = false;
|
||||||
if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
|
// Did setting mFrameCallbackTimedOut make the window exposed?
|
||||||
sendExposeEvent(QRect(QPoint(), geometry().size()));
|
updateExposure();
|
||||||
if (wasExposed && hasPendingUpdateRequest())
|
if (wasExposed && hasPendingUpdateRequest())
|
||||||
deliverUpdateRequest();
|
deliverUpdateRequest();
|
||||||
|
|
||||||
@ -861,7 +850,7 @@ bool QWaylandWindow::waitForFrameSync(int timeout)
|
|||||||
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
||||||
mFrameCallbackTimedOut = true;
|
mFrameCallbackTimedOut = true;
|
||||||
mWaitingForUpdate = false;
|
mWaitingForUpdate = false;
|
||||||
sendExposeEvent(QRect());
|
updateExposure();
|
||||||
}
|
}
|
||||||
|
|
||||||
return !mWaitingForFrameCallback;
|
return !mWaitingForFrameCallback;
|
||||||
@ -1517,7 +1506,7 @@ void QWaylandWindow::requestActivateWindow()
|
|||||||
mShellSurface->requestActivate();
|
mShellSurface->requestActivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWaylandWindow::isExposed() const
|
bool QWaylandWindow::calculateExposure() const
|
||||||
{
|
{
|
||||||
if (!window()->isVisible())
|
if (!window()->isVisible())
|
||||||
return false;
|
return false;
|
||||||
@ -1534,6 +1523,30 @@ bool QWaylandWindow::isExposed() const
|
|||||||
return !(shouldCreateShellSurface() || shouldCreateSubSurface());
|
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
|
bool QWaylandWindow::isActive() const
|
||||||
{
|
{
|
||||||
return mDisplay->isWindowActivated(this);
|
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";
|
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
|
||||||
mFrameCallbackTimedOut = true;
|
mFrameCallbackTimedOut = true;
|
||||||
mWaitingForUpdate = false;
|
mWaitingForUpdate = false;
|
||||||
sendExposeEvent(QRect());
|
updateExposure();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandWindow::requestUpdate()
|
void QWaylandWindow::requestUpdate()
|
||||||
|
@ -232,7 +232,10 @@ public:
|
|||||||
void endFrame();
|
void endFrame();
|
||||||
|
|
||||||
void closeChildPopups();
|
void closeChildPopups();
|
||||||
void sendRecursiveExposeEvent();
|
|
||||||
|
// should be invoked whenever a property that potentially affects
|
||||||
|
// exposure changes
|
||||||
|
void updateExposure();
|
||||||
|
|
||||||
virtual void reinit();
|
virtual void reinit();
|
||||||
void reset();
|
void reset();
|
||||||
@ -249,6 +252,9 @@ Q_SIGNALS:
|
|||||||
protected:
|
protected:
|
||||||
virtual void doHandleFrameCallback();
|
virtual void doHandleFrameCallback();
|
||||||
virtual QRect defaultGeometry() const;
|
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);
|
void sendExposeEvent(const QRect &rect);
|
||||||
|
|
||||||
QWaylandDisplay *mDisplay = nullptr;
|
QWaylandDisplay *mDisplay = nullptr;
|
||||||
@ -299,6 +305,7 @@ protected:
|
|||||||
|
|
||||||
// True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
|
// True when we have called deliverRequestUpdate, but the client has not yet attached a new buffer
|
||||||
bool mWaitingForUpdate = false;
|
bool mWaitingForUpdate = false;
|
||||||
|
bool mExposed = false;
|
||||||
|
|
||||||
QRecursiveMutex mResizeLock;
|
QRecursiveMutex mResizeLock;
|
||||||
bool mWaitingToApplyConfigure = false;
|
bool mWaitingToApplyConfigure = false;
|
||||||
@ -349,6 +356,7 @@ private:
|
|||||||
bool isOpaque() const;
|
bool isOpaque() const;
|
||||||
void updateInputRegion();
|
void updateInputRegion();
|
||||||
void updateViewport();
|
void updateViewport();
|
||||||
|
bool calculateExposure() const;
|
||||||
|
|
||||||
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
|
||||||
void handleScreensChanged();
|
void handleScreensChanged();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user