1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QQUICKFLICKABLE_P_P_H
5#define QQUICKFLICKABLE_P_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include "qquickflickable_p.h"
19#include "qquickitem_p.h"
20#include "qquickitemchangelistener_p.h"
21
22#include <QtQml/qqml.h>
23#include <QtCore/qdatetime.h>
24#include "qplatformdefs.h"
25
26#include <private/qquicktimeline_p_p.h>
27#include <private/qquickanimation_p_p.h>
28#include <private/qquicktransitionmanager_p_p.h>
29#include <private/qpodvector_p.h>
30
31QT_BEGIN_NAMESPACE
32
33class QQuickFlickableVisibleArea;
34class QQuickTransition;
35class QQuickFlickableReboundTransition;
36
37class Q_QUICK_EXPORT QQuickFlickablePrivate : public QQuickItemPrivate,
38 public QSafeQuickItemChangeListener<QQuickFlickablePrivate>
39{
40 Q_DECLARE_PUBLIC(QQuickFlickable)
41
42public:
43 static inline QQuickFlickablePrivate *get(QQuickFlickable *o) { return o->d_func(); }
44
45 QQuickFlickablePrivate();
46 void init();
47
48 struct Velocity : public QQuickTimeLineValue
49 {
50 Velocity(QQuickFlickablePrivate *p)
51 : parent(p) {}
52 void setValue(qreal v) override {
53 if (v != value()) {
54 QQuickTimeLineValue::setValue(v);
55 parent->updateVelocity();
56 }
57 }
58 QQuickFlickablePrivate *parent;
59 };
60
61 enum MovementReason { Other, SetIndex, Mouse };
62
63 struct AxisData {
64 AxisData(QQuickFlickablePrivate *fp, void (QQuickFlickablePrivate::*func)(qreal))
65 : move(fp, func)
66 , smoothVelocity(fp), atEnd(false), atBeginning(true)
67 , transitionToSet(false)
68 , fixingUp(false), inOvershoot(false), inRebound(false), moving(false), flicking(false)
69 , flickingWhenDragBegan(false), dragging(false), extentsChanged(false)
70 , explicitValue(false), contentPositionChangedExternallyDuringDrag(false)
71 , minExtentDirty(true), maxExtentDirty(true)
72 {}
73
74 ~AxisData();
75
76 void reset() {
77 velocityBuffer.clear();
78 dragStartOffset = 0;
79 fixingUp = false;
80 inOvershoot = false;
81 contentPositionChangedExternallyDuringDrag = false;
82 }
83
84 void markExtentsDirty() {
85 minExtentDirty = true;
86 maxExtentDirty = true;
87 extentsChanged = true;
88 }
89
90 void resetTransitionTo() {
91 transitionTo = 0;
92 transitionToSet = false;
93 }
94
95 void addVelocitySample(qreal v, qreal maxVelocity);
96 void updateVelocity();
97
98 QQuickTimeLineValueProxy<QQuickFlickablePrivate> move;
99 QQuickFlickableReboundTransition *transitionToBounds = nullptr;
100 qreal viewSize = -1;
101 qreal pressPos = 0;
102 qreal lastPos = 0;
103 qreal dragStartOffset = 0;
104 qreal dragMinBound = 0;
105 qreal dragMaxBound = 0;
106 qreal previousDragDelta = 0;
107 qreal velocity = 0;
108 qreal flickTarget = 0;
109 qreal startMargin = 0;
110 qreal endMargin = 0;
111 qreal origin = 0;
112 qreal overshoot = 0;
113 qreal transitionTo = 0;
114 qreal continuousFlickVelocity = 0;
115 QElapsedTimer velocityTime;
116 int vTime = 0;
117 QQuickFlickablePrivate::Velocity smoothVelocity;
118 QPODVector<qreal,10> velocityBuffer;
119 // bitfield
120 uint atEnd : 1;
121 uint atBeginning : 1;
122 uint transitionToSet : 1;
123 uint fixingUp : 1;
124 uint inOvershoot : 1;
125 uint inRebound : 1;
126 uint moving : 1;
127 uint flicking : 1;
128 uint flickingWhenDragBegan : 1;
129 uint dragging : 1;
130 uint extentsChanged : 1;
131 uint explicitValue : 1;
132 uint contentPositionChangedExternallyDuringDrag : 1;
133 // mutable portion of bitfield
134 mutable uint minExtentDirty : 1;
135 mutable uint maxExtentDirty : 1;
136 // end bitfield
137 };
138
139 bool flickX(QEvent::Type eventType, qreal velocity);
140 bool flickY(QEvent::Type eventType, qreal velocity);
141 virtual bool flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
142 QQuickTimeLineCallback::Callback fixupCallback,
143 QEvent::Type eventType, qreal velocity);
144 void flickingStarted(bool flickingH, bool flickingV);
145
146 void fixupX();
147 void fixupY();
148 virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
149 void adjustContentPos(AxisData &data, qreal toPos);
150 void resetTimeline(AxisData &data);
151 void clearTimeline();
152
153 void updateBeginningEnd();
154
155 bool isInnermostPressDelay(QQuickItem *item) const;
156 void captureDelayedPress(QQuickItem *item, QPointerEvent *event);
157 void clearDelayedPress();
158 void replayDelayedPress();
159
160 void setViewportX(qreal x);
161 void setViewportY(qreal y);
162
163 qreal overShootDistance(qreal velocity) const;
164
165 void itemGeometryChanged(QQuickItem *, QQuickGeometryChange, const QRectF &) override;
166
167 void draggingStarting();
168 void draggingEnding();
169
170 bool isViewMoving() const;
171
172 void cancelInteraction();
173
174 void addPointerHandler(QQuickPointerHandler *h) override;
175
176 virtual bool wantsPointerEvent(const QPointerEvent *) { return true; }
177
178public:
179 QQuickItem *contentItem;
180
181 AxisData hData;
182 AxisData vData;
183
184 MovementReason moveReason = Other;
185
186 QQuickTimeLine timeline;
187 bool hMoved : 1;
188 bool vMoved : 1;
189 bool stealMouse : 1;
190 bool pressed : 1;
191 bool scrollingPhase : 1;
192 bool interactive : 1;
193 bool calcVelocity : 1;
194 bool pixelAligned : 1;
195 bool syncDrag : 1;
196 Qt::MouseButtons acceptedButtons = Qt::LeftButton;
197 QElapsedTimer timer;
198 qint64 lastPosTime;
199 qint64 lastPressTime;
200 QPointF lastPos;
201 QPointF pressPos;
202 QVector2D accumulatedWheelPixelDelta;
203 qreal deceleration;
204 qreal wheelDeceleration;
205 qreal maxVelocity;
206 QPointerEvent *delayedPressEvent;
207 QBasicTimer delayedPressTimer;
208 int pressDelay;
209 int fixupDuration;
210 qreal flickBoost;
211 qreal initialWheelFlickDistance;
212
213 enum FixupMode { Normal, Immediate, ExtentChanged };
214 FixupMode fixupMode;
215
216 static void fixupY_callback(void *);
217 static void fixupX_callback(void *);
218
219 void updateVelocity();
220 int vTime;
221 QQuickTimeLine velocityTimeline;
222 QQuickFlickableVisibleArea *visibleArea;
223 QQuickFlickable::FlickableDirection flickableDirection;
224 QQuickFlickable::BoundsBehavior boundsBehavior;
225 QQuickFlickable::BoundsMovement boundsMovement;
226 QQuickTransition *rebound;
227
228 void viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent,
229 QQuickTimeLineCallback::Callback fixupCallback);
230
231 void handlePressEvent(QPointerEvent *);
232 void handleMoveEvent(QPointerEvent *);
233 void handleReleaseEvent(QPointerEvent *);
234 bool buttonsAccepted(const QSinglePointEvent *event);
235
236 void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn,
237 Qt::MouseButtons buttons = Qt::NoButton);
238 void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos,
239 const QVector2D &deltas, bool overThreshold, bool momentum,
240 bool velocitySensitiveOverBounds, const QVector2D &velocity);
241
242 QVector2D firstPointLocalVelocity(QPointerEvent *event);
243 qint64 computeCurrentTime(QInputEvent *event) const;
244
245 // flickableData property
246 static void data_append(QQmlListProperty<QObject> *, QObject *);
247 static qsizetype data_count(QQmlListProperty<QObject> *);
248 static QObject *data_at(QQmlListProperty<QObject> *, qsizetype);
249 static void data_clear(QQmlListProperty<QObject> *);
250};
251
252class Q_QUICK_EXPORT QQuickFlickableVisibleArea : public QObject
253{
254 Q_OBJECT
255
256 Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged FINAL)
257 Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged FINAL)
258 Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged FINAL)
259 Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged FINAL)
260 QML_ANONYMOUS
261 QML_ADDED_IN_VERSION(2, 0)
262
263public:
264 QQuickFlickableVisibleArea(QQuickFlickable *parent=nullptr);
265
266 qreal xPosition() const;
267 qreal widthRatio() const;
268 qreal yPosition() const;
269 qreal heightRatio() const;
270
271 void updateVisible();
272
273Q_SIGNALS:
274 void xPositionChanged(qreal xPosition);
275 void yPositionChanged(qreal yPosition);
276 void widthRatioChanged(qreal widthRatio);
277 void heightRatioChanged(qreal heightRatio);
278
279private:
280 QQuickFlickable *flickable;
281 qreal m_xPosition;
282 qreal m_widthRatio;
283 qreal m_yPosition;
284 qreal m_heightRatio;
285};
286
287QT_END_NAMESPACE
288
289#endif // QQUICKFLICKABLE_P_P_H
290

source code of qtdeclarative/src/quick/items/qquickflickable_p_p.h