diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 85c27834393..f804542b34d 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -939,8 +939,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) const QPoint targetPointInScreenCoords = screen()->geometry().topLeft() + event.point; - QEvent::Type buttonEventType = QEvent::None; - QWindow *const targetWindow = ([this, &targetPointInScreenCoords]() -> QWindow * { auto *targetWindow = m_windowManipulation.operation() == WindowManipulation::Operation::None ? @@ -968,7 +966,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) switch (event.type) { case EventType::PointerDown: { - buttonEventType = QEvent::MouseButtonPress; if (targetWindow) targetWindow->requestActivate(); @@ -981,8 +978,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) } case EventType::PointerUp: { - buttonEventType = QEvent::MouseButtonRelease; - m_windowManipulation.onPointerUp(event); if (m_pressedWindow) { @@ -997,8 +992,6 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) } case EventType::PointerMove: { - buttonEventType = QEvent::MouseMove; - if (wasmTargetWindow && event.mouseButtons.testFlag(Qt::NoButton)) { const bool isOnResizeRegion = wasmTargetWindow->isPointOnResizeRegion(targetPointInScreenCoords); @@ -1033,24 +1026,51 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) leaveWindow(m_lastMouseTargetWindow); } - bool shouldDeliverEvent = pointerIsWithinTargetWindowBounds; - QWindow *eventTarget = targetWindow; - if (!eventTarget && event.type == EventType::PointerUp) { - eventTarget = m_lastMouseTargetWindow; - m_lastMouseTargetWindow = nullptr; - shouldDeliverEvent = true; - } - const bool eventAccepted = - eventTarget != nullptr && shouldDeliverEvent && - QWindowSystemInterface::handleMouseEvent( - eventTarget, QWasmIntegration::getTimestamp(), pointInTargetWindowCoords, targetPointInScreenCoords, - event.mouseButtons, event.mouseButton, buttonEventType, event.modifiers); - + const bool eventAccepted = deliverEventToTarget(event, targetWindow); if (!eventAccepted && event.type == EventType::PointerDown) QGuiApplicationPrivate::instance()->closeAllPopups(); return eventAccepted; } +bool QWasmCompositor::deliverEventToTarget(const PointerEvent &event, QWindow *eventTarget) +{ + const QPoint pointInScreenCoords = screen()->geometry().topLeft() + event.point; + const QPoint targetPointClippedToScreen( + std::max(screen()->geometry().left(), + std::min(screen()->geometry().right(), pointInScreenCoords.x())), + std::max(screen()->geometry().top(), + std::min(screen()->geometry().bottom(), pointInScreenCoords.y()))); + + bool deliveringToPreviouslyClickedWindow = false; + + if (!eventTarget) { + if (event.type != EventType::PointerUp || !m_lastMouseTargetWindow) + return false; + + eventTarget = m_lastMouseTargetWindow; + m_lastMouseTargetWindow = nullptr; + deliveringToPreviouslyClickedWindow = true; + } + + WindowArea windowArea = WindowArea::Client; + if (!eventTarget->geometry().contains(targetPointClippedToScreen) + && !deliveringToPreviouslyClickedWindow) { + if (!eventTarget->frameGeometry().contains(targetPointClippedToScreen)) + return false; + windowArea = WindowArea::NonClient; + } + + const QEvent::Type eventType = + MouseEvent::mouseEventTypeFromEventType(event.type, windowArea); + + return eventType != QEvent::None && + QWindowSystemInterface::handleMouseEvent( + eventTarget, QWasmIntegration::getTimestamp(), + eventTarget->mapFromGlobal(targetPointClippedToScreen), + targetPointClippedToScreen, event.mouseButtons, event.mouseButton, + eventType, event.modifiers); +} + QWasmCompositor::WindowManipulation::WindowManipulation(QWasmScreen *screen) : m_screen(screen) { @@ -1124,14 +1144,10 @@ void QWasmCompositor::WindowManipulation::onPointerMove( if (operation() == Operation::None || event.pointerId != m_state->pointerId) return; - const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point; - switch (operation()) { case Operation::Move: { - const QPoint targetPointClippedToScreen( - std::max(m_screen->geometry().left(), std::min(m_screen->geometry().right(), pointInScreenCoords.x())), - std::max(m_screen->geometry().top(), std::min(m_screen->geometry().bottom(), pointInScreenCoords.y()))); - + const QPoint targetPointClippedToScreen = + m_screen->translateAndClipGlobalPoint(event.point); const QPoint difference = targetPointClippedToScreen - std::get(m_state->operationSpecific).m_lastPointInScreenCoords; @@ -1141,6 +1157,7 @@ void QWasmCompositor::WindowManipulation::onPointerMove( break; } case Operation::Resize: { + const auto pointInScreenCoords = m_screen->geometry().topLeft() + event.point; resizeWindow(pointInScreenCoords - std::get(m_state->operationSpecific).m_originInScreenCoords); break; diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index b7a93d110be..2cfd355b617 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.h +++ b/src/plugins/platforms/wasm/qwasmcompositor.h @@ -208,6 +208,7 @@ private: static int wheel_cb(int eventType, const EmscriptenWheelEvent *wheelEvent, void *userData); bool processPointer(const PointerEvent& event); + bool deliverEventToTarget(const PointerEvent& event, QWindow *eventTarget); static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData); diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h index 784591fb958..df9276b7465 100644 --- a/src/plugins/platforms/wasm/qwasmevent.h +++ b/src/plugins/platforms/wasm/qwasmevent.h @@ -8,6 +8,7 @@ #include #include +#include #include @@ -29,6 +30,11 @@ enum class PointerType { Other, }; +enum class WindowArea { + NonClient, + Client, +}; + namespace KeyboardModifier { namespace internal { @@ -129,7 +135,24 @@ struct Q_CORE_EXPORT MouseEvent : public Event static constexpr Qt::MouseButtons buttonsFromWeb(unsigned short webButtons) { // Coincidentally, Qt and web bitfields match. return Qt::MouseButtons::fromInt(webButtons); -} + } + + static constexpr QEvent::Type mouseEventTypeFromEventType( + EventType eventType, WindowArea windowArea) { + switch (eventType) { + case EventType::PointerDown : + return windowArea == WindowArea::Client ? + QEvent::MouseButtonPress : QEvent::NonClientAreaMouseButtonPress; + case EventType::PointerUp : + return windowArea == WindowArea::Client ? + QEvent::MouseButtonRelease : QEvent::NonClientAreaMouseButtonRelease; + case EventType::PointerMove : + return windowArea == WindowArea::Client ? + QEvent::MouseMove : QEvent::NonClientAreaMouseMove; + default: + return QEvent::None; + } + } }; struct Q_CORE_EXPORT PointerEvent : public MouseEvent diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index 42ca608da17..350832ebf58 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -258,6 +258,15 @@ QWindow *QWasmScreen::topLevelAt(const QPoint &p) const return m_compositor->windowAt(p); } +QPoint QWasmScreen::translateAndClipGlobalPoint(const QPoint &p) const +{ + return QPoint( + std::max(screen()->geometry().left(), + std::min(screen()->geometry().right(), screen()->geometry().left() + p.x())), + std::max(screen()->geometry().top(), + std::min(screen()->geometry().bottom(), screen()->geometry().top() + p.y()))); +} + void QWasmScreen::invalidateSize() { m_geometry = QRect(); diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h index 0e7d5f1e436..405ea7e7b86 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.h +++ b/src/plugins/platforms/wasm/qwasmscreen.h @@ -53,6 +53,8 @@ public: QWindow *topWindow() const; QWindow *topLevelAt(const QPoint &p) const override; + QPoint translateAndClipGlobalPoint(const QPoint &p) const; + void invalidateSize(); void updateQScreenAndCanvasRenderSize(); void installCanvasResizeObserver(); diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index ec5e4d51d58..6072740db85 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -1079,14 +1079,14 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event) if (state == nullptr || !state->dragging) break; -#ifndef Q_OS_MAC +#if !defined(Q_OS_MAC) && !defined(Q_OS_WASM) if (state->nca) { endDrag(); } #endif break; case QEvent::NonClientAreaMouseButtonRelease: -#ifdef Q_OS_MAC +#if defined(Q_OS_MAC) || defined(Q_OS_WASM) if (state) endDrag(); #endif