summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/wasm/CMakeLists.txt1
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp8
-rw-r--r--src/plugins/platforms/wasm/qwasmdrag.cpp78
-rw-r--r--src/plugins/platforms/wasm/qwasmdrag.h17
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.cpp113
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.h43
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp6
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h4
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp30
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h13
10 files changed, 176 insertions, 137 deletions
diff --git a/src/plugins/platforms/wasm/CMakeLists.txt b/src/plugins/platforms/wasm/CMakeLists.txt
index 8902597001..ade727423c 100644
--- a/src/plugins/platforms/wasm/CMakeLists.txt
+++ b/src/plugins/platforms/wasm/CMakeLists.txt
@@ -37,7 +37,6 @@ qt_internal_add_plugin(QWasmIntegrationPlugin
qwasmwindowclientarea.cpp qwasmwindowclientarea.h
qwasmwindownonclientarea.cpp qwasmwindownonclientarea.h
qwasminputcontext.cpp qwasminputcontext.h
- qwasmdrag.cpp qwasmdrag.h
qwasmwindowstack.cpp qwasmwindowstack.h
DEFINES
QT_EGL_NO_X11
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 70938b323b..0700d66a55 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -83,9 +83,6 @@ void QWasmCompositor::deregisterEventHandlers()
emscripten_set_touchend_callback(screenElementSelector.constData(), 0, 0, NULL);
emscripten_set_touchmove_callback(screenElementSelector.constData(), 0, 0, NULL);
emscripten_set_touchcancel_callback(screenElementSelector.constData(), 0, 0, NULL);
-
- screen()->element().call<void>("removeEventListener", std::string("drop"),
- val::module_property("qtDrop"), val(true));
}
void QWasmCompositor::destroy()
@@ -123,11 +120,6 @@ void QWasmCompositor::initEventHandlers()
&touchCallback);
emscripten_set_touchcancel_callback(screenElementSelector.constData(), (void *)this, UseCapture,
&touchCallback);
-
- screen()->element().call<void>("addEventListener", std::string("drop"),
- val::module_property("qtDrop"), val(true));
- screen()->element().set("data-qtdropcontext", // ? unique
- emscripten::val(quintptr(reinterpret_cast<void *>(screen()))));
}
void QWasmCompositor::addWindow(QWasmWindow *window)
diff --git a/src/plugins/platforms/wasm/qwasmdrag.cpp b/src/plugins/platforms/wasm/qwasmdrag.cpp
deleted file mode 100644
index 144c30e0fb..0000000000
--- a/src/plugins/platforms/wasm/qwasmdrag.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-#include "qwasmdrag.h"
-
-#include "qwasmdom.h"
-#include "qwasmeventtranslator.h"
-#include <qpa/qwindowsysteminterface.h>
-#include <QMimeData>
-
-#include <emscripten.h>
-#include <emscripten/val.h>
-#include <emscripten/bind.h>
-
-#include <memory>
-#include <string>
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-Qt::DropAction parseDropActions(emscripten::val event)
-{
- const std::string dEffect = event["dataTransfer"]["dropEffect"].as<std::string>();
-
- if (dEffect == "copy")
- return Qt::CopyAction;
- else if (dEffect == "move")
- return Qt::MoveAction;
- else if (dEffect == "link")
- return Qt::LinkAction;
- return Qt::IgnoreAction;
-}
-} // namespace
-
-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
- event.call<void>("preventDefault"); // prevent browser from handling drop event
-
- 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["target"]["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, {},
- {});
- });
-}
-
-EMSCRIPTEN_BINDINGS(drop_module)
-{
- function("qtDrop", &dropEvent);
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmdrag.h b/src/plugins/platforms/wasm/qwasmdrag.h
deleted file mode 100644
index 624e9e3db6..0000000000
--- a/src/plugins/platforms/wasm/qwasmdrag.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
-
-#ifndef QWASMDRAG_H
-#define QWASMDRAG_H
-
-#include <QtCore/qtconfigmacros.h>
-
-#include <emscripten/val.h>
-
-QT_BEGIN_NAMESPACE
-
-void dropEvent(emscripten::val event);
-
-QT_END_NAMESPACE
-
-#endif // QWASMDRAG_H
diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp
index 19730c2c68..b6568e13fa 100644
--- a/src/plugins/platforms/wasm/qwasmevent.cpp
+++ b/src/plugins/platforms/wasm/qwasmevent.cpp
@@ -16,10 +16,63 @@ QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
}
} // namespace KeyboardModifier
-std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
+Event::Event(EventType type, emscripten::val target) : type(type), target(target) { }
+
+Event::~Event() = default;
+
+Event::Event(const Event &other) = default;
+
+Event::Event(Event &&other) = default;
+
+Event &Event::operator=(const Event &other) = default;
+
+Event &Event::operator=(Event &&other) = default;
+
+MouseEvent::MouseEvent(EventType type, emscripten::val event) : Event(type, event["target"])
+{
+ mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
+ mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as<unsigned short>());
+ // The current button state (event.buttons) may be out of sync for some PointerDown
+ // events where the "down" state is very brief, for example taps on Apple trackpads.
+ // Qt expects that the current button state is in sync with the event, so we sync
+ // it up here.
+ if (type == EventType::PointerDown)
+ mouseButtons |= mouseButton;
+ localPoint = QPoint(event["offsetX"].as<int>(), event["offsetY"].as<int>());
+ pointInPage = QPoint(event["pageX"].as<int>(), event["pageY"].as<int>());
+ pointInViewport = QPoint(event["clientX"].as<int>(), event["clientY"].as<int>());
+ modifiers = KeyboardModifier::getForEvent(event);
+}
+
+MouseEvent::~MouseEvent() = default;
+
+MouseEvent::MouseEvent(const MouseEvent &other) = default;
+
+MouseEvent::MouseEvent(MouseEvent &&other) = default;
+
+MouseEvent &MouseEvent::operator=(const MouseEvent &other) = default;
+
+MouseEvent &MouseEvent::operator=(MouseEvent &&other) = default;
+
+PointerEvent::PointerEvent(EventType type, emscripten::val event) : MouseEvent(type, event)
{
- PointerEvent ret;
+ pointerId = event["pointerId"].as<int>();
+ pointerType = event["pointerType"].as<std::string>() == "mouse" ? PointerType::Mouse
+ : PointerType::Other;
+}
+
+PointerEvent::~PointerEvent() = default;
+
+PointerEvent::PointerEvent(const PointerEvent &other) = default;
+
+PointerEvent::PointerEvent(PointerEvent &&other) = default;
+
+PointerEvent &PointerEvent::operator=(const PointerEvent &other) = default;
+PointerEvent &PointerEvent::operator=(PointerEvent &&other) = default;
+
+std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
+{
const auto eventType = ([&event]() -> std::optional<EventType> {
const auto eventTypeString = event["type"].as<std::string>();
@@ -38,27 +91,47 @@ std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
if (!eventType)
return std::nullopt;
- ret.type = *eventType;
- ret.target = event["target"];
- ret.pointerType = event["pointerType"].as<std::string>() == "mouse" ?
- PointerType::Mouse : PointerType::Other;
- ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
- ret.mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as<unsigned short>());
+ return PointerEvent(*eventType, event);
+}
- // The current button state (event.buttons) may be out of sync for some PointerDown
- // events where the "down" state is very brief, for example taps on Apple trackpads.
- // Qt expects that the current button state is in sync with the event, so we sync
- // it up here.
- if (*eventType == EventType::PointerDown)
- ret.mouseButtons |= ret.mouseButton;
+DragEvent::DragEvent(EventType type, emscripten::val event)
+ : MouseEvent(type, event), dataTransfer(event["dataTransfer"])
+{
+ dropAction = ([event]() {
+ const std::string effect = event["dataTransfer"]["dropEffect"].as<std::string>();
+
+ if (effect == "copy")
+ return Qt::CopyAction;
+ else if (effect == "move")
+ return Qt::MoveAction;
+ else if (effect == "link")
+ return Qt::LinkAction;
+ return Qt::IgnoreAction;
+ })();
+}
- ret.localPoint = QPoint(event["offsetX"].as<int>(), event["offsetY"].as<int>());
- ret.pointInPage = QPoint(event["pageX"].as<int>(), event["pageY"].as<int>());
- ret.pointInViewport = QPoint(event["clientX"].as<int>(), event["clientY"].as<int>());
- ret.pointerId = event["pointerId"].as<int>();
- ret.modifiers = KeyboardModifier::getForEvent(event);
+DragEvent::~DragEvent() = default;
- return ret;
+DragEvent::DragEvent(const DragEvent &other) = default;
+
+DragEvent::DragEvent(DragEvent &&other) = default;
+
+DragEvent &DragEvent::operator=(const DragEvent &other) = default;
+
+DragEvent &DragEvent::operator=(DragEvent &&other) = default;
+
+std::optional<DragEvent> DragEvent::fromWeb(emscripten::val event)
+{
+ const auto eventType = ([&event]() -> std::optional<EventType> {
+ const auto eventTypeString = event["type"].as<std::string>();
+
+ if (eventTypeString == "drop")
+ return EventType::Drop;
+ return std::nullopt;
+ })();
+ if (!eventType)
+ return std::nullopt;
+ return DragEvent(*eventType, event);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h
index f9d6411d60..215d06bae5 100644
--- a/src/plugins/platforms/wasm/qwasmevent.h
+++ b/src/plugins/platforms/wasm/qwasmevent.h
@@ -18,6 +18,7 @@
QT_BEGIN_NAMESPACE
enum class EventType {
+ Drop,
PointerDown,
PointerMove,
PointerUp,
@@ -107,13 +108,20 @@ QFlags<Qt::KeyboardModifier> getForEvent<EmscriptenKeyboardEvent>(
} // namespace KeyboardModifier
-struct Q_CORE_EXPORT Event
+struct Event
{
EventType type;
emscripten::val target = emscripten::val::undefined();
+
+ Event(EventType type, emscripten::val target);
+ ~Event();
+ Event(const Event &other);
+ Event(Event &&other);
+ Event &operator=(const Event &other);
+ Event &operator=(Event &&other);
};
-struct Q_CORE_EXPORT MouseEvent : public Event
+struct MouseEvent : public Event
{
QPoint localPoint;
QPoint pointInPage;
@@ -122,6 +130,13 @@ struct Q_CORE_EXPORT MouseEvent : public Event
Qt::MouseButtons mouseButtons;
QFlags<Qt::KeyboardModifier> modifiers;
+ MouseEvent(EventType type, emscripten::val webEvent);
+ ~MouseEvent();
+ MouseEvent(const MouseEvent &other);
+ MouseEvent(MouseEvent &&other);
+ MouseEvent &operator=(const MouseEvent &other);
+ MouseEvent &operator=(MouseEvent &&other);
+
static constexpr Qt::MouseButton buttonFromWeb(int webButton) {
switch (webButton) {
case 0:
@@ -158,14 +173,36 @@ struct Q_CORE_EXPORT MouseEvent : public Event
}
};
-struct Q_CORE_EXPORT PointerEvent : public MouseEvent
+struct PointerEvent : public MouseEvent
{
static std::optional<PointerEvent> fromWeb(emscripten::val webEvent);
+ PointerEvent(EventType type, emscripten::val webEvent);
+ ~PointerEvent();
+ PointerEvent(const PointerEvent &other);
+ PointerEvent(PointerEvent &&other);
+ PointerEvent &operator=(const PointerEvent &other);
+ PointerEvent &operator=(PointerEvent &&other);
+
PointerType pointerType;
int pointerId;
};
+struct DragEvent : public MouseEvent
+{
+ static std::optional<DragEvent> fromWeb(emscripten::val webEvent);
+
+ DragEvent(EventType type, emscripten::val webEvent);
+ ~DragEvent();
+ DragEvent(const DragEvent &other);
+ DragEvent(DragEvent &&other);
+ DragEvent &operator=(const DragEvent &other);
+ DragEvent &operator=(DragEvent &&other);
+
+ Qt::DropAction dropAction;
+ emscripten::val dataTransfer;
+};
+
QT_END_NAMESPACE
#endif // QWASMEVENT_H
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index 090218a118..b92e456668 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -80,12 +80,6 @@ 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>();
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index 8468c4c9e1..decf25009e 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -12,10 +12,6 @@
#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>
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index a8f577cfea..3735c7dff4 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -84,6 +84,12 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingSt
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerenter", callback);
m_pointerLeaveCallback =
std::make_unique<qstdweb::EventCallback>(m_qtWindow, "pointerleave", callback);
+
+ m_dropCallback = std::make_unique<qstdweb::EventCallback>(
+ m_qtWindow, "drop", [this](emscripten::val event) {
+ if (processDrop(*DragEvent::fromWeb(event)))
+ event.call<void>("preventDefault");
+ });
}
QWasmWindow::~QWasmWindow()
@@ -418,6 +424,30 @@ bool QWasmWindow::processPointer(const PointerEvent &event)
return false;
}
+bool QWasmWindow::processDrop(const DragEvent &event)
+{
+ m_dropDataReadCancellationFlag = qstdweb::readDataTransfer(
+ event.dataTransfer,
+ [](QByteArray fileContent) {
+ QImage image;
+ image.loadFromData(fileContent, nullptr);
+ return image;
+ },
+ [this, event](std::unique_ptr<QMimeData> data) {
+ QWindowSystemInterface::handleDrag(window(), data.get(), event.pointInPage,
+ event.dropAction, event.mouseButton,
+ event.modifiers);
+
+ QWindowSystemInterface::handleDrop(window(), data.get(), event.pointInPage,
+ event.dropAction, event.mouseButton,
+ event.modifiers);
+
+ QWindowSystemInterface::handleDrag(window(), nullptr, QPoint(), Qt::IgnoreAction,
+ {}, {});
+ });
+ return true;
+}
+
QRect QWasmWindow::normalGeometry() const
{
return m_normalGeometry;
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
index 5651495c74..906a7a1daf 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.h
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -18,13 +18,21 @@
#include <emscripten/val.h>
+#include <memory>
+
QT_BEGIN_NAMESPACE
namespace qstdweb {
+struct CancellationFlag;
+}
+
+namespace qstdweb {
class EventCallback;
}
class ClientArea;
+struct DragEvent;
+struct PointerEvent;
class QWasmWindow final : public QPlatformWindow
{
@@ -84,6 +92,7 @@ private:
void applyWindowState();
bool processPointer(const PointerEvent &event);
+ bool processDrop(const DragEvent &event);
QWindow *m_window = nullptr;
QWasmCompositor *m_compositor = nullptr;
@@ -105,6 +114,8 @@ private:
std::unique_ptr<qstdweb::EventCallback> m_pointerEnterCallback;
std::unique_ptr<qstdweb::EventCallback> m_pointerMoveCallback;
+ std::unique_ptr<qstdweb::EventCallback> m_dropCallback;
+
Qt::WindowStates m_state = Qt::WindowNoState;
Qt::WindowStates m_previousWindowState = Qt::WindowNoState;
@@ -120,6 +131,8 @@ private:
friend class QWasmCompositor;
friend class QWasmEventTranslator;
bool windowIsPopupType(Qt::WindowFlags flags) const;
+
+ std::shared_ptr<qstdweb::CancellationFlag> m_dropDataReadCancellationFlag;
};
QT_END_NAMESPACE