diff options
Diffstat (limited to 'src/quick/handlers/qquickdraghandler.cpp')
-rw-r--r-- | src/quick/handlers/qquickdraghandler.cpp | 181 |
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" |