wasm: don't enable specialHTMLTargets by default
Adding specialHTMLTargets to EXPORTED_RUNTIME_METHODS carries the obligation to actually use it as well; failing to do so makes Emscripten stop with a reference error on startup. However, we can't guarantee that Qt will use it in all cases. The current usage depends on QGuiApplication being used. Application code could be using QCoreApplication, or no application object at all. Detect if specialHTMLTargets is present instead, and then enable the code paths which uses it if that's the case. This means that apps which want to use e.g. multiple browser windows can opt into support by making sure EXPORTED_RUNTIME_METHODS contains specialHTMLTargets. Change-Id: I81105aa01946602fcf593f170e305d7dc9bad3be Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
This commit is contained in:
parent
cfa44787de
commit
86103f3af5
@ -4,7 +4,7 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
|
|||||||
|
|
||||||
target_link_options("${wasmTarget}" INTERFACE
|
target_link_options("${wasmTarget}" INTERFACE
|
||||||
"SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=1"
|
"SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=1"
|
||||||
"SHELL:-s EXPORTED_RUNTIME_METHODS=[UTF16ToString,stringToUTF16,specialHTMLTargets]"
|
"SHELL:-s EXPORTED_RUNTIME_METHODS=[UTF16ToString,stringToUTF16]"
|
||||||
"SHELL:-s USE_WEBGL2=1"
|
"SHELL:-s USE_WEBGL2=1"
|
||||||
"--bind"
|
"--bind"
|
||||||
"SHELL:-s FETCH=1"
|
"SHELL:-s FETCH=1"
|
||||||
|
@ -34,7 +34,7 @@ EMCC_COMMON_LFLAGS += \
|
|||||||
-s FULL_ES3=1 \
|
-s FULL_ES3=1 \
|
||||||
-s USE_WEBGL2=1 \
|
-s USE_WEBGL2=1 \
|
||||||
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \
|
-s ERROR_ON_UNDEFINED_SYMBOLS=1 \
|
||||||
-s EXPORTED_RUNTIME_METHODS=[UTF16ToString,stringToUTF16,specialHTMLTargets] \
|
-s EXPORTED_RUNTIME_METHODS=[UTF16ToString,stringToUTF16] \
|
||||||
--bind \
|
--bind \
|
||||||
-s FETCH=1 \
|
-s FETCH=1 \
|
||||||
-s MODULARIZE=1 \
|
-s MODULARIZE=1 \
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "emscripten.h"
|
#include "emscripten.h"
|
||||||
#include <emscripten/html5.h>
|
#include <emscripten/html5.h>
|
||||||
#include <emscripten/threading.h>
|
#include <emscripten/threading.h>
|
||||||
|
#include <emscripten/val.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
@ -78,9 +78,14 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
|
|||||||
// apps/ages only, since Emscripten uses the main document to look up the element.
|
// apps/ages only, since Emscripten uses the main document to look up the element.
|
||||||
// As a workaround for this, Emscripten supports registering custom mappings in the
|
// As a workaround for this, Emscripten supports registering custom mappings in the
|
||||||
// "specialHTMLTargets" object. Add a mapping for the canvas for this screen.
|
// "specialHTMLTargets" object. Add a mapping for the canvas for this screen.
|
||||||
emscripten::val specialHtmlTargets = emscripten::val::module_property("specialHTMLTargets");
|
//
|
||||||
std::string id = std::string("!qtcanvas_") + std::to_string(uint32_t(this));
|
// This functionality is gated on "specialHTMLTargets" being available as a module
|
||||||
specialHtmlTargets.set(id, m_canvas);
|
// property. One way to ensure this is the case is to add it to EXPORTED_RUNTIME_METHODS.
|
||||||
|
// Qt does not currently do this by default since if added it _must_ be used in order
|
||||||
|
// to avoid an undefined reference error at startup, and there are cases when Qt won't use
|
||||||
|
// it, for example if QGuiApplication is not usded.
|
||||||
|
if (hasSpecialHtmlTargets())
|
||||||
|
emscripten::val::module_property("specialHTMLTargets").set(canvasSpecialHtmlTargetId(), m_canvas);
|
||||||
|
|
||||||
// Install event handlers on the container/canvas. This must be
|
// Install event handlers on the container/canvas. This must be
|
||||||
// done after the canvas has been created above.
|
// done after the canvas has been created above.
|
||||||
@ -97,9 +102,9 @@ QWasmScreen::~QWasmScreen()
|
|||||||
// event handlers.
|
// event handlers.
|
||||||
m_compositor = nullptr;
|
m_compositor = nullptr;
|
||||||
|
|
||||||
emscripten::val specialHtmlTargets = emscripten::val::module_property("specialHTMLTargets");
|
if (hasSpecialHtmlTargets())
|
||||||
std::string id = std::string("!qtcanvas_") + std::to_string(uint32_t(this));
|
emscripten::val::module_property("specialHTMLTargets")
|
||||||
specialHtmlTargets.set(id, emscripten::val::undefined());
|
.set(canvasSpecialHtmlTargetId(), emscripten::val::undefined());
|
||||||
|
|
||||||
m_canvas.set(m_canvasResizeObserverCallbackContextPropertyName, emscripten::val(intptr_t(0)));
|
m_canvas.set(m_canvasResizeObserverCallbackContextPropertyName, emscripten::val(intptr_t(0)));
|
||||||
}
|
}
|
||||||
@ -146,13 +151,33 @@ QString QWasmScreen::canvasId() const
|
|||||||
return QWasmString::toQString(m_canvas["id"]);
|
return QWasmString::toQString(m_canvas["id"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the canvas _target_ id, for use with Emscripten's
|
// Returns the canvas _target_ id, for use with Emscripten's event registration
|
||||||
// event registration functions. The target id is a globally
|
// functions. This either based on the id registered in specialHtmlTargets, or
|
||||||
// unique id, unlike the html element id which is only unique
|
// on the canvas id.
|
||||||
// within one html document. See specialHtmlTargets.
|
|
||||||
QString QWasmScreen::canvasTargetId() const
|
QString QWasmScreen::canvasTargetId() const
|
||||||
{
|
{
|
||||||
return QStringLiteral("!qtcanvas_") + QString::number(int32_t(this));
|
if (hasSpecialHtmlTargets())
|
||||||
|
return QString::fromStdString(canvasSpecialHtmlTargetId());
|
||||||
|
else
|
||||||
|
return QStringLiteral("#") + canvasId();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string QWasmScreen::canvasSpecialHtmlTargetId() const
|
||||||
|
{
|
||||||
|
// Return a globally unique id for the canvas. We can choose any string,
|
||||||
|
// as long as it starts with a "!".
|
||||||
|
return std::string("!qtcanvas_") + std::to_string(uint32_t(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWasmScreen::hasSpecialHtmlTargets() const
|
||||||
|
{
|
||||||
|
static bool gotIt = []{
|
||||||
|
// specialHTMLTargets is a JavaScript Array if available. Note that it is
|
||||||
|
// an abort() function if not, so a simple isUndefined() test wont't work here.
|
||||||
|
return emscripten::val::module_property("specialHTMLTargets")
|
||||||
|
["constructor"]["name"].as<std::string>() == std::string("Array");
|
||||||
|
}();
|
||||||
|
return gotIt;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect QWasmScreen::geometry() const
|
QRect QWasmScreen::geometry() const
|
||||||
|
@ -62,6 +62,9 @@ public slots:
|
|||||||
void setGeometry(const QRect &rect);
|
void setGeometry(const QRect &rect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string canvasSpecialHtmlTargetId() const;
|
||||||
|
bool hasSpecialHtmlTargets() const;
|
||||||
|
|
||||||
emscripten::val m_container;
|
emscripten::val m_container;
|
||||||
emscripten::val m_canvas;
|
emscripten::val m_canvas;
|
||||||
std::unique_ptr<QWasmCompositor> m_compositor;
|
std::unique_ptr<QWasmCompositor> m_compositor;
|
||||||
|
Loading…
Reference in New Issue
Block a user