1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2019 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtQuick module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 #ifndef QQUICKFLICKABLE_P_P_H 41 #define QQUICKFLICKABLE_P_P_H 42 43 // 44 // W A R N I N G 45 // ------------- 46 // 47 // This file is not part of the Qt API. It exists purely as an 48 // implementation detail. This header file may change from version to 49 // version without notice, or even be removed. 50 // 51 // We mean it. 52 // 53 54 #include "qquickflickable_p.h" 55 #include "qquickitem_p.h" 56 #include "qquickitemchangelistener_p.h" 57 58 #include <QtQml/qqml.h> 59 #include <QtCore/qdatetime.h> 60 #include "qplatformdefs.h" 61 62 #include <private/qquicktimeline_p_p.h> 63 #include <private/qquickanimation_p_p.h> 64 #include <private/qquicktransitionmanager_p_p.h> 65 #include <private/qpodvector_p.h> 66 67 QT_BEGIN_NAMESPACE 68 69 // Really slow flicks can be annoying. 70 const qreal MinimumFlickVelocity = 75.0; 71 72 class QQuickFlickableVisibleArea; 73 class QQuickTransition; 74 class QQuickFlickableReboundTransition; 75 76 class Q_QUICK_PRIVATE_EXPORT QQuickFlickablePrivate : public QQuickItemPrivate, public QQuickItemChangeListener 77 { Q_DECLARE_PUBLIC(QQuickFlickable)78 Q_DECLARE_PUBLIC(QQuickFlickable) 79 80 public: 81 static inline QQuickFlickablePrivate *get(QQuickFlickable *o) { return o->d_func(); } 82 83 QQuickFlickablePrivate(); 84 void init(); 85 86 struct Velocity : public QQuickTimeLineValue 87 { VelocityVelocity88 Velocity(QQuickFlickablePrivate *p) 89 : parent(p) {} setValueVelocity90 void setValue(qreal v) override { 91 if (v != value()) { 92 QQuickTimeLineValue::setValue(v); 93 parent->updateVelocity(); 94 } 95 } 96 QQuickFlickablePrivate *parent; 97 }; 98 99 struct AxisData { AxisDataAxisData100 AxisData(QQuickFlickablePrivate *fp, void (QQuickFlickablePrivate::*func)(qreal)) 101 : move(fp, func) 102 , transitionToBounds(nullptr) 103 , viewSize(-1), lastPos(0), previousDragDelta(0), velocity(0), startMargin(0), endMargin(0) 104 , origin(0), overshoot(0) 105 , transitionTo(0) 106 , continuousFlickVelocity(0), velocityTime(), vTime(0) 107 , smoothVelocity(fp), atEnd(false), atBeginning(true) 108 , transitionToSet(false) 109 , fixingUp(false), inOvershoot(false), inRebound(false), moving(false), flicking(false) 110 , dragging(false), extentsChanged(false) 111 , explicitValue(false), minExtentDirty(true), maxExtentDirty(true) 112 , unused(0) 113 {} 114 115 ~AxisData(); 116 resetAxisData117 void reset() { 118 velocityBuffer.clear(); 119 dragStartOffset = 0; 120 fixingUp = false; 121 inOvershoot = false; 122 } 123 markExtentsDirtyAxisData124 void markExtentsDirty() { 125 minExtentDirty = true; 126 maxExtentDirty = true; 127 extentsChanged = true; 128 } 129 resetTransitionToAxisData130 void resetTransitionTo() { 131 transitionTo = 0; 132 transitionToSet = false; 133 } 134 135 void addVelocitySample(qreal v, qreal maxVelocity); 136 void updateVelocity(); 137 138 QQuickTimeLineValueProxy<QQuickFlickablePrivate> move; 139 QQuickFlickableReboundTransition *transitionToBounds; 140 qreal viewSize; 141 qreal pressPos; 142 qreal lastPos; 143 qreal dragStartOffset; 144 qreal dragMinBound; 145 qreal dragMaxBound; 146 qreal previousDragDelta; 147 qreal velocity; 148 qreal flickTarget; 149 qreal startMargin; 150 qreal endMargin; 151 qreal origin; 152 qreal overshoot; 153 qreal transitionTo; 154 qreal continuousFlickVelocity; 155 QElapsedTimer velocityTime; 156 int vTime; 157 QQuickFlickablePrivate::Velocity smoothVelocity; 158 QPODVector<qreal,10> velocityBuffer; 159 bool atEnd : 1; 160 bool atBeginning : 1; 161 bool transitionToSet : 1; 162 bool fixingUp : 1; 163 bool inOvershoot : 1; 164 bool inRebound : 1; 165 bool moving : 1; 166 bool flicking : 1; 167 bool dragging : 1; 168 bool extentsChanged : 1; 169 bool explicitValue : 1; 170 mutable bool minExtentDirty : 1; 171 mutable bool maxExtentDirty : 1; 172 uint unused : 19; 173 }; 174 175 bool flickX(qreal velocity); 176 bool flickY(qreal velocity); 177 virtual bool flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, 178 QQuickTimeLineCallback::Callback fixupCallback, qreal velocity); 179 void flickingStarted(bool flickingH, bool flickingV); 180 181 void fixupX(); 182 void fixupY(); 183 virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent); 184 void adjustContentPos(AxisData &data, qreal toPos); 185 void resetTimeline(AxisData &data); 186 void clearTimeline(); 187 188 void updateBeginningEnd(); 189 190 bool isInnermostPressDelay(QQuickItem *item) const; 191 void captureDelayedPress(QQuickItem *item, QMouseEvent *event); 192 void clearDelayedPress(); 193 void replayDelayedPress(); 194 195 void setViewportX(qreal x); 196 void setViewportY(qreal y); 197 198 qreal overShootDistance(qreal size) const; 199 200 void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override; 201 202 void draggingStarting(); 203 void draggingEnding(); 204 205 bool isViewMoving() const; 206 207 void cancelInteraction(); 208 209 void addPointerHandler(QQuickPointerHandler *h) override; 210 211 // TODO Qt 6: QPointerEvent wantsPointerEvent(const QEvent *)212 virtual bool wantsPointerEvent(const QEvent *) { return true; } 213 214 public: 215 QQuickItem *contentItem; 216 217 AxisData hData; 218 AxisData vData; 219 220 QQuickTimeLine timeline; 221 bool hMoved : 1; 222 bool vMoved : 1; 223 bool stealMouse : 1; 224 bool pressed : 1; 225 bool scrollingPhase : 1; 226 bool interactive : 1; 227 bool calcVelocity : 1; 228 bool pixelAligned : 1; 229 bool syncDrag : 1; 230 QElapsedTimer timer; 231 qint64 lastPosTime; 232 qint64 lastPressTime; 233 QPointF lastPos; 234 QPointF pressPos; 235 QVector2D accumulatedWheelPixelDelta; 236 qreal deceleration; 237 qreal maxVelocity; 238 qreal reportedVelocitySmoothing; 239 QMouseEvent *delayedPressEvent; 240 QBasicTimer delayedPressTimer; 241 int pressDelay; 242 int fixupDuration; 243 qreal flickBoost; 244 245 enum FixupMode { Normal, Immediate, ExtentChanged }; 246 FixupMode fixupMode; 247 248 static void fixupY_callback(void *); 249 static void fixupX_callback(void *); 250 251 void updateVelocity(); 252 int vTime; 253 QQuickTimeLine velocityTimeline; 254 QQuickFlickableVisibleArea *visibleArea; 255 QQuickFlickable::FlickableDirection flickableDirection; 256 QQuickFlickable::BoundsBehavior boundsBehavior; 257 QQuickFlickable::BoundsMovement boundsMovement; 258 QQuickTransition *rebound; 259 260 void viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, 261 QQuickTimeLineCallback::Callback fixupCallback); 262 263 void handleMousePressEvent(QMouseEvent *); 264 void handleMouseMoveEvent(QMouseEvent *); 265 void handleMouseReleaseEvent(QMouseEvent *); 266 267 void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn); 268 void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos, 269 const QVector2D &deltas, bool overThreshold, bool momentum, 270 bool velocitySensitiveOverBounds, const QVector2D &velocity); 271 272 qint64 computeCurrentTime(QInputEvent *event) const; 273 qreal devicePixelRatio() const; 274 275 // flickableData property 276 static void data_append(QQmlListProperty<QObject> *, QObject *); 277 static int data_count(QQmlListProperty<QObject> *); 278 static QObject *data_at(QQmlListProperty<QObject> *, int); 279 static void data_clear(QQmlListProperty<QObject> *); 280 }; 281 282 class QQuickFlickableVisibleArea : public QObject 283 { 284 Q_OBJECT 285 286 Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged) 287 Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged) 288 Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged) 289 Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged) 290 QML_ANONYMOUS 291 292 public: 293 QQuickFlickableVisibleArea(QQuickFlickable *parent=nullptr); 294 295 qreal xPosition() const; 296 qreal widthRatio() const; 297 qreal yPosition() const; 298 qreal heightRatio() const; 299 300 void updateVisible(); 301 302 Q_SIGNALS: 303 void xPositionChanged(qreal xPosition); 304 void yPositionChanged(qreal yPosition); 305 void widthRatioChanged(qreal widthRatio); 306 void heightRatioChanged(qreal heightRatio); 307 308 private: 309 QQuickFlickable *flickable; 310 qreal m_xPosition; 311 qreal m_widthRatio; 312 qreal m_yPosition; 313 qreal m_heightRatio; 314 }; 315 316 QT_END_NAMESPACE 317 318 QML_DECLARE_TYPE(QQuickFlickableVisibleArea) 319 320 #endif // QQUICKFLICKABLE_P_P_H 321