diff options
-rw-r--r-- | src/plugins/platforms/wasm/qwasmbackingstore.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.cpp | 148 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.h | 19 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmscreen.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindow.cpp | 10 |
5 files changed, 116 insertions, 65 deletions
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.cpp b/src/plugins/platforms/wasm/qwasmbackingstore.cpp index 3d667ccf97..989c2a1b90 100644 --- a/src/plugins/platforms/wasm/qwasmbackingstore.cpp +++ b/src/plugins/platforms/wasm/qwasmbackingstore.cpp @@ -90,7 +90,7 @@ void QWasmBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoi Q_UNUSED(offset); m_dirty |= region; - m_compositor->requestRedraw(); + m_compositor->handleBackingStoreFlush(); } void QWasmBackingStore::updateTexture() diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 063144d71d..aa498c8238 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -28,6 +28,7 @@ ****************************************************************************/ #include "qwasmcompositor.h" +#include "qwasmeventdispatcher.h" #include "qwasmwindow.h" #include "qwasmstylepixmaps_p.h" @@ -69,6 +70,8 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen) QWasmCompositor::~QWasmCompositor() { + if (m_requestAnimationFrameId != -1) + emscripten_cancel_animation_frame(m_requestAnimationFrameId); destroy(); } @@ -148,7 +151,7 @@ void QWasmCompositor::setVisible(QWasmWindow *window, bool visible) else m_globalDamage = compositedWindow.window->geometry(); // repaint previously covered area. - requestRedraw(); + requestUpdateWindow(window, QWasmCompositor::ExposeEventDelivery); } void QWasmCompositor::raise(QWasmWindow *window) @@ -181,16 +184,7 @@ void QWasmCompositor::setParent(QWasmWindow *window, QWasmWindow *parent) { m_compositedWindows[window].parentWindow = parent; - requestRedraw(); -} - -void QWasmCompositor::flush(QWasmWindow *window, const QRegion ®ion) -{ - QWasmCompositedWindow &compositedWindow = m_compositedWindows[window]; - compositedWindow.flushPending = true; - compositedWindow.damage = region; - - requestRedraw(); + requestUpdate(); } int QWasmCompositor::windowCount() const @@ -198,28 +192,6 @@ int QWasmCompositor::windowCount() const return m_windowStack.count(); } - -void QWasmCompositor::redrawWindowContent() -{ - // Redraw window content by sending expose events. This redraw - // will cause a backing store flush, which will call requestRedraw() - // to composit. - for (QWasmWindow *platformWindow : m_windowStack) { - QWindow *window = platformWindow->window(); - QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>( - window, QRect(QPoint(0, 0), window->geometry().size())); - } -} - -void QWasmCompositor::requestRedraw() -{ - if (m_needComposit) - return; - - m_needComposit = true; - QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); -} - QWindow *QWasmCompositor::windowAt(QPoint globalPoint, int padding) const { int index = m_windowStack.count() - 1; @@ -245,17 +217,6 @@ QWindow *QWasmCompositor::keyWindow() const return m_windowStack.at(m_windowStack.count() - 1)->window(); } -bool QWasmCompositor::event(QEvent *ev) -{ - if (ev->type() == QEvent::UpdateRequest) { - if (m_isEnabled) - frame(); - return true; - } - - return QObject::event(ev); -} - void QWasmCompositor::blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, const QOpenGLTexture *texture, QRect targetGeometry) { QMatrix4x4 m; @@ -366,6 +327,97 @@ QRect QWasmCompositor::titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::Su return rect; } +void QWasmCompositor::requestUpdateAllWindows() +{ + m_requestUpdateAllWindows = true; + requestUpdate(); +} + +void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType) +{ + auto it = m_requestUpdateWindows.find(window); + if (it == m_requestUpdateWindows.end()) { + m_requestUpdateWindows.insert(window, updateType); + } else { + // Already registered, but upgrade ExposeEventDeliveryType to UpdateRequestDeliveryType. + // if needed, to make sure QWindow::updateRequest's are matched. + if (it.value() == ExposeEventDelivery && updateType == UpdateRequestDelivery) + it.value() = UpdateRequestDelivery; + } + + requestUpdate(); +} + +// Requests an upate/new frame using RequestAnimationFrame +void QWasmCompositor::requestUpdate() +{ + if (m_requestAnimationFrameId != -1) + return; + + static auto frame = [](double frameTime, void *context) -> int { + Q_UNUSED(frameTime); + QWasmCompositor *compositor = reinterpret_cast<QWasmCompositor *>(context); + compositor->m_requestAnimationFrameId = -1; + compositor->deliverUpdateRequests(); + return 0; + }; + m_requestAnimationFrameId = emscripten_request_animation_frame(frame, this); +} + +void QWasmCompositor::deliverUpdateRequests() +{ + // We may get new update requests during the window content update below: + // prepare for recording the new update set by setting aside the current + // update set. + auto requestUpdateWindows = m_requestUpdateWindows; + m_requestUpdateWindows.clear(); + bool requestUpdateAllWindows = m_requestUpdateAllWindows; + m_requestUpdateAllWindows = false; + + // Update window content, either all windows or a spesific set of windows. Use the correct update + // type: QWindow subclasses expect that requested and delivered updateRequests matches exactly. + m_inDeliverUpdateRequest = true; + if (requestUpdateAllWindows) { + for (QWasmWindow *window : m_windowStack) { + auto it = requestUpdateWindows.find(window); + UpdateRequestDeliveryType updateType = + (it == m_requestUpdateWindows.end() ? ExposeEventDelivery : it.value()); + deliverUpdateRequest(window, updateType); + } + } else { + for (auto it = requestUpdateWindows.constBegin(); it != requestUpdateWindows.constEnd(); ++it) { + auto *window = it.key(); + UpdateRequestDeliveryType updateType = it.value(); + deliverUpdateRequest(window, updateType); + } + } + m_inDeliverUpdateRequest = false; + + // Compose window content + frame(); +} + +void QWasmCompositor::deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType) +{ + // update by deliverUpdateRequest and expose event accordingly. + if (updateType == UpdateRequestDelivery) { + window->QPlatformWindow::deliverUpdateRequest(); + } else { + QWindow *qwindow = window->window(); + QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>( + qwindow, QRect(QPoint(0, 0), qwindow->geometry().size())); + } +} + +void QWasmCompositor::handleBackingStoreFlush() +{ + // Request update to flush the updated backing store content, + // unless we are currently processing an update, in which case + // the new content will flushed as a part of that update. + if (!m_inDeliverUpdateRequest) + requestUpdate(); +} + int dpiScaled(qreal value) { return value * (qreal(qt_defaultDpiX()) / 96.0); @@ -678,11 +730,6 @@ void QWasmCompositor::drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *sc void QWasmCompositor::frame() { - if (!m_needComposit) - return; - - m_needComposit = false; - if (!m_isEnabled || m_windowStack.empty() || !screen()) return; @@ -748,8 +795,7 @@ void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window) return; } - requestRedraw(); - + requestUpdate(); } QWasmScreen *QWasmCompositor::screen() diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index b579059344..1a51016c03 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.h +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -110,25 +110,24 @@ public: void lower(QWasmWindow *window); void setParent(QWasmWindow *window, QWasmWindow *parent); - void flush(QWasmWindow *surface, const QRegion ®ion); - int windowCount() const; - void redrawWindowContent(); - void requestRedraw(); - QWindow *windowAt(QPoint globalPoint, int padding = 0) const; QWindow *keyWindow() const; - bool event(QEvent *event); - static QWasmTitleBarOptions makeTitleBarOptions(const QWasmWindow *window); static QRect titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::SubControls subcontrol); QWasmScreen *screen(); QOpenGLContext *context(); -private slots: + enum UpdateRequestDeliveryType { ExposeEventDelivery, UpdateRequestDelivery }; + void requestUpdateAllWindows(); + void requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType = ExposeEventDelivery); + void requestUpdate(); + void deliverUpdateRequests(); + void deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType); + void handleBackingStoreFlush(); void frame(); private: @@ -152,6 +151,10 @@ private: bool m_isEnabled; QSize m_targetSize; qreal m_targetDevicePixelRatio; + QMap<QWasmWindow *, UpdateRequestDeliveryType> m_requestUpdateWindows; + bool m_requestUpdateAllWindows = false; + int m_requestAnimationFrameId = -1; + bool m_inDeliverUpdateRequest = false; static QPalette makeWindowPalette(); diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index 0b11415fd3..3cc067bbe7 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -216,7 +216,7 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize() QPoint position(rect["left"].as<int>() - offset.x(), rect["top"].as<int>() - offset.y()); setGeometry(QRect(position, cssSize.toSize())); - m_compositor->redrawWindowContent(); + m_compositor->requestUpdateAllWindows(); } void QWasmScreen::canvasResizeObserverCallback(emscripten::val entries, emscripten::val) diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index 9c5f1e4e74..3819e8daa6 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -111,8 +111,6 @@ void QWasmWindow::setGeometry(const QRect &rect) } QWindowSystemInterface::handleGeometryChange(window(), r); QPlatformWindow::setGeometry(r); - - QWindowSystemInterface::flushWindowSystemEvents(); invalidate(); } @@ -128,7 +126,6 @@ void QWasmWindow::setVisible(bool visible) else if (m_windowState & Qt::WindowMaximized) newGeom = platformScreen()->availableGeometry(); } - QPlatformWindow::setVisible(visible); m_compositor->setVisible(this, visible); @@ -366,7 +363,7 @@ QRegion QWasmWindow::titleControlRegion() const void QWasmWindow::invalidate() { - m_compositor->requestRedraw(); + m_compositor->requestUpdateWindow(this); } QWasmCompositor::SubControls QWasmWindow::activeSubControl() const @@ -397,6 +394,11 @@ qreal QWasmWindow::devicePixelRatio() const void QWasmWindow::requestUpdate() { + if (m_compositor) { + m_compositor->requestUpdateWindow(this, QWasmCompositor::UpdateRequestDelivery); + return; + } + static auto frame = [](double time, void *context) -> int { Q_UNUSED(time); QWasmWindow *window = static_cast<QWasmWindow *>(context); |