summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/wasm')
-rw-r--r--src/plugins/platforms/wasm/qtloader.js55
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp53
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp25
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h7
-rw-r--r--src/plugins/platforms/wasm/qwasmcursor.cpp16
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp38
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.h6
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp56
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h11
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.cpp4
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp69
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h25
-rw-r--r--src/plugins/platforms/wasm/wasm_shell.html14
14 files changed, 224 insertions, 156 deletions
diff --git a/src/plugins/platforms/wasm/qtloader.js b/src/plugins/platforms/wasm/qtloader.js
index 203213db56..049eb1c35e 100644
--- a/src/plugins/platforms/wasm/qtloader.js
+++ b/src/plugins/platforms/wasm/qtloader.js
@@ -50,6 +50,7 @@
// External mode.usage:
//
// var config = {
+// canvasElements : [$("canvas-id")],
// showLoader: function() {
// loader.style.display = 'block'
// canvas.style.display = 'hidden'
@@ -69,6 +70,8 @@
// One or more HTML elements. QtLoader will display loader elements
// on these while loading the applicaton, and replace the loader with a
// canvas on load complete.
+// canvasElements : [canvas-element, ...]
+// One or more canvas elements.
// showLoader : function(status, containerElement)
// Optional loading element constructor function. Implement to create
// a custom loading screen. This function may be called multiple times,
@@ -146,8 +149,25 @@ function QtLoader(config)
while (element.firstChild) element.removeChild(element.firstChild);
}
- // Set default state handler functions if needed
+ function createCanvas() {
+ var canvas = document.createElement("canvas");
+ canvas.className = "QtCanvas";
+ canvas.style.height = "100%";
+ canvas.style.width = "100%";
+
+ // Set contentEditable in order to enable clipboard events; hide the resulting focus frame.
+ canvas.contentEditable = true;
+ canvas.style.outline = "0px solid transparent";
+ canvas.style.cursor = "default";
+
+ return canvas;
+ }
+
+ // Set default state handler functions and create canvases if needed
if (config.containerElements !== undefined) {
+
+ config.canvasElements = config.containerElements.map(createCanvas);
+
config.showError = config.showError || function(errorText, container) {
removeChildren(container);
var errorTextElement = document.createElement("text");
@@ -164,19 +184,8 @@ function QtLoader(config)
return loadingText;
};
- config.showCanvas = config.showCanvas || function(container) {
+ config.showCanvas = config.showCanvas || function(canvas, container) {
removeChildren(container);
- var canvas = document.createElement("canvas");
- canvas.className = "QtCanvas"
- canvas.style.height = "100%"
- canvas.style.width = "100%"
-
- // Set contentEditable in order to enable clipboard events; hide the resulting focus frame.
- canvas.contentEditable = true;
- canvas.style.outline = "0px solid transparent";
- canvas.style.cursor = "default";
-
- return canvas;
}
config.showExit = config.showExit || function(crashed, exitCode, container) {
@@ -391,6 +400,8 @@ function QtLoader(config)
Module.mainScriptUrlOrBlob = new Blob([emscriptenModuleSource], {type: 'text/javascript'});
+ Module.qtCanvasElements = config.canvasElements;
+
config.restart = function() {
// Restart by reloading the page. This will wipe all state which means
@@ -445,19 +456,17 @@ function QtLoader(config)
}
function setCanvasContent() {
- var firstCanvas;
if (config.containerElements === undefined) {
- firstCanvas = config.showCanvas();
- } else {
- for (container of config.containerElements) {
- var canvasElement = config.showCanvas(container);
- container.appendChild(canvasElement);
- }
- firstCanvas = config.containerElements[0].firstChild;
+ if (config.showCanvas !== undefined)
+ config.showCanvas();
+ return;
}
- if (Module.canvas === undefined) {
- Module.canvas = firstCanvas;
+ for (var i = 0; i < config.containerElements.length; ++i) {
+ var container = config.containerElements[i];
+ var canvas = config.canvasElements[i];
+ config.showCanvas(canvas, container);
+ container.appendChild(canvas);
}
}
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
index 63fea7738d..7a7b253b19 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.cpp
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -123,9 +123,11 @@ EMSCRIPTEN_BINDINGS(clipboard_module) {
function("qClipboardPasteTo", &qClipboardPasteTo);
}
-QWasmClipboard::QWasmClipboard() :
- hasClipboardApi(false)
+QWasmClipboard::QWasmClipboard()
{
+ val clipboard = val::global("navigator")["clipboard"];
+ hasClipboardApi = (!clipboard.isUndefined() && !clipboard["readText"].isUndefined());
+
initClipboardEvents();
}
@@ -177,29 +179,32 @@ void QWasmClipboard::qWasmClipboardPaste(QMimeData *mData)
void QWasmClipboard::initClipboardEvents()
{
- val navigator = val::global("navigator");
- val permissions = navigator["permissions"];
- val clipboard = navigator["clipboard"];
+ if (!hasClipboardApi)
+ return;
- hasClipboardApi = (!clipboard.isUndefined() && !clipboard["readText"].isUndefined());
- if (hasClipboardApi) {
- val readPermissionsMap = val::object();
- readPermissionsMap.set("name", val("clipboard-read"));
- permissions.call<val>("query", readPermissionsMap);
-
- val writePermissionsMap = val::object();
- writePermissionsMap.set("name", val("clipboard-write"));
- permissions.call<val>("query", writePermissionsMap);
-
- } else {
- val canvas = val::module_property("canvas");
- canvas.call<void>("addEventListener", std::string("cut"),
- val::module_property("qClipboardCutTo"));
- canvas.call<void>("addEventListener", std::string("copy"),
- val::module_property("qClipboardCopyTo"));
- canvas.call<void>("addEventListener", std::string("paste"),
- val::module_property("qClipboardPasteTo"));
- }
+ val permissions = val::global("navigator")["permissions"];
+ val readPermissionsMap = val::object();
+ readPermissionsMap.set("name", val("clipboard-read"));
+ permissions.call<val>("query", readPermissionsMap);
+
+ val writePermissionsMap = val::object();
+ writePermissionsMap.set("name", val("clipboard-write"));
+ permissions.call<val>("query", writePermissionsMap);
+}
+
+void QWasmClipboard::installEventHandlers(const QString &canvasId)
+{
+ if (hasClipboardApi)
+ return;
+
+ // Fallback path for browsers which do not support direct clipboard access
+ val canvas = val::global(canvasId.toUtf8().constData());
+ canvas.call<void>("addEventListener", std::string("cut"),
+ val::module_property("qClipboardCutTo"));
+ canvas.call<void>("addEventListener", std::string("copy"),
+ val::module_property("qClipboardCopyTo"));
+ canvas.call<void>("addEventListener", std::string("paste"),
+ val::module_property("qClipboardPasteTo"));
}
void QWasmClipboard::readTextFromClipboard()
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.h b/src/plugins/platforms/wasm/qwasmclipboard.h
index e64b2e5007..00aae8fead 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.h
+++ b/src/plugins/platforms/wasm/qwasmclipboard.h
@@ -51,6 +51,7 @@ public:
static void qWasmClipboardPaste(QMimeData *mData);
void initClipboardEvents();
+ void installEventHandlers(const QString &canvasId);
bool hasClipboardApi;
void readTextFromClipboard();
void writeTextToClipboard();
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 3dc6b7d2f3..90cc20789d 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -56,8 +56,9 @@ QWasmCompositedWindow::QWasmCompositedWindow()
{
}
-QWasmCompositor::QWasmCompositor()
- : m_frameBuffer(nullptr)
+QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
+ :QObject(screen)
+ , m_frameBuffer(nullptr)
, m_blitter(new QOpenGLTextureBlitter)
, m_needComposit(false)
, m_inFlush(false)
@@ -107,11 +108,6 @@ void QWasmCompositor::removeWindow(QWasmWindow *window)
notifyTopWindowChanged(window);
}
-void QWasmCompositor::setScreen(QWasmScreen *screen)
-{
- m_screen = screen;
-}
-
void QWasmCompositor::setVisible(QWasmWindow *window, bool visible)
{
QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
@@ -654,7 +650,7 @@ void QWasmCompositor::frame()
m_needComposit = false;
- if (m_windowStack.empty() || !m_screen)
+ if (m_windowStack.empty() || !screen())
return;
QWasmWindow *someWindow = nullptr;
@@ -673,7 +669,7 @@ void QWasmCompositor::frame()
if (m_context.isNull()) {
m_context.reset(new QOpenGLContext());
//mContext->setFormat(mScreen->format());
- m_context->setScreen(m_screen->screen());
+ m_context->setScreen(screen()->screen());
m_context->create();
}
@@ -682,8 +678,8 @@ void QWasmCompositor::frame()
if (!m_blitter->isCreated())
m_blitter->create();
- qreal dpr = m_screen->devicePixelRatio();
- glViewport(0, 0, m_screen->geometry().width() * dpr, m_screen->geometry().height() * dpr);
+ qreal dpr = screen()->devicePixelRatio();
+ glViewport(0, 0, screen()->geometry().width() * dpr, screen()->geometry().height() * dpr);
m_context->functions()->glClearColor(0.2, 0.2, 0.2, 1.0);
m_context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -697,7 +693,7 @@ void QWasmCompositor::frame()
if (!compositedWindow.visible)
continue;
- drawWindow(m_blitter.data(), m_screen, window);
+ drawWindow(m_blitter.data(), screen(), window);
}
m_blitter->release();
@@ -719,3 +715,8 @@ void QWasmCompositor::notifyTopWindowChanged(QWasmWindow *window)
requestRedraw();
QWindowSystemInterface::handleWindowActivated(window->window());
}
+
+QWasmScreen *QWasmCompositor::screen()
+{
+ return static_cast<QWasmScreen *>(parent());
+}
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 4e5ed46cec..ed6facdcc3 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -62,7 +62,7 @@ class QWasmCompositor : public QObject
{
Q_OBJECT
public:
- QWasmCompositor();
+ QWasmCompositor(QWasmScreen *screen);
~QWasmCompositor();
enum QWasmSubControl {
@@ -103,7 +103,6 @@ public:
void addWindow(QWasmWindow *window, QWasmWindow *parentWindow = nullptr);
void removeWindow(QWasmWindow *window);
- void setScreen(QWasmScreen *screen);
void setVisible(QWasmWindow *window, bool visible);
void raise(QWasmWindow *window);
@@ -129,8 +128,7 @@ private slots:
void frame();
private:
- void createFrameBuffer();
- void flushCompletedCallback(int32_t);
+ QWasmScreen *screen();
void notifyTopWindowChanged(QWasmWindow *window);
void drawWindow(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
void drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window);
@@ -142,7 +140,6 @@ private:
QImage *m_frameBuffer;
QScopedPointer<QOpenGLContext> m_context;
QScopedPointer<QOpenGLTextureBlitter> m_blitter;
- QWasmScreen *m_screen;
QHash<QWasmWindow *, QWasmCompositedWindow> m_compositedWindows;
QList<QWasmWindow *> m_windowStack;
diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp
index 744b160dd1..2b3f37300d 100644
--- a/src/plugins/platforms/wasm/qwasmcursor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcursor.cpp
@@ -28,20 +28,21 @@
****************************************************************************/
#include "qwasmcursor.h"
+#include "qwasmscreen.h"
#include <QtCore/qdebug.h>
+#include <QtGui/qwindow.h>
#include <emscripten/emscripten.h>
#include <emscripten/bind.h>
void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
{
- if (windowCursor == nullptr)
+ if (!windowCursor || !window)
+ return;
+ QScreen *screen = window->screen();
+ if (!screen)
return;
-
- // FIXME: The HTML5 plugin sets the cursor on the native canvas; when using multiple windows
- // multiple cursors need to be managed taking mouse postion and stacking into account.
- Q_UNUSED(window);
// Bitmap and custom cursors are not implemented (will fall back to "auto")
if (windowCursor->shape() == Qt::BitmapCursor || windowCursor->shape() >= Qt::CustomCursor)
@@ -52,8 +53,9 @@ void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
if (htmlCursorName.isEmpty())
htmlCursorName = "auto";
- // Set cursor on the main canvas
- emscripten::val canvasStyle = emscripten::val::module_property("canvas")["style"];
+ // Set cursor on the canvas
+ QString canvasId = QWasmScreen::get(screen)->canvasId();
+ emscripten::val canvasStyle = emscripten::val::global(canvasId.toUtf8().constData())["style"];
canvasStyle.set("cursor", emscripten::val(htmlCursorName.constData()));
}
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index 23bf9a7de6..14222da807 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -320,8 +320,8 @@ EMSCRIPTEN_BINDINGS(mouse_module) {
function("mouseWheelEvent", &mouseWheelEvent);
}
-QWasmEventTranslator::QWasmEventTranslator(QObject *parent)
- : QObject(parent)
+QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen)
+ : QObject(screen)
, draggedWindow(nullptr)
, lastWindow(nullptr)
, pressedButtons(Qt::NoButton)
@@ -332,13 +332,16 @@ QWasmEventTranslator::QWasmEventTranslator(QObject *parent)
touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition);
QWindowSystemInterface::registerTouchDevice(touchDevice);
- QWasmScreen *wasmScreen = QWasmIntegration::get()->screen();
- initEventHandlers(wasmScreen->m_canvasId);
+ initEventHandlers();
}
-void QWasmEventTranslator::initEventHandlers(const QString &canvas)
+void QWasmEventTranslator::initEventHandlers()
{
- const char *canvasId = canvas.toLocal8Bit().constData();
+ qDebug() << "QWasmEventTranslator::initEventHandlers";
+
+ QByteArray _canvasId = screen()->canvasId().toUtf8();
+ const char *canvasId = _canvasId.constData();
+
// The Platform Detect: expand coverage and move as needed
enum Platform {
GenericPlatform,
@@ -375,7 +378,7 @@ void QWasmEventTranslator::initEventHandlers(const QString &canvas)
emscripten_set_touchmove_callback(canvasId, (void *)this, 1, &touchCallback);
emscripten_set_touchcancel_callback(canvasId, (void *)this, 1, &touchCallback);
- emscripten_set_resize_callback(canvasId, (void *)this, 1, uiEvent_cb);
+ emscripten_set_resize_callback(nullptr, (void *)this, 1, uiEvent_cb); // Note: handles browser window resize
}
@@ -425,6 +428,11 @@ int QWasmEventTranslator::keyboard_cb(int eventType, const EmscriptenKeyboardEve
return accepted ? 1 : 0;
}
+QWasmScreen *QWasmEventTranslator::screen()
+{
+ return static_cast<QWasmScreen *>(parent());
+}
+
Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey)
{
Qt::Key qtKey = Qt::Key_unknown;
@@ -541,14 +549,14 @@ void resizeWindow(QWindow *window, QWasmWindow::ResizeMode mode,
void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEvent *mouseEvent)
{
auto timestamp = mouseEvent->timestamp;
- QPoint point(mouseEvent->canvasX, mouseEvent->canvasY);
+ QPoint point(mouseEvent->targetX, mouseEvent->targetY);
QEvent::Type buttonEventType = QEvent::None;
Qt::MouseButton button = translateMouseButton(mouseEvent->button);
Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent);
- QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
+ QWindow *window2 = screen()->compositor()->windowAt(point, 5);
if (window2 != nullptr)
lastWindow = window2;
@@ -645,6 +653,7 @@ int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wh
{
Q_UNUSED(eventType)
+ QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
EmscriptenMouseEvent mouseEvent = wheelEvent->mouse;
int scrollFactor = 0;
@@ -668,7 +677,7 @@ int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wh
auto timestamp = mouseEvent.timestamp;
QPoint globalPoint(mouseEvent.canvasX, mouseEvent.canvasY);
- QWindow *window2 = QWasmIntegration::get()->compositor()->windowAt(globalPoint, 5);
+ QWindow *window2 = eventTranslator->screen()->compositor()->windowAt(globalPoint, 5);
QPoint localPoint(globalPoint.x() - window2->geometry().x(), globalPoint.y() - window2->geometry().y());
@@ -686,6 +695,7 @@ int QWasmEventTranslator::wheel_cb(int eventType, const EmscriptenWheelEvent *wh
int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
+ QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
QList<QWindowSystemInterface::TouchPoint> touchPointList;
touchPointList.reserve(touchEvent->numTouches);
QWindow *window2;
@@ -695,7 +705,7 @@ int QWasmEventTranslator::touchCallback(int eventType, const EmscriptenTouchEven
const EmscriptenTouchPoint *touches = &touchEvent->touches[i];
QPoint point(touches->canvasX, touches->canvasY);
- window2 = QWasmIntegration::get()->compositor()->windowAt(point, 5);
+ window2 = eventTranslator->screen()->compositor()->windowAt(point, 5);
QWindowSystemInterface::TouchPoint touchPoint;
@@ -878,15 +888,13 @@ bool QWasmEventTranslator::processKeyboard(int eventType, const EmscriptenKeyboa
int QWasmEventTranslator::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
{
Q_UNUSED(e)
- Q_UNUSED(userData)
+ QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
if (eventType == EMSCRIPTEN_EVENT_RESIZE) {
// This resize event is called when the HTML window is resized. Depending
// on the page layout the the canvas might also have been resized, so we
// update the Qt screen size (and canvas render size).
- QWasmScreen *wasmScreen = QWasmIntegration::get()->screen();
-
- wasmScreen->updateQScreenAndCanvasRenderSize(wasmScreen->m_canvasId.toLocal8Bit().constData());
+ eventTranslator->screen()->updateQScreenAndCanvasRenderSize();
}
return 0;
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h
index a9a00eab0b..ba08dce946 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.h
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h
@@ -48,7 +48,7 @@ class QWasmEventTranslator : public QObject
public:
- explicit QWasmEventTranslator(QObject *parent = 0);
+ explicit QWasmEventTranslator(QWasmScreen *screen);
static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
static int mouse_cb(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData);
@@ -60,12 +60,12 @@ public:
static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData);
void processEvents();
- void initEventHandlers(const QString &);
+ void initEventHandlers();
Q_SIGNALS:
void getWindowAt(const QPoint &point, QWindow **window);
private:
-
+ QWasmScreen *screen();
Qt::Key translateEmscriptKey(const EmscriptenKeyboardEvent *emscriptKey);
template <typename Event>
QFlags<Qt::KeyboardModifier> translatKeyModifier(const Event *event);
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index f45048ffa4..1964cefdad 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -70,36 +70,35 @@ QWasmIntegration *QWasmIntegration::s_instance;
QWasmIntegration::QWasmIntegration()
: m_fontDb(nullptr),
- m_compositor(new QWasmCompositor),
- m_screen(new QWasmScreen(m_compositor)),
m_eventDispatcher(nullptr),
m_clipboard(new QWasmClipboard)
{
-
- globalHtml5Integration = this;
s_instance = this;
- emscripten::val defaultCanvasId = emscripten::val::global("canvas");
- canvasIds.append(QString::fromStdString(defaultCanvasId["id"].as<std::string>()));
- m_screen->setCanvas(canvasIds.at(0));
-
- globalHtml5Integration = this;
-
- screen()->updateQScreenAndCanvasRenderSize(m_screen->m_canvasId);
- screenAdded(m_screen);
-
- m_eventTranslator = new QWasmEventTranslator;
+ // We expect that qtloader.js has populated Module.qtCanvasElements with one or more canvases.
+ // Also check Module.canvas, which may be set if the emscripen or a custom loader is used.
+ emscripten::val qtCanvaseElements = val::module_property("qtCanvasElements");
+ emscripten::val canvas = val::module_property("canvas");
+
+ if (!qtCanvaseElements.isUndefined()) {
+ int screenCount = qtCanvaseElements["length"].as<int>();
+ for (int i = 0; i < screenCount; ++i) {
+ emscripten::val canvas = qtCanvaseElements[i].as<emscripten::val>();
+ QString canvasId = QString::fromStdString(canvas["id"].as<std::string>());
+ addScreen(canvasId);
+ }
+ } else if (!canvas.isUndefined()){
+ QString canvasId = QString::fromStdString(canvas["id"].as<std::string>());
+ addScreen(canvasId);
+ }
emscripten::val::global("window").set("onbeforeunload", val::module_property("browserBeforeUnload"));
-
}
QWasmIntegration::~QWasmIntegration()
{
- delete m_compositor;
- destroyScreen(m_screen);
delete m_fontDb;
- delete m_eventTranslator;
+ qDeleteAll(m_screens);
s_instance = nullptr;
}
@@ -124,13 +123,15 @@ bool QWasmIntegration::hasCapability(QPlatformIntegration::Capability cap) const
QPlatformWindow *QWasmIntegration::createPlatformWindow(QWindow *window) const
{
- return new QWasmWindow(window, m_compositor, m_backingStores.value(window));
+ QWasmCompositor *compositor = QWasmScreen::get(window->screen())->compositor();
+ return new QWasmWindow(window, compositor, m_backingStores.value(window));
}
QPlatformBackingStore *QWasmIntegration::createPlatformBackingStore(QWindow *window) const
{
#ifndef QT_NO_OPENGL
- QWasmBackingStore *backingStore = new QWasmBackingStore(m_compositor, window);
+ QWasmCompositor *compositor = QWasmScreen::get(window->screen())->compositor();
+ QWasmBackingStore *backingStore = new QWasmBackingStore(compositor, window);
m_backingStores.insert(window, backingStore);
return backingStore;
#else
@@ -177,9 +178,20 @@ QPlatformTheme *QWasmIntegration::createPlatformTheme(const QString &name) const
QPlatformClipboard* QWasmIntegration::clipboard() const
{
- if (!m_clipboard)
- m_clipboard = new QWasmClipboard;
return m_clipboard;
}
+QVector<QWasmScreen *> QWasmIntegration::screens()
+{
+ return m_screens;
+}
+
+void QWasmIntegration::addScreen(const QString &canvasId)
+{
+ QWasmScreen *screen = new QWasmScreen(canvasId);
+ m_clipboard->installEventHandlers(canvasId);
+ m_screens.append(screen);
+ screenAdded(screen);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index 0b73303bf4..5c0ac0b297 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -71,23 +71,20 @@ public:
QPlatformTheme *createPlatformTheme(const QString &name) const override;
QPlatformClipboard *clipboard() const override;
- QWasmScreen *screen() { return m_screen; }
- QWasmCompositor *compositor() { return m_compositor; }
- QWasmEventTranslator *eventTranslator() { return m_eventTranslator; }
+ QVector<QWasmScreen *>screens();
QWasmClipboard *getWasmClipboard() { return m_clipboard; }
static QWasmIntegration *get() { return s_instance; }
static void QWasmBrowserExit();
- QStringList canvasIds;
private:
+ void addScreen(const QString &canvasId);
+
mutable QWasmFontDatabase *m_fontDb;
- QWasmCompositor *m_compositor;
- mutable QWasmScreen *m_screen;
- mutable QWasmEventTranslator *m_eventTranslator;
mutable QWasmEventDispatcher *m_eventDispatcher;
mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores;
+ QVector<QWasmScreen *> m_screens;
mutable QWasmClipboard *m_clipboard;
static QWasmIntegration *s_instance;
};
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
index e71da0c217..ae43e2ebf0 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
@@ -57,9 +57,7 @@ void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surfac
emscripten_webgl_destroy_context(m_context);
// Create new context
- QWasmScreen *wasmScreen = QWasmIntegration::get()->screen();
- const QString canvasId = wasmScreen->m_canvasId;
- // FIXME: get the actual canvas from the surface.
+ const QString canvasId = QWasmScreen::get(surface->screen())->canvasId();
m_context = createEmscriptenContext(canvasId, m_requestedFormat);
// Register context-lost callback.
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index fb14803ff8..a26cafa900 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -29,8 +29,10 @@
#include "qwasmscreen.h"
#include "qwasmwindow.h"
+#include "qwasmeventtranslator.h"
#include "qwasmcompositor.h"
#include <emscripten/bind.h>
+#include <emscripten/val.h>
#include <QtEglSupport/private/qeglconvenience_p.h>
#ifndef QT_NO_OPENGL
@@ -44,12 +46,13 @@
QT_BEGIN_NAMESPACE
-QWasmScreen::QWasmScreen(QWasmCompositor *compositor)
- : m_compositor(compositor)
- , m_depth(32)
- , m_format(QImage::Format_RGB32)
+QWasmScreen::QWasmScreen(const QString &canvasId)
+ : m_canvasId(canvasId)
+
{
- m_compositor->setScreen(this);
+ m_compositor = new QWasmCompositor(this);
+ m_eventTranslator = new QWasmEventTranslator(this);
+ updateQScreenAndCanvasRenderSize();
}
QWasmScreen::~QWasmScreen()
@@ -57,6 +60,31 @@ QWasmScreen::~QWasmScreen()
}
+QWasmScreen *QWasmScreen::get(QPlatformScreen *screen)
+{
+ return static_cast<QWasmScreen *>(screen);
+}
+
+QWasmScreen *QWasmScreen::get(QScreen *screen)
+{
+ return get(screen->handle());
+}
+
+QWasmCompositor *QWasmScreen::compositor()
+{
+ return m_compositor;
+}
+
+QWasmEventTranslator *QWasmScreen::eventTranslator()
+{
+ return m_eventTranslator;
+}
+
+QString QWasmScreen::canvasId() const
+{
+ return m_canvasId;
+}
+
QRect QWasmScreen::geometry() const
{
return m_geometry;
@@ -82,6 +110,11 @@ qreal QWasmScreen::devicePixelRatio() const
return qreal(htmlWindowDpr);
}
+QString QWasmScreen::name() const
+{
+ return m_canvasId;
+}
+
QPlatformCursor *QWasmScreen::cursor() const
{
return const_cast<QWasmCursor *>(&m_cursor);
@@ -114,14 +147,7 @@ void QWasmScreen::setGeometry(const QRect &rect)
resizeMaximizedWindows();
}
-static void set_canvas_size(double width, double height, const char *canvasId)
-{
- emscripten::val canvas = emscripten::val::global(canvasId);
- canvas.set("width", width);
- canvas.set("height", height);
-}
-
-void QWasmScreen::updateQScreenAndCanvasRenderSize(const QString &canvasId)
+void QWasmScreen::updateQScreenAndCanvasRenderSize()
{
// The HTML canvas has two sizes: the CSS size and the canvas render size.
// The CSS size is determined according to standard CSS rules, while the
@@ -130,17 +156,22 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize(const QString &canvasId)
// Setting the render size to a value larger than the CSS size enables high-dpi
// rendering.
+ QByteArray canvasId = m_canvasId.toUtf8();
double css_width;
double css_height;
- emscripten_get_element_css_size(canvasId.toLocal8Bit().constData(), &css_width, &css_height);
+ emscripten_get_element_css_size(canvasId.constData(), &css_width, &css_height);
QSizeF cssSize(css_width, css_height);
- QWasmScreen *screen = QWasmIntegration::get()->screen();
- QSizeF canvasSize = cssSize * screen->devicePixelRatio();
+ QSizeF canvasSize = cssSize * devicePixelRatio();
+ emscripten::val canvas = emscripten::val::global(canvasId.constData());
+ canvas.set("width", canvasSize.width());
+ canvas.set("height", canvasSize.height());
+
+ emscripten::val rect = canvas.call<emscripten::val>("getBoundingClientRect");
+ QPoint position(rect["left"].as<int>(), rect["top"].as<int>());
- set_canvas_size(canvasSize.width(), canvasSize.height(), canvasId.toLocal8Bit().constData());
- screen->setGeometry(QRect(QPoint(0, 0), cssSize.toSize()));
- QWasmIntegration::get()->compositor()->redrawWindowContent();
+ setGeometry(QRect(position, cssSize.toSize()));
+ m_compositor->redrawWindowContent();
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
index d5080835c9..82d2a83edb 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.h
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -43,20 +43,28 @@ class QPlatformOpenGLContext;
class QWasmWindow;
class QWasmBackingStore;
class QWasmCompositor;
+class QWasmEventTranslator;
class QOpenGLContext;
class QWasmScreen : public QObject, public QPlatformScreen
{
Q_OBJECT
public:
-
- QWasmScreen(QWasmCompositor *compositor);
+ QWasmScreen(const QString &canvasId);
~QWasmScreen();
+ static QWasmScreen *get(QPlatformScreen *screen);
+ static QWasmScreen *get(QScreen *screen);
+ QString canvasId() const;
+
+ QWasmCompositor *compositor();
+ QWasmEventTranslator *eventTranslator();
+
QRect geometry() const override;
int depth() const override;
QImage::Format format() const override;
qreal devicePixelRatio() const override;
+ QString name() const override;
QPlatformCursor *cursor() const override;
void resizeMaximizedWindows();
@@ -64,19 +72,18 @@ public:
QWindow *topLevelAt(const QPoint &p) const override;
void invalidateSize();
- static void updateQScreenAndCanvasRenderSize(const QString &);
- QString m_canvasId;
- void setCanvas(const QString &canvasId) { m_canvasId = canvasId; }
+ void updateQScreenAndCanvasRenderSize();
public slots:
void setGeometry(const QRect &rect);
private:
- QWasmCompositor *m_compositor;
-
+ QString m_canvasId;
+ QWasmCompositor *m_compositor = nullptr;
+ QWasmEventTranslator *m_eventTranslator = nullptr;
QRect m_geometry = QRect(0, 0, 100, 100);
- int m_depth;
- QImage::Format m_format;
+ int m_depth = 32;
+ QImage::Format m_format = QImage::Format_RGB32;
QWasmCursor m_cursor;
};
diff --git a/src/plugins/platforms/wasm/wasm_shell.html b/src/plugins/platforms/wasm/wasm_shell.html
index 110d45e036..39bb711b6b 100644
--- a/src/plugins/platforms/wasm/wasm_shell.html
+++ b/src/plugins/platforms/wasm/wasm_shell.html
@@ -15,23 +15,24 @@
</style>
</head>
<body onload="init()">
- <figure style="overflow:visible;" id="spinner">
+ <figure style="overflow:visible;" id="qtspinner">
<center style="margin-top:1.5em; line-height:150%">
<img src="qtlogo.svg"; width=320; height=200; style="display:block"> </img>
<strong>Qt for WebAssembly: APPNAME</strong>
- <div id="status"></div>
+ <div id="qtstatus"></div>
<noscript>JavaScript is disabled. Please enable JavaScript to use this application.</noscript>
</center>
</figure>
- <canvas id="canvas" oncontextmenu="event.preventDefault()" contenteditable="true"></canvas>
+ <canvas id="qtcanvas" oncontextmenu="event.preventDefault()" contenteditable="true"></canvas>
<script type='text/javascript'>
function init() {
- var spinner = document.getElementById('spinner');
- var canvas = document.getElementById('canvas');
- var status = document.getElementById('status')
+ var spinner = document.getElementById('qtspinner');
+ var canvas = document.getElementById('qtcanvas');
+ var status = document.getElementById('qtstatus')
var qtLoader = QtLoader({
+ canvasElements : [canvas],
showLoader: function(loaderStatus) {
spinner.style.display = 'block';
canvas.style.display = 'none';
@@ -54,7 +55,6 @@
showCanvas: function() {
spinner.style.display = 'none';
canvas.style.display = 'block';
- return canvas;
},
});
qtLoader.loadEmscriptenModule("APPNAME");