summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikolaj Boc <[email protected]>2022-12-19 17:22:11 +0100
committerMikolaj Boc <[email protected]>2023-02-07 14:14:28 +0100
commit00bb65191969f3385686ae44a43bd59cd6f63916 (patch)
tree2473f06aa98e06e1acbed6e7b53d00678d36f4c7
parent4ab04b35abbc684088203bf857dc3f81edd7b267 (diff)
Streamline reading of js DataTransfer object
qwasmclipboard.cpp and qwasmdrag.cpp had the same logic that read the js DataTransfer object implemented twice with small differences. Use a single implementation in both. This also introduces a clearer memory ownership model in the reader code, and fixes a potential race condition by introducing a cancellation flag. Removed the useless QWasmDrag type which was in essence a SimpleDrag and made the m_drag in QWasmIntegration a smart pointer. Fixes: QTBUG-109626 Change-Id: I5b76dd3b70ab2e5a8364d9a136c970ee8d4fae9c Reviewed-by: Morten Johan Sørvig <[email protected]> (cherry picked from commit 16bf899557febb8c0762e64ce88acf21bc84e334) Reviewed-by: Volker Hilsheimer <[email protected]> Reviewed-by: Mikołaj Boc <[email protected]>
-rw-r--r--src/corelib/platform/wasm/qstdweb.cpp114
-rw-r--r--src/corelib/platform/wasm/qstdweb_p.h21
-rw-r--r--src/plugins/platforms/wasm/qwasmclipboard.cpp116
-rw-r--r--src/plugins/platforms/wasm/qwasmdom.cpp5
-rw-r--r--src/plugins/platforms/wasm/qwasmdom.h2
-rw-r--r--src/plugins/platforms/wasm/qwasmdrag.cpp227
-rw-r--r--src/plugins/platforms/wasm/qwasmdrag.h32
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp11
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h18
9 files changed, 233 insertions, 313 deletions
diff --git a/src/corelib/platform/wasm/qstdweb.cpp b/src/corelib/platform/wasm/qstdweb.cpp
index ef8f8e8abe1..e5a2dcfe728 100644
--- a/src/corelib/platform/wasm/qstdweb.cpp
+++ b/src/corelib/platform/wasm/qstdweb.cpp
@@ -5,6 +5,8 @@
#include <QtCore/qcoreapplication.h>
#include <QtCore/qfile.h>
+#include <QtCore/qmimedata.h>
+
#include <emscripten/bind.h>
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
@@ -368,6 +370,111 @@ bool jsHaveAsyncify() { return false; }
#endif
+struct DataTransferReader
+{
+public:
+ using DoneCallback = std::function<void(std::unique_ptr<QMimeData>)>;
+
+ static std::shared_ptr<CancellationFlag> read(emscripten::val webDataTransfer,
+ std::function<QVariant(QByteArray)> imageReader,
+ DoneCallback onCompleted)
+ {
+ auto cancellationFlag = std::make_shared<CancellationFlag>();
+ (new DataTransferReader(std::move(onCompleted), std::move(imageReader), cancellationFlag))
+ ->read(webDataTransfer);
+ return cancellationFlag;
+ }
+
+ ~DataTransferReader() = default;
+
+private:
+ DataTransferReader(DoneCallback onCompleted, std::function<QVariant(QByteArray)> imageReader,
+ std::shared_ptr<CancellationFlag> cancellationFlag)
+ : mimeData(std::make_unique<QMimeData>()),
+ imageReader(std::move(imageReader)),
+ onCompleted(std::move(onCompleted)),
+ cancellationFlag(cancellationFlag)
+ {
+ }
+
+ void read(emscripten::val webDataTransfer)
+ {
+ enum class ItemKind {
+ File,
+ String,
+ };
+
+ const auto items = webDataTransfer["items"];
+ for (int i = 0; i < items["length"].as<int>(); ++i) {
+ const auto item = items[i];
+ const auto itemKind =
+ item["kind"].as<std::string>() == "string" ? ItemKind::String : ItemKind::File;
+ const auto itemMimeType = QString::fromStdString(item["type"].as<std::string>());
+
+ switch (itemKind) {
+ case ItemKind::File: {
+ ++fileCount;
+
+ qstdweb::File file(item.call<emscripten::val>("getAsFile"));
+
+ QByteArray fileContent(file.size(), Qt::Uninitialized);
+ file.stream(fileContent.data(), [this, itemMimeType, fileContent]() {
+ if (!fileContent.isEmpty()) {
+ if (itemMimeType.startsWith("image/")) {
+ mimeData->setImageData(imageReader(fileContent));
+ } else {
+ mimeData->setData(itemMimeType, fileContent.data());
+ }
+ }
+ ++doneCount;
+ onFileRead();
+ });
+ break;
+ }
+ case ItemKind::String:
+ if (itemMimeType.contains("STRING", Qt::CaseSensitive)
+ || itemMimeType.contains("TEXT", Qt::CaseSensitive)) {
+ break;
+ }
+ QString a;
+ const QString data = QString::fromStdString(webDataTransfer.call<std::string>(
+ "getData", emscripten::val(itemMimeType.toStdString())));
+
+ if (!data.isEmpty()) {
+ if (itemMimeType == "text/html")
+ mimeData->setHtml(data);
+ else if (itemMimeType.isEmpty() || itemMimeType == "text/plain")
+ mimeData->setText(data); // the type can be empty
+ else
+ mimeData->setData(itemMimeType, data.toLocal8Bit());
+ }
+ break;
+ }
+ }
+
+ onFileRead();
+ }
+
+ void onFileRead()
+ {
+ Q_ASSERT(doneCount <= fileCount);
+ if (doneCount < fileCount)
+ return;
+
+ std::unique_ptr<DataTransferReader> deleteThisLater(this);
+ if (!cancellationFlag.expired())
+ onCompleted(std::move(mimeData));
+ }
+
+ int fileCount = 0;
+ int doneCount = 0;
+ std::unique_ptr<QMimeData> mimeData;
+ std::function<QVariant(QByteArray)> imageReader;
+ DoneCallback onCompleted;
+
+ std::weak_ptr<CancellationFlag> cancellationFlag;
+};
+
} // namespace
ArrayBuffer::ArrayBuffer(uint32_t size)
@@ -738,6 +845,13 @@ bool haveAsyncify()
return HaveAsyncify;
}
+std::shared_ptr<CancellationFlag>
+readDataTransfer(emscripten::val webDataTransfer, std::function<QVariant(QByteArray)> imageReader,
+ std::function<void(std::unique_ptr<QMimeData>)> onDone)
+{
+ return DataTransferReader::read(webDataTransfer, std::move(imageReader), std::move(onDone));
+}
+
} // namespace qstdweb
QT_END_NAMESPACE
diff --git a/src/corelib/platform/wasm/qstdweb_p.h b/src/corelib/platform/wasm/qstdweb_p.h
index d8c0db191bc..204343baaa0 100644
--- a/src/corelib/platform/wasm/qstdweb_p.h
+++ b/src/corelib/platform/wasm/qstdweb_p.h
@@ -16,15 +16,22 @@
//
#include <private/qglobal_p.h>
+#include <QtCore/qglobal.h>
+#include "QtCore/qhash.h"
+
#include <emscripten/val.h>
+
#include <cstdint>
#include <functional>
-#include "initializer_list"
-#include <QtCore/qglobal.h>
-#include "QtCore/qhash.h"
+#include <initializer_list>
+#include <memory>
+#include <string>
+#include <utility>
QT_BEGIN_NAMESPACE
+class QMimeData;
+
namespace qstdweb {
extern const char makeContextfulPromiseFunctionName[];
@@ -195,6 +202,14 @@ namespace qstdweb {
}
bool haveAsyncify();
+
+ struct CancellationFlag
+ {
+ };
+
+ std::shared_ptr<CancellationFlag>
+ readDataTransfer(emscripten::val webObject, std::function<QVariant(QByteArray)> imageReader,
+ std::function<void(std::unique_ptr<QMimeData>)> onDone);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp
index 80f71707482..de2a87db358 100644
--- a/src/plugins/platforms/wasm/qwasmclipboard.cpp
+++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp
@@ -2,20 +2,18 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qwasmclipboard.h"
+#include "qwasmdom.h"
#include "qwasmwindow.h"
#include "qwasmstring.h"
#include <private/qstdweb_p.h>
-#include <emscripten.h>
-#include <emscripten/html5.h>
-#include <emscripten/bind.h>
-#include <emscripten/val.h>
-
#include <QCoreApplication>
#include <qpa/qwindowsysteminterface.h>
#include <QBuffer>
#include <QString>
+#include <emscripten/val.h>
+
QT_BEGIN_NAMESPACE
using namespace emscripten;
@@ -68,93 +66,29 @@ static void qClipboardCopyTo(val event)
commonCopyEvent(event);
}
-static void qWasmClipboardPaste(QMimeData *mData)
-{
- // Persist clipboard data so that the app can read it when handling the CTRL+V
- QWasmIntegration::get()->clipboard()->
- QPlatformClipboard::setMimeData(mData, QClipboard::Clipboard);
-
- QWindowSystemInterface::handleKeyEvent(
- 0, QEvent::KeyPress, Qt::Key_V, Qt::ControlModifier, "V");
-}
-
-static void qClipboardPasteTo(val dataTransfer)
+static void qClipboardPasteTo(val event)
{
- enum class ItemKind {
- File,
- String,
- };
-
- struct Data
- {
- std::unique_ptr<QMimeData> data;
- int fileCount = 0;
- int doneCount = 0;
- };
-
- auto sharedData = std::make_shared<Data>();
- sharedData->data = std::make_unique<QMimeData>();
-
- auto continuation = [sharedData]() {
- Q_ASSERT(sharedData->doneCount <= sharedData->fileCount);
- if (sharedData->doneCount < sharedData->fileCount)
- return;
-
- if (!sharedData->data->formats().isEmpty())
- qWasmClipboardPaste(sharedData->data.release());
- };
-
- const val clipboardData = dataTransfer["clipboardData"];
- const val items = clipboardData["items"];
- for (int i = 0; i < items["length"].as<int>(); ++i) {
- const val item = items[i];
- const auto itemKind =
- item["kind"].as<std::string>() == "string" ? ItemKind::String : ItemKind::File;
- const auto itemMimeType = QString::fromStdString(item["type"].as<std::string>());
-
- switch (itemKind) {
- case ItemKind::File: {
- ++sharedData->fileCount;
-
- qstdweb::File file(item.call<emscripten::val>("getAsFile"));
-
- QByteArray fileContent(file.size(), Qt::Uninitialized);
- file.stream(fileContent.data(),
- [continuation, itemMimeType, fileContent, sharedData]() {
- if (!fileContent.isEmpty()) {
- if (itemMimeType.startsWith("image/")) {
- QImage image;
- image.loadFromData(fileContent, nullptr);
- sharedData->data->setImageData(image);
- } else {
- sharedData->data->setData(itemMimeType, fileContent.data());
- }
- }
- ++sharedData->doneCount;
- continuation();
- });
- break;
- }
- case ItemKind::String:
- if (itemMimeType.contains("STRING", Qt::CaseSensitive)
- || itemMimeType.contains("TEXT", Qt::CaseSensitive)) {
- break;
- }
- const QString data = QWasmString::toQString(
- clipboardData.call<val>("getData", val(itemMimeType.toStdString())));
-
- if (!data.isEmpty()) {
- if (itemMimeType == "text/html")
- sharedData->data->setHtml(data);
- else if (itemMimeType.isEmpty() || itemMimeType == "text/plain")
- sharedData->data->setText(data); // the type can be empty
- else
- sharedData->data->setData(itemMimeType, data.toLocal8Bit());
- }
- break;
- }
- }
- continuation();
+ event.call<void>("preventDefault"); // prevent browser from handling drop event
+
+ static std::shared_ptr<qstdweb::CancellationFlag> readDataCancellation = nullptr;
+ readDataCancellation = qstdweb::readDataTransfer(
+ event["clipboardData"],
+ [](QByteArray fileContent) {
+ QImage image;
+ image.loadFromData(fileContent, nullptr);
+ return image;
+ },
+ [event](std::unique_ptr<QMimeData> data) {
+ if (data->formats().isEmpty())
+ return;
+
+ // Persist clipboard data so that the app can read it when handling the CTRL+V
+ QWasmIntegration::get()->clipboard()->QPlatformClipboard::setMimeData(
+ data.release(), QClipboard::Clipboard);
+
+ QWindowSystemInterface::handleKeyEvent(0, QEvent::KeyPress, Qt::Key_V,
+ Qt::ControlModifier, "V");
+ });
}
EMSCRIPTEN_BINDINGS(qtClipboardModule) {
diff --git a/src/plugins/platforms/wasm/qwasmdom.cpp b/src/plugins/platforms/wasm/qwasmdom.cpp
index 1573b5bf9c0..f9705f1a1c1 100644
--- a/src/plugins/platforms/wasm/qwasmdom.cpp
+++ b/src/plugins/platforms/wasm/qwasmdom.cpp
@@ -3,14 +3,18 @@
#include "qwasmdom.h"
+#include <QMimeData>
#include <QtCore/qpoint.h>
#include <QtCore/qrect.h>
+#include <QtGui/qimage.h>
+#include <private/qstdweb_p.h>
#include <utility>
QT_BEGIN_NAMESPACE
namespace dom {
+
void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag)
{
if (flag) {
@@ -31,6 +35,7 @@ QPoint mapPoint(emscripten::val source, emscripten::val target, const QPoint &po
auto offset = sourceBoundingRect.topLeft() - targetBoundingRect.topLeft();
return (point + offset).toPoint();
}
+
} // namespace dom
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmdom.h b/src/plugins/platforms/wasm/qwasmdom.h
index 92f710a13dd..80661fce195 100644
--- a/src/plugins/platforms/wasm/qwasmdom.h
+++ b/src/plugins/platforms/wasm/qwasmdom.h
@@ -8,6 +8,8 @@
#include <emscripten/val.h>
+#include <functional>
+#include <memory>
#include <string>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmdrag.cpp b/src/plugins/platforms/wasm/qwasmdrag.cpp
index 7520fa19288..46242744af3 100644
--- a/src/plugins/platforms/wasm/qwasmdrag.cpp
+++ b/src/plugins/platforms/wasm/qwasmdrag.cpp
@@ -3,207 +3,76 @@
#include "qwasmdrag.h"
-#include <iostream>
-#include <QMimeDatabase>
+#include "qwasmdom.h"
+#include "qwasmeventtranslator.h"
+#include <qpa/qwindowsysteminterface.h>
+#include <QMimeData>
#include <emscripten.h>
-#include <emscripten/html5.h>
#include <emscripten/val.h>
#include <emscripten/bind.h>
-#include <private/qstdweb_p.h>
-#include <qpa/qwindowsysteminterface.h>
-#include <private/qsimpledrag_p.h>
-#include "qwasmcompositor.h"
-#include "qwasmeventtranslator.h"
-#include <QtCore/QEventLoop>
-#include <QMimeData>
-#include <private/qshapedpixmapdndwindow_p.h>
-
-QT_BEGIN_NAMESPACE
-using namespace emscripten;
+#include <memory>
+#include <string>
-static void getTextPlainCallback(val m_string)
-{
- QWasmDrag *thisDrag = static_cast<QWasmDrag*>(QWasmIntegration::get()->drag());
- thisDrag->m_mimeData->setText(QString::fromStdString(m_string.as<std::string>()));
- thisDrag->qWasmDrop();
-}
-
-static void getTextUrlCallback(val m_string)
-{
- QWasmDrag *thisDrag = static_cast<QWasmDrag*>(QWasmIntegration::get()->drag());
- thisDrag->m_mimeData->setData(QStringLiteral("text/uri-list"),
- QByteArray::fromStdString(m_string.as<std::string>()));
-
- thisDrag->qWasmDrop();
-}
+QT_BEGIN_NAMESPACE
-static void getTextHtmlCallback(val m_string)
+namespace {
+Qt::DropAction parseDropActions(emscripten::val event)
{
- QWasmDrag *thisDrag = static_cast<QWasmDrag*>(QWasmIntegration::get()->drag());
- thisDrag->m_mimeData->setHtml(QString::fromStdString(m_string.as<std::string>()));
+ const std::string dEffect = event["dataTransfer"]["dropEffect"].as<std::string>();
- thisDrag->qWasmDrop();
+ if (dEffect == "copy")
+ return Qt::CopyAction;
+ else if (dEffect == "move")
+ return Qt::MoveAction;
+ else if (dEffect == "link")
+ return Qt::LinkAction;
+ return Qt::IgnoreAction;
}
+} // namespace
-static void dropEvent(val event)
+void dropEvent(emscripten::val event)
{
// someone dropped a file into the browser window
// event is dataTransfer object
// if drop event from outside browser, we do not get any mouse release, maybe mouse move
// after the drop event
-
- // data-context thing was not working here :(
- QWasmDrag *wasmDrag = static_cast<QWasmDrag*>(QWasmIntegration::get()->drag());
-
- wasmDrag->m_wasmScreen =
- reinterpret_cast<QWasmScreen*>(event["target"]["data-qtdropcontext"].as<quintptr>());
-
- wasmDrag->m_mouseDropPoint = QPoint(event["x"].as<int>(), event["y"].as<int>());
- if (wasmDrag->m_mimeData)
- delete wasmDrag->m_mimeData;
- wasmDrag->m_mimeData = new QMimeData;
- wasmDrag->m_qButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
-
- wasmDrag->m_keyModifiers = Qt::NoModifier;
- if (event["altKey"].as<bool>())
- wasmDrag->m_keyModifiers |= Qt::AltModifier;
- if (event["ctrlKey"].as<bool>())
- wasmDrag->m_keyModifiers |= Qt::ControlModifier;
- if (event["metaKey"].as<bool>())
- wasmDrag->m_keyModifiers |= Qt::MetaModifier;
-
event.call<void>("preventDefault"); // prevent browser from handling drop event
- std::string dEffect = event["dataTransfer"]["dropEffect"].as<std::string>();
-
- wasmDrag->m_dropActions = Qt::IgnoreAction;
- if (dEffect == "copy")
- wasmDrag->m_dropActions = Qt::CopyAction;
- if (dEffect == "move")
- wasmDrag->m_dropActions = Qt::MoveAction;
- if (dEffect == "link")
- wasmDrag->m_dropActions = Qt::LinkAction;
-
- val dt = event["dataTransfer"]["items"]["length"];
-
- val typesCount = event["dataTransfer"]["types"]["length"];
-
- // handle mimedata
- int count = dt.as<int>();
- wasmDrag->m_mimeTypesCount = count;
- // kind is file type: file or string
- for (int i=0; i < count; i++) {
- val item = event["dataTransfer"]["items"][i];
- val kind = item["kind"];
- val fileType = item["type"];
-
- if (kind.as<std::string>() == "file") {
- val m_file = item.call<val>("getAsFile");
- if (m_file.isUndefined()) {
- continue;
- }
-
- qstdweb::File file(m_file);
-
- QString mimeFormat = QString::fromStdString(file.type());
- QByteArray fileContent;
- fileContent.resize(file.size());
-
- file.stream(fileContent.data(), [mimeFormat, fileContent]() {
- if (!fileContent.isEmpty()) {
- QWasmDrag *wasmDrag = static_cast<QWasmDrag *>(QWasmIntegration::get()->drag());
- if (mimeFormat.contains("image")) {
- QImage image;
- image.loadFromData(fileContent, nullptr);
- wasmDrag->m_mimeData->setImageData(image);
- } else {
- wasmDrag->m_mimeData->setData(mimeFormat, fileContent.data());
- }
- wasmDrag->qWasmDrop();
- }
+ static std::shared_ptr<qstdweb::CancellationFlag> readDataCancellation = nullptr;
+ readDataCancellation = qstdweb::readDataTransfer(
+ event["dataTransfer"],
+ [](QByteArray fileContent) {
+ QImage image;
+ image.loadFromData(fileContent, nullptr);
+ return image;
+ },
+ [wasmScreen = reinterpret_cast<QWasmScreen *>(
+ event["currentTarget"]["data-qtdropcontext"].as<quintptr>()),
+ event](std::unique_ptr<QMimeData> data) {
+ const auto mouseDropPoint = QPoint(event["x"].as<int>(), event["y"].as<int>());
+ const auto button = MouseEvent::buttonFromWeb(event["button"].as<int>());
+ const Qt::KeyboardModifiers modifiers = KeyboardModifier::getForEvent(event);
+ const auto dropAction = parseDropActions(event);
+ auto *window = wasmScreen->topLevelAt(mouseDropPoint);
+
+ QWindowSystemInterface::handleDrag(window, data.get(), mouseDropPoint, dropAction,
+ button, modifiers);
+
+ // drag drop
+ QWindowSystemInterface::handleDrop(window, data.get(), mouseDropPoint, dropAction,
+ button, modifiers);
+
+ // drag leave
+ QWindowSystemInterface::handleDrag(window, nullptr, QPoint(), Qt::IgnoreAction, {},
+ {});
});
-
- } else { // string
-
- if (fileType.as<std::string>() == "text/uri-list"
- || fileType.as<std::string>() == "text/x-moz-url") {
- item.call<val>("getAsString", val::module_property("qtgetTextUrl"));
- } else if (fileType.as<std::string>() == "text/html") {
- item.call<val>("getAsString", val::module_property("qtgetTextHtml"));
- } else { // handle everything else here as plain text
- item.call<val>("getAsString", val::module_property("qtgetTextPlain"));
- }
- }
- }
-}
-
-EMSCRIPTEN_BINDINGS(drop_module) {
- function("qtDrop", &dropEvent);
- function("qtgetTextPlain", &getTextPlainCallback);
- function("qtgetTextUrl", &getTextUrlCallback);
- function("qtgetTextHtml", &getTextHtmlCallback);
-}
-
-
-QWasmDrag::QWasmDrag()
-{
- init();
-}
-
-QWasmDrag::~QWasmDrag()
-{
- if (m_mimeData)
- delete m_mimeData;
-}
-
-void QWasmDrag::init()
-{
-}
-
-void QWasmDrag::drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
-{
- QSimpleDrag::drop(globalPos, b, mods);
-}
-
-void QWasmDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods)
-{
- QSimpleDrag::move(globalPos, b, mods);
}
-void QWasmDrag::qWasmDrop()
+EMSCRIPTEN_BINDINGS(drop_module)
{
- // collect mime
- QWasmDrag *thisDrag = static_cast<QWasmDrag*>(QWasmIntegration::get()->drag());
-
- if (thisDrag->m_mimeTypesCount != thisDrag->m_mimeData->formats().size())
- return; // keep collecting mimetypes
-
- // start drag enter
- QWindowSystemInterface::handleDrag(thisDrag->m_wasmScreen->topLevelAt(thisDrag->m_mouseDropPoint),
- thisDrag->m_mimeData,
- thisDrag->m_mouseDropPoint,
- thisDrag->m_dropActions,
- thisDrag->m_qButton,
- thisDrag->m_keyModifiers);
-
- // drag drop
- QWindowSystemInterface::handleDrop(thisDrag->m_wasmScreen->topLevelAt(thisDrag->m_mouseDropPoint),
- thisDrag->m_mimeData,
- thisDrag->m_mouseDropPoint,
- thisDrag->m_dropActions,
- thisDrag->m_qButton,
- thisDrag->m_keyModifiers);
-
- // drag leave
- QWindowSystemInterface::handleDrag(thisDrag->m_wasmScreen->topLevelAt(thisDrag->m_mouseDropPoint),
- nullptr,
- QPoint(),
- Qt::IgnoreAction, { }, { });
-
- thisDrag->m_mimeData->clear();
- thisDrag->m_mimeTypesCount = 0;
+ function("qtDrop", &dropEvent);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmdrag.h b/src/plugins/platforms/wasm/qwasmdrag.h
index 6358b415c3d..624e9e3db60 100644
--- a/src/plugins/platforms/wasm/qwasmdrag.h
+++ b/src/plugins/platforms/wasm/qwasmdrag.h
@@ -4,39 +4,13 @@
#ifndef QWASMDRAG_H
#define QWASMDRAG_H
-#include <qpa/qplatformdrag.h>
-#include <private/qsimpledrag_p.h>
-#include <private/qstdweb_p.h>
-#include <QDrag>
-#include "qwasmscreen.h"
+#include <QtCore/qtconfigmacros.h>
-QT_REQUIRE_CONFIG(draganddrop);
+#include <emscripten/val.h>
QT_BEGIN_NAMESPACE
-class QWasmDrag : public QSimpleDrag
-{
-public:
-
- QWasmDrag();
- ~QWasmDrag();
-
- void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
- void move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override;
-
- Qt::MouseButton m_qButton;
- QPoint m_mouseDropPoint;
- QFlags<Qt::KeyboardModifier> m_keyModifiers;
- Qt::DropActions m_dropActions;
- QWasmScreen *m_wasmScreen = nullptr;
- int m_mimeTypesCount = 0;
- QMimeData *m_mimeData = nullptr;
- void qWasmDrop();
-
-private:
- void init();
-};
-
+void dropEvent(emscripten::val event);
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index ab04a10726a..dc68abd53b4 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -81,6 +81,12 @@ QWasmIntegration::QWasmIntegration()
m_clipboard(new QWasmClipboard),
m_accessibility(new QWasmAccessibility)
{
+ // Temporary measure to make dropEvent appear in the library. EMSCRIPTEN_KEEPALIVE does not
+ // work, nor does a Q_CONSTRUCTOR_FUNCTION in qwasmdrag.cpp.
+ volatile bool foolEmcc = false;
+ if (foolEmcc)
+ dropEvent(emscripten::val::undefined());
+
s_instance = this;
touchPoints = emscripten::val::global("navigator")["maxTouchPoints"].as<int>();
@@ -122,7 +128,7 @@ QWasmIntegration::QWasmIntegration()
visualViewport.call<void>("addEventListener", val("resize"),
val::module_property("qtResizeAllScreens"));
}
- m_drag = new QWasmDrag();
+ m_drag = std::make_unique<QSimpleDrag>();
}
QWasmIntegration::~QWasmIntegration()
@@ -139,7 +145,6 @@ QWasmIntegration::~QWasmIntegration()
delete m_desktopServices;
if (m_platformInputContext)
delete m_platformInputContext;
- delete m_drag;
delete m_accessibility;
for (const auto &elementAndScreen : m_screens)
@@ -328,7 +333,7 @@ quint64 QWasmIntegration::getTimestamp()
#if QT_CONFIG(draganddrop)
QPlatformDrag *QWasmIntegration::drag() const
{
- return m_drag;
+ return m_drag.get();
}
#endif // QT_CONFIG(draganddrop)
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index 76296ff1a7c..8468c4c9e11 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -6,23 +6,25 @@
#include "qwasmwindow.h"
+#include "qwasminputcontext.h"
+
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformscreen.h>
#include <qpa/qplatforminputcontext.h>
+#if QT_CONFIG(draganddrop)
+# include "qwasmdrag.h"
+#endif
+
#include <QtCore/qhash.h>
+#include <private/qsimpledrag_p.h>
+#include <private/qstdweb_p.h>
+
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/val.h>
-#include "qwasminputcontext.h"
-#include <private/qstdweb_p.h>
-
-#if QT_CONFIG(draganddrop)
-#include "qwasmdrag.h"
-#endif
-
QT_BEGIN_NAMESPACE
class QWasmEventTranslator;
@@ -97,7 +99,7 @@ private:
mutable QWasmInputContext *m_platformInputContext = nullptr;
#if QT_CONFIG(draganddrop)
- QWasmDrag *m_drag;
+ std::unique_ptr<QSimpleDrag> m_drag;
#endif
};