wasm: store and pass canvases as emscripten::val
Store and pass canvases as emscripten::val instead of a QString containing the element id. This simplifies code which interacts with the canvas using the emscripten::val API, by removing the need to look up with getElementById. The Emscripten C event API does not accept emscripten::val, and using the element id is still needed here. emscripten::val does not provide a hash key suitable for use with QHash, but does provide an equality-compare in the form of val::equals(). Change the canvas->screen mapping code to use a QVector instead of a QHash. Change-Id: I1dbdbbc8fb06bb869031f1500e83ae2d64780a7f Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
This commit is contained in:
parent
e290ebae9f
commit
2b0af50c8b
@ -192,15 +192,12 @@ void QWasmClipboard::initClipboardEvents()
|
||||
permissions.call<val>("query", writePermissionsMap);
|
||||
}
|
||||
|
||||
void QWasmClipboard::installEventHandlers(const QString &canvasId)
|
||||
void QWasmClipboard::installEventHandlers(const emscripten::val &canvas)
|
||||
{
|
||||
if (hasClipboardApi)
|
||||
return;
|
||||
|
||||
// Fallback path for browsers which do not support direct clipboard access
|
||||
val document = val::global("document");
|
||||
val canvas = document.call<val>("getElementById", QWasmString::fromQString(canvasId));
|
||||
|
||||
canvas.call<void>("addEventListener", val("cut"),
|
||||
val::module_property("qtClipboardCutTo"));
|
||||
canvas.call<void>("addEventListener", val("copy"),
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <QMimeData>
|
||||
|
||||
#include <emscripten/bind.h>
|
||||
#include <emscripten/val.h>
|
||||
|
||||
class QWasmClipboard : public QObject, public QPlatformClipboard
|
||||
{
|
||||
@ -51,7 +52,7 @@ public:
|
||||
|
||||
static void qWasmClipboardPaste(QMimeData *mData);
|
||||
void initClipboardEvents();
|
||||
void installEventHandlers(const QString &canvasId);
|
||||
void installEventHandlers(const emscripten::val &canvas);
|
||||
bool hasClipboardApi;
|
||||
void readTextFromClipboard();
|
||||
void writeTextToClipboard();
|
||||
|
@ -57,9 +57,7 @@ void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
|
||||
htmlCursorName = "auto";
|
||||
|
||||
// Set cursor on the canvas
|
||||
val jsCanvasId = QWasmString::fromQString(QWasmScreen::get(screen)->canvasId());
|
||||
val document = val::global("document");
|
||||
val canvas = document.call<val>("getElementById", jsCanvasId);
|
||||
val canvas = QWasmScreen::get(screen)->canvas();
|
||||
val canvasStyle = canvas["style"];
|
||||
canvasStyle.set("cursor", val(htmlCursorName.constData()));
|
||||
}
|
||||
|
@ -354,9 +354,7 @@ void QWasmEventTranslator::initEventHandlers()
|
||||
g_useNaturalScrolling = false; // make this !default on macOS
|
||||
|
||||
if (emscripten::val::global("window")["safari"].isUndefined()) {
|
||||
val document = val::global("document");
|
||||
val jsCanvasId = QWasmString::fromQString(screen()->canvasId());
|
||||
val canvas = document.call<val>("getElementById", jsCanvasId);
|
||||
val canvas = screen()->canvas();
|
||||
canvas.call<void>("addEventListener",
|
||||
val("wheel"),
|
||||
val::module_property("qtMouseWheelEvent"));
|
||||
|
@ -68,20 +68,17 @@ static void browserBeforeUnload(emscripten::val)
|
||||
|
||||
static void addCanvasElement(emscripten::val canvas)
|
||||
{
|
||||
QString canvasId = QWasmString::toQString(canvas["id"]);
|
||||
QWasmIntegration::get()->addScreen(canvasId);
|
||||
QWasmIntegration::get()->addScreen(canvas);
|
||||
}
|
||||
|
||||
static void removeCanvasElement(emscripten::val canvas)
|
||||
{
|
||||
QString canvasId = QWasmString::toQString(canvas["id"]);
|
||||
QWasmIntegration::get()->removeScreen(canvasId);
|
||||
QWasmIntegration::get()->removeScreen(canvas);
|
||||
}
|
||||
|
||||
static void resizeCanvasElement(emscripten::val canvas)
|
||||
{
|
||||
QString canvasId = QWasmString::toQString(canvas["id"]);
|
||||
QWasmIntegration::get()->resizeScreen(canvasId);
|
||||
QWasmIntegration::get()->resizeScreen(canvas);
|
||||
}
|
||||
|
||||
static void qtUpdateDpi()
|
||||
@ -114,15 +111,12 @@ QWasmIntegration::QWasmIntegration()
|
||||
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 = QWasmString::toQString(canvas["id"]);
|
||||
addScreen(canvasId);
|
||||
addScreen(qtCanvaseElements[i].as<emscripten::val>());
|
||||
}
|
||||
} 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.";
|
||||
QString canvasId = QWasmString::toQString(canvas["id"]);
|
||||
addScreen(canvasId);
|
||||
addScreen(canvas);
|
||||
}
|
||||
|
||||
emscripten::val::global("window").set("onbeforeunload", val::module_property("qtBrowserBeforeUnload"));
|
||||
@ -148,8 +142,8 @@ QWasmIntegration::~QWasmIntegration()
|
||||
delete m_fontDb;
|
||||
delete m_desktopServices;
|
||||
|
||||
for (auto it = m_screens.constBegin(); it != m_screens.constEnd(); ++it)
|
||||
QWindowSystemInterface::handleScreenRemoved(*it);
|
||||
for (const auto &canvasAndScreen : m_screens)
|
||||
QWindowSystemInterface::handleScreenRemoved(canvasAndScreen.second);
|
||||
m_screens.clear();
|
||||
|
||||
s_instance = nullptr;
|
||||
@ -271,24 +265,37 @@ QPlatformClipboard* QWasmIntegration::clipboard() const
|
||||
return m_clipboard;
|
||||
}
|
||||
|
||||
void QWasmIntegration::addScreen(const QString &canvasId)
|
||||
void QWasmIntegration::addScreen(const emscripten::val &canvas)
|
||||
{
|
||||
QWasmScreen *screen = new QWasmScreen(canvasId);
|
||||
m_clipboard->installEventHandlers(canvasId);
|
||||
m_screens.insert(canvasId, screen);
|
||||
QWasmScreen *screen = new QWasmScreen(canvas);
|
||||
m_screens.append(qMakePair(canvas, screen));
|
||||
m_clipboard->installEventHandlers(canvas);
|
||||
QWindowSystemInterface::handleScreenAdded(screen);
|
||||
}
|
||||
|
||||
void QWasmIntegration::removeScreen(const QString &canvasId)
|
||||
void QWasmIntegration::removeScreen(const emscripten::val &canvas)
|
||||
{
|
||||
QWasmScreen *exScreen = m_screens.take(canvasId);
|
||||
auto it = std::find_if(m_screens.begin(), m_screens.end(),
|
||||
[&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(canvas); });
|
||||
if (it == m_screens.end()) {
|
||||
qWarning() << "Attempting to remove non-existing screen for canvas" << QWasmString::toQString(canvas["id"]);;
|
||||
return;
|
||||
}
|
||||
QWasmScreen *exScreen = it->second;
|
||||
m_screens.erase(it);
|
||||
exScreen->destroy(); // clean up before deleting the screen
|
||||
QWindowSystemInterface::handleScreenRemoved(exScreen);
|
||||
}
|
||||
|
||||
void QWasmIntegration::resizeScreen(const QString &canvasId)
|
||||
void QWasmIntegration::resizeScreen(const emscripten::val &canvas)
|
||||
{
|
||||
m_screens.value(canvasId)->updateQScreenAndCanvasRenderSize();
|
||||
auto it = std::find_if(m_screens.begin(), m_screens.end(),
|
||||
[&] (const QPair<emscripten::val, QWasmScreen *> &candidate) { return candidate.first.equals(canvas); });
|
||||
if (it == m_screens.end()) {
|
||||
qWarning() << "Attempting to resize non-existing screen for canvas" << QWasmString::toQString(canvas["id"]);;
|
||||
return;
|
||||
}
|
||||
it->second->updateQScreenAndCanvasRenderSize();
|
||||
}
|
||||
|
||||
void QWasmIntegration::updateDpi()
|
||||
@ -297,15 +304,14 @@ void QWasmIntegration::updateDpi()
|
||||
if (dpi.isUndefined())
|
||||
return;
|
||||
qreal dpiValue = dpi.as<qreal>();
|
||||
for (QWasmScreen *screen : m_screens)
|
||||
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->screen(), dpiValue, dpiValue);
|
||||
for (const auto &canvasAndScreen : m_screens)
|
||||
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(canvasAndScreen.second->screen(), dpiValue, dpiValue);
|
||||
}
|
||||
|
||||
void QWasmIntegration::resizeAllScreens()
|
||||
{
|
||||
qDebug() << "resizeAllScreens";
|
||||
for (QWasmScreen *screen : m_screens)
|
||||
screen->updateQScreenAndCanvasRenderSize();
|
||||
for (const auto &canvasAndScreen : m_screens)
|
||||
canvasAndScreen.second->updateQScreenAndCanvasRenderSize();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#include <emscripten/val.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -83,9 +84,9 @@ public:
|
||||
static QWasmIntegration *get() { return s_instance; }
|
||||
static void QWasmBrowserExit();
|
||||
|
||||
void addScreen(const QString &canvasId);
|
||||
void removeScreen(const QString &canvasId);
|
||||
void resizeScreen(const QString &canvasId);
|
||||
void addScreen(const emscripten::val &canvas);
|
||||
void removeScreen(const emscripten::val &canvas);
|
||||
void resizeScreen(const emscripten::val &canvas);
|
||||
void resizeAllScreens();
|
||||
void updateDpi();
|
||||
|
||||
@ -93,8 +94,7 @@ private:
|
||||
mutable QWasmFontDatabase *m_fontDb;
|
||||
mutable QWasmServices *m_desktopServices;
|
||||
mutable QHash<QWindow *, QWasmBackingStore *> m_backingStores;
|
||||
|
||||
QHash<QString, QWasmScreen *> m_screens;
|
||||
QVector<QPair<emscripten::val, QWasmScreen *>> m_screens;
|
||||
mutable QWasmClipboard *m_clipboard;
|
||||
qreal m_fontDpi = -1;
|
||||
mutable QScopedPointer<QPlatformInputContext> m_inputContext;
|
||||
|
@ -50,15 +50,13 @@ using namespace emscripten;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QWasmScreen::QWasmScreen(const QString &canvasId)
|
||||
: m_canvasId(canvasId)
|
||||
|
||||
QWasmScreen::QWasmScreen(const emscripten::val &canvas)
|
||||
: m_canvas(canvas)
|
||||
{
|
||||
m_compositor = new QWasmCompositor(this);
|
||||
m_eventTranslator = new QWasmEventTranslator(this);
|
||||
updateQScreenAndCanvasRenderSize();
|
||||
emscripten::val canvas = emscripten::val::global(m_canvasId.toUtf8().constData());
|
||||
canvas.call<void>("focus");
|
||||
m_canvas.call<void>("focus");
|
||||
}
|
||||
|
||||
QWasmScreen::~QWasmScreen()
|
||||
@ -91,9 +89,14 @@ QWasmEventTranslator *QWasmScreen::eventTranslator()
|
||||
return m_eventTranslator;
|
||||
}
|
||||
|
||||
emscripten::val QWasmScreen::canvas() const
|
||||
{
|
||||
return m_canvas;
|
||||
}
|
||||
|
||||
QString QWasmScreen::canvasId() const
|
||||
{
|
||||
return m_canvasId;
|
||||
return QWasmString::toQString(m_canvas["id"]);
|
||||
}
|
||||
|
||||
QRect QWasmScreen::geometry() const
|
||||
@ -134,7 +137,7 @@ qreal QWasmScreen::devicePixelRatio() const
|
||||
|
||||
QString QWasmScreen::name() const
|
||||
{
|
||||
return m_canvasId;
|
||||
return canvasId();
|
||||
}
|
||||
|
||||
QPlatformCursor *QWasmScreen::cursor() const
|
||||
@ -180,24 +183,22 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize()
|
||||
// Setting the render size to a value larger than the CSS size enables high-dpi
|
||||
// rendering.
|
||||
|
||||
QByteArray canvasSelector = "#" + m_canvasId.toUtf8();
|
||||
QByteArray canvasSelector = "#" + canvasId().toUtf8();
|
||||
double css_width;
|
||||
double css_height;
|
||||
emscripten_get_element_css_size(canvasSelector.constData(), &css_width, &css_height);
|
||||
QSizeF cssSize(css_width, css_height);
|
||||
|
||||
QSizeF canvasSize = cssSize * devicePixelRatio();
|
||||
val document = val::global("document");
|
||||
val canvas = document.call<val>("getElementById", QWasmString::fromQString(m_canvasId));
|
||||
|
||||
canvas.set("width", canvasSize.width());
|
||||
canvas.set("height", canvasSize.height());
|
||||
m_canvas.set("width", canvasSize.width());
|
||||
m_canvas.set("height", canvasSize.height());
|
||||
|
||||
QPoint offset;
|
||||
offset.setX(canvas["offsetTop"].as<int>());
|
||||
offset.setY(canvas["offsetLeft"].as<int>());
|
||||
offset.setX(m_canvas["offsetTop"].as<int>());
|
||||
offset.setY(m_canvas["offsetLeft"].as<int>());
|
||||
|
||||
emscripten::val rect = canvas.call<emscripten::val>("getBoundingClientRect");
|
||||
emscripten::val rect = m_canvas.call<emscripten::val>("getBoundingClientRect");
|
||||
QPoint position(rect["left"].as<int>() - offset.x(), rect["top"].as<int>() - offset.y());
|
||||
|
||||
setGeometry(QRect(position, cssSize.toSize()));
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
#include <QtCore/qtextstream.h>
|
||||
|
||||
#include <emscripten/val.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QPlatformOpenGLContext;
|
||||
@ -50,12 +52,13 @@ class QWasmScreen : public QObject, public QPlatformScreen
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QWasmScreen(const QString &canvasId);
|
||||
QWasmScreen(const emscripten::val &canvas);
|
||||
~QWasmScreen();
|
||||
void destroy();
|
||||
|
||||
static QWasmScreen *get(QPlatformScreen *screen);
|
||||
static QWasmScreen *get(QScreen *screen);
|
||||
emscripten::val canvas() const;
|
||||
QString canvasId() const;
|
||||
|
||||
QWasmCompositor *compositor();
|
||||
@ -80,7 +83,7 @@ public slots:
|
||||
void setGeometry(const QRect &rect);
|
||||
|
||||
private:
|
||||
QString m_canvasId;
|
||||
emscripten::val m_canvas;
|
||||
QWasmCompositor *m_compositor = nullptr;
|
||||
QWasmEventTranslator *m_eventTranslator = nullptr;
|
||||
QRect m_geometry = QRect(0, 0, 100, 100);
|
||||
|
Loading…
x
Reference in New Issue
Block a user