diff --git a/src/quicktemplates/qquickdrawer.cpp b/src/quicktemplates/qquickdrawer.cpp index f2395147a2..69c0edb2cd 100644 --- a/src/quicktemplates/qquickdrawer.cpp +++ b/src/quicktemplates/qquickdrawer.cpp @@ -16,6 +16,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcDrawer, "qt.quick.controls.drawer") + /*! \qmltype Drawer \inherits Popup @@ -462,8 +464,9 @@ bool QQuickDrawerPrivate::blockInput(QQuickItem *item, const QPointF &point) con bool QQuickDrawerPrivate::handlePress(QQuickItem *item, const QPointF &point, ulong timestamp) { + Q_Q(QQuickDrawer); offset = 0; - velocityCalculator.startMeasuring(point, timestamp); + velocityCalculator.startMeasuring(q->position(), timestamp); if (!QQuickPopupPrivate::handlePress(item, point, timestamp)) return interactive && popupItem == item; @@ -482,14 +485,17 @@ bool QQuickDrawerPrivate::handleMove(QQuickItem *item, const QPointF &point, ulo offset = 0; bool isGrabbed = popupItem->keepMouseGrab() || popupItem->keepTouchGrab(); - if (isGrabbed) + if (isGrabbed) { q->setPosition(positionAt(point) - offset); + velocityCalculator.updateMeasurement(q->position(), timestamp); + } return isGrabbed; } bool QQuickDrawerPrivate::handleRelease(QQuickItem *item, const QPointF &point, ulong timestamp) { + Q_Q(QQuickDrawer); auto cleanup = qScopeGuard([this] { popupItem->setKeepMouseGrab(false); popupItem->setKeepTouchGrab(false); @@ -503,30 +509,23 @@ bool QQuickDrawerPrivate::handleRelease(QQuickItem *item, const QPointF &point, return QQuickPopupPrivate::handleRelease(item, point, timestamp); } - velocityCalculator.stopMeasuring(point, timestamp); + velocityCalculator.stopMeasuring(q->position(), timestamp); Qt::Edge effEdge = effectiveEdge(); - qreal velocity = 0; - if (effEdge == Qt::LeftEdge || effEdge == Qt::RightEdge) - velocity = velocityCalculator.velocity().x(); - else - velocity = velocityCalculator.velocity().y(); - - // the velocity is calculated so that swipes from left to right - // and top to bottom have positive velocity, and swipes from right - // to left and bottom to top have negative velocity. - // - // - top/left edge: positive velocity opens, negative velocity closes - // - bottom/right edge: negative velocity opens, positive velocity closes - // - // => invert the velocity for bottom and right edges, for the threshold comparison below - if (effEdge == Qt::RightEdge || effEdge == Qt::BottomEdge) - velocity = -velocity; - - if (position > 0.7 || velocity > openCloseVelocityThreshold) { + + // Calculator returns "Position units per second"; + // Convert to "Pixels per second" + qreal velocity = velocityCalculator.velocity() * q->height(); + qCDebug(lcDrawer) << "Directional average velocity is" << velocityCalculator.velocity() * q->height() << "pixels/s"; + + if ((position > 0.7 && velocity >= 0) || velocity > openCloseVelocityThreshold) { + qCDebug(lcDrawer) << "Automatically entering"; transitionManager.transitionEnter(); - } else if (position < 0.3 || velocity < -openCloseVelocityThreshold) { + } else if ((position < 0.3 && velocity <= 0) || velocity < -openCloseVelocityThreshold) { + qCDebug(lcDrawer) << "Automatically exiting"; transitionManager.transitionExit(); } else { + qCDebug(lcDrawer) << "Comparing point" << point << "with pressPoint" << pressPoint; + // TODO: Simplify the following by comparing starting position and final position switch (effEdge) { case Qt::LeftEdge: if (point.x() - pressPoint.x() > 0) diff --git a/src/quicktemplates/qquickdrawer_p_p.h b/src/quicktemplates/qquickdrawer_p_p.h index 7eae26b0cb..d4806828f9 100644 --- a/src/quicktemplates/qquickdrawer_p_p.h +++ b/src/quicktemplates/qquickdrawer_p_p.h @@ -21,6 +21,75 @@ QT_BEGIN_NAMESPACE +class LinearvelocityCalculator +{ +public: + enum Direction { + Unknown, + Forward, + Reverse + }; + + void startMeasuring(qreal startPos, qint64 timestamp) + { + m_point1 = startPos; + m_point1Timestamp = timestamp; + } + + void updateMeasurement(qreal pos, qint64 timestamp) + { + const bool movedForward = pos > m_point2; + const bool movedBackward = pos < m_point2; + if ((m_direction == Forward && movedBackward) + || (m_direction == Reverse && movedForward)) + { + // Use new reference point + m_point1 = m_point2; + m_point1Timestamp = m_point2Timestamp; + } + m_point2 = pos; + m_point2Timestamp = timestamp; + + if (movedForward) + m_direction = Forward; + else if (movedBackward) + m_direction = Reverse; + } + + void stopMeasuring(qreal finalPos, qint64 timestamp) + { + if (m_point1Timestamp == 0) { + qWarning() << "LinearvelocityCalculator: a call to stopMeasuring() must be preceded by a call to startMeasuring()"; + return; + } + + m_point2 = finalPos; + m_point2Timestamp = timestamp; + } + + void reset() + { + *this = LinearvelocityCalculator(); + } + + qreal velocity() const + { + if (m_point2Timestamp == 0 || m_point1Timestamp == m_point2Timestamp) + return qQNaN(); + + const qreal secondsElapsed = (m_point2Timestamp - m_point1Timestamp) / 1000.0; + const qreal distance = m_point2 - m_point1; + return distance / secondsElapsed; + } + +private: + qreal m_point1 = qQNaN(); + qreal m_point2 = qQNaN(); + qint64 m_point1Timestamp = 0; + qint64 m_point2Timestamp = 0; + Direction m_direction = Unknown; +}; + class QQuickDrawerPrivate : public QQuickPopupPrivate { Q_DECLARE_PUBLIC(QQuickDrawer) @@ -62,7 +131,7 @@ public: qreal offset = 0; qreal position = 0; qreal dragMargin = 0; - QQuickVelocityCalculator velocityCalculator; + LinearvelocityCalculator velocityCalculator; bool delayedEnterTransition = false; }; -- 2.44.0.windows.1