Fix the coordinate problems in wasm windows
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 <morten.sorvig@qt.io>
This commit is contained in:
parent
6d780fa0ab
commit
4d07f84307
@ -369,10 +369,12 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
|||||||
if (event.pointerType != PointerType::Mouse)
|
if (event.pointerType != PointerType::Mouse)
|
||||||
return false;
|
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()
|
auto *targetWindow = m_mouseCaptureWindow != nullptr ? m_mouseCaptureWindow.get()
|
||||||
: m_windowManipulation.operation() == WindowManipulation::Operation::None
|
: m_windowManipulation.operation() == WindowManipulation::Operation::None
|
||||||
? screen()->compositor()->windowAt(event.point, 5)
|
? screen()->compositor()->windowAt(pointInScreen, 5)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
return targetWindow ? targetWindow : m_lastMouseTargetWindow.get();
|
return targetWindow ? targetWindow : m_lastMouseTargetWindow.get();
|
||||||
@ -381,13 +383,13 @@ bool QWasmCompositor::processPointer(const PointerEvent& event)
|
|||||||
return false;
|
return false;
|
||||||
m_lastMouseTargetWindow = targetWindow;
|
m_lastMouseTargetWindow = targetWindow;
|
||||||
|
|
||||||
const QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(event.point);
|
const QPoint pointInTargetWindowCoords = targetWindow->mapFromGlobal(pointInScreen);
|
||||||
const bool pointerIsWithinTargetWindowBounds = targetWindow->geometry().contains(event.point);
|
const bool pointerIsWithinTargetWindowBounds = targetWindow->geometry().contains(pointInScreen);
|
||||||
|
|
||||||
if (m_mouseInScreen && m_windowUnderMouse != targetWindow
|
if (m_mouseInScreen && m_windowUnderMouse != targetWindow
|
||||||
&& pointerIsWithinTargetWindowBounds) {
|
&& pointerIsWithinTargetWindowBounds) {
|
||||||
// delayed mouse enter
|
// delayed mouse enter
|
||||||
enterWindow(targetWindow, pointInTargetWindowCoords, event.point);
|
enterWindow(targetWindow, pointInTargetWindowCoords, pointInScreen);
|
||||||
m_windowUnderMouse = targetWindow;
|
m_windowUnderMouse = targetWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,11 +441,13 @@ bool QWasmCompositor::deliverEventToTarget(const PointerEvent &event, QWindow *e
|
|||||||
{
|
{
|
||||||
Q_ASSERT(!m_mouseCaptureWindow || m_mouseCaptureWindow.get() == eventTarget);
|
Q_ASSERT(!m_mouseCaptureWindow || m_mouseCaptureWindow.get() == eventTarget);
|
||||||
|
|
||||||
|
const auto pointInScreen = screen()->mapFromLocal(event.localPoint);
|
||||||
|
|
||||||
const QPoint targetPointClippedToScreen(
|
const QPoint targetPointClippedToScreen(
|
||||||
std::max(screen()->geometry().left(),
|
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::max(screen()->geometry().top(),
|
||||||
std::min(screen()->geometry().bottom(), event.point.y())));
|
std::min(screen()->geometry().bottom(), pointInScreen.y())));
|
||||||
|
|
||||||
bool deliveringToPreviouslyClickedWindow = false;
|
bool deliveringToPreviouslyClickedWindow = false;
|
||||||
|
|
||||||
@ -509,12 +513,13 @@ void QWasmCompositor::WindowManipulation::onPointerDown(
|
|||||||
if (isTargetWindowBlocked)
|
if (isTargetWindowBlocked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!asWasmWindow(windowAtPoint)->isPointOnTitle(event.point))
|
if (!asWasmWindow(windowAtPoint)->isPointOnTitle(event.pointInViewport))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_state.reset(new OperationState{ .pointerId = event.pointerId,
|
m_state.reset(new OperationState{ .pointerId = event.pointerId,
|
||||||
.window = windowAtPoint,
|
.window = windowAtPoint,
|
||||||
.lastPointInScreenCoords = event.point });
|
.lastPointInScreenCoords =
|
||||||
|
m_screen->mapFromLocal(event.localPoint) });
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWasmCompositor::WindowManipulation::onPointerMove(
|
void QWasmCompositor::WindowManipulation::onPointerMove(
|
||||||
@ -525,7 +530,8 @@ void QWasmCompositor::WindowManipulation::onPointerMove(
|
|||||||
|
|
||||||
switch (operation()) {
|
switch (operation()) {
|
||||||
case Operation::Move: {
|
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;
|
const QPoint difference = targetPointClippedToScreen - m_state->lastPointInScreenCoords;
|
||||||
|
|
||||||
m_state->lastPointInScreenCoords = targetPointClippedToScreen;
|
m_state->lastPointInScreenCoords = targetPointClippedToScreen;
|
||||||
|
@ -43,8 +43,9 @@ std::optional<PointerEvent> PointerEvent::fromWeb(emscripten::val event)
|
|||||||
PointerType::Mouse : PointerType::Other;
|
PointerType::Mouse : PointerType::Other;
|
||||||
ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
|
ret.mouseButton = MouseEvent::buttonFromWeb(event["button"].as<int>());
|
||||||
ret.mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as<unsigned short>());
|
ret.mouseButtons = MouseEvent::buttonsFromWeb(event["buttons"].as<unsigned short>());
|
||||||
ret.point = QPoint(event["offsetX"].as<int>(), event["offsetY"].as<int>());
|
ret.localPoint = QPoint(event["offsetX"].as<int>(), event["offsetY"].as<int>());
|
||||||
ret.pointInViewport = QPoint(event["x"].as<int>(), event["y"].as<int>());
|
ret.pointInPage = QPoint(event["pageX"].as<int>(), event["pageY"].as<int>());
|
||||||
|
ret.pointInViewport = QPoint(event["clientX"].as<int>(), event["clientY"].as<int>());
|
||||||
ret.pointerId = event["pointerId"].as<int>();
|
ret.pointerId = event["pointerId"].as<int>();
|
||||||
ret.modifiers = KeyboardModifier::getForEvent(event);
|
ret.modifiers = KeyboardModifier::getForEvent(event);
|
||||||
|
|
||||||
|
@ -114,7 +114,8 @@ struct Q_CORE_EXPORT Event
|
|||||||
|
|
||||||
struct Q_CORE_EXPORT MouseEvent : public Event
|
struct Q_CORE_EXPORT MouseEvent : public Event
|
||||||
{
|
{
|
||||||
QPoint point;
|
QPoint localPoint;
|
||||||
|
QPoint pointInPage;
|
||||||
QPoint pointInViewport;
|
QPoint pointInViewport;
|
||||||
Qt::MouseButton mouseButton;
|
Qt::MouseButton mouseButton;
|
||||||
Qt::MouseButtons mouseButtons;
|
Qt::MouseButtons mouseButtons;
|
||||||
|
@ -223,6 +223,11 @@ QWindow *QWasmScreen::topLevelAt(const QPoint &p) const
|
|||||||
return m_compositor->windowAt(p);
|
return m_compositor->windowAt(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPoint QWasmScreen::mapFromLocal(const QPoint &p) const
|
||||||
|
{
|
||||||
|
return geometry().topLeft() + p;
|
||||||
|
}
|
||||||
|
|
||||||
QPoint QWasmScreen::clipPoint(const QPoint &p) const
|
QPoint QWasmScreen::clipPoint(const QPoint &p) const
|
||||||
{
|
{
|
||||||
return QPoint(
|
return QPoint(
|
||||||
|
@ -52,6 +52,7 @@ public:
|
|||||||
QWindow *topWindow() const;
|
QWindow *topWindow() const;
|
||||||
QWindow *topLevelAt(const QPoint &p) const override;
|
QWindow *topLevelAt(const QPoint &p) const override;
|
||||||
|
|
||||||
|
QPoint mapFromLocal(const QPoint &p) const;
|
||||||
QPoint clipPoint(const QPoint &p) const;
|
QPoint clipPoint(const QPoint &p) const;
|
||||||
|
|
||||||
void invalidateSize();
|
void invalidateSize();
|
||||||
|
@ -133,7 +133,7 @@ public:
|
|||||||
m_element.call<void>("setPointerCapture", event.pointerId);
|
m_element.call<void>("setPointerCapture", event.pointerId);
|
||||||
m_capturedPointerId = event.pointerId;
|
m_capturedPointerId = event.pointerId;
|
||||||
|
|
||||||
m_resizer->startResize(m_edges, event.pointInViewport);
|
m_resizer->startResize(m_edges, event.pointInPage);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ public:
|
|||||||
if (m_capturedPointerId != event.pointerId)
|
if (m_capturedPointerId != event.pointerId)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_resizer->continueResize(event.pointInViewport);
|
m_resizer->continueResize(event.pointInPage);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user