aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/handlers/qquickdraghandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/handlers/qquickdraghandler.cpp')
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp181
1 files changed, 104 insertions, 77 deletions
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index e5e9b03f32..5e9d6d8230 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** 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.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquickdraghandler_p.h"
#include <private/qquickwindow_p.h>
@@ -88,7 +52,7 @@ Q_LOGGING_CATEGORY(lcDragHandler, "qt.quick.handler.drag")
At this time, drag-and-drop is not yet supported.
- \sa Drag, MouseArea
+ \sa Drag, MouseArea, {Qt Quick Examples - Pointer Handlers}
*/
QQuickDragHandler::QQuickDragHandler(QQuickItem *parent)
@@ -96,17 +60,13 @@ QQuickDragHandler::QQuickDragHandler(QQuickItem *parent)
{
}
-bool QQuickDragHandler::targetContainsCentroid()
-{
- Q_ASSERT(parentItem() && target());
- return target()->contains(targetCentroidPosition());
-}
-
QPointF QQuickDragHandler::targetCentroidPosition()
{
QPointF pos = centroid().position();
- if (target() != parentItem())
- pos = parentItem()->mapToItem(target(), pos);
+ if (auto par = parentItem()) {
+ if (target() != par)
+ pos = par->mapToItem(target(), pos);
+ }
return pos;
}
@@ -117,7 +77,7 @@ void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDe
// In case the grab got handed over from another grabber, we might not get the Press.
auto isDescendant = [](QQuickItem *parent, QQuickItem *target) {
- return (target != parent) && !target->isAncestorOf(parent);
+ return parent && (target != parent) && !target->isAncestorOf(parent);
};
if (m_snapMode == SnapAlways
|| (m_snapMode == SnapIfPressedOutsideTarget && !m_pressedInsideTarget)
@@ -131,17 +91,17 @@ void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDe
}
/*!
- \qmlproperty enumeration QtQuick.DragHandler::snapMode
+ \qmlproperty enumeration QtQuick::DragHandler::snapMode
This property holds the snap mode.
- The snap mode configures snapping of the \l target item's center to the event point.
+ The snap mode configures snapping of the \l target item's center to the \l eventPoint.
Possible values:
\value DragHandler.SnapNever Never snap
- \value DragHandler.SnapAuto The \l target snaps if the event point was pressed outside of the \l target
- item \e and the \l target is a descendant of \l parentItem (default)
- \value DragHandler.SnapWhenPressedOutsideTarget The \l target snaps if the event point was pressed outside of the \l target
+ \value DragHandler.SnapAuto The \l target snaps if the \l eventPoint was pressed outside of the \l target
+ item \e and the \l target is a descendant of \l {PointerHandler::}{parent} item (default)
+ \value DragHandler.SnapWhenPressedOutsideTarget The \l target snaps if the \l eventPoint was pressed outside of the \l target
\value DragHandler.SnapAlways Always snap
*/
QQuickDragHandler::SnapMode QQuickDragHandler::snapMode() const
@@ -160,9 +120,12 @@ void QQuickDragHandler::setSnapMode(QQuickDragHandler::SnapMode mode)
void QQuickDragHandler::onActiveChanged()
{
QQuickMultiPointHandler::onActiveChanged();
- if (active()) {
+ const bool curActive = active();
+ m_xAxis.onActiveChanged(curActive, 0);
+ m_yAxis.onActiveChanged(curActive, 0);
+ if (curActive) {
if (auto parent = parentItem()) {
- if (QQuickWindowPrivate::isTouchEvent(currentEvent()))
+ if (QQuickDeliveryAgentPrivate::isTouchEvent(currentEvent()))
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
@@ -179,8 +142,30 @@ void QQuickDragHandler::onActiveChanged()
}
}
+bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event)
+{
+ if (!QQuickMultiPointHandler::wantsPointerEvent(event))
+ /* Do handle other events than we would normally care about
+ while we are still doing a drag; otherwise we would suddenly
+ become inactive when a wheel event arrives during dragging.
+ This extra condition needs to be kept in sync with
+ handlePointerEventImpl */
+ if (!active())
+ return false;
+
+#if QT_CONFIG(gestures)
+ if (event->type() == QEvent::NativeGesture)
+ return false;
+#endif
+
+ return true;
+}
+
void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
{
+ if (active() && !QQuickMultiPointHandler::wantsPointerEvent(event))
+ return; // see QQuickDragHandler::wantsPointerEvent; we don't want to handle those events
+
QQuickMultiPointHandler::handlePointerEventImpl(event);
event->setAccepted(true);
@@ -192,18 +177,20 @@ 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,
// and in approximately the same direction
qreal minAngle = 361;
qreal maxAngle = -361;
- bool allOverThreshold = !event->isEndEvent();
+ bool allOverThreshold = QQuickDeliveryAgentPrivate::isTouchEvent(event) ?
+ static_cast<QTouchEvent *>(event)->touchPointStates() != QEventPoint::Released :
+ !event->isEndEvent();
QVector<QEventPoint> chosenPoints;
if (event->isBeginEvent())
- m_pressedInsideTarget = target() && currentPoints().count() > 0;
+ m_pressedInsideTarget = target() && currentPoints().size() > 0;
for (const QQuickHandlerPoint &p : currentPoints()) {
if (!allOverThreshold)
@@ -251,7 +238,7 @@ void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
// (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(QQuickWindowPrivate::isMouseEvent(event)); // stop propagation iff it's a mouse event
+ point->setAccepted(QQuickDeliveryAgentPrivate::isMouseEvent(event)); // stop propagation iff it's a mouse event
}
}
if (allOverThreshold) {
@@ -279,17 +266,6 @@ void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
}
}
-void QQuickDragHandler::enforceConstraints()
-{
- if (!target() || !target()->parentItem())
- return;
- QPointF pos = target()->position();
- QPointF copy(pos);
- enforceAxisConstraints(&pos);
- if (pos != copy)
- target()->setPosition(pos);
-}
-
void QQuickDragHandler::enforceAxisConstraints(QPointF *localPos)
{
if (m_xAxis.enabled())
@@ -298,12 +274,28 @@ 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 == persistentTranslation())
+ return;
+
+ m_xAxis.updateValue(m_xAxis.activeValue(), trans.x());
+ m_yAxis.updateValue(m_yAxis.activeValue(), trans.y());
+ emit translationChanged({});
+}
+
+void QQuickDragHandler::setActiveTranslation(const QVector2D &trans)
{
- if (trans == m_translation) // fuzzy compare?
+ if (trans == activeTranslation())
return;
- m_translation = trans;
- emit translationChanged();
+
+ const QVector2D delta = trans - activeTranslation();
+ m_xAxis.updateValue(trans.x(), m_xAxis.persistentValue() + delta.x(), delta.x());
+ m_yAxis.updateValue(trans.y(), m_yAxis.persistentValue() + delta.y(), delta.y());
+
+ qCDebug(lcDragHandler) << "translation: delta" << delta
+ << "active" << trans << "accumulated" << persistentTranslation();
+ emit translationChanged(delta);
}
/*!
@@ -311,6 +303,7 @@ void QQuickDragHandler::setTranslation(const QVector2D &trans)
\qmlproperty real QtQuick::DragHandler::xAxis.minimum
\qmlproperty real QtQuick::DragHandler::xAxis.maximum
\qmlproperty bool QtQuick::DragHandler::xAxis.enabled
+ \qmlproperty real QtQuick::DragHandler::xAxis.activeValue
\c xAxis controls the constraints for horizontal dragging.
@@ -319,13 +312,19 @@ void QQuickDragHandler::setTranslation(const QVector2D &trans)
\c maximum is the maximum acceptable value of \l {Item::x}{x} to be
applied to the \l {PointerHandler::target} {target}.
If \c enabled is true, horizontal dragging is allowed.
- */
+ \c activeValue is the same as \l {QtQuick::DragHandler::activeTranslation}{activeTranslation.x}.
+
+ The \c activeValueChanged signal is emitted when \c activeValue changes, to
+ provide the increment by which it changed.
+ This is intended for incrementally adjusting one property via multiple handlers.
+*/
/*!
\qmlpropertygroup QtQuick::DragHandler::yAxis
\qmlproperty real QtQuick::DragHandler::yAxis.minimum
\qmlproperty real QtQuick::DragHandler::yAxis.maximum
\qmlproperty bool QtQuick::DragHandler::yAxis.enabled
+ \qmlproperty real QtQuick::DragHandler::yAxis.activeValue
\c yAxis controls the constraints for vertical dragging.
@@ -334,13 +333,41 @@ void QQuickDragHandler::setTranslation(const QVector2D &trans)
\c maximum is the maximum acceptable value of \l {Item::y}{y} to be
applied to the \l {PointerHandler::target} {target}.
If \c enabled is true, vertical dragging is allowed.
- */
+ \c activeValue is the same as \l {QtQuick::DragHandler::activeTranslation}{activeTranslation.y}.
+
+ The \c activeValueChanged signal is emitted when \c activeValue changes, to
+ provide the increment by which it changed.
+ This is intended for incrementally adjusting one property via multiple handlers:
+
+ \snippet pointerHandlers/rotateViaWheelOrDrag.qml 0
+*/
/*!
\readonly
\qmlproperty QVector2D QtQuick::DragHandler::translation
+ \deprecated [6.2] Use activeTranslation
+*/
- The translation since the gesture began.
+/*!
+ \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 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
+
+#include "moc_qquickdraghandler_p.cpp"