aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2021-06-02 17:31:25 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2021-06-04 15:23:16 +0200
commit60d11e1f69470d588666b76092cd40ae5644a855 (patch)
treeadb6040a00687438df7d39f58dafd1bddb305f02 /src
parent63b1f379b710c510f00311e03641aa65e72aaf34 (diff)
Add DragHandler.activeTranslation and persistentTranslation
If you want to set target: null and then bind translation to some object's x and y properties directly (perhaps an Item, a Qt Quick 3D Model object, etc.), it's a lot less trouble to use a translation property that does not keep changing back to 0,0 every time a gesture begins. In hindsight, the translation property should have been the persistent one (for consistency with the fix for QTBUG-68941, in which we made PinchHandler.scale persistent and added activeScale: b4d31c9ff5f0c5821ea127c663532d9fc2cae43e). But for several years, the translation property has been restarting with each gesture; so now we add a persistentTranslation property. The new activeTranslation property has the same value as the translation property (which is deprecated). Also, the persistentTranslation property is settable, because in some UIs there may be multiple ways to move the same object, and there needs to be a way to sync them up. Also fixed a bug: when minimumPointCount == 2, QQuickMultiPointHandler::wantsPointerEvent() doesn't initialize d->currentPoints until two points are pressed. But often, one point is pressed, and in the next event, the second point is pressed while the first is held Stationary. So QQuickHandlerPoint::reset() needs to set pressPosition and scenePressPosition on both points at the same time, because it is called on each HandlerPoint in d->currentPoints at that time when both points are pressed. So if any point is pressed, act as if they all were freshly pressed. Without this fix, the centroid's scenePressPosition is wrong (based on the average of 0,0 and the second point), therefore a "jump" was occurring when persistentTranslation is used to directly drive a binding (like the tilt in map.qml). [ChangeLog][QtQuick][Event Handlers] DragHandler.activeTranslation now holds the amount of movement since the drag gesture began. DragHandler.persistentTranslation holds the accumulated sum of movement that has occurred during subsequent drag gestures, and can be set to arbitrary values between gestures. Task-number: QTBUG-94168 Change-Id: I1b2f8ea31d0f6ff55ccffe393bc9ba28c1a71d09 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp43
-rw-r--r--src/quick/handlers/qquickdraghandler_p.h13
-rw-r--r--src/quick/handlers/qquickhandlerpoint.cpp9
3 files changed, 51 insertions, 14 deletions
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index 809adfd043..233516c3a3 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -165,6 +165,7 @@ void QQuickDragHandler::onActiveChanged()
// mouse grab too, whenever dragging occurs in an enabled direction
parent->setKeepMouseGrab(true);
}
+ m_startTranslation = m_persistentTranslation;
} else {
m_pressTargetPos = QPointF();
m_pressedInsideTarget = false;
@@ -210,7 +211,7 @@ void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
accumulatedDragDelta.setX(0);
if (!m_yAxis.enabled())
accumulatedDragDelta.setY(0);
- setTranslation(accumulatedDragDelta);
+ setActiveTranslation(accumulatedDragDelta);
} else {
// Check that all points have been dragged past the drag threshold,
// to the extent that the constraints allow,
@@ -316,11 +317,24 @@ void QQuickDragHandler::enforceAxisConstraints(QPointF *localPos)
localPos->setY(qBound(m_yAxis.minimum(), localPos->y(), m_yAxis.maximum()));
}
-void QQuickDragHandler::setTranslation(const QVector2D &trans)
+void QQuickDragHandler::setPersistentTranslation(const QVector2D &trans)
{
- if (trans == m_translation) // fuzzy compare?
+ if (trans == m_persistentTranslation)
return;
- m_translation = trans;
+
+ m_persistentTranslation = trans;
+ emit translationChanged();
+}
+
+void QQuickDragHandler::setActiveTranslation(const QVector2D &trans)
+{
+ if (trans == m_activeTranslation)
+ return;
+
+ m_activeTranslation = trans;
+ m_persistentTranslation = m_startTranslation + trans;
+ qCDebug(lcDragHandler) << "translation: start" << m_startTranslation
+ << "active" << m_activeTranslation << "accumulated" << m_persistentTranslation;
emit translationChanged();
}
@@ -357,8 +371,27 @@ void QQuickDragHandler::setTranslation(const QVector2D &trans)
/*!
\readonly
\qmlproperty QVector2D QtQuick::DragHandler::translation
+ \deprecated Use activeTranslation
+*/
+
+/*!
+ \qmlproperty QVector2D QtQuick::DragHandler::persistentTranslation
+
+ The translation to be applied to the \l target if it is not \c null.
+ Otherwise, bindings can be used to do arbitrary things with this value.
+ While the drag gesture is being performed, \l activeTranslation is
+ continuously added to it; after the gesture ends, it stays the same.
+*/
+
+/*!
+ \readonly
+ \qmlproperty QVector2D QtQuick::DragHandler::activeTranslation
- The translation since the gesture began.
+ The translation while the drag gesture is being performed.
+ It is \c {0, 0} when the gesture begins, and increases as the event
+ point(s) are dragged downward and to the right. After the gesture ends, it
+ stays the same; and when the next drag gesture begins, it is reset to
+ \c {0, 0} again.
*/
QT_END_NAMESPACE
diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h
index a0dce10314..a42281819c 100644
--- a/src/quick/handlers/qquickdraghandler_p.h
+++ b/src/quick/handlers/qquickdraghandler_p.h
@@ -62,6 +62,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickDragHandler : public QQuickMultiPointHandler
Q_PROPERTY(QQuickDragAxis * xAxis READ xAxis CONSTANT)
Q_PROPERTY(QQuickDragAxis * yAxis READ yAxis CONSTANT)
Q_PROPERTY(QVector2D translation READ translation NOTIFY translationChanged)
+ Q_PROPERTY(QVector2D activeTranslation READ activeTranslation NOTIFY translationChanged REVISION(6, 2))
+ Q_PROPERTY(QVector2D persistentTranslation READ persistentTranslation WRITE setPersistentTranslation NOTIFY translationChanged REVISION(6, 2))
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged REVISION(2, 14))
QML_NAMED_ELEMENT(DragHandler)
QML_ADDED_IN_VERSION(2, 12)
@@ -82,8 +84,11 @@ public:
QQuickDragAxis *xAxis() { return &m_xAxis; }
QQuickDragAxis *yAxis() { return &m_yAxis; }
- QVector2D translation() const { return m_translation; }
- void setTranslation(const QVector2D &trans);
+ QVector2D translation() const { return m_activeTranslation; }
+ QVector2D activeTranslation() const { return m_activeTranslation; }
+ void setActiveTranslation(const QVector2D &trans);
+ QVector2D persistentTranslation() const { return m_persistentTranslation; }
+ void setPersistentTranslation(const QVector2D &trans);
QQuickDragHandler::SnapMode snapMode() const;
void setSnapMode(QQuickDragHandler::SnapMode mode);
@@ -107,7 +112,9 @@ private:
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.
- QVector2D m_translation;
+ QVector2D m_activeTranslation;
+ QVector2D m_persistentTranslation;
+ QVector2D m_startTranslation;
QQuickDragAxis m_xAxis;
QQuickDragAxis m_yAxis;
diff --git a/src/quick/handlers/qquickhandlerpoint.cpp b/src/quick/handlers/qquickhandlerpoint.cpp
index 54951b82b3..c3149983c0 100644
--- a/src/quick/handlers/qquickhandlerpoint.cpp
+++ b/src/quick/handlers/qquickhandlerpoint.cpp
@@ -100,17 +100,14 @@ void QQuickHandlerPoint::reset()
void QQuickHandlerPoint::reset(const QPointerEvent *event, const QEventPoint &point)
{
+ const bool isTouch = QQuickDeliveryAgentPrivate::isTouchEvent(event);
m_id = point.id();
m_device = event->pointingDevice();
- switch (point.state()) {
- case QEventPoint::Pressed:
+ const auto state = (isTouch ? static_cast<const QTouchEvent *>(event)->touchPointStates() : point.state());
+ if (state.testFlag(QEventPoint::Pressed)) {
m_pressPosition = point.position();
m_scenePressPosition = point.scenePosition();
- break;
- default:
- break;
}
- const bool isTouch = QQuickDeliveryAgentPrivate::isTouchEvent(event);
if (!isTouch)
m_pressedButtons = static_cast<const QSinglePointEvent *>(event)->buttons();
m_pressedModifiers = event->modifiers();