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("query", readPermissionsMap); + val permissions = val::global("navigator")["permissions"]; + val readPermissionsMap = val::object(); + readPermissionsMap.set("name", val("clipboard-read")); + permissions.call("query", readPermissionsMap); - val writePermissionsMap = val::object(); - writePermissionsMap.set("name", val("clipboard-write")); - permissions.call("query", writePermissionsMap); + val writePermissionsMap = val::object(); + writePermissionsMap.set("name", val("clipboard-write")); + permissions.call("query", writePermissionsMap); +} - } else { - val canvas = val::module_property("canvas"); - canvas.call("addEventListener", std::string("cut"), - val::module_property("qClipboardCutTo")); - canvas.call("addEventListener", std::string("copy"), - val::module_property("qClipboardCopyTo")); - canvas.call("addEventListener", std::string("paste"), - val::module_property("qClipboardPasteTo")); - } +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("addEventListener", std::string("cut"), + val::module_property("qClipboardCutTo")); + canvas.call("addEventListener", std::string("copy"), + val::module_property("qClipboardCopyTo")); + canvas.call("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(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 m_context; QScopedPointer m_blitter; - QWasmScreen *m_screen; QHash m_compositedWindows; QList 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 +#include #include #include 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(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(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(userData); QList 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(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 QFlags 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())); - m_screen->setCanvas(canvasIds.at(0)); + // 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"); - globalHtml5Integration = this; - - screen()->updateQScreenAndCanvasRenderSize(m_screen->m_canvasId); - screenAdded(m_screen); - - m_eventTranslator = new QWasmEventTranslator; + if (!qtCanvaseElements.isUndefined()) { + int screenCount = qtCanvaseElements["length"].as(); + for (int i = 0; i < screenCount; ++i) { + emscripten::val canvas = qtCanvaseElements[i].as(); + QString canvasId = QString::fromStdString(canvas["id"].as()); + addScreen(canvasId); + } + } else if (!canvas.isUndefined()){ + QString canvasId = QString::fromStdString(canvas["id"].as()); + 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 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; } + QVectorscreens(); 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 m_backingStores; + QVector 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 +#include #include #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(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(&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()); - set_canvas_size(canvasSize.width(), canvasSize.height(), canvasId.toLocal8Bit().constData()); - screen->setGeometry(QRect(QPoint(0, 0), cssSize.toSize())); - QWasmIntegration::get()->compositor()->redrawWindowContent(); + emscripten::val rect = canvas.call("getBoundingClientRect"); + QPoint position(rect["left"].as(), rect["top"].as()); + + 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 @@ -
+
Qt for WebAssembly: APPNAME -
+
- +