diff options
author | Mikolaj Boc <mikolaj.boc@qt.io> | 2022-07-20 14:29:06 +0200 |
---|---|---|
committer | Mikolaj Boc <mikolaj.boc@qt.io> | 2022-08-19 15:15:06 +0200 |
commit | 0edf92aa4eaf5f7ade95291f5514c569b7806325 (patch) | |
tree | 88cc2de8a1ff533ebe9620ad77f44dc0906f8f7a /src | |
parent | fe1319a4c8b49840605cf7335e222191e418c85d (diff) |
Deliver non-client area mouse events to WASM windows
QWasmCompositor now delivers non-client area mouse events to windows as
it should, which fixes a lot of issues with window manipulation. One of
such issues is re-docking of dock widgets.
Fixes: QTBUG-105092
Change-Id: I9de45b7e1b1a80b64387031eb0cc0b31a4be2571
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
(cherry picked from commit 19507dc6788f252cd0795d80d9a39d22f1306882)
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.cpp | 67 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmcompositor.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmevent.h | 25 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmscreen.cpp | 9 | ||||
-rw-r--r-- | src/plugins/platforms/wasm/qwasmscreen.h | 2 | ||||
-rw-r--r-- | src/widgets/widgets/qdockwidget.cpp | 4 |
6 files changed, 80 insertions, 28 deletions
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index 85c2783439..f804542b34 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,22 +1026,49 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) leaveWindow(m_lastMouseTargetWindow); } - bool shouldDeliverEvent = pointerIsWithinTargetWindowBounds; - QWindow *eventTarget = targetWindow; - if (!eventTarget && event.type == EventType::PointerUp) { + 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; - shouldDeliverEvent = true; + deliveringToPreviouslyClickedWindow = true; } - const bool eventAccepted = - eventTarget != nullptr && shouldDeliverEvent && - QWindowSystemInterface::handleMouseEvent<QWindowSystemInterface::SynchronousDelivery>( - eventTarget, QWasmIntegration::getTimestamp(), pointInTargetWindowCoords, targetPointInScreenCoords, - event.mouseButtons, event.mouseButton, buttonEventType, event.modifiers); - if (!eventAccepted && event.type == EventType::PointerDown) - QGuiApplicationPrivate::instance()->closeAllPopups(); - return eventAccepted; + 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<QWindowSystemInterface::SynchronousDelivery>( + eventTarget, QWasmIntegration::getTimestamp(), + eventTarget->mapFromGlobal(targetPointClippedToScreen), + targetPointClippedToScreen, event.mouseButtons, event.mouseButton, + eventType, event.modifiers); } QWasmCompositor::WindowManipulation::WindowManipulation(QWasmScreen *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<MoveState>(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<ResizeState>(m_state->operationSpecific).m_originInScreenCoords); break; diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h index b7a93d110b..2cfd355b61 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 784591fb95..df9276b746 100644 --- a/src/plugins/platforms/wasm/qwasmevent.h +++ b/src/plugins/platforms/wasm/qwasmevent.h @@ -8,6 +8,7 @@ #include <QtCore/qglobal.h> #include <QtCore/qnamespace.h> +#include <QtGui/qevent.h> #include <QPoint> @@ -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 42ca608da1..350832ebf5 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 0e7d5f1e43..405ea7e7b8 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 ec5e4d51d5..6072740db8 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 |