wasm: make wasm platform target a specific canvas instead of default

This allows for multi canvas use

Task-number: QTBUG-64079
Change-Id: I69c998aa4c2869bb5b7f14ba65bb63284365ad70
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
Lorn Potter 2019-01-31 14:06:39 +10:00 committed by Morten Johan Sørvig
parent 859f837d46
commit 452c644c5c
8 changed files with 98 additions and 73 deletions

View File

@ -327,34 +327,25 @@ QWasmEventTranslator::QWasmEventTranslator(QObject *parent)
, pressedButtons(Qt::NoButton) , pressedButtons(Qt::NoButton)
, resizeMode(QWasmWindow::ResizeNone) , resizeMode(QWasmWindow::ResizeNone)
{ {
emscripten_set_keydown_callback(0, (void *)this, 1, &keyboard_cb);
emscripten_set_keyup_callback(0, (void *)this, 1, &keyboard_cb);
emscripten_set_mousedown_callback(0, (void *)this, 1, &mouse_cb);
emscripten_set_mouseup_callback(0, (void *)this, 1, &mouse_cb);
emscripten_set_mousemove_callback(0, (void *)this, 1, &mouse_cb);
emscripten_set_focus_callback(0, (void *)this, 1, &focus_cb);
emscripten_set_wheel_callback(0, (void *)this, 1, &wheel_cb);
touchDevice = new QTouchDevice; touchDevice = new QTouchDevice;
touchDevice->setType(QTouchDevice::TouchScreen); touchDevice->setType(QTouchDevice::TouchScreen);
touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition); touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition);
QWindowSystemInterface::registerTouchDevice(touchDevice); QWindowSystemInterface::registerTouchDevice(touchDevice);
emscripten_set_touchstart_callback("#canvas", (void *)this, 1, &touchCallback); QWasmScreen *wasmScreen = QWasmIntegration::get()->screen();
emscripten_set_touchend_callback("#canvas", (void *)this, 1, &touchCallback); initEventHandlers(wasmScreen->m_canvasId);
emscripten_set_touchmove_callback("#canvas", (void *)this, 1, &touchCallback); }
emscripten_set_touchcancel_callback("#canvas", (void *)this, 1, &touchCallback);
void QWasmEventTranslator::initEventHandlers(const QString &canvas)
{
const char *canvasId = canvas.toLocal8Bit().constData();
// The Platform Detect: expand coverage and move as needed // The Platform Detect: expand coverage and move as needed
enum Platform { enum Platform {
GenericPlatform, GenericPlatform,
MacOSPlatform MacOSPlatform
}; };
Platform platform = Platform(emscripten::val::global("navigator")["platform"] Platform platform = Platform(emscripten::val::global("navigator")["platform"]
.call<bool>("includes", emscripten::val("Mac"))); .call<bool>("includes", emscripten::val("Mac")));
g_usePlatformMacCtrlMetaSwitching = (platform == MacOSPlatform); g_usePlatformMacCtrlMetaSwitching = (platform == MacOSPlatform);
if (platform == MacOSPlatform) { if (platform == MacOSPlatform) {
@ -362,11 +353,30 @@ QWasmEventTranslator::QWasmEventTranslator(QObject *parent)
if (emscripten::val::global("window")["safari"].isUndefined()) { if (emscripten::val::global("window")["safari"].isUndefined()) {
emscripten::val::global("canvas").call<void>("addEventListener", emscripten::val::global(canvasId).call<void>("addEventListener",
std::string("wheel"), std::string("wheel"),
val::module_property("mouseWheelEvent")); val::module_property("mouseWheelEvent"));
} }
} }
emscripten_set_keydown_callback(canvasId, (void *)this, 1, &keyboard_cb);
emscripten_set_keyup_callback(canvasId, (void *)this, 1, &keyboard_cb);
emscripten_set_mousedown_callback(canvasId, (void *)this, 1, &mouse_cb);
emscripten_set_mouseup_callback(canvasId, (void *)this, 1, &mouse_cb);
emscripten_set_mousemove_callback(canvasId, (void *)this, 1, &mouse_cb);
emscripten_set_focus_callback(canvasId, (void *)this, 1, &focus_cb);
emscripten_set_wheel_callback(canvasId, (void *)this, 1, &wheel_cb);
emscripten_set_touchstart_callback(canvasId, (void *)this, 1, &touchCallback);
emscripten_set_touchend_callback(canvasId, (void *)this, 1, &touchCallback);
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);
} }
template <typename Event> template <typename Event>
@ -865,4 +875,21 @@ bool QWasmEventTranslator::processKeyboard(int eventType, const EmscriptenKeyboa
return accepted; return accepted;
} }
int QWasmEventTranslator::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
{
Q_UNUSED(e)
Q_UNUSED(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());
}
return 0;
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -57,7 +57,10 @@ public:
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData); static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData);
void processEvents(); void processEvents();
void initEventHandlers(const QString &);
Q_SIGNALS: Q_SIGNALS:
void getWindowAt(const QPoint &point, QWindow **window); void getWindowAt(const QPoint &point, QWindow **window);

View File

@ -75,11 +75,18 @@ QWasmIntegration::QWasmIntegration()
m_eventDispatcher(nullptr), m_eventDispatcher(nullptr),
m_clipboard(new QWasmClipboard) m_clipboard(new QWasmClipboard)
{ {
globalHtml5Integration = this;
s_instance = this; s_instance = this;
updateQScreenAndCanvasRenderSize(); 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); screenAdded(m_screen);
emscripten_set_resize_callback(0, (void *)this, 1, uiEvent_cb);
m_eventTranslator = new QWasmEventTranslator; m_eventTranslator = new QWasmEventTranslator;
@ -168,50 +175,6 @@ QPlatformTheme *QWasmIntegration::createPlatformTheme(const QString &name) const
return QPlatformIntegration::createPlatformTheme(name); return QPlatformIntegration::createPlatformTheme(name);
} }
int QWasmIntegration::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
{
Q_UNUSED(e)
Q_UNUSED(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).
updateQScreenAndCanvasRenderSize();
}
return 0;
}
static void set_canvas_size(double width, double height)
{
emscripten::val canvas = emscripten::val::global("canvas");
canvas.set("width", width);
canvas.set("height", height);
}
void QWasmIntegration::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
// render size is set using the "width" and "height" attributes. The render
// size must be set manually and is not auto-updated on CSS size change.
// Setting the render size to a value larger than the CSS size enables high-dpi
// rendering.
double css_width;
double css_height;
emscripten_get_element_css_size(0, &css_width, &css_height);
QSizeF cssSize(css_width, css_height);
QWasmScreen *screen = QWasmIntegration::get()->m_screen;
QSizeF canvasSize = cssSize * screen->devicePixelRatio();
set_canvas_size(canvasSize.width(), canvasSize.height());
screen->setGeometry(QRect(QPoint(0, 0), cssSize.toSize()));
QWasmIntegration::get()->m_compositor->redrawWindowContent();
}
QPlatformClipboard* QWasmIntegration::clipboard() const QPlatformClipboard* QWasmIntegration::clipboard() const
{ {
if (!m_clipboard) if (!m_clipboard)

View File

@ -78,7 +78,7 @@ public:
static QWasmIntegration *get() { return s_instance; } static QWasmIntegration *get() { return s_instance; }
static void QWasmBrowserExit(); static void QWasmBrowserExit();
static void updateQScreenAndCanvasRenderSize(); QStringList canvasIds;
private: private:
mutable QWasmFontDatabase *m_fontDb; mutable QWasmFontDatabase *m_fontDb;
@ -86,7 +86,6 @@ private:
mutable QWasmScreen *m_screen; mutable QWasmScreen *m_screen;
mutable QWasmEventTranslator *m_eventTranslator; mutable QWasmEventTranslator *m_eventTranslator;
mutable QWasmEventDispatcher *m_eventDispatcher; mutable QWasmEventDispatcher *m_eventDispatcher;
static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData);
mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores; mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores;
mutable QWasmClipboard *m_clipboard; mutable QWasmClipboard *m_clipboard;

View File

@ -28,7 +28,7 @@
****************************************************************************/ ****************************************************************************/
#include "qwasmopenglcontext.h" #include "qwasmopenglcontext.h"
#include "qwasmintegration.h"
#include <EGL/egl.h> #include <EGL/egl.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -57,7 +57,9 @@ void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surfac
emscripten_webgl_destroy_context(m_context); emscripten_webgl_destroy_context(m_context);
// Create new context // Create new context
const char *canvasId = 0; // (use default canvas) FIXME: get the actual canvas from the surface. QWasmScreen *wasmScreen = QWasmIntegration::get()->screen();
const QString canvasId = wasmScreen->m_canvasId;
// FIXME: get the actual canvas from the surface.
m_context = createEmscriptenContext(canvasId, m_requestedFormat); m_context = createEmscriptenContext(canvasId, m_requestedFormat);
// Register context-lost callback. // Register context-lost callback.
@ -73,11 +75,11 @@ void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surfac
return true; return true;
}; };
bool capture = true; bool capture = true;
emscripten_set_webglcontextlost_callback(canvasId, this, capture, callback); emscripten_set_webglcontextlost_callback(canvasId.toLocal8Bit().constData(), this, capture, callback);
} }
} }
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const char *canvasId, QSurfaceFormat format) EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const QString &canvasId, QSurfaceFormat format)
{ {
EmscriptenWebGLContextAttributes attributes; EmscriptenWebGLContextAttributes attributes;
emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes emscripten_webgl_init_context_attributes(&attributes); // Populate with default attributes
@ -96,7 +98,7 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons
attributes.depth = format.depthBufferSize() > 0; attributes.depth = format.depthBufferSize() > 0;
attributes.stencil = format.stencilBufferSize() > 0; attributes.stencil = format.stencilBufferSize() > 0;
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId, &attributes); EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(canvasId.toLocal8Bit().constData(), &attributes);
return context; return context;
} }

View File

@ -51,7 +51,7 @@ public:
private: private:
void maybeRecreateEmscriptenContext(QPlatformSurface *surface); void maybeRecreateEmscriptenContext(QPlatformSurface *surface);
static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const char *canvasId, QSurfaceFormat format); static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const QString &canvasId, QSurfaceFormat format);
bool m_contextLost = false; bool m_contextLost = false;
QSurfaceFormat m_requestedFormat; QSurfaceFormat m_requestedFormat;

View File

@ -114,4 +114,33 @@ void QWasmScreen::setGeometry(const QRect &rect)
resizeMaximizedWindows(); 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)
{
// 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
// render size is set using the "width" and "height" attributes. The render
// size must be set manually and is not auto-updated on CSS size change.
// Setting the render size to a value larger than the CSS size enables high-dpi
// rendering.
double css_width;
double css_height;
emscripten_get_element_css_size(canvasId.toLocal8Bit().constData(), &css_width, &css_height);
QSizeF cssSize(css_width, css_height);
QWasmScreen *screen = QWasmIntegration::get()->screen();
QSizeF canvasSize = cssSize * screen->devicePixelRatio();
set_canvas_size(canvasSize.width(), canvasSize.height(), canvasId.toLocal8Bit().constData());
screen->setGeometry(QRect(QPoint(0, 0), cssSize.toSize()));
QWasmIntegration::get()->compositor()->redrawWindowContent();
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -64,10 +64,12 @@ public:
QWindow *topLevelAt(const QPoint &p) const override; QWindow *topLevelAt(const QPoint &p) const override;
void invalidateSize(); void invalidateSize();
static void updateQScreenAndCanvasRenderSize(const QString &);
QString m_canvasId;
void setCanvas(const QString &canvasId) { m_canvasId = canvasId; }
public slots: public slots:
void setGeometry(const QRect &rect); void setGeometry(const QRect &rect);
protected:
private: private:
QWasmCompositor *m_compositor; QWasmCompositor *m_compositor;