summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorMikolaj Boc <mikolaj.boc@qt.io>2022-12-23 12:48:13 +0100
committerMikolaj Boc <mikolaj.boc@qt.io>2023-01-22 23:24:01 +0100
commitc54416a06ce25a97de463803a489762c44926cef (patch)
treebdbe65934d530bdb6a6ef491134b6c57780f6f91 /src/plugins/platforms
parent5d356ae2bd57a92fbe041944849627ee511efc5a (diff)
Handle the wheel event in the wasm window
Align the wheel event handling with other events - move the handler to wasm window and create a C++ wrapper class for the js wheel event. Fixes: QTBUG-109622 Change-Id: I915e502de7c0784ec9a6745a90ddcda062e91b2b Reviewed-by: Mikołaj Boc <Mikolaj.Boc@qt.io> Reviewed-by: Lorn Potter <lorn.potter@gmail.com> Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp76
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h3
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.cpp41
-rw-r--r--src/plugins/platforms/wasm/qwasmevent.h19
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp30
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h4
6 files changed, 94 insertions, 79 deletions
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 0700d66a55..a66c5f5beb 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -29,19 +29,6 @@ using namespace emscripten;
Q_GUI_EXPORT int qt_defaultDpiX();
-bool g_scrollingInvertedFromDevice = false;
-
-static void mouseWheelEvent(emscripten::val event)
-{
- emscripten::val wheelInverted = event["webkitDirectionInvertedFromDevice"];
- if (wheelInverted.as<bool>())
- g_scrollingInvertedFromDevice = true;
-}
-
-EMSCRIPTEN_BINDINGS(qtMouseModule) {
- function("qtMouseWheelEvent", &mouseWheelEvent);
-}
-
QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
: QObject(screen),
m_windowStack(std::bind(&QWasmCompositor::onTopWindowChanged, this)),
@@ -77,8 +64,6 @@ void QWasmCompositor::deregisterEventHandlers()
emscripten_set_keydown_callback(screenElementSelector.constData(), 0, 0, NULL);
emscripten_set_keyup_callback(screenElementSelector.constData(), 0, 0, NULL);
- emscripten_set_wheel_callback(screenElementSelector.constData(), 0, 0, NULL);
-
emscripten_set_touchstart_callback(screenElementSelector.constData(), 0, 0, NULL);
emscripten_set_touchend_callback(screenElementSelector.constData(), 0, 0, NULL);
emscripten_set_touchmove_callback(screenElementSelector.constData(), 0, 0, NULL);
@@ -94,13 +79,6 @@ void QWasmCompositor::destroy()
void QWasmCompositor::initEventHandlers()
{
- if (platform() == Platform::MacOS) {
- if (!emscripten::val::global("window")["safari"].isUndefined()) {
- screen()->element().call<void>("addEventListener", val("wheel"),
- val::module_property("qtMouseWheelEvent"));
- }
- }
-
constexpr EM_BOOL UseCapture = 1;
const QByteArray screenElementSelector = screen()->eventTargetId().toUtf8();
@@ -109,9 +87,6 @@ void QWasmCompositor::initEventHandlers()
emscripten_set_keyup_callback(screenElementSelector.constData(), (void *)this, UseCapture,
&keyboard_cb);
- emscripten_set_wheel_callback(screenElementSelector.constData(), (void *)this, UseCapture,
- &wheel_cb);
-
emscripten_set_touchstart_callback(screenElementSelector.constData(), (void *)this, UseCapture,
&touchCallback);
emscripten_set_touchend_callback(screenElementSelector.constData(), (void *)this, UseCapture,
@@ -314,12 +289,6 @@ int QWasmCompositor::keyboard_cb(int eventType, const EmscriptenKeyboardEvent *k
return static_cast<int>(wasmCompositor->processKeyboard(eventType, keyEvent));
}
-int QWasmCompositor::wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData)
-{
- QWasmCompositor *compositor = (QWasmCompositor *) userData;
- return static_cast<int>(compositor->processWheel(eventType, wheelEvent));
-}
-
int QWasmCompositor::touchCallback(int eventType, const EmscriptenTouchEvent *touchEvent, void *userData)
{
auto compositor = reinterpret_cast<QWasmCompositor*>(userData);
@@ -354,51 +323,6 @@ bool QWasmCompositor::processKeyboard(int eventType, const EmscriptenKeyboardEve
: result;
}
-bool QWasmCompositor::processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent)
-{
- Q_UNUSED(eventType);
-
- const EmscriptenMouseEvent* mouseEvent = &wheelEvent->mouse;
-
- int scrollFactor = 0;
- switch (wheelEvent->deltaMode) {
- case DOM_DELTA_PIXEL:
- scrollFactor = 1;
- break;
- case DOM_DELTA_LINE:
- scrollFactor = 12;
- break;
- case DOM_DELTA_PAGE:
- scrollFactor = 20;
- break;
- };
-
- scrollFactor = -scrollFactor; // Web scroll deltas are inverted from Qt deltas.
-
- Qt::KeyboardModifiers modifiers = KeyboardModifier::getForEvent(*mouseEvent);
- QPoint targetPointInScreenCoords =
- screen()->mapFromLocal(QPoint(mouseEvent->targetX, mouseEvent->targetY));
-
- QWindow *targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords, 5);
- if (!targetWindow)
- return 0;
- QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(targetPointInScreenCoords);
-
- QPoint pixelDelta;
-
- if (wheelEvent->deltaY != 0) pixelDelta.setY(wheelEvent->deltaY * scrollFactor);
- if (wheelEvent->deltaX != 0) pixelDelta.setX(wheelEvent->deltaX * scrollFactor);
-
- QPoint angleDelta = pixelDelta; // FIXME: convert from pixels?
-
- bool accepted = QWindowSystemInterface::handleWheelEvent(
- targetWindow, QWasmIntegration::getTimestamp(), pointInTargetWindowCoords,
- targetPointInScreenCoords, pixelDelta, angleDelta, modifiers,
- Qt::NoScrollPhase, Qt::MouseEventNotSynthesized,
- g_scrollingInvertedFromDevice);
- return accepted;
-}
-
bool QWasmCompositor::processTouch(int eventType, const EmscriptenTouchEvent *touchEvent)
{
QList<QWindowSystemInterface::TouchPoint> touchPointList;
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 7845987e9f..211579fb5a 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -79,13 +79,10 @@ private:
void deliverUpdateRequest(QWasmWindow *window, UpdateRequestDeliveryType updateType);
static int keyboard_cb(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData);
- static int focus_cb(int eventType, const EmscriptenFocusEvent *focusEvent, void *userData);
- static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData);
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
bool processKeyboard(int eventType, const EmscriptenKeyboardEvent *keyEvent);
- bool processWheel(int eventType, const EmscriptenWheelEvent *wheelEvent);
bool processTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
void enterWindow(QWindow *window, const QPoint &localPoint, const QPoint &globalPoint);
diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp
index b6568e13fa..eb2c8c145a 100644
--- a/src/plugins/platforms/wasm/qwasmevent.cpp
+++ b/src/plugins/platforms/wasm/qwasmevent.cpp
@@ -134,4 +134,45 @@ std::optional<DragEvent> DragEvent::fromWeb(emscripten::val event)
return DragEvent(*eventType, event);
}
+WheelEvent::WheelEvent(EventType type, emscripten::val event) : MouseEvent(type, event)
+{
+ deltaMode = ([event]() {
+ const int deltaMode = event["deltaMode"].as<int>();
+ const auto jsWheelEventType = emscripten::val::global("WheelEvent");
+ if (deltaMode == jsWheelEventType["DOM_DELTA_PIXEL"].as<int>())
+ return DeltaMode::Pixel;
+ else if (deltaMode == jsWheelEventType["DOM_DELTA_LINE"].as<int>())
+ return DeltaMode::Line;
+ return DeltaMode::Page;
+ })();
+
+ delta = QPoint(event["deltaX"].as<int>(), event["deltaY"].as<int>());
+
+ webkitDirectionInvertedFromDevice = event["webkitDirectionInvertedFromDevice"].as<bool>();
+}
+
+WheelEvent::~WheelEvent() = default;
+
+WheelEvent::WheelEvent(const WheelEvent &other) = default;
+
+WheelEvent::WheelEvent(WheelEvent &&other) = default;
+
+WheelEvent &WheelEvent::operator=(const WheelEvent &other) = default;
+
+WheelEvent &WheelEvent::operator=(WheelEvent &&other) = default;
+
+std::optional<WheelEvent> WheelEvent::fromWeb(emscripten::val event)
+{
+ const auto eventType = ([&event]() -> std::optional<EventType> {
+ const auto eventTypeString = event["type"].as<std::string>();
+
+ if (eventTypeString == "wheel")
+ return EventType::Wheel;
+ return std::nullopt;
+ })();
+ if (!eventType)
+ return std::nullopt;
+ return WheelEvent(*eventType, event);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h
index 215d06bae5..e8aea9072e 100644
--- a/src/plugins/platforms/wasm/qwasmevent.h
+++ b/src/plugins/platforms/wasm/qwasmevent.h
@@ -24,6 +24,7 @@ enum class EventType {
PointerUp,
PointerEnter,
PointerLeave,
+ Wheel,
};
enum class PointerType {
@@ -36,6 +37,8 @@ enum class WindowArea {
Client,
};
+enum class DeltaMode { Pixel, Line, Page };
+
namespace KeyboardModifier {
namespace internal
{
@@ -203,6 +206,22 @@ struct DragEvent : public MouseEvent
emscripten::val dataTransfer;
};
+struct WheelEvent : public MouseEvent
+{
+ static std::optional<WheelEvent> fromWeb(emscripten::val webEvent);
+
+ WheelEvent(EventType type, emscripten::val webEvent);
+ ~WheelEvent();
+ WheelEvent(const WheelEvent &other);
+ WheelEvent(WheelEvent &&other);
+ WheelEvent &operator=(const WheelEvent &other);
+ WheelEvent &operator=(WheelEvent &&other);
+
+ DeltaMode deltaMode;
+ bool webkitDirectionInvertedFromDevice;
+ QPoint delta;
+};
+
QT_END_NAMESPACE
#endif // QWASMEVENT_H
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index 07f1200c7d..7ad844a67c 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -89,6 +89,12 @@ QWasmWindow::QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingSt
if (processDrop(*DragEvent::fromWeb(event)))
event.call<void>("preventDefault");
});
+
+ m_wheelEventCallback = std::make_unique<qstdweb::EventCallback>(
+ m_qtWindow, "wheel", [this](emscripten::val event) {
+ if (processWheel(*WheelEvent::fromWeb(event)))
+ event.call<void>("preventDefault");
+ });
}
QWasmWindow::~QWasmWindow()
@@ -447,6 +453,30 @@ bool QWasmWindow::processDrop(const DragEvent &event)
return true;
}
+bool QWasmWindow::processWheel(const WheelEvent &event)
+{
+ // Web scroll deltas are inverted from Qt deltas - negate.
+ const int scrollFactor = -([&event]() {
+ switch (event.deltaMode) {
+ case DeltaMode::Pixel:
+ return 1;
+ case DeltaMode::Line:
+ return 12;
+ case DeltaMode::Page:
+ return 20;
+ };
+ })();
+
+ const auto pointInScreen = platformScreen()->mapFromLocal(
+ dom::mapPoint(event.target, platformScreen()->element(), event.localPoint));
+
+ return QWindowSystemInterface::handleWheelEvent(
+ window(), QWasmIntegration::getTimestamp(), mapFromGlobal(pointInScreen), pointInScreen,
+ event.delta * scrollFactor, event.delta * scrollFactor, event.modifiers,
+ Qt::NoScrollPhase, Qt::MouseEventNotSynthesized,
+ event.webkitDirectionInvertedFromDevice);
+}
+
QRect QWasmWindow::normalGeometry() const
{
return m_normalGeometry;
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
index 906a7a1daf..20e30f3d97 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.h
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -33,6 +33,7 @@ class EventCallback;
class ClientArea;
struct DragEvent;
struct PointerEvent;
+struct WheelEvent;
class QWasmWindow final : public QPlatformWindow
{
@@ -93,6 +94,7 @@ private:
bool processPointer(const PointerEvent &event);
bool processDrop(const DragEvent &event);
+ bool processWheel(const WheelEvent &event);
QWindow *m_window = nullptr;
QWasmCompositor *m_compositor = nullptr;
@@ -116,6 +118,8 @@ private:
std::unique_ptr<qstdweb::EventCallback> m_dropCallback;
+ std::unique_ptr<qstdweb::EventCallback> m_wheelEventCallback;
+
Qt::WindowStates m_state = Qt::WindowNoState;
Qt::WindowStates m_previousWindowState = Qt::WindowNoState;