From c51ab381da0e86d2b4714560a8c100ebd1a0d66e Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 8 Apr 2024 11:42:08 +0100 Subject: [PATCH] deferred apply When we get a configure event defer applying it until all pending callbacks are processsed. This ensures we only only process configure events that match the last thing we requested. --- src/qwaylandlayersurface.cpp | 43 ++++++++++++++++++++++++++---------- src/qwaylandlayersurface_p.h | 6 ++--- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/qwaylandlayersurface.cpp b/src/qwaylandlayersurface.cpp index d7c9538..743c303 100644 --- a/src/qwaylandlayersurface.cpp +++ b/src/qwaylandlayersurface.cpp @@ -67,13 +67,15 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, }); setDesiredSize(window->windowContentGeometry().size()); + requestWaylandSync(); } QWaylandLayerSurface::~QWaylandLayerSurface() { - if (m_waitForSyncCallback) { - wl_callback_destroy(m_waitForSyncCallback); + for (auto syncCallback: m_waitForSyncCallbacks) { + wl_callback_destroy(syncCallback); } + m_waitForSyncCallbacks.clear(); destroy(); } @@ -89,6 +91,13 @@ void QWaylandLayerSurface::zwlr_layer_surface_v1_configure(uint32_t serial, uint ack_configure(serial); m_pendingSize = QSize(width, height); + // because configure lacks a way to match it up with our resize requests + // we apply it only when our callback sync is complete + if (!m_waitForSyncCallbacks.isEmpty()) { + m_hasPendingConfigureToApply = true; + return; + } + if (!m_configured) { m_configured = true; applyConfigure(); @@ -98,6 +107,7 @@ void QWaylandLayerSurface::zwlr_layer_surface_v1_configure(uint32_t serial, uint // are not painting to the window. window()->applyConfigureWhenPossible(); } + } void QWaylandLayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface *popup) @@ -229,27 +239,36 @@ const wl_callback_listener QWaylandLayerSurface::syncCallbackListener = { Q_UNUSED(time); wl_callback_destroy(callback); QWaylandLayerSurface *layerSurface = static_cast(data); - layerSurface->m_waitForSyncCallback = nullptr; - layerSurface->sendExpose(); + layerSurface->m_waitForSyncCallbacks.removeOne(callback); + layerSurface->handleWaylandSyncDone(); } }; void QWaylandLayerSurface::requestWaylandSync() { - if (m_waitForSyncCallback) { - return; - } - - m_waitForSyncCallback = wl_display_sync(m_window->display()->wl_display()); - wl_callback_add_listener(m_waitForSyncCallback, &syncCallbackListener, this); + auto syncCallback = wl_display_sync(m_window->display()->wl_display()); + m_waitForSyncCallbacks.append(syncCallback); + wl_callback_add_listener(syncCallback, &syncCallbackListener, this); } void QWaylandLayerSurface::handleWaylandSyncDone() { - if (!window()->isExposed()) { + if (!window()->window()->isVisible() || !m_waitForSyncCallbacks.isEmpty()) { return; } - sendExpose(); + + if (m_hasPendingConfigureToApply) { + m_hasPendingConfigureToApply = false; + if (!m_configured) { + m_configured = true; + applyConfigure(); + sendExpose(); + } else { + // Later configures are resizes, so we have to queue them up for a time when we + // are not painting to the window. + window()->applyConfigureWhenPossible(); + } + } } void QWaylandLayerSurface::sendExpose() diff --git a/src/qwaylandlayersurface_p.h b/src/qwaylandlayersurface_p.h index dee81e1..a34a47a 100644 --- a/src/qwaylandlayersurface_p.h +++ b/src/qwaylandlayersurface_p.h @@ -30,7 +30,7 @@ public: bool isExposed() const override { - return m_configured && !m_waitForSyncCallback; + return m_configured && m_waitForSyncCallbacks.isEmpty(); } void attachPopup(QtWaylandClient::QWaylandShellSurface *popup) override; @@ -64,11 +64,11 @@ private: bool m_configured = false; bool m_configuring = false; + bool m_hasPendingConfigureToApply = false; static const wl_callback_listener syncCallbackListener; - struct wl_callback *m_waitForSyncCallback = nullptr; + QList m_waitForSyncCallbacks; }; - } #endif