diff options
Diffstat (limited to 'src/corelib/kernel/qeventdispatcher_wasm.cpp')
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_wasm.cpp | 90 |
1 files changed, 32 insertions, 58 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_wasm.cpp b/src/corelib/kernel/qeventdispatcher_wasm.cpp index c733f46c14..73f468aae5 100644 --- a/src/corelib/kernel/qeventdispatcher_wasm.cpp +++ b/src/corelib/kernel/qeventdispatcher_wasm.cpp @@ -26,14 +26,16 @@ Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers"); #define LOCK_GUARD(M) #endif -#ifdef QT_HAVE_EMSCRIPTEN_ASYNCIFY - // Emscripten asyncify currently supports one level of suspend - // recursion is not permitted. We track the suspend state here // on order to fail (more) gracefully, but we can of course only // track Qts own usage of asyncify. static bool g_is_asyncify_suspended = false; +EM_JS(bool, qt_have_asyncify_js, (), { + return typeof Asyncify != "undefined"; +}); + EM_JS(void, qt_asyncify_suspend_js, (), { let sleepFn = (wakeUp) => { Module.qtAsyncifyWakeUp = wakeUp; @@ -52,6 +54,15 @@ EM_JS(void, qt_asyncify_resume_js, (), { setTimeout(wakeUp); }); +// Returns true if asyncify is available. +bool qt_have_asyncify() +{ + static bool have_asyncify = []{ + return qt_have_asyncify_js(); + }(); + return have_asyncify; +} + // Suspends the main thread until qt_asyncify_resume() is called. Returns // false immediately if Qt has already suspended the main thread (recursive // suspend is not supported by Emscripten). Returns true (after resuming), @@ -76,19 +87,6 @@ bool qt_asyncify_resume() return true; } -// Yields control to the browser, so that it can process events. Must -// be called on the main thread. Returns false immediately if Qt has -// already suspended the main thread. Returns true after yielding. -bool qt_asyncify_yield() -{ - if (g_is_asyncify_suspended) - return false; - emscripten_sleep(0); - return true; -} - -#endif // QT_HAVE_EMSCRIPTEN_ASYNCIFY - Q_CONSTINIT QEventDispatcherWasm *QEventDispatcherWasm::g_mainThreadEventDispatcher = nullptr; #if QT_CONFIG(thread) Q_CONSTINIT QVector<QEventDispatcherWasm *> QEventDispatcherWasm::g_secondaryThreadEventDispatchers; @@ -198,9 +196,6 @@ bool QEventDispatcherWasm::processEvents(QEventLoop::ProcessEventsFlags flags) handleApplicationExec(); } - if (!(flags & QEventLoop::ExcludeUserInputEvents)) - pollForNativeEvents(); - hasPendingEvents = qGlobalPostedEventsCount() > 0; if (!hasPendingEvents && (flags & QEventLoop::WaitForMoreEvents)) @@ -373,34 +368,14 @@ void QEventDispatcherWasm::handleApplicationExec() void QEventDispatcherWasm::handleDialogExec() { -#ifndef QT_HAVE_EMSCRIPTEN_ASYNCIFY - qWarning() << "Warning: dialog exec() is not supported on Qt for WebAssembly in this" - << "configuration. Please use show() instead, or enable experimental support" - << "for asyncify.\n" - << "When using exec() (without asyncify) the dialog will show, the user can interact" - << "with it and the appropriate signals will be emitted on close. However, the" - << "exec() call never returns, stack content at the time of the exec() call" - << "is leaked, and the exec() call may interfere with input event processing"; - emscripten_sleep(1); // This call never returns -#endif + if (!qt_have_asyncify()) { + qWarning() << "Warning: exec() is not supported on Qt for WebAssembly in this configuration. Please build" + << "with asyncify support, or use an asynchronous API like QDialog::open()"; + emscripten_sleep(1); // This call never returns + } // For the asyncify case we do nothing here and wait for events in wait() } -void QEventDispatcherWasm::pollForNativeEvents() -{ - // Secondary thread event dispatchers do not support native events - if (isSecondaryThreadEventDispatcher()) - return; - -#if HAVE_EMSCRIPTEN_ASYNCIFY - // Asyncify allows us to yield to the browser and have it process native events - - // but this will fail if we are recursing and are already in a yield. - bool didYield = qt_asyncify_yield(); - if (!didYield) - qWarning("QEventDispatcherWasm::processEvents() did not asyncify process native events"); -#endif -} - // Blocks/suspends the calling thread. This is possible in two cases: // - Caller is a secondary thread: block on m_moreEvents // - Caller is the main thread and asyncify is enabled: suspend using qt_asyncify_suspend() @@ -422,20 +397,20 @@ bool QEventDispatcherWasm::wait(int timeout) #endif Q_ASSERT(emscripten_is_main_runtime_thread()); Q_ASSERT(isMainThreadEventDispatcher()); -#ifdef QT_HAVE_EMSCRIPTEN_ASYNCIFY - if (timeout > 0) - qWarning() << "QEventDispatcherWasm asyncify wait with timeout is not supported; timeout will be ignored"; // FIXME - - bool didSuspend = qt_asyncify_suspend(); - if (!didSuspend) { - qWarning("QEventDispatcherWasm: current thread is already suspended; could not asyncify wait for events"); - return false; + if (qt_have_asyncify()) { + if (timeout > 0) + qWarning() << "QEventDispatcherWasm asyncify wait with timeout is not supported; timeout will be ignored"; // FIXME + + bool didSuspend = qt_asyncify_suspend(); + if (!didSuspend) { + qWarning("QEventDispatcherWasm: current thread is already suspended; could not asyncify wait for events"); + return false; + } + return true; + } else { + qWarning("QEventLoop::WaitForMoreEvents is not supported on the main thread without asyncify"); + Q_UNUSED(timeout); } - return true; -#else - qWarning("QEventLoop::WaitForMoreEvents is not supported on the main thread without asyncify"); - Q_UNUSED(timeout); -#endif return false; } @@ -453,12 +428,10 @@ bool QEventDispatcherWasm::wakeEventDispatcherThread() } #endif Q_ASSERT(isMainThreadEventDispatcher()); -#ifdef QT_HAVE_EMSCRIPTEN_ASYNCIFY if (g_is_asyncify_suspended) { runOnMainThread([]{ qt_asyncify_resume(); }); return true; } -#endif return false; } @@ -522,6 +495,7 @@ void QEventDispatcherWasm::updateNativeTimer() if (m_timerId > 0) { emscripten_clear_timeout(m_timerId); m_timerId = 0; + m_timerTargetTime = 0; } return; } |