Use floating point coords for mouse/wheel events on wasm

Fractional mouse movements may be reported on hi-dpi. Floating point
event fields help us perform correct calculations in line with the
web platform.

Change-Id: Ic0c457db408c2bf28179ffcfdb032cde64ca8bbd
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
Reviewed-by: Aleksandr Reviakin <aleksandr.reviakin@qt.io>
This commit is contained in:
Mikolaj Boc 2023-02-03 18:16:17 +01:00
parent 249d613a60
commit d6eea89bc6
11 changed files with 51 additions and 52 deletions

View File

@ -292,11 +292,10 @@ bool QWasmCompositor::processTouch(int eventType, const EmscriptenTouchEvent *to
const EmscriptenTouchPoint *emTouchPoint = &touchEvent->touches[i]; const EmscriptenTouchPoint *emTouchPoint = &touchEvent->touches[i];
QPointF targetPointInScreenCoords =
QPoint targetPointInScreenCoords =
screen()->mapFromLocal(QPoint(emTouchPoint->targetX, emTouchPoint->targetY)); screen()->mapFromLocal(QPoint(emTouchPoint->targetX, emTouchPoint->targetY));
targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords, 5); targetWindow = screen()->compositor()->windowAt(targetPointInScreenCoords.toPoint(), 5);
if (targetWindow == nullptr) if (targetWindow == nullptr)
continue; continue;
@ -312,7 +311,7 @@ bool QWasmCompositor::processTouch(int eventType, const EmscriptenTouchEvent *to
if (tp != m_pressedTouchIds.constEnd()) if (tp != m_pressedTouchIds.constEnd())
touchPoint.normalPosition = tp.value(); touchPoint.normalPosition = tp.value();
QPointF pointInTargetWindowCoords = QPointF(targetWindow->mapFromGlobal(targetPointInScreenCoords)); QPointF pointInTargetWindowCoords = targetWindow->mapFromGlobal(targetPointInScreenCoords);
QPointF normalPosition(pointInTargetWindowCoords.x() / targetWindow->width(), QPointF normalPosition(pointInTargetWindowCoords.x() / targetWindow->width(),
pointInTargetWindowCoords.y() / targetWindow->height()); pointInTargetWindowCoords.y() / targetWindow->height());

View File

@ -25,15 +25,15 @@ void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool fl
element["classList"].call<void>("remove", emscripten::val(std::move(cssClassName))); element["classList"].call<void>("remove", emscripten::val(std::move(cssClassName)));
} }
QPoint mapPoint(emscripten::val source, emscripten::val target, const QPoint &point) QPointF mapPoint(emscripten::val source, emscripten::val target, const QPointF &point)
{ {
auto sourceBoundingRect = const auto sourceBoundingRect =
QRectF::fromDOMRect(source.call<emscripten::val>("getBoundingClientRect")); QRectF::fromDOMRect(source.call<emscripten::val>("getBoundingClientRect"));
auto targetBoundingRect = const auto targetBoundingRect =
QRectF::fromDOMRect(target.call<emscripten::val>("getBoundingClientRect")); QRectF::fromDOMRect(target.call<emscripten::val>("getBoundingClientRect"));
auto offset = sourceBoundingRect.topLeft() - targetBoundingRect.topLeft(); const auto offset = sourceBoundingRect.topLeft() - targetBoundingRect.topLeft();
return (point + offset).toPoint(); return point + offset;
} }
} // namespace dom } // namespace dom

View File

@ -24,7 +24,7 @@ inline emscripten::val document()
void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag); void syncCSSClassWith(emscripten::val element, std::string cssClassName, bool flag);
QPoint mapPoint(emscripten::val source, emscripten::val target, const QPoint &point); QPointF mapPoint(emscripten::val source, emscripten::val target, const QPointF &point);
} // namespace dom } // namespace dom
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -114,9 +114,9 @@ MouseEvent::MouseEvent(EventType type, emscripten::val event) : Event(type, even
// it up here. // it up here.
if (type == EventType::PointerDown) if (type == EventType::PointerDown)
mouseButtons |= mouseButton; mouseButtons |= mouseButton;
localPoint = QPoint(event["offsetX"].as<int>(), event["offsetY"].as<int>()); localPoint = QPointF(event["offsetX"].as<qreal>(), event["offsetY"].as<qreal>());
pointInPage = QPoint(event["pageX"].as<int>(), event["pageY"].as<int>()); pointInPage = QPointF(event["pageX"].as<qreal>(), event["pageY"].as<qreal>());
pointInViewport = QPoint(event["clientX"].as<int>(), event["clientY"].as<int>()); pointInViewport = QPointF(event["clientX"].as<qreal>(), event["clientY"].as<qreal>());
modifiers = KeyboardModifier::getForEvent(event); modifiers = KeyboardModifier::getForEvent(event);
} }
@ -222,7 +222,7 @@ WheelEvent::WheelEvent(EventType type, emscripten::val event) : MouseEvent(type,
return DeltaMode::Page; return DeltaMode::Page;
})(); })();
delta = QPoint(event["deltaX"].as<int>(), event["deltaY"].as<int>()); delta = QPointF(event["deltaX"].as<qreal>(), event["deltaY"].as<qreal>());
webkitDirectionInvertedFromDevice = event["webkitDirectionInvertedFromDevice"].as<bool>(); webkitDirectionInvertedFromDevice = event["webkitDirectionInvertedFromDevice"].as<bool>();
} }

View File

@ -190,9 +190,9 @@ struct MouseEvent : public Event
} }
} }
QPoint localPoint; QPointF localPoint;
QPoint pointInPage; QPointF pointInPage;
QPoint pointInViewport; QPointF pointInViewport;
Qt::MouseButton mouseButton; Qt::MouseButton mouseButton;
Qt::MouseButtons mouseButtons; Qt::MouseButtons mouseButtons;
QFlags<Qt::KeyboardModifier> modifiers; QFlags<Qt::KeyboardModifier> modifiers;
@ -241,7 +241,7 @@ struct WheelEvent : public MouseEvent
DeltaMode deltaMode; DeltaMode deltaMode;
bool webkitDirectionInvertedFromDevice; bool webkitDirectionInvertedFromDevice;
QPoint delta; QPointF delta;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -203,15 +203,16 @@ QWindow *QWasmScreen::topLevelAt(const QPoint &p) const
return m_compositor->windowAt(p); return m_compositor->windowAt(p);
} }
QPoint QWasmScreen::mapFromLocal(const QPoint &p) const QPointF QWasmScreen::mapFromLocal(const QPointF &p) const
{ {
return geometry().topLeft() + p; return geometry().topLeft() + p;
} }
QPoint QWasmScreen::clipPoint(const QPoint &p) const QPointF QWasmScreen::clipPoint(const QPointF &p) const
{ {
return QPoint(qBound(screen()->geometry().left(), p.x(), screen()->geometry().right()), const auto geometryF = screen()->geometry().toRectF();
qBound(screen()->geometry().top(), p.y(), screen()->geometry().bottom())); return QPointF(qBound(geometryF.left(), p.x(), geometryF.right()),
qBound(geometryF.top(), p.y(), geometryF.bottom()));
} }
void QWasmScreen::invalidateSize() void QWasmScreen::invalidateSize()

View File

@ -52,8 +52,8 @@ 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; QPointF mapFromLocal(const QPointF &p) const;
QPoint clipPoint(const QPoint &p) const; QPointF clipPoint(const QPointF &p) const;
void invalidateSize(); void invalidateSize();
void updateQScreenAndCanvasRenderSize(); void updateQScreenAndCanvasRenderSize();

View File

@ -165,7 +165,7 @@ void QWasmWindow::onNonClientAreaInteraction()
bool QWasmWindow::onNonClientEvent(const PointerEvent &event) bool QWasmWindow::onNonClientEvent(const PointerEvent &event)
{ {
QPoint pointInScreen = platformScreen()->mapFromLocal( QPointF pointInScreen = platformScreen()->mapFromLocal(
dom::mapPoint(event.target, platformScreen()->element(), event.localPoint)); dom::mapPoint(event.target, platformScreen()->element(), event.localPoint));
return QWindowSystemInterface::handleMouseEvent( return QWindowSystemInterface::handleMouseEvent(
window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen), window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
@ -504,13 +504,13 @@ bool QWasmWindow::processDrop(const DragEvent &event)
return image; return image;
}, },
[this, event](std::unique_ptr<QMimeData> data) { [this, event](std::unique_ptr<QMimeData> data) {
QWindowSystemInterface::handleDrag(window(), data.get(), event.pointInPage, QWindowSystemInterface::handleDrag(window(), data.get(),
event.dropAction, event.mouseButton, event.pointInPage.toPoint(), event.dropAction,
event.modifiers); event.mouseButton, event.modifiers);
QWindowSystemInterface::handleDrop(window(), data.get(), event.pointInPage, QWindowSystemInterface::handleDrop(window(), data.get(),
event.dropAction, event.mouseButton, event.pointInPage.toPoint(), event.dropAction,
event.modifiers); event.mouseButton, event.modifiers);
QWindowSystemInterface::handleDrag(window(), nullptr, QPoint(), Qt::IgnoreAction, QWindowSystemInterface::handleDrag(window(), nullptr, QPoint(), Qt::IgnoreAction,
{}, {}); {}, {});
@ -536,10 +536,10 @@ bool QWasmWindow::processWheel(const WheelEvent &event)
dom::mapPoint(event.target, platformScreen()->element(), event.localPoint)); dom::mapPoint(event.target, platformScreen()->element(), event.localPoint));
return QWindowSystemInterface::handleWheelEvent( return QWindowSystemInterface::handleWheelEvent(
window(), QWasmIntegration::getTimestamp(), mapFromGlobal(pointInScreen), pointInScreen, window(), QWasmIntegration::getTimestamp(), window()->mapFromGlobal(pointInScreen),
event.delta * scrollFactor, event.delta * scrollFactor, event.modifiers, pointInScreen, (event.delta * scrollFactor).toPoint(),
Qt::NoScrollPhase, Qt::MouseEventNotSynthesized, (event.delta * scrollFactor).toPoint(), event.modifiers, Qt::NoScrollPhase,
event.webkitDirectionInvertedFromDevice); Qt::MouseEventNotSynthesized, event.webkitDirectionInvertedFromDevice);
} }
QRect QWasmWindow::normalGeometry() const QRect QWasmWindow::normalGeometry() const

View File

@ -39,7 +39,7 @@ bool ClientArea::processPointer(const PointerEvent &event)
dom::mapPoint(event.target, m_screen->element(), event.localPoint); dom::mapPoint(event.target, m_screen->element(), event.localPoint);
const auto pointInScreen = m_screen->mapFromLocal(localScreenPoint); const auto pointInScreen = m_screen->mapFromLocal(localScreenPoint);
const QPoint pointInTargetWindowCoords = m_window->mapFromGlobal(pointInScreen); const QPointF pointInTargetWindowCoords = m_window->window()->mapFromGlobal(pointInScreen);
switch (event.type) { switch (event.type) {
case EventType::PointerDown: { case EventType::PointerDown: {
@ -73,11 +73,10 @@ bool ClientArea::deliverEvent(const PointerEvent &event)
const auto pointInScreen = m_screen->mapFromLocal( const auto pointInScreen = m_screen->mapFromLocal(
dom::mapPoint(event.target, m_screen->element(), event.localPoint)); dom::mapPoint(event.target, m_screen->element(), event.localPoint));
const QPoint targetPointClippedToScreen( const auto geometryF = m_screen->geometry().toRectF();
std::max(m_screen->geometry().left(), const QPointF targetPointClippedToScreen(
std::min(m_screen->geometry().right(), pointInScreen.x())), qBound(geometryF.left(), pointInScreen.x(), geometryF.right()),
std::max(m_screen->geometry().top(), qBound(geometryF.top(), pointInScreen.y(), geometryF.bottom()));
std::min(m_screen->geometry().bottom(), pointInScreen.y())));
const QEvent::Type eventType = const QEvent::Type eventType =
MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::Client); MouseEvent::mouseEventTypeFromEventType(event.type, WindowArea::Client);

View File

@ -219,7 +219,7 @@ void Resizer::continueResize(const PointerEvent &event)
{ {
const auto pointInScreen = const auto pointInScreen =
dom::mapPoint(event.target, m_window->platformScreen()->element(), event.localPoint); dom::mapPoint(event.target, m_window->platformScreen()->element(), event.localPoint);
const auto amount = pointInScreen - m_currentResizeData->originInScreenCoords; const auto amount = (pointInScreen - m_currentResizeData->originInScreenCoords).toPoint();
const QPoint cappedGrowVector( const QPoint cappedGrowVector(
std::min(m_currentResizeData->maxGrow.x(), std::min(m_currentResizeData->maxGrow.x(),
std::max(m_currentResizeData->minShrink.x(), std::max(m_currentResizeData->minShrink.x(),
@ -377,8 +377,8 @@ bool TitleBar::onPointerDown(const PointerEvent &event)
m_element.call<void>("setPointerCapture", event.pointerId); m_element.call<void>("setPointerCapture", event.pointerId);
m_capturedPointerId = event.pointerId; m_capturedPointerId = event.pointerId;
const QPoint targetPointClippedToScreen = clipPointWithScreen(event.localPoint); m_moveStartWindowPosition = m_window->window()->position();
m_lastMovePoint = targetPointClippedToScreen; m_moveStartPoint = clipPointWithScreen(event.localPoint);
m_window->onNonClientEvent(event); m_window->onNonClientEvent(event);
return true; return true;
} }
@ -388,11 +388,9 @@ bool TitleBar::onPointerMove(const PointerEvent &event)
if (m_capturedPointerId != event.pointerId) if (m_capturedPointerId != event.pointerId)
return false; return false;
const QPoint targetPointClippedToScreen = clipPointWithScreen(event.localPoint); const QPoint delta = (clipPointWithScreen(event.localPoint) - m_moveStartPoint).toPoint();
const QPoint delta = targetPointClippedToScreen - m_lastMovePoint;
m_lastMovePoint = targetPointClippedToScreen;
m_window->window()->setPosition(m_window->window()->position() + delta); m_window->window()->setPosition(m_moveStartWindowPosition + delta);
m_window->onNonClientEvent(event); m_window->onNonClientEvent(event);
return true; return true;
} }
@ -414,7 +412,7 @@ bool TitleBar::onDoubleClick()
return true; return true;
} }
QPoint TitleBar::clipPointWithScreen(const QPoint &pointInTitleBarCoords) const QPointF TitleBar::clipPointWithScreen(const QPointF &pointInTitleBarCoords) const
{ {
auto *screen = m_window->platformScreen(); auto *screen = m_window->platformScreen();
return screen->clipPoint(screen->mapFromLocal( return screen->clipPoint(screen->mapFromLocal(

View File

@ -4,6 +4,7 @@
#ifndef QWASMWINDOWNONCLIENTAREA_H #ifndef QWASMWINDOWNONCLIENTAREA_H
#define QWASMWINDOWNONCLIENTAREA_H #define QWASMWINDOWNONCLIENTAREA_H
#include <QtCore/qrect.h>
#include <QtCore/qtconfigmacros.h> #include <QtCore/qtconfigmacros.h>
#include <QtCore/qnamespace.h> #include <QtCore/qnamespace.h>
@ -155,7 +156,7 @@ private:
struct ResizeData struct ResizeData
{ {
Qt::Edges edges = Qt::Edges::fromInt(0); Qt::Edges edges = Qt::Edges::fromInt(0);
QPoint originInScreenCoords; QPointF originInScreenCoords;
QPoint minShrink; QPoint minShrink;
QPoint maxGrow; QPoint maxGrow;
QRect initialBounds; QRect initialBounds;
@ -188,7 +189,7 @@ private:
bool onPointerUp(const PointerEvent &event); bool onPointerUp(const PointerEvent &event);
bool onDoubleClick(); bool onDoubleClick();
QPoint clipPointWithScreen(const QPoint &pointInTitleBarCoords) const; QPointF clipPointWithScreen(const QPointF &pointInTitleBarCoords) const;
QWasmWindow *m_window; QWasmWindow *m_window;
@ -201,7 +202,8 @@ private:
std::unique_ptr<WebImageButton> m_icon; std::unique_ptr<WebImageButton> m_icon;
int m_capturedPointerId = -1; int m_capturedPointerId = -1;
QPoint m_lastMovePoint; QPointF m_moveStartPoint;
QPoint m_moveStartWindowPosition;
std::unique_ptr<qstdweb::EventCallback> m_mouseDownEvent; std::unique_ptr<qstdweb::EventCallback> m_mouseDownEvent;
std::unique_ptr<qstdweb::EventCallback> m_mouseMoveEvent; std::unique_ptr<qstdweb::EventCallback> m_mouseMoveEvent;