diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js index 08bf0ed421c..4f5bfcc2d87 100644 --- a/src/plugins/platforms/wasm/qtloader.js +++ b/src/plugins/platforms/wasm/qtloader.js @@ -142,7 +142,7 @@ function QtLoader(config) // Qt properties. These are propagated to the Emscripten module after // it has been created. - self.qtCanvasElements = undefined; + self.qtContainerElements = undefined; self.qtFontDpi = 96; function webAssemblySupported() { @@ -431,13 +431,13 @@ function QtLoader(config) module.ENV[key.toUpperCase()] = value; } // Propagate Qt module properties - module.qtCanvasElements = self.qtCanvasElements; + module.qtContainerElements = self.qtContainerElements; module.qtFontDpi = self.qtFontDpi; }); self.moduleConfig.mainScriptUrlOrBlob = new Blob([emscriptenModuleSource], {type: 'text/javascript'}); - self.qtCanvasElements = config.canvasElements; + self.qtContainerElements = config.canvasElements; config.restart = function() { diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index fe0ea81692a..5c5fc80adba 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -102,8 +102,6 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen) QPointingDevice::Capability::Position | QPointingDevice::Capability::Area | QPointingDevice::Capability::NormalizedPosition, 10, 0); QWindowSystemInterface::registerInputDevice(touchDevice); - - initEventHandlers(); } QWasmCompositor::~QWasmCompositor() diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index d405f8035b8..27f518635d6 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.h +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -72,6 +72,7 @@ class QWasmCompositor : public QObject public: QWasmCompositor(QWasmScreen *screen); ~QWasmCompositor(); + void initEventHandlers(); void deregisterEventHandlers(); void destroy(); @@ -160,7 +161,6 @@ private slots: void frame(); private: - void initEventHandlers(); void notifyTopWindowChanged(QWasmWindow *window); void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window); void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window); diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index 5a09cc710a6..cf3a506ef8c 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -123,19 +123,34 @@ QWasmIntegration::QWasmIntegration() platform = AndroidPlatform; } - // We expect that qtloader.js has populated Module.qtCanvasElements with one or more canvases. - emscripten::val qtCanvaseElements = val::module_property("qtCanvasElements"); - emscripten::val canvas = val::module_property("canvas"); // TODO: remove for Qt 6.0 - - if (!qtCanvaseElements.isUndefined()) { - int screenCount = qtCanvaseElements["length"].as(); - for (int i = 0; i < screenCount; ++i) { - addScreen(qtCanvaseElements[i].as()); + // Create screens for container elements. Each container element can be a div element (preferred), + // or a canvas element (legacy). Qt versions prior to 6.x read the "qtCanvasElements" module property, + // which we continue to do to preserve compatibility. The preferred property is now "qtContainerElements". + emscripten::val qtContainerElements = val::module_property("qtContainerElements"); + emscripten::val qtCanvasElements = val::module_property("qtCanvasElements"); + if (!qtContainerElements.isUndefined()) { + emscripten::val length = qtContainerElements["length"]; + int count = length.as(); + if (length.isUndefined()) + qWarning("qtContainerElements does not have the length property set. Qt expects an array of html elements (possibly containing one element only)"); + for (int i = 0; i < count; ++i) { + emscripten::val element = qtContainerElements[i].as(); + if (element.isNull() ||element.isUndefined()) { + qWarning() << "Skipping null or undefined element in qtContainerElements"; + } else { + addScreen(element); + } } - } else if (!canvas.isUndefined()) { - qWarning() << "Module.canvas is deprecated. A future version of Qt will stop reading this property. " - << "Instead, set Module.qtCanvasElements to be an array of canvas elements, or use qtloader.js."; - addScreen(canvas); + } else if (!qtCanvasElements.isUndefined()) { + qWarning() << "The qtCanvaseElements property is deprecated. Qt will stop reading" + << "it in some future veresion, please use qtContainerElements instead"; + emscripten::val length = qtCanvasElements["length"]; + int count = length.as(); + for (int i = 0; i < count; ++i) + addScreen(qtCanvasElements[i].as()); + } else { + // No screens, which may or may not be intended + qWarning() << "Note: The qtContainerElements module property was not set. Proceeding with no screens."; } // install browser window resize handler diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index 2ee56bc5aec..52da924f8ff 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -52,11 +52,30 @@ QT_BEGIN_NAMESPACE const char * QWasmScreen::m_canvasResizeObserverCallbackContextPropertyName = "data-qtCanvasResizeObserverCallbackContext"; -QWasmScreen::QWasmScreen(const emscripten::val &canvas) - : m_canvas(canvas) +QWasmScreen::QWasmScreen(const emscripten::val &containerOrCanvas) + : m_container(containerOrCanvas) + , m_canvas(emscripten::val::undefined()) , m_compositor(new QWasmCompositor(this)) , m_eventTranslator(new QWasmEventTranslator()) { + // Each screen is backed by a html canvas element. Use either + // a user-supplied canvas or create one as a child of the user- + // supplied root element. + std::string tagName = containerOrCanvas["tagName"].as(); + if (tagName == "CANVAS" || tagName == "canvas") { + m_canvas = containerOrCanvas; + } else { + // Create the canvas (for the correct document) as a child of the container + m_canvas = containerOrCanvas["ownerDocument"].call("createElement", std::string("canvas")); + containerOrCanvas.call("appendChild", m_canvas); + m_canvas.set("id", std::string("qtcanvas_") + std::to_string(uint32_t(this))); + + // Make the canvas occupy 100% of parent + emscripten::val style = m_canvas["style"]; + style.set("width", std::string("100%")); + style.set("height", std::string("100%")); + } + // Configure canvas emscripten::val style = m_canvas["style"]; style.set("border", std::string("0px none")); @@ -78,6 +97,10 @@ QWasmScreen::QWasmScreen(const emscripten::val &canvas) event.call("preventDefault"); }); + // Install event handlers on the container/canvas. This must be + // done after the canvas has been created above. + m_compositor->initEventHandlers(); + updateQScreenAndCanvasRenderSize(); m_canvas.call("focus"); } @@ -113,6 +136,11 @@ QWasmEventTranslator *QWasmScreen::eventTranslator() return m_eventTranslator.get(); } +emscripten::val QWasmScreen::container() const +{ + return m_container; +} + emscripten::val QWasmScreen::canvas() const { return m_canvas; diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h index 41b5aeeb2f4..4fb387f10a2 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.h +++ b/src/plugins/platforms/wasm/qwasmscreen.h @@ -53,12 +53,13 @@ class QWasmScreen : public QObject, public QPlatformScreen { Q_OBJECT public: - QWasmScreen(const emscripten::val &canvas); + QWasmScreen(const emscripten::val &containerOrCanvas); ~QWasmScreen(); void destroy(); static QWasmScreen *get(QPlatformScreen *screen); static QWasmScreen *get(QScreen *screen); + emscripten::val container() const; emscripten::val canvas() const; QString canvasId() const; @@ -86,6 +87,7 @@ public slots: void setGeometry(const QRect &rect); private: + emscripten::val m_container; emscripten::val m_canvas; std::unique_ptr m_compositor; std::unique_ptr m_eventTranslator;