diff options
author | Mikolaj Boc <mikolaj.boc@qt.io> | 2022-12-23 12:48:13 +0100 |
---|---|---|
committer | Mikolaj Boc <mikolaj.boc@qt.io> | 2023-01-22 23:24:01 +0100 |
commit | c54416a06ce25a97de463803a489762c44926cef (patch) | |
tree | bdbe65934d530bdb6a6ef491134b6c57780f6f91 /src/plugins/platforms | |
parent | 5d356ae2bd57a92fbe041944849627ee511efc5a (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.cpp | 76 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmevent.cpp | 41 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmevent.h | 19 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindow.cpp | 30 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindow.h | 4 |
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; |