wasm: use “specialHtmlTargets” for canvas lookup
We’d like to support use cases which require using multiple html documents, for example when displaying application content using more than one browser window. Normally Emscripten uses the primary html document when looking up elements by id, which means that targeting elements on secondary documents is not possible. Emscripten does provide a workaround: the application can create custom id mappings to any html element on the “specialHtmlTargets” object, and then use the “!id” syntax instead of normal “#id” lookup. Change-Id: I4dda920868cfbc6f8991425daf8933144c0ffad8 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
4bc85b9850
commit
08733dff58
@ -115,7 +115,7 @@ QWasmCompositor::~QWasmCompositor()
|
||||
|
||||
void QWasmCompositor::deregisterEventHandlers()
|
||||
{
|
||||
QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8();
|
||||
QByteArray canvasSelector = screen()->canvasTargetId().toUtf8();
|
||||
emscripten_set_keydown_callback(canvasSelector.constData(), 0, 0, NULL);
|
||||
emscripten_set_keyup_callback(canvasSelector.constData(), 0, 0, NULL);
|
||||
|
||||
@ -156,7 +156,7 @@ void QWasmCompositor::destroy()
|
||||
|
||||
void QWasmCompositor::initEventHandlers()
|
||||
{
|
||||
QByteArray canvasSelector = "#" + screen()->canvasId().toUtf8();
|
||||
QByteArray canvasSelector = screen()->canvasTargetId().toUtf8();
|
||||
|
||||
eventTranslator->g_usePlatformMacSpecifics
|
||||
= (QWasmIntegration::get()->platform == QWasmIntegration::MacOSPlatform);
|
||||
|
@ -87,13 +87,12 @@ bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface)
|
||||
if (m_context)
|
||||
return m_screen == screen;
|
||||
|
||||
QString canvasId = QWasmScreen::get(screen)->canvasId();
|
||||
m_context = createEmscriptenContext(canvasId, m_requestedFormat);
|
||||
m_context = createEmscriptenContext(QWasmScreen::get(screen)->canvasTargetId(), m_requestedFormat);
|
||||
m_screen = screen;
|
||||
return true;
|
||||
}
|
||||
|
||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const QString &canvasId, QSurfaceFormat format)
|
||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const QString &canvasTargetId, QSurfaceFormat format)
|
||||
{
|
||||
EmscriptenWebGLContextAttributes attributes;
|
||||
emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes
|
||||
@ -114,7 +113,7 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons
|
||||
attributes.depth = useDepthStencil;
|
||||
attributes.stencil = useDepthStencil;
|
||||
|
||||
QByteArray convasSelector = "#" + canvasId.toUtf8();
|
||||
QByteArray convasSelector = canvasTargetId.toUtf8();
|
||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(convasSelector.constData(), &attributes);
|
||||
|
||||
return context;
|
||||
|
@ -68,7 +68,8 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
|
||||
// Create the canvas (for the correct document) as a child of the container
|
||||
m_canvas = containerOrCanvas["ownerDocument"].call<emscripten::val>("createElement", std::string("canvas"));
|
||||
containerOrCanvas.call<void>("appendChild", m_canvas);
|
||||
m_canvas.set("id", std::string("qtcanvas_") + std::to_string(uint32_t(this)));
|
||||
std::string screenId = std::string("qtcanvas_") + std::to_string(uint32_t(this));
|
||||
m_canvas.set("id", screenId);
|
||||
|
||||
// Make the canvas occupy 100% of parent
|
||||
emscripten::val style = m_canvas["style"];
|
||||
@ -96,6 +97,16 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
|
||||
m_onContextMenu = std::make_unique<qstdweb::EventCallback>(m_canvas, "contextmenu", [](emscripten::val event){
|
||||
event.call<void>("preventDefault");
|
||||
});
|
||||
|
||||
// Create "specialHTMLTargets" mapping for the canvas. Normally, Emscripten
|
||||
// uses the html element id when targeting elements, for example when registering
|
||||
// event callbacks. However, this approach is limited to supporting single-document
|
||||
// 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
|
||||
// "specialHTMLTargets" object. Add a mapping for the canvas for this screen.
|
||||
EM_ASM({
|
||||
specialHTMLTargets["!qtcanvas_" + $0] = Emval.toValue($1);
|
||||
}, uint32_t(this), m_canvas.as_handle());
|
||||
|
||||
// Install event handlers on the container/canvas. This must be
|
||||
// done after the canvas has been created above.
|
||||
@ -107,6 +118,10 @@ QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas)
|
||||
|
||||
QWasmScreen::~QWasmScreen()
|
||||
{
|
||||
EM_ASM({
|
||||
specialHTMLTargets["!qtcanvas_" + $0] = undefined;
|
||||
}, uint32_t(this));
|
||||
|
||||
m_canvas.set(m_canvasResizeObserverCallbackContextPropertyName, emscripten::val(intptr_t(0)));
|
||||
destroy();
|
||||
}
|
||||
@ -146,11 +161,21 @@ emscripten::val QWasmScreen::canvas() const
|
||||
return m_canvas;
|
||||
}
|
||||
|
||||
// Returns the html element id for the screen's canvas.
|
||||
QString QWasmScreen::canvasId() const
|
||||
{
|
||||
return QWasmString::toQString(m_canvas["id"]);
|
||||
}
|
||||
|
||||
// Returns the canvas _target_ id, for use with Emscripten's
|
||||
// event registration functions. The target id is a globally
|
||||
// unique id, unlike the html element id which is only unique
|
||||
// within one html document. See specialHtmlTargets.
|
||||
QString QWasmScreen::canvasTargetId() const
|
||||
{
|
||||
return QStringLiteral("!qtcanvas_") + QString::number(int32_t(this));
|
||||
}
|
||||
|
||||
QRect QWasmScreen::geometry() const
|
||||
{
|
||||
return m_geometry;
|
||||
@ -246,7 +271,7 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize()
|
||||
// Setting the render size to a value larger than the CSS size enables high-dpi
|
||||
// rendering.
|
||||
|
||||
QByteArray canvasSelector = "#" + canvasId().toUtf8();
|
||||
QByteArray canvasSelector = canvasTargetId().toUtf8();
|
||||
double css_width;
|
||||
double css_height;
|
||||
emscripten_get_element_css_size(canvasSelector.constData(), &css_width, &css_height);
|
||||
|
@ -62,6 +62,7 @@ public:
|
||||
emscripten::val container() const;
|
||||
emscripten::val canvas() const;
|
||||
QString canvasId() const;
|
||||
QString canvasTargetId() const;
|
||||
|
||||
QWasmCompositor *compositor();
|
||||
QWasmEventTranslator *eventTranslator();
|
||||
|
Loading…
Reference in New Issue
Block a user