wasm: Support non-canvas container elements
Support specifying that Qt should use a div element as the root container, in which case canvas management is moved to Qt C++ code. This enables us to take ownership of the canvas and its configuration. In addition, it allows creating child elements for the Qt container (canvas element children have a special role are as fallback elements displayed in case the browser can’t show the canvas) Remove support for reading Module.canvas, which was deprecated in Qt 5. Add support for reading Module.qtContainerElements, which can be either a canvas element (legacy) or a div element (preferred). Deprecate qtCanvasElements and print warning on usage. Change QWasmScreen to accept either a canvas or any html element. In the latter case, create the canvas and configure it as required by Qt. Change-Id: I57df8fb5772b2bfbba081af3f572b8b0e7d51897 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
aa4a2bb1e1
commit
4ff5a571b3
@ -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() {
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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<int>();
|
||||
for (int i = 0; i < screenCount; ++i) {
|
||||
addScreen(qtCanvaseElements[i].as<emscripten::val>());
|
||||
// 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<int>();
|
||||
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<emscripten::val>();
|
||||
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<int>();
|
||||
for (int i = 0; i < count; ++i)
|
||||
addScreen(qtCanvasElements[i].as<emscripten::val>());
|
||||
} 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
|
||||
|
@ -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<std::string>();
|
||||
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<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)));
|
||||
|
||||
// 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<void>("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<void>("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;
|
||||
|
@ -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<QWasmCompositor> m_compositor;
|
||||
std::unique_ptr<QWasmEventTranslator> m_eventTranslator;
|
||||
|
Loading…
x
Reference in New Issue
Block a user