diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-06-11 07:38:46 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2018-07-19 10:56:06 +0000 |
commit | ca7cdd71ee33f0d77eb6bf1367d2532e26155cb2 (patch) | |
tree | af1b30bffea87bedb23e8cd795f23692f29b50a9 | |
parent | d310ca768bb5f45bae4fcec9a5d8151b6a366b8d (diff) |
Make DragHandler a MultiPointHandler
That is, minimumPointCount can now be set to a value > 1 to require
multiple fingers to do the dragging, or to track the displacement
of multiple fingers to adjust some value (such as the tilt of a map).
Task-number: QTBUG-68106
Change-Id: Ib35823e36deb81c8b277d3070fcc758c7c019564
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
14 files changed, 318 insertions, 198 deletions
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index 8bb8612fb3..707b247f72 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -43,6 +43,10 @@ QT_BEGIN_NAMESPACE +static const qreal DragAngleToleranceDegrees = 10; + +Q_LOGGING_CATEGORY(lcDragHandler, "qt.quick.handler.drag") + /*! \qmltype DragHandler \instantiates QQuickDragHandler @@ -71,13 +75,21 @@ QT_BEGIN_NAMESPACE \snippet pointerHandlers/dragHandlerNullTarget.qml 0 + If minimumPointCount and maximumPointCount are set to values larger than 1, + the user will need to drag that many fingers in the same direction to start + dragging. A multi-finger drag gesture can be detected independently of both + a (default) single-finger DragHandler and a PinchHandler on the same Item, + and thus can be used to adjust some other feature independently of the + usual pinch behavior: for example adjust a tilt transformation, or adjust + some other numeric value. + At this time, drag-and-drop is not yet supported. \sa Drag, MouseArea */ QQuickDragHandler::QQuickDragHandler(QObject *parent) - : QQuickSinglePointHandler(parent) + : QQuickMultiPointHandler(parent, 1, 1) { } @@ -85,22 +97,15 @@ QQuickDragHandler::~QQuickDragHandler() { } -bool QQuickDragHandler::wantsEventPoint(QQuickEventPoint *point) -{ - // If we've already been interested in a point, stay interested, even if it has strayed outside bounds. - return ((point->state() != QQuickEventPoint::Pressed && this->point().id() == point->pointId()) - || QQuickSinglePointHandler::wantsEventPoint(point)); -} - -bool QQuickDragHandler::targetContains(QQuickEventPoint *point) +bool QQuickDragHandler::targetContainsCentroid() { Q_ASSERT(parentItem() && target()); - return target()->contains(localTargetPosition(point)); + return target()->contains(targetCentroidPosition()); } -QPointF QQuickDragHandler::localTargetPosition(QQuickEventPoint *point) +QPointF QQuickDragHandler::targetCentroidPosition() { - QPointF pos = point->position(); + QPointF pos = m_centroid.position(); if (target() != parentItem()) pos = parentItem()->mapToItem(target(), pos); return pos; @@ -108,82 +113,137 @@ QPointF QQuickDragHandler::localTargetPosition(QQuickEventPoint *point) void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point) { + QQuickMultiPointHandler::onGrabChanged(grabber, stateChange, point); if (grabber == this && stateChange == QQuickEventPoint::GrabExclusive) { // In case the grab got handed over from another grabber, we might not get the Press. if (!m_pressedInsideTarget) { if (target()) m_pressTargetPos = QPointF(target()->width(), target()->height()) / 2; - m_pressScenePos = point->scenePosition(); } else if (m_pressTargetPos.isNull()) { if (target()) - m_pressTargetPos = localTargetPosition(point); - m_pressScenePos = point->scenePosition(); + m_pressTargetPos = targetCentroidPosition(); } } - QQuickSinglePointHandler::onGrabChanged(grabber, stateChange, point); } void QQuickDragHandler::onActiveChanged() { - if (!active()) { + QQuickMultiPointHandler::onActiveChanged(); + if (active()) { + if (auto parent = parentItem()) { + if (currentEvent()->asPointerTouchEvent()) + parent->setKeepTouchGrab(true); + // tablet and mouse are treated the same by Item's legacy event handling, and + // touch becomes synth-mouse for Flickable, so we need to prevent stealing + // mouse grab too, whenever dragging occurs in an enabled direction + parent->setKeepMouseGrab(true); + } + } else { m_pressTargetPos = QPointF(); - m_pressScenePos = m_pressTargetPos; m_pressedInsideTarget = false; + if (auto parent = parentItem()) { + parent->setKeepTouchGrab(false); + parent->setKeepMouseGrab(false); + } } } -void QQuickDragHandler::handleEventPoint(QQuickEventPoint *point) +void QQuickDragHandler::handlePointerEventImpl(QQuickPointerEvent *event) { - point->setAccepted(); - switch (point->state()) { - case QQuickEventPoint::Pressed: - if (target()) { - m_pressedInsideTarget = targetContains(point); - m_pressTargetPos = localTargetPosition(point); - } - m_pressScenePos = point->scenePosition(); - setPassiveGrab(point); - break; - case QQuickEventPoint::Updated: { - QVector2D accumulatedDragDelta = QVector2D(point->scenePosition() - m_pressScenePos); - if (active()) { - // update translation property. Make sure axis is respected for it. - if (!m_xAxis.enabled()) + QQuickMultiPointHandler::handlePointerEventImpl(event); + event->setAccepted(true); + + if (active()) { + // Calculate drag delta, taking into account the axis enabled constraint + // i.e. if xAxis is not enabled, then ignore the horizontal component of the actual movement + QVector2D accumulatedDragDelta = QVector2D(m_centroid.scenePosition() - m_centroid.scenePressPosition()); + if (!m_xAxis.enabled()) + accumulatedDragDelta.setX(0); + if (!m_yAxis.enabled()) + accumulatedDragDelta.setY(0); + setTranslation(accumulatedDragDelta); + } else { + // Check that all points have been dragged past the drag threshold, + // to the extent that the constraints allow, + // and in approximately the same direction + qreal minAngle = 361; + qreal maxAngle = -361; + bool allOverThreshold = !event->isReleaseEvent(); + QVector <QQuickEventPoint *> chosenPoints; + + if (event->isPressEvent()) + m_pressedInsideTarget = target() && m_currentPoints.count() > 0; + + for (const QQuickHandlerPoint &p : m_currentPoints) { + if (!allOverThreshold) + break; + QQuickEventPoint *point = event->pointById(p.id()); + chosenPoints << point; + setPassiveGrab(point); + // Calculate drag delta, taking into account the axis enabled constraint + // i.e. if xAxis is not enabled, then ignore the horizontal component of the actual movement + QVector2D accumulatedDragDelta = QVector2D(point->scenePosition() - point->scenePressPosition()); + if (!m_xAxis.enabled()) { + // If horizontal dragging is disallowed, but the user is dragging + // mostly horizontally, then don't activate. + if (qAbs(accumulatedDragDelta.x()) > qAbs(accumulatedDragDelta.y())) + accumulatedDragDelta.setY(0); accumulatedDragDelta.setX(0); - if (!m_yAxis.enabled()) + } + if (!m_yAxis.enabled()) { + // If vertical dragging is disallowed, but the user is dragging + // mostly vertically, then don't activate. + if (qAbs(accumulatedDragDelta.y()) > qAbs(accumulatedDragDelta.x())) + accumulatedDragDelta.setX(0); accumulatedDragDelta.setY(0); - setTranslation(accumulatedDragDelta); - - if (target() && target()->parentItem()) { - const QPointF newTargetTopLeft = localTargetPosition(point) - m_pressTargetPos; - const QPointF xformOrigin = target()->transformOriginPoint(); - const QPointF targetXformOrigin = newTargetTopLeft + xformOrigin; - QPointF pos = target()->parentItem()->mapFromItem(target(), targetXformOrigin); - pos -= xformOrigin; - QPointF targetItemPos = target()->position(); - if (!m_xAxis.enabled()) - pos.setX(targetItemPos.x()); - if (!m_yAxis.enabled()) - pos.setY(targetItemPos.y()); - enforceAxisConstraints(&pos); - moveTarget(pos, point); } - } else if (!point->exclusiveGrabber() && - ((m_xAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(accumulatedDragDelta.x(), Qt::XAxis, point)) || - (m_yAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(accumulatedDragDelta.y(), Qt::YAxis, point)))) { - setExclusiveGrab(point); - if (auto parent = parentItem()) { - if (point->pointerEvent()->asPointerTouchEvent()) - parent->setKeepTouchGrab(true); - // tablet and mouse are treated the same by Item's legacy event handling, and - // touch becomes synth-mouse for Flickable, so we need to prevent stealing - // mouse grab too, whenever dragging occurs in an enabled direction - parent->setKeepMouseGrab(true); + qreal angle = std::atan2(accumulatedDragDelta.y(), accumulatedDragDelta.x()) * 180 / M_PI; + bool overThreshold = QQuickWindowPrivate::dragOverThreshold(accumulatedDragDelta); + qCDebug(lcDragHandler) << "movement" << accumulatedDragDelta << "angle" << angle << "of point" << point + << "pressed @" << point->scenePressPosition() << "over threshold?" << overThreshold; + minAngle = qMin(angle, minAngle); + maxAngle = qMax(angle, maxAngle); + if (allOverThreshold && !overThreshold) + allOverThreshold = false; + + if (event->isPressEvent()) { + // m_pressedInsideTarget should stay true iff ALL points in which DragHandler is interested + // have been pressed inside the target() Item. (E.g. in a Slider the parent might be the + // whole control while the target is just the knob.) + if (target()) { + const QPointF localPressPos = target()->mapFromScene(point->scenePressPosition()); + m_pressedInsideTarget &= target()->contains(localPressPos); + m_pressTargetPos = targetCentroidPosition(); + } + // QQuickWindowPrivate::deliverToPassiveGrabbers() skips subsequent delivery if the event is filtered. + // (That affects behavior for mouse but not for touch, because Flickable only handles mouse.) + // So we have to compensate by accepting the event here to avoid any parent Flickable from + // getting the event via direct delivery and grabbing too soon. + point->setAccepted(event->asPointerMouseEvent()); // stop propagation iff it's a mouse event } } - } break; - default: - break; + if (allOverThreshold) { + qreal angleDiff = maxAngle - minAngle; + if (angleDiff > 180) + angleDiff = 360 - angleDiff; + qCDebug(lcDragHandler) << "angle min" << minAngle << "max" << maxAngle << "range" << angleDiff; + if (angleDiff < DragAngleToleranceDegrees && grabPoints(chosenPoints)) + setActive(true); + } + } + if (active() && target() && target()->parentItem()) { + const QPointF newTargetTopLeft = targetCentroidPosition() - m_pressTargetPos; + const QPointF xformOrigin = target()->transformOriginPoint(); + const QPointF targetXformOrigin = newTargetTopLeft + xformOrigin; + QPointF pos = target()->parentItem()->mapFromItem(target(), targetXformOrigin); + pos -= xformOrigin; + QPointF targetItemPos = target()->position(); + if (!m_xAxis.enabled()) + pos.setX(targetItemPos.x()); + if (!m_yAxis.enabled()) + pos.setY(targetItemPos.y()); + enforceAxisConstraints(&pos); + moveTarget(pos); } } diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h index 7ba1021924..ea49d59902 100644 --- a/src/quick/handlers/qquickdraghandler_p.h +++ b/src/quick/handlers/qquickdraghandler_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQuick module of the Qt Toolkit. @@ -51,12 +51,12 @@ // We mean it. // -#include "qquicksinglepointhandler_p.h" +#include "qquickmultipointhandler_p.h" #include "qquickdragaxis_p.h" QT_BEGIN_NAMESPACE -class Q_AUTOTEST_EXPORT QQuickDragHandler : public QQuickSinglePointHandler +class Q_AUTOTEST_EXPORT QQuickDragHandler : public QQuickMultiPointHandler { Q_OBJECT Q_PROPERTY(QQuickDragAxis * xAxis READ xAxis CONSTANT) @@ -67,7 +67,7 @@ public: explicit QQuickDragHandler(QObject *parent = nullptr); ~QQuickDragHandler(); - void handleEventPoint(QQuickEventPoint *point) override; + void handlePointerEventImpl(QQuickPointerEvent *event) override; QQuickDragAxis *xAxis() { return &m_xAxis; } QQuickDragAxis *yAxis() { return &m_yAxis; } @@ -82,18 +82,16 @@ Q_SIGNALS: void translationChanged(); protected: - bool wantsEventPoint(QQuickEventPoint *point) override; void onActiveChanged() override; void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point) override; private: void ungrab(); void enforceAxisConstraints(QPointF *localPos); - bool targetContains(QQuickEventPoint *point); - QPointF localTargetPosition(QQuickEventPoint *point); + bool targetContainsCentroid(); + QPointF targetCentroidPosition(); private: - QPointF m_pressScenePos; QPointF m_pressTargetPos; // We must also store the local targetPos, because we cannot deduce // the press target pos from the scene pos in case there was e.g a // flick in one of the ancestors during the drag. diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp index b08b00e5a7..d688058c4e 100644 --- a/src/quick/handlers/qquickmultipointhandler.cpp +++ b/src/quick/handlers/qquickmultipointhandler.cpp @@ -59,10 +59,10 @@ QT_BEGIN_NAMESPACE for any type of handler which requires and acts upon a specific number of multiple touchpoints. */ -QQuickMultiPointHandler::QQuickMultiPointHandler(QObject *parent, int minimumPointCount) +QQuickMultiPointHandler::QQuickMultiPointHandler(QObject *parent, int minimumPointCount, int maximumPointCount) : QQuickPointerDeviceHandler(parent) , m_minimumPointCount(minimumPointCount) - , m_maximumPointCount(-1) + , m_maximumPointCount(maximumPointCount) { } @@ -117,9 +117,27 @@ void QQuickMultiPointHandler::onActiveChanged() { if (active()) { m_centroid.m_sceneGrabPosition = m_centroid.m_scenePosition; + } else { + // Don't call m_centroid.reset() here, because in a QML onActiveChanged + // callback, we'd like to see what the position _was_, what the velocity _was_, etc. + // (having them undefined is not useful) + // But pressedButtons and pressedModifiers are meant to be more real-time than those + // (which seems a bit inconsistent, from one side). + m_centroid.m_pressedButtons = Qt::NoButton; + m_centroid.m_pressedModifiers = Qt::NoModifier; } } +void QQuickMultiPointHandler::onGrabChanged(QQuickPointerHandler *, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *) +{ + // If another handler or item takes over this set of points, assume it has + // decided that it's the better fit for them. Don't immediately re-grab + // at the next opportunity. This should help to avoid grab cycles + // (e.g. between DragHandler and PinchHandler). + if (stateChange == QQuickEventPoint::UngrabExclusive || stateChange == QQuickEventPoint::CancelGrabExclusive) + m_currentPoints.clear(); +} + QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointerEvent *event) { QVector<QQuickEventPoint *> ret; @@ -279,7 +297,7 @@ bool QQuickMultiPointHandler::grabPoints(QVector<QQuickEventPoint *> points) { bool allowed = true; for (QQuickEventPoint* point : points) { - if (!canGrab(point)) { + if (point->exclusiveGrabber() != this && !canGrab(point)) { allowed = false; break; } @@ -291,4 +309,10 @@ bool QQuickMultiPointHandler::grabPoints(QVector<QQuickEventPoint *> points) return allowed; } +void QQuickMultiPointHandler::moveTarget(QPointF pos) +{ + target()->setPosition(pos); + m_centroid.m_position = target()->mapFromScene(m_centroid.m_scenePosition); +} + QT_END_NAMESPACE diff --git a/src/quick/handlers/qquickmultipointhandler_p.h b/src/quick/handlers/qquickmultipointhandler_p.h index d1cf67b2cb..80f6917d24 100644 --- a/src/quick/handlers/qquickmultipointhandler_p.h +++ b/src/quick/handlers/qquickmultipointhandler_p.h @@ -66,7 +66,7 @@ class Q_AUTOTEST_EXPORT QQuickMultiPointHandler : public QQuickPointerDeviceHand Q_PROPERTY(QQuickHandlerPoint centroid READ centroid NOTIFY centroidChanged) public: - explicit QQuickMultiPointHandler(QObject *parent = nullptr, int minimumPointCount = 2); + explicit QQuickMultiPointHandler(QObject *parent = nullptr, int minimumPointCount = 2, int maximumPointCount = -1); ~QQuickMultiPointHandler(); int minimumPointCount() const { return m_minimumPointCount; } @@ -94,6 +94,7 @@ protected: bool wantsPointerEvent(QQuickPointerEvent *event) override; void handlePointerEventImpl(QQuickPointerEvent *event) override; void onActiveChanged() override; + void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point) override; bool hasCurrentPoints(QQuickPointerEvent *event); QVector<QQuickEventPoint *> eligiblePoints(QQuickPointerEvent *event); qreal averageTouchPointDistance(const QPointF &ref); @@ -104,6 +105,7 @@ protected: static qreal averageAngleDelta(const QVector<PointData> &old, const QVector<PointData> &newAngles); void acceptPoints(const QVector<QQuickEventPoint *> &points); bool grabPoints(QVector<QQuickEventPoint *> points); + void moveTarget(QPointF pos); protected: QVector<QQuickHandlerPoint> m_currentPoints; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index f921e3962b..22425a96a6 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2511,6 +2511,12 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, int pointCount = event->pointCount(); QVector<QQuickItem *> targetItems; bool isTouchEvent = (event->asPointerTouchEvent() != nullptr); + if (isTouchEvent && event->isPressEvent()) { + // When a second point is pressed, we're starting over with delivery, so + // don't let prior conception of which one is acting as a mouse interfere + touchMouseId = -1; + touchMouseDevice = nullptr; + } for (int i = 0; i < pointCount; ++i) { auto point = event->point(i); point->setAccepted(false); // because otherwise touchEventForItem will ignore it @@ -2977,6 +2983,12 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent return overThreshold; } +bool QQuickWindowPrivate::dragOverThreshold(QVector2D delta) +{ + int threshold = qApp->styleHints()->startDragDistance(); + return qAbs(delta.x()) > threshold || qAbs(delta.y()) > threshold; +} + /*! \qmlproperty list<Object> Window::data \default diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 9a83e8523b..10c8477417 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -302,6 +302,7 @@ public: QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point)); } + static bool dragOverThreshold(QVector2D delta); // data property static void data_append(QQmlListProperty<QObject> *, QObject *); diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index 6aa2eaa3cb..11a67cea82 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -93,7 +93,7 @@ void tst_FlickableInterop::createView(QScopedPointer<QQuickView> &window, const window->show(); QVERIFY(QTest::qWaitForWindowActive(window.data())); - QVERIFY(window->rootObject() != 0); + QVERIFY(window->rootObject() != nullptr); } void tst_FlickableInterop::initTestCase() diff --git a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp index 0561a9e4f1..5ea5a42044 100644 --- a/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp +++ b/tests/auto/quick/pointerhandlers/multipointtoucharea_interop/tst_multipointtoucharea_interop.cpp @@ -105,12 +105,12 @@ void tst_MptaInterop::touchDrag() // Press one touchpoint: // DragHandler gets a passive grab // PinchHandler declines, because it wants 3 touchpoints - // MPTA doesn't get a chance, because DragHandler accepted the single EventPoint + // MPTA grabs because DragHandler doesn't accept the single EventPoint QPoint p1 = mpta->mapToScene(QPointF(20, 20)).toPoint(); touch.press(1, p1).commit(); QQuickTouchUtils::flush(window); auto pointerEvent = QQuickWindowPrivate::get(window)->pointerEventInstance(touchPointerDevice); - QCOMPARE(tp.at(0)->property("pressed").toBool(), false); + QCOMPARE(tp.at(0)->property("pressed").toBool(), true); QTRY_VERIFY(pointerEvent->point(0)->passiveGrabbers().contains(drag)); // Start moving @@ -161,7 +161,7 @@ void tst_MptaInterop::touchesThenPinch() QPoint p1 = mpta->mapToScene(QPointF(20, 20)).toPoint(); touch.press(1, p1).commit(); QQuickTouchUtils::flush(window); - QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), nullptr); + QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta); QTRY_COMPARE(pointerEvent->point(0)->passiveGrabbers().first(), drag); // Press a second touchpoint: MPTA grabs it @@ -170,31 +170,21 @@ void tst_MptaInterop::touchesThenPinch() QQuickTouchUtils::flush(window); QVERIFY(tp.at(0)->property("pressed").toBool()); QTRY_VERIFY(tp.at(1)->property("pressed").toBool()); - QCOMPARE(mptaPressedSpy.count(), 1); + QCOMPARE(mptaPressedSpy.count(), 2); - // ATM it's required that when PinchHandler sees the third touchpoint, - // the pre-existing points must have moved far enough to exceed the drag threshold. - // If MPTA is allowed to grab that third point, then PinchHandler won't steal. - // TODO should we change that? make sure that if PH has a passive grab, it always gets updated even though MPTA has the grab? - for (int i = 0; i < 2; ++i) { - p1 += QPoint(dragThreshold, dragThreshold); - p2 += QPoint(dragThreshold, dragThreshold); - touch.move(1, p1).move(2, p2).commit(); - } - - // Press a third touchpoint: PinchHandler grabs, MPTA loses its grabs + // Press a third touchpoint: MPTA grabs it too QPoint p3 = mpta->mapToScene(QPointF(110, 200)).toPoint(); touch.stationary(1).stationary(2).press(3, p3).commit(); QQuickTouchUtils::flush(window); - QCOMPARE(tp.at(0)->property("pressed").toBool(), false); - QCOMPARE(tp.at(1)->property("pressed").toBool(), false); - QCOMPARE(tp.at(2)->property("pressed").toBool(), false); - QCOMPARE(mptaPressedSpy.count(), 1); - QCOMPARE(mptaCanceledSpy.count(), 1); - QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), pinch); - QTRY_COMPARE(pointerEvent->point(1)->exclusiveGrabber(), pinch); - QTRY_COMPARE(pointerEvent->point(2)->exclusiveGrabber(), pinch); - QVERIFY(pinch->active()); + QCOMPARE(tp.at(0)->property("pressed").toBool(), true); + QCOMPARE(tp.at(1)->property("pressed").toBool(), true); + QCOMPARE(tp.at(2)->property("pressed").toBool(), true); + QCOMPARE(mptaPressedSpy.count(), 3); + QCOMPARE(mptaCanceledSpy.count(), 0); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta); + QVERIFY(!pinch->active()); // Start moving: PinchHandler steals the exclusive grab from MPTA as soon as dragThreshold is exceeded int pinchStoleGrab = 0; @@ -204,11 +194,12 @@ void tst_MptaInterop::touchesThenPinch() p3 += QPoint(-dragThreshold / 2, dragThreshold / 2); touch.move(1, p1).move(2, p2).move(3, p3).commit(); QQuickTouchUtils::flush(window); - QTRY_COMPARE(tp.at(0)->property("pressed").toBool(), false); - QCOMPARE(tp.at(1)->property("pressed").toBool(), false); - QCOMPARE(tp.at(2)->property("pressed").toBool(), false); - if (!pinchStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == pinch) + if (!pinchStoleGrab && pointerEvent->point(0)->exclusiveGrabber() == pinch) { pinchStoleGrab = i; + QCOMPARE(tp.at(0)->property("pressed").toBool(), false); + QCOMPARE(tp.at(1)->property("pressed").toBool(), false); + QCOMPARE(tp.at(2)->property("pressed").toBool(), false); + } } qCDebug(lcPointerTests) << "pinch started after" << pinchStoleGrab << "moves; ended with scale" << pinch->activeScale() << "rot" << pinch->rotation(); QTRY_VERIFY(pinch->rotation() > 4); @@ -217,28 +208,26 @@ void tst_MptaInterop::touchesThenPinch() // Press one more point (pinkie finger) QPoint p4 = mpta->mapToScene(QPointF(300, 200)).toPoint(); touch.move(1, p1).move(2, p2).move(3, p3).press(4, p4).commit(); - // PinchHandler gives up its grabs (only on non-stationary points at this time: see QQuickPointerHandler::handlePointerEvent()) - // because it has minimum touch points 3, maximum touch points 3, and now there are 4 points. - // MPTA grabs all points which are not already grabbed - QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta); - QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta); - QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta); + // MPTA grabs the newly pressed point + QTRY_COMPARE(pointerEvent->point(0)->exclusiveGrabber(), pinch); + QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), pinch); + QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), pinch); QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta); - // Move some more... MPTA keeps reacting + // Move some more... PinchHandler and MPTA both keep reacting for (int i = 0; i < 8; ++i) { p1 += QPoint(4, 4); p2 += QPoint(4, 4); p3 += QPoint(-4, 4); p4 += QPoint(-4, -4); touch.move(1, p1).move(2, p2).move(3, p3).move(4, p4).commit(); - QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), mpta); - QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), mpta); - QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), mpta); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), pinch); + QCOMPARE(pointerEvent->point(1)->exclusiveGrabber(), pinch); + QCOMPARE(pointerEvent->point(2)->exclusiveGrabber(), pinch); QCOMPARE(pointerEvent->point(3)->exclusiveGrabber(), mpta); QCOMPARE(tp.at(0)->property("pressed").toBool(), true); - QCOMPARE(tp.at(1)->property("pressed").toBool(), true); - QCOMPARE(tp.at(2)->property("pressed").toBool(), true); - QCOMPARE(tp.at(3)->property("pressed").toBool(), true); + QCOMPARE(tp.at(1)->property("pressed").toBool(), false); + QCOMPARE(tp.at(2)->property("pressed").toBool(), false); + QCOMPARE(tp.at(3)->property("pressed").toBool(), false); } // Release the pinkie: PinchHandler acquires passive grabs on the 3 remaining points diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml index e468280ea6..7b3601bea0 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml @@ -39,20 +39,21 @@ Item { Rectangle { id: ball - objectName: "Ball " + index + objectName: "Ball " + (index + 1) color: dragHandler.active ? "blue" : "lightsteelblue" width: 80; height: 80; x: 200 + index * 200; y: 200; radius: width / 2 onParentChanged: console.log(this + " parent " + parent) DragHandler { id: dragHandler - objectName: "DragHandler " + index + objectName: "DragHandler " + (index + 1) } Text { color: "white" anchors.centerIn: parent - text: dragHandler.point.position.x.toFixed(1) + "," + dragHandler.point.position.y.toFixed(1) + horizontalAlignment: Text.AlignHCenter + text: ball.objectName + "\n" + dragHandler.centroid.position.x.toFixed(1) + "," + dragHandler.centroid.position.y.toFixed(1) } } } diff --git a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp index 0271924c9b..f71145c2bc 100644 --- a/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickdraghandler/tst_qquickdraghandler.cpp @@ -119,11 +119,11 @@ void tst_DragHandler::defaultPropertyValues() QCOMPARE(dragHandler->acceptedButtons(), Qt::LeftButton); QCOMPARE(dragHandler->translation(), QVector2D()); - QCOMPARE(dragHandler->point().position(), QPointF()); - QCOMPARE(dragHandler->point().scenePosition(), QPointF()); - QCOMPARE(dragHandler->point().pressPosition(), QPointF()); - QCOMPARE(dragHandler->point().scenePressPosition(), QPointF()); - QCOMPARE(dragHandler->point().sceneGrabPosition(), QPointF()); + QCOMPARE(dragHandler->centroid().position(), QPointF()); + QCOMPARE(dragHandler->centroid().scenePosition(), QPointF()); + QCOMPARE(dragHandler->centroid().pressPosition(), QPointF()); + QCOMPARE(dragHandler->centroid().scenePressPosition(), QPointF()); + QCOMPARE(dragHandler->centroid().sceneGrabPosition(), QPointF()); } void tst_DragHandler::touchDrag() @@ -146,10 +146,10 @@ void tst_DragHandler::touchDrag() QTest::touchEvent(window, touchDevice).press(1, p1, window); QQuickTouchUtils::flush(window); QVERIFY(!dragHandler->active()); - QCOMPARE(dragHandler->point().position(), ballCenter); - QCOMPARE(dragHandler->point().pressPosition(), ballCenter); - QCOMPARE(dragHandler->point().scenePosition(), scenePressPos); - QCOMPARE(dragHandler->point().scenePressPosition(), scenePressPos); + QCOMPARE(dragHandler->centroid().position(), ballCenter); + QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter); + QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos); + QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos); p1 += QPoint(dragThreshold, 0); QTest::touchEvent(window, touchDevice).move(1, p1, window); QQuickTouchUtils::flush(window); @@ -161,22 +161,22 @@ void tst_DragHandler::touchDrag() QCOMPARE(translationChangedSpy.count(), 0); QCOMPARE(dragHandler->translation().x(), 0.0); QPointF sceneGrabPos = p1; - QCOMPARE(dragHandler->point().sceneGrabPosition(), sceneGrabPos); + QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos); p1 += QPoint(19, 0); QTest::touchEvent(window, touchDevice).move(1, p1, window); QQuickTouchUtils::flush(window); QTRY_VERIFY(dragHandler->active()); - QCOMPARE(dragHandler->point().position(), ballCenter); - QCOMPARE(dragHandler->point().pressPosition(), ballCenter); - QCOMPARE(dragHandler->point().scenePosition(), ball->mapToScene(ballCenter)); - QCOMPARE(dragHandler->point().scenePressPosition(), scenePressPos); - QCOMPARE(dragHandler->point().sceneGrabPosition(), sceneGrabPos); + QCOMPARE(dragHandler->centroid().position(), ballCenter); + QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter); + QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter)); + QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos); + QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos); QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0); QCOMPARE(dragHandler->translation().y(), 0.0); QTest::touchEvent(window, touchDevice).release(1, p1, window); QQuickTouchUtils::flush(window); QTRY_VERIFY(!dragHandler->active()); - QCOMPARE(dragHandler->point().pressedButtons(), Qt::NoButton); + QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton); QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1); QCOMPARE(translationChangedSpy.count(), 1); } @@ -200,10 +200,10 @@ void tst_DragHandler::mouseDrag() QPoint p1 = scenePressPos.toPoint(); QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); QVERIFY(!dragHandler->active()); - QCOMPARE(dragHandler->point().position(), ballCenter); - QCOMPARE(dragHandler->point().pressPosition(), ballCenter); - QCOMPARE(dragHandler->point().scenePosition(), scenePressPos); - QCOMPARE(dragHandler->point().scenePressPosition(), scenePressPos); + QCOMPARE(dragHandler->centroid().position(), ballCenter); + QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter); + QCOMPARE(dragHandler->centroid().scenePosition(), scenePressPos); + QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos); p1 += QPoint(dragThreshold, 0); QTest::mouseMove(window, p1); QVERIFY(!dragHandler->active()); @@ -213,20 +213,20 @@ void tst_DragHandler::mouseDrag() QCOMPARE(translationChangedSpy.count(), 0); QCOMPARE(dragHandler->translation().x(), 0.0); QPointF sceneGrabPos = p1; - QCOMPARE(dragHandler->point().sceneGrabPosition(), sceneGrabPos); + QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos); p1 += QPoint(19, 0); QTest::mouseMove(window, p1); QTRY_VERIFY(dragHandler->active()); - QCOMPARE(dragHandler->point().position(), ballCenter); - QCOMPARE(dragHandler->point().pressPosition(), ballCenter); - QCOMPARE(dragHandler->point().scenePosition(), ball->mapToScene(ballCenter)); - QCOMPARE(dragHandler->point().scenePressPosition(), scenePressPos); - QCOMPARE(dragHandler->point().sceneGrabPosition(), sceneGrabPos); + QCOMPARE(dragHandler->centroid().position(), ballCenter); + QCOMPARE(dragHandler->centroid().pressPosition(), ballCenter); + QCOMPARE(dragHandler->centroid().scenePosition(), ball->mapToScene(ballCenter)); + QCOMPARE(dragHandler->centroid().scenePressPosition(), scenePressPos); + QCOMPARE(dragHandler->centroid().sceneGrabPosition(), sceneGrabPos); QCOMPARE(dragHandler->translation().x(), dragThreshold + 20.0); QCOMPARE(dragHandler->translation().y(), 0.0); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); QTRY_VERIFY(!dragHandler->active()); - QCOMPARE(dragHandler->point().pressedButtons(), Qt::NoButton); + QCOMPARE(dragHandler->centroid().pressedButtons(), Qt::NoButton); QCOMPARE(ball->mapToScene(ballCenter).toPoint(), p1); QCOMPARE(translationChangedSpy.count(), 1); } @@ -243,12 +243,14 @@ void tst_DragHandler::touchDragMulti() QQuickDragHandler *dragHandler1 = ball1->findChild<QQuickDragHandler*>(); QVERIFY(dragHandler1); QSignalSpy translationChangedSpy1(dragHandler1, SIGNAL(translationChanged())); + QSignalSpy centroidChangedSpy1(dragHandler1, SIGNAL(centroidChanged())); QQuickItem *ball2 = window->rootObject()->childItems().at(1); QVERIFY(ball2); QQuickDragHandler *dragHandler2 = ball2->findChild<QQuickDragHandler*>(); QVERIFY(dragHandler2); QSignalSpy translationChangedSpy2(dragHandler2, SIGNAL(translationChanged())); + QSignalSpy centroidChangedSpy2(dragHandler1, SIGNAL(centroidChanged())); QPointF ball1Center = ball1->clipRect().center(); QPointF scenePressPos1 = ball1->mapToScene(ball1Center); @@ -261,20 +263,33 @@ void tst_DragHandler::touchDragMulti() touchSeq.press(1, p1, window).press(2, p2, window).commit(); QQuickTouchUtils::flush(window); QVERIFY(!dragHandler1->active()); - QCOMPARE(dragHandler1->point().position(), ball1Center); - QCOMPARE(dragHandler1->point().pressPosition(), ball1Center); - QCOMPARE(dragHandler1->point().scenePosition(), scenePressPos1); - QCOMPARE(dragHandler1->point().scenePressPosition(), scenePressPos1); + QCOMPARE(centroidChangedSpy1.count(), 1); + QCOMPARE(dragHandler1->centroid().position(), ball1Center); + QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center); + QCOMPARE(dragHandler1->centroid().scenePosition(), scenePressPos1); + QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1); QVERIFY(!dragHandler2->active()); - QCOMPARE(dragHandler2->point().position(), ball2Center); - QCOMPARE(dragHandler2->point().pressPosition(), ball2Center); - QCOMPARE(dragHandler2->point().scenePosition(), scenePressPos2); - QCOMPARE(dragHandler2->point().scenePressPosition(), scenePressPos2); + QCOMPARE(centroidChangedSpy2.count(), 1); + QCOMPARE(dragHandler2->centroid().position(), ball2Center); + QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center); + QCOMPARE(dragHandler2->centroid().scenePosition(), scenePressPos2); + QCOMPARE(dragHandler2->centroid().scenePressPosition(), scenePressPos2); p1 += QPoint(dragThreshold, 0); p2 += QPoint(0, dragThreshold); touchSeq.move(1, p1, window).move(2, p2, window).commit(); QQuickTouchUtils::flush(window); QVERIFY(!dragHandler1->active()); + QCOMPARE(centroidChangedSpy1.count(), 2); + QCOMPARE(dragHandler1->centroid().position(), ball1Center + QPointF(dragThreshold, 0)); + QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center); + QCOMPARE(dragHandler1->centroid().scenePosition().toPoint(), p1); + QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1); + QVERIFY(!dragHandler2->active()); + QCOMPARE(centroidChangedSpy2.count(), 2); + QCOMPARE(dragHandler2->centroid().position(), ball2Center + QPointF(0, dragThreshold)); + QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center); + QCOMPARE(dragHandler2->centroid().scenePosition().toPoint(), p2); + QCOMPARE(dragHandler2->centroid().scenePressPosition(), scenePressPos2); p1 += QPoint(1, 0); p2 += QPoint(0, 1); touchSeq.move(1, p1, window).move(2, p2, window).commit(); @@ -285,37 +300,37 @@ void tst_DragHandler::touchDragMulti() QCOMPARE(dragHandler1->translation().x(), 0.0); QPointF sceneGrabPos1 = p1; QPointF sceneGrabPos2 = p2; - QCOMPARE(dragHandler1->point().sceneGrabPosition(), sceneGrabPos1); - QCOMPARE(dragHandler2->point().sceneGrabPosition(), sceneGrabPos2); + QCOMPARE(dragHandler1->centroid().sceneGrabPosition(), sceneGrabPos1); + QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2); p1 += QPoint(19, 0); p2 += QPoint(0, 19); QVERIFY(dragHandler2->active()); QCOMPARE(translationChangedSpy2.count(), 0); QCOMPARE(dragHandler2->translation().x(), 0.0); - QCOMPARE(dragHandler2->point().sceneGrabPosition(), sceneGrabPos2); + QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2); touchSeq.move(1, p1, window).move(2, p2, window).commit(); QQuickTouchUtils::flush(window); QVERIFY(dragHandler1->active()); QVERIFY(dragHandler2->active()); - QCOMPARE(dragHandler1->point().position(), ball1Center); - QCOMPARE(dragHandler1->point().pressPosition(), ball1Center); - QCOMPARE(dragHandler1->point().scenePosition(), ball1->mapToScene(ball1Center)); - QCOMPARE(dragHandler1->point().scenePressPosition(), scenePressPos1); - QCOMPARE(dragHandler1->point().sceneGrabPosition(), sceneGrabPos1); + QCOMPARE(dragHandler1->centroid().position(), ball1Center); + QCOMPARE(dragHandler1->centroid().pressPosition(), ball1Center); + QCOMPARE(dragHandler1->centroid().scenePosition(), ball1->mapToScene(ball1Center)); + QCOMPARE(dragHandler1->centroid().scenePressPosition(), scenePressPos1); + QCOMPARE(dragHandler1->centroid().sceneGrabPosition(), sceneGrabPos1); QCOMPARE(dragHandler1->translation().x(), dragThreshold + 20.0); QCOMPARE(dragHandler1->translation().y(), 0.0); - QCOMPARE(dragHandler2->point().position(), ball2Center); - QCOMPARE(dragHandler2->point().pressPosition(), ball2Center); - QCOMPARE(dragHandler2->point().scenePosition(), ball2->mapToScene(ball2Center)); - QCOMPARE(dragHandler2->point().scenePressPosition(), scenePressPos2); - QCOMPARE(dragHandler2->point().sceneGrabPosition(), sceneGrabPos2); + QCOMPARE(dragHandler2->centroid().position(), ball2Center); + QCOMPARE(dragHandler2->centroid().pressPosition(), ball2Center); + QCOMPARE(dragHandler2->centroid().scenePosition(), ball2->mapToScene(ball2Center)); + QCOMPARE(dragHandler2->centroid().scenePressPosition(), scenePressPos2); + QCOMPARE(dragHandler2->centroid().sceneGrabPosition(), sceneGrabPos2); QCOMPARE(dragHandler2->translation().x(), 0.0); QCOMPARE(dragHandler2->translation().y(), dragThreshold + 20.0); touchSeq.release(1, p1, window).stationary(2).commit(); QQuickTouchUtils::flush(window); QTRY_VERIFY(!dragHandler1->active()); QVERIFY(dragHandler2->active()); - QCOMPARE(dragHandler1->point().pressedButtons(), Qt::NoButton); + QCOMPARE(dragHandler1->centroid().pressedButtons(), Qt::NoButton); QCOMPARE(ball1->mapToScene(ball1Center).toPoint(), p1); QCOMPARE(translationChangedSpy1.count(), 1); touchSeq.release(2, p2, window).commit(); @@ -454,7 +469,12 @@ void tst_DragHandler::touchPassiveGrabbers() QQuickDragHandler *dragHandler = nullptr; for (QQuickPointerHandler *handler: expectedPassiveGrabbers) { - QCOMPARE(static_cast<QQuickSinglePointHandler *>(handler)->point().scenePressPosition(), p1); + QPointF scenePressPos; + if (QQuickMultiPointHandler *mph = qmlobject_cast<QQuickMultiPointHandler *>(handler)) + scenePressPos = mph->centroid().scenePressPosition(); + else + scenePressPos = static_cast<QQuickSinglePointHandler *>(handler)->point().scenePressPosition(); + QCOMPARE(scenePressPos, p1); QQuickDragHandler *dh = qmlobject_cast<QQuickDragHandler *>(handler); if (dh) dragHandler = dh; diff --git a/tests/manual/pointer/content/FakeFlickable.qml b/tests/manual/pointer/content/FakeFlickable.qml index 5a20a6825a..ffb5c4e914 100644 --- a/tests/manual/pointer/content/FakeFlickable.qml +++ b/tests/manual/pointer/content/FakeFlickable.qml @@ -67,7 +67,7 @@ Item { DragHandler { id: dragHandler - onActiveChanged: if (!active) anim.restart(point.velocity) + onActiveChanged: if (!active) anim.restart(centroid.velocity) } MomentumAnimation { id: anim diff --git a/tests/manual/pointer/flingAnimation.qml b/tests/manual/pointer/flingAnimation.qml index b17429f4e4..2bc6de7065 100644 --- a/tests/manual/pointer/flingAnimation.qml +++ b/tests/manual/pointer/flingAnimation.qml @@ -90,7 +90,7 @@ Rectangle { objectName: "dragHandler" + index onActiveChanged: { if (!active) - anim.restart(point.velocity) + anim.restart(centroid.velocity) } } Rectangle { @@ -103,12 +103,12 @@ Rectangle { Rectangle { visible: width > 0 - width: dragHandler.point.velocity.length() * 100 + width: dragHandler.centroid.velocity.length() * 100 height: 2 x: ball.width / 2 y: ball.height / 2 z: -1 - rotation: Math.atan2(dragHandler.point.velocity.y, dragHandler.point.velocity.x) * 180 / Math.PI + rotation: Math.atan2(dragHandler.centroid.velocity.y, dragHandler.centroid.velocity.x) * 180 / Math.PI transformOrigin: Item.BottomLeft antialiasing: true diff --git a/tests/manual/pointer/map.qml b/tests/manual/pointer/map.qml index ae7ec042d3..3ed732b523 100644 --- a/tests/manual/pointer/map.qml +++ b/tests/manual/pointer/map.qml @@ -39,6 +39,7 @@ Item { y: (parent.height - height) / 2 width: image.width height: image.height + transform: Rotation { id: tilt; origin.x: width / 2; origin.y: height / 2; axis { x: 1; y: 0; z: 0 } } Image { id: image @@ -57,16 +58,29 @@ Item { PinchHandler { id: pinch + objectName: "two-point pinch" target: map minimumScale: 0.1 maximumScale: 10 onActiveChanged: if (!active) reRenderIfNecessary() + grabPermissions: PinchHandler.TakeOverForbidden // don't allow takeover if pinch has started } DragHandler { + objectName: "single-point drag" target: map } + DragHandler { + id: tiltHandler + objectName: "two-point tilt" + minimumPointCount: 2 + maximumPointCount: 2 + xAxis.enabled: false + target: null + onTranslationChanged: tilt.angle = translation.y / -2 + } + function reRenderIfNecessary() { var newSourceWidth = image.sourceSize.width * pinch.scale var ratio = newSourceWidth / image.sourceSize.width diff --git a/tests/manual/pointer/singlePointHandlerProperties.qml b/tests/manual/pointer/singlePointHandlerProperties.qml index 40a4f49e5e..6ee88f9f9d 100644 --- a/tests/manual/pointer/singlePointHandlerProperties.qml +++ b/tests/manual/pointer/singlePointHandlerProperties.qml @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the manual tests of the Qt Toolkit. @@ -36,11 +36,11 @@ Rectangle { Item { id: crosshairs - x: dragHandler.point.position.x - width / 2 - y: dragHandler.point.position.y - height / 2 + x: dragHandler.centroid.position.x - width / 2 + y: dragHandler.centroid.position.y - height / 2 width: parent.width / 2; height: parent.height / 2 visible: dragHandler.active - rotation: dragHandler.point.rotation + rotation: dragHandler.centroid.rotation Rectangle { color: "goldenrod" @@ -56,7 +56,7 @@ Rectangle { } Rectangle { color: "goldenrod" - width: Math.max(2, 50 * dragHandler.point.pressure) + width: Math.max(2, 50 * dragHandler.centroid.pressure) height: width radius: width / 2 anchors.centerIn: parent @@ -69,9 +69,9 @@ Rectangle { implicitHeight: label.implicitHeight Text { id: label - text: 'id: ' + dragHandler.point.id.toString(16) + " uid: " + dragHandler.point.uniqueId.numericId + - '\npos: (' + dragHandler.point.position.x.toFixed(2) + ', ' + dragHandler.point.position.y.toFixed(2) + ')' + - '\nmodifiers: ' + dragHandler.point.modifiers.toString(16) + text: 'id: ' + dragHandler.centroid.id.toString(16) + " uid: " + dragHandler.centroid.uniqueId.numericId + + '\npos: (' + dragHandler.centroid.position.x.toFixed(2) + ', ' + dragHandler.centroid.position.y.toFixed(2) + ')' + + '\nmodifiers: ' + dragHandler.centroid.modifiers.toString(16) } } } @@ -79,8 +79,8 @@ Rectangle { color: "transparent" border.color: "white" antialiasing: true - width: dragHandler.point.ellipseDiameters.width - height: dragHandler.point.ellipseDiameters.height + width: dragHandler.centroid.ellipseDiameters.width + height: dragHandler.centroid.ellipseDiameters.height radius: Math.min(width / 2, height / 2) anchors.centerIn: parent } @@ -88,11 +88,11 @@ Rectangle { Rectangle { id: velocityVector visible: width > 0 - width: dragHandler.point.velocity.length() * 100 + width: dragHandler.centroid.velocity.length() * 100 height: 2 - x: dragHandler.point.position.x - y: dragHandler.point.position.y - rotation: Math.atan2(dragHandler.point.velocity.y, dragHandler.point.velocity.x) * 180 / Math.PI + x: dragHandler.centroid.position.x + y: dragHandler.centroid.position.y + rotation: Math.atan2(dragHandler.centroid.velocity.y, dragHandler.centroid.velocity.x) * 180 / Math.PI transformOrigin: Item.BottomLeft antialiasing: true @@ -138,15 +138,14 @@ Rectangle { DragHandler { id: dragHandler target: null - acceptedButtons: Qt.AllButtons - onGrabChanged: if (active) { // 'point' is an implicit parameter referencing to a QQuickEventPoint instance - console.log("grabbed " + point.pointId + " @ " + point.sceneGrabPos) - grabbingLocationIndicator.createObject(root, {"x": point.sceneGrabPosition.x, "y": point.sceneGrabPosition.y - 16}) +// acceptedButtons: Qt.AllButtons // TODO: only SinglePointHandler has this so far + onGrabChanged: if (active) { + console.log("grabbed " + centroid.pointId + " @ " + centroid.sceneGrabPos) + grabbingLocationIndicator.createObject(root, {"x": centroid.sceneGrabPosition.x, "y": centroid.sceneGrabPosition.y - 16}) } - onPointChanged: { - // Here, 'point' is referring to the property of the DragHandler - if (point.pressedButtons) - mouseButtonIndicator.createObject(root, {"x": point.pressPosition.x - 44, "y": point.pressPosition.y - 64, "buttons": point.pressedButtons}) + onCentroidChanged: { + if (centroid.pressedButtons) + mouseButtonIndicator.createObject(root, {"x": centroid.pressPosition.x - 44, "y": centroid.pressPosition.y - 64, "buttons": centroid.pressedButtons}) } } } |