From 4d07f843072b367f45cb636d49415ceb92ca1dd9 Mon Sep 17 00:00:00 2001 From: Mikolaj Boc Date: Tue, 6 Dec 2022 08:42:34 +0100 Subject: [PATCH] Fix the coordinate problems in wasm windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QWasmScreen's top left coordinate does not precisely translate to correct page coordinates, especially when fixed position is used and page margins are set. Also, this is wrong in complicated setups with e.g. multiple nested elements. Therefore, to get the correct coordinates in pointer event handlers, we have to assume the local coordinates of the screen, and translate those to the (possibly incorrect) coordinates that QWasmScreen thinks it has in page. It is another problem to fix the wrong coordinates QWasmScreen thinks it has in the page. This has been checked with complicated setups with screens in scroll containers, screens with fixed position, screens with relative position, with and without body margins etc. Change-Id: I749f2507fec7ae278b6f9d7d13ae288e65472dba Reviewed-by: Morten Johan Sørvig --- .../platforms/wasm/qwasmcompositor.cpp | 26 ++++++++++++------- src/plugins/platforms/wasm/qwasmevent.cpp | 5 ++-- src/plugins/platforms/wasm/qwasmevent.h | 3 ++- src/plugins/platforms/wasm/qwasmscreen.cpp | 5 ++++ src/plugins/platforms/wasm/qwasmscreen.h | 1 + src/plugins/platforms/wasm/qwasmwindow.cpp | 4 +-- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index b84e05e1c9..0f082543ff 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -369,10 +369,12 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) if (event.pointerType != PointerType::Mouse) return false; - QWindow *const targetWindow = ([this, &event]() -> QWindow * { + const auto pointInScreen = screen()->mapFromLocal(event.localPoint); + + QWindow *const targetWindow = ([this, pointInScreen]() -> QWindow * { auto *targetWindow = m_mouseCaptureWindow != nullptr ? m_mouseCaptureWindow.get() : m_windowManipulation.operation() == WindowManipulation::Operation::None - ? screen()->compositor()->windowAt(event.point, 5) + ? screen()->compositor()->windowAt(pointInScreen, 5) : nullptr; return targetWindow ? targetWindow : m_lastMouseTargetWindow.get(); @@ -381,13 +383,13 @@ bool QWasmCompositor::processPointer(const PointerEvent& event) return false; m_lastMouseTargetWindow = targetWindow; - const QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(event.point); - const bool pointerIsWithinTargetWindowBounds = targetWindow->geometry().contains(event.point); + const QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(pointInScreen); + const bool pointerIsWithinTargetWindowBounds = targetWindow->geometry().contains(pointInScreen); if (m_mouseInScreen && m_windowUnderMouse != targetWindow && pointerIsWithinTargetWindowBounds) { // delayed mouse enter - enterWindow(targetWindow, pointInTargetWindowCoords, event.point); + enterWindow(targetWindow, pointInTargetWindowCoords, pointInScreen); m_windowUnderMouse = targetWindow; } @@ -439,11 +441,13 @@ bool QWasmCompositor::deliverEventToTarget(const PointerEvent &event, QWindow *e { Q_ASSERT(!m_mouseCaptureWindow || m_mouseCaptureWindow.get() == eventTarget); + const auto pointInScreen = screen()->mapFromLocal(event.localPoint); + const QPoint targetPointClippedToScreen( std::max(screen()->geometry().left(), - std::min(screen()->geometry().right(), event.point.x())), + std::min(screen()->geometry().right(), pointInScreen.x())), std::max(screen()->geometry().top(), - std::min(screen()->geometry().bottom(), event.point.y()))); + std::min(screen()->geometry().bottom(), pointInScreen.y()))); bool deliveringToPreviouslyClickedWindow = false; @@ -509,12 +513,13 @@ void QWasmCompositor::WindowManipulation::onPointerDown( if (isTargetWindowBlocked) return; - if (!asWasmWindow(windowAtPoint)->isPointOnTitle(event.point)) + if (!asWasmWindow(windowAtPoint)->isPointOnTitle(event.pointInViewport)) return; m_state.reset(new OperationState{ .pointerId = event.pointerId, .window = windowAtPoint, - .lastPointInScreenCoords = event.point }); + .lastPointInScreenCoords = + m_screen->mapFromLocal(event.localPoint) }); } void QWasmCompositor::WindowManipulation::onPointerMove( @@ -525,7 +530,8 @@ void QWasmCompositor::WindowManipulation::onPointerMove( switch (operation()) { case Operation::Move: { - const QPoint targetPointClippedToScreen = m_screen->clipPoint(event.point); + const QPoint targetPointClippedToScreen = + m_screen->clipPoint(m_screen->mapFromLocal(event.localPoint)); const QPoint difference = targetPointClippedToScreen - m_state->lastPointInScreenCoords; m_state->lastPointInScreenCoords = targetPointClippedToScreen; diff --git a/src/plugins/platforms/wasm/qwasmevent.cpp b/src/plugins/platforms/wasm/qwasmevent.cpp index 452a22ad5c..0e43a381bf 100644 --- a/src/plugins/platforms/wasm/qwasmevent.cpp +++ b/src/plugins/platforms/wasm/qwasmevent.cpp @@ -43,8 +43,9 @@ std::optional PointerEvent::fromWeb(emscripten::val event) PointerType::Mouse : PointerType::Other; ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as()); ret.mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as()); - ret.point = QPoint(event["offsetX"].as(), event["offsetY"].as()); - ret.pointInViewport = QPoint(event["x"].as(), event["y"].as()); + ret.localPoint = QPoint(event["offsetX"].as(), event["offsetY"].as()); + ret.pointInPage = QPoint(event["pageX"].as(), event["pageY"].as()); + ret.pointInViewport = QPoint(event["clientX"].as(), event["clientY"].as()); ret.pointerId = event["pointerId"].as(); ret.modifiers = KeyboardModifier::getForEvent(event); diff --git a/src/plugins/platforms/wasm/qwasmevent.h b/src/plugins/platforms/wasm/qwasmevent.h index 9f43b6a85f..26b6b5f22a 100644 --- a/src/plugins/platforms/wasm/qwasmevent.h +++ b/src/plugins/platforms/wasm/qwasmevent.h @@ -114,7 +114,8 @@ struct Q_CORE_EXPORT Event struct Q_CORE_EXPORT MouseEvent : public Event { - QPoint point; + QPoint localPoint; + QPoint pointInPage; QPoint pointInViewport; Qt::MouseButton mouseButton; Qt::MouseButtons mouseButtons; diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index 0e7d3e10a7..366d495089 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -223,6 +223,11 @@ QWindow *QWasmScreen::topLevelAt(const QPoint &p) const return m_compositor->windowAt(p); } +QPoint QWasmScreen::mapFromLocal(const QPoint &p) const +{ + return geometry().topLeft() + p; +} + QPoint QWasmScreen::clipPoint(const QPoint &p) const { return QPoint( diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h index fd573059e6..a87fa9156d 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.h +++ b/src/plugins/platforms/wasm/qwasmscreen.h @@ -52,6 +52,7 @@ public: QWindow *topWindow() const; QWindow *topLevelAt(const QPoint &p) const override; + QPoint mapFromLocal(const QPoint &p) const; QPoint clipPoint(const QPoint &p) const; void invalidateSize(); diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp index c85142882e..e38335f81c 100644 --- a/src/plugins/platforms/wasm/qwasmwindow.cpp +++ b/src/plugins/platforms/wasm/qwasmwindow.cpp @@ -133,7 +133,7 @@ public: m_element.call("setPointerCapture", event.pointerId); m_capturedPointerId = event.pointerId; - m_resizer->startResize(m_edges, event.pointInViewport); + m_resizer->startResize(m_edges, event.pointInPage); return true; } @@ -142,7 +142,7 @@ public: if (m_capturedPointerId != event.pointerId) return false; - m_resizer->continueResize(event.pointInViewport); + m_resizer->continueResize(event.pointInPage); return true; }