diff options
Diffstat (limited to 'src/plugins/platforms/wasm/qwasmwindowclientarea.cpp')
-rw-r--r-- | src/plugins/platforms/wasm/qwasmwindowclientarea.cpp | 182 |
1 files changed, 142 insertions, 40 deletions
diff --git a/src/plugins/platforms/wasm/qwasmwindowclientarea.cpp b/src/plugins/platforms/wasm/qwasmwindowclientarea.cpp index e3e17baa1e..6da3e24c05 100644 --- a/src/plugins/platforms/wasm/qwasmwindowclientarea.cpp +++ b/src/plugins/platforms/wasm/qwasmwindowclientarea.cpp @@ -7,9 +7,10 @@ #include "qwasmevent.h" #include "qwasmscreen.h" #include "qwasmwindow.h" +#include "qwasmdrag.h" #include <QtGui/private/qguiapplication_p.h> -#include <qpa/qwindowsysteminterface.h> +#include <QtGui/qpointingdevice.h> #include <QtCore/qassert.h> @@ -19,8 +20,9 @@ ClientArea::ClientArea(QWasmWindow *window, QWasmScreen *screen, emscripten::val : m_screen(screen), m_window(window), m_element(element) { const auto callback = std::function([this](emscripten::val event) { - if (processPointer(*PointerEvent::fromWeb(event))) - event.call<void>("preventDefault"); + processPointer(*PointerEvent::fromWeb(event)); + event.call<void>("preventDefault"); + event.call<void>("stopPropagation"); }); m_pointerDownCallback = @@ -28,36 +30,52 @@ ClientArea::ClientArea(QWasmWindow *window, QWasmScreen *screen, emscripten::val m_pointerMoveCallback = std::make_unique<qstdweb::EventCallback>(element, "pointermove", callback); m_pointerUpCallback = std::make_unique<qstdweb::EventCallback>(element, "pointerup", callback); + m_pointerCancelCallback = + std::make_unique<qstdweb::EventCallback>(element, "pointercancel", callback); + + element.call<void>("setAttribute", emscripten::val("draggable"), emscripten::val("true")); + + m_dragStartCallback = std::make_unique<qstdweb::EventCallback>( + element, "dragstart", [this](emscripten::val webEvent) { + webEvent.call<void>("preventDefault"); + auto event = *DragEvent::fromWeb(webEvent, m_window->window()); + QWasmDrag::instance()->onNativeDragStarted(&event); + }); + m_dragOverCallback = std::make_unique<qstdweb::EventCallback>( + element, "dragover", [this](emscripten::val webEvent) { + webEvent.call<void>("preventDefault"); + auto event = *DragEvent::fromWeb(webEvent, m_window->window()); + QWasmDrag::instance()->onNativeDragOver(&event); + }); + m_dropCallback = std::make_unique<qstdweb::EventCallback>( + element, "drop", [this](emscripten::val webEvent) { + webEvent.call<void>("preventDefault"); + auto event = *DragEvent::fromWeb(webEvent, m_window->window()); + QWasmDrag::instance()->onNativeDrop(&event); + }); + m_dragEndCallback = std::make_unique<qstdweb::EventCallback>( + element, "dragend", [this](emscripten::val webEvent) { + webEvent.call<void>("preventDefault"); + auto event = *DragEvent::fromWeb(webEvent, m_window->window()); + QWasmDrag::instance()->onNativeDragFinished(&event); + }); + } bool ClientArea::processPointer(const PointerEvent &event) { - if (event.pointerType != PointerType::Mouse) - return false; - - const auto localScreenPoint = - dom::mapPoint(event.target, m_screen->element(), event.localPoint); - const auto pointInScreen = m_screen->mapFromLocal(localScreenPoint); - - const QPoint pointInTargetWindowCoords = m_window->mapFromGlobal(pointInScreen); switch (event.type) { - case EventType::PointerDown: { + case EventType::PointerDown: m_element.call<void>("setPointerCapture", event.pointerId); - m_window->window()->requestActivate(); + if ((m_window->window()->flags() & Qt::WindowDoesNotAcceptFocus) + != Qt::WindowDoesNotAcceptFocus + && m_window->window()->isTopLevel()) + m_window->window()->requestActivate(); break; - } - case EventType::PointerUp: { + case EventType::PointerUp: m_element.call<void>("releasePointerCapture", event.pointerId); break; - } - case EventType::PointerEnter:; - QWindowSystemInterface::handleEnterEvent( - m_window->window(), pointInTargetWindowCoords, pointInScreen); - break; - case EventType::PointerLeave: - QWindowSystemInterface::handleLeaveEvent(m_window->window()); - break; default: break; }; @@ -71,23 +89,107 @@ bool ClientArea::processPointer(const PointerEvent &event) bool ClientArea::deliverEvent(const PointerEvent &event) { const auto pointInScreen = m_screen->mapFromLocal( - dom::mapPoint(event.target, m_screen->element(), event.localPoint)); - - const QPoint targetPointClippedToScreen( - std::max(m_screen->geometry().left(), - std::min(m_screen->geometry().right(), pointInScreen.x())), - std::max(m_screen->geometry().top(), - std::min(m_screen->geometry().bottom(), pointInScreen.y()))); - - const QEvent::Type eventType = - MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::Client); - - return eventType != QEvent::None - && QWindowSystemInterface::handleMouseEvent( - m_window->window(), QWasmIntegration::getTimestamp(), - m_window->window()->mapFromGlobal(targetPointClippedToScreen), - targetPointClippedToScreen, event.mouseButtons, event.mouseButton, eventType, - event.modifiers); + dom::mapPoint(event.target(), m_screen->element(), event.localPoint)); + + const auto geometryF = m_screen->geometry().toRectF(); + const QPointF targetPointClippedToScreen( + qBound(geometryF.left(), pointInScreen.x(), geometryF.right()), + qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom())); + + if (event.pointerType == PointerType::Mouse) { + const QEvent::Type eventType = + MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::Client); + + return eventType != QEvent::None + && QWindowSystemInterface::handleMouseEvent( + m_window->window(), QWasmIntegration::getTimestamp(), + m_window->window()->mapFromGlobal(targetPointClippedToScreen), + targetPointClippedToScreen, event.mouseButtons, event.mouseButton, + eventType, event.modifiers); + } + + if (event.pointerType == PointerType::Pen) { + qreal pressure; + switch (event.type) { + case EventType::PointerDown : + case EventType::PointerMove : + pressure = event.pressure; + break; + case EventType::PointerUp : + pressure = 0.0; + break; + default: + return false; + } + // Tilt in the browser is in the range +-90, but QTabletEvent only goes to +-60. + qreal xTilt = qBound(-60.0, event.tiltX, 60.0); + qreal yTilt = qBound(-60.0, event.tiltY, 60.0); + // Barrel rotation is reported as 0 to 359, but QTabletEvent wants a signed value. + qreal rotation = event.twist > 180.0 ? 360.0 - event.twist : event.twist; + return QWindowSystemInterface::handleTabletEvent( + m_window->window(), QWasmIntegration::getTimestamp(), m_screen->tabletDevice(), + m_window->window()->mapFromGlobal(targetPointClippedToScreen), + targetPointClippedToScreen, event.mouseButtons, pressure, xTilt, yTilt, + event.tangentialPressure, rotation, event.modifiers); + } + + QWindowSystemInterface::TouchPoint *touchPoint; + + QPointF pointInTargetWindowCoords = + QPointF(m_window->window()->mapFromGlobal(targetPointClippedToScreen)); + QPointF normalPosition(pointInTargetWindowCoords.x() / m_window->window()->width(), + pointInTargetWindowCoords.y() / m_window->window()->height()); + + const auto tp = m_pointerIdToTouchPoints.find(event.pointerId); + if (event.pointerType != PointerType::Pen && tp != m_pointerIdToTouchPoints.end()) { + touchPoint = &tp.value(); + } else { + touchPoint = &m_pointerIdToTouchPoints + .insert(event.pointerId, QWindowSystemInterface::TouchPoint()) + .value(); + + // Assign touch point id. TouchPoint::id is int, but QGuiApplicationPrivate::processTouchEvent() + // will not synthesize mouse events for touch points with negative id; use the absolute value for + // the touch point id. + touchPoint->id = qAbs(event.pointerId); + + touchPoint->state = QEventPoint::State::Pressed; + } + + const bool stationaryTouchPoint = (normalPosition == touchPoint->normalPosition); + touchPoint->normalPosition = normalPosition; + touchPoint->area = QRectF(targetPointClippedToScreen, QSizeF(event.width, event.height)) + .translated(-event.width / 2, -event.height / 2); + touchPoint->pressure = event.pressure; + + switch (event.type) { + case EventType::PointerUp: + touchPoint->state = QEventPoint::State::Released; + break; + case EventType::PointerMove: + touchPoint->state = (stationaryTouchPoint ? QEventPoint::State::Stationary + : QEventPoint::State::Updated); + break; + default: + break; + } + + QList<QWindowSystemInterface::TouchPoint> touchPointList; + touchPointList.reserve(m_pointerIdToTouchPoints.size()); + std::transform(m_pointerIdToTouchPoints.begin(), m_pointerIdToTouchPoints.end(), + std::back_inserter(touchPointList), + [](const QWindowSystemInterface::TouchPoint &val) { return val; }); + + if (event.type == EventType::PointerUp) + m_pointerIdToTouchPoints.remove(event.pointerId); + + return event.type == EventType::PointerCancel + ? QWindowSystemInterface::handleTouchCancelEvent( + m_window->window(), QWasmIntegration::getTimestamp(), m_screen->touchDevice(), + event.modifiers) + : QWindowSystemInterface::handleTouchEvent( + m_window->window(), QWasmIntegration::getTimestamp(), m_screen->touchDevice(), + touchPointList, event.modifiers); } QT_END_NAMESPACE |