diff --git a/src/corelib/kernel/qeventdispatcher_wasm.cpp b/src/corelib/kernel/qeventdispatcher_wasm.cpp index 5f4c46c07f2..f5061f35d74 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm.cpp +++ b/src/corelib/kernel/qeventdispatcher_wasm.cpp @@ -218,9 +218,12 @@ QEventDispatcherWasm::QEventDispatcherWasm() #if QT_CONFIG(thread) g_mainThread = pthread_self(); #endif + // Call the "onLoaded" JavaScript callback, unless startup tasks - // have been registered which should complete first. - checkCallQtLoaded(); + // have been registered which should complete first. Run async + // to make sure event dispatcher construction (in particular any + // subclass construction) has completed first. + runAsync(callOnLoadedIfRequired); } else { #if QT_CONFIG(thread) std::lock_guard lock(g_staticDataMutex); @@ -916,10 +919,10 @@ void QEventDispatcherWasm::registerStartupTask() void QEventDispatcherWasm::completeStarupTask() { --g_startupTasks; - checkCallQtLoaded(); + callOnLoadedIfRequired(); } -void QEventDispatcherWasm::checkCallQtLoaded() +void QEventDispatcherWasm::callOnLoadedIfRequired() { if (g_startupTasks > 0) return; @@ -929,12 +932,16 @@ void QEventDispatcherWasm::checkCallQtLoaded() return; qtLoadedCalled = true; - QTimer::singleShot(0, [](){ - emscripten::val qt = emscripten::val::module_property("qt"); - if (qt.isUndefined()) - return; - qt.call("onLoaded"); - }); + Q_ASSERT(g_mainThreadEventDispatcher); + g_mainThreadEventDispatcher->onLoaded(); +} + +void QEventDispatcherWasm::onLoaded() +{ + emscripten::val qt = emscripten::val::module_property("qt"); + if (qt.isUndefined()) + return; + qt.call("onLoaded"); } namespace { diff --git a/src/corelib/kernel/qeventdispatcher_wasm_p.h b/src/corelib/kernel/qeventdispatcher_wasm_p.h index afffc8a813b..0d94c48a25d 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm_p.h +++ b/src/corelib/kernel/qeventdispatcher_wasm_p.h @@ -59,7 +59,8 @@ public: static void registerStartupTask(); static void completeStarupTask(); - static void checkCallQtLoaded(); + static void callOnLoadedIfRequired(); + virtual void onLoaded(); protected: virtual bool processPostedEvents(); diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 66eaea62faa..48445d5db95 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -4,6 +4,8 @@ #include "qwasmcompositor.h" #include "qwasmwindow.h" +#include + #include #include @@ -41,6 +43,17 @@ void QWasmCompositor::setEnabled(bool enabled) m_isEnabled = enabled; } +// requestUpdate delivery is initially disabled at startup, while Qt completes +// startup tasks such as font loading. This function enables requestUpdate delivery +// again. +void QWasmCompositor::releaseRequesetUpdateHold() +{ + if (!m_requestUpdateHoldEnabled) + return; + m_requestUpdateHoldEnabled = false; + requestUpdate(); +} + void QWasmCompositor::requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType) { auto it = m_requestUpdateWindows.find(window); @@ -62,6 +75,9 @@ void QWasmCompositor::requestUpdate() if (m_requestAnimationFrameId != -1) return; + if (m_requestUpdateHoldEnabled) + return; + static auto frame = [](double frameTime, void *context) -> int { Q_UNUSED(frameTime); diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index 182ea2b1678..5de401844c3 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.h +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -31,8 +31,8 @@ public: QWasmScreen *screen(); void setEnabled(bool enabled); + void releaseRequesetUpdateHold(); enum UpdateRequestDeliveryType { ExposeEventDelivery, UpdateRequestDelivery }; - void requestUpdateWindow(QWasmWindow *window, UpdateRequestDeliveryType updateType = ExposeEventDelivery); void handleBackingStoreFlush(QWindow *window); @@ -50,6 +50,7 @@ private: bool m_isEnabled = true; QMap m_requestUpdateWindows; int m_requestAnimationFrameId = -1; + bool m_requestUpdateHoldEnabled = true; bool m_inDeliverUpdateRequest = false; }; diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp index cd2cefc14d9..1f2d3095d65 100644 --- a/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp +++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qwasmeventdispatcher.h" +#include "qwasmintegration.h" #include @@ -15,4 +16,20 @@ bool QWasmEventDispatcher::processPostedEvents() return QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); } +void QWasmEventDispatcher::onLoaded() +{ + // This function is called when the application is ready to paint + // the first frame. Send the qtlaoder onLoaded event first (via + // the base class implementation), and then enable/call requestUpdate + // to deliver a frame. + QEventDispatcherWasm::onLoaded(); + + // Make sure all screens have a defined size; and pick + // up size changes due to onLoaded event handling. + QWasmIntegration *wasmIntegration = QWasmIntegration::get(); + wasmIntegration->resizeAllScreens(); + + wasmIntegration->releaseRequesetUpdateHold(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmeventdispatcher.h b/src/plugins/platforms/wasm/qwasmeventdispatcher.h index 33d672a57fb..cbf10482e3f 100644 --- a/src/plugins/platforms/wasm/qwasmeventdispatcher.h +++ b/src/plugins/platforms/wasm/qwasmeventdispatcher.h @@ -12,6 +12,7 @@ class QWasmEventDispatcher : public QEventDispatcherWasm { protected: bool processPostedEvents() override; + void onLoaded() override; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index c665251d0d2..d2e7c8716cc 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -206,6 +206,13 @@ void QWasmIntegration::removeBackingStore(QWindow* window) m_backingStores.remove(window); } +void QWasmIntegration::releaseRequesetUpdateHold() +{ + for (const auto &elementAndScreen : m_screens) { + elementAndScreen.wasmScreen->compositor()->releaseRequesetUpdateHold(); + } +} + #ifndef QT_NO_OPENGL QPlatformOpenGLContext *QWasmIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h index eeb68109a0d..870bd0d16b4 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.h +++ b/src/plugins/platforms/wasm/qwasmintegration.h @@ -78,6 +78,7 @@ public: void resizeAllScreens(); void loadLocalFontFamilies(emscripten::val families); void removeBackingStore(QWindow* window); + void releaseRequesetUpdateHold(); static quint64 getTimestamp(); int touchPoints;