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
67QT_BEGIN_NAMESPACE
68
69// Really slow flicks can be annoying.
70const qreal MinimumFlickVelocity = 75.0;
71
72class QQuickFlickableVisibleArea;
73class QQuickTransition;
74class QQuickFlickableReboundTransition;
75
76class Q_AUTOTEST_EXPORT QQuickFlickablePrivate : public QQuickItemPrivate, public QQuickItemChangeListener
77{
78 Q_DECLARE_PUBLIC(QQuickFlickable)
79
80public:
81 static inline QQuickFlickablePrivate *get(QQuickFlickable *o) { return o->d_func(); }
82
83 QQuickFlickablePrivate();
84 void init();
85
86 struct Velocity : public QQuickTimeLineValue
87 {
88 Velocity(QQuickFlickablePrivate *p)
89 : parent(p) {}
90 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 {
100 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
117 void reset() {
118 velocityBuffer.clear();
119 dragStartOffset = 0;
120 fixingUp = false;
121 inOvershoot = false;
122 }
123
124 void markExtentsDirty() {
125 minExtentDirty = true;
126 maxExtentDirty = true;
127 extentsChanged = true;
128 }
129
130 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
211public:
212 QQuickItem *contentItem;
213
214 AxisData hData;
215 AxisData vData;
216
217 QQuickTimeLine timeline;
218 bool hMoved : 1;
219 bool vMoved : 1;
220 bool stealMouse : 1;
221 bool pressed : 1;
222 bool scrollingPhase : 1;
223 bool interactive : 1;
224 bool calcVelocity : 1;
225 bool pixelAligned : 1;
226 bool syncDrag : 1;
227 QElapsedTimer timer;
228 qint64 lastPosTime;
229 qint64 lastPressTime;
230 QPointF lastPos;
231 QPointF pressPos;
232 QVector2D accumulatedWheelPixelDelta;
233 qreal deceleration;
234 qreal maxVelocity;
235 qreal reportedVelocitySmoothing;
236 QMouseEvent *delayedPressEvent;
237 QBasicTimer delayedPressTimer;
238 int pressDelay;
239 int fixupDuration;
240 qreal flickBoost;
241
242 enum FixupMode { Normal, Immediate, ExtentChanged };
243 FixupMode fixupMode;
244
245 static void fixupY_callback(void *);
246 static void fixupX_callback(void *);
247
248 void updateVelocity();
249 int vTime;
250 QQuickTimeLine velocityTimeline;
251 QQuickFlickableVisibleArea *visibleArea;
252 QQuickFlickable::FlickableDirection flickableDirection;
253 QQuickFlickable::BoundsBehavior boundsBehavior;
254 QQuickFlickable::BoundsMovement boundsMovement;
255 QQuickTransition *rebound;
256
257 void viewportAxisMoved(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
258 QQuickTimeLineCallback::Callback fixupCallback);
259
260 void handleMousePressEvent(QMouseEvent *);
261 void handleMouseMoveEvent(QMouseEvent *);
262 void handleMouseReleaseEvent(QMouseEvent *);
263
264 void maybeBeginDrag(qint64 currentTimestamp, const QPointF &pressPosn);
265 void drag(qint64 currentTimestamp, QEvent::Type eventType, const QPointF &localPos,
266 const QVector2D &deltas, bool overThreshold, bool momentum,
267 bool velocitySensitiveOverBounds, const QVector2D &velocity);
268
269 qint64 computeCurrentTime(QInputEvent *event) const;
270 qreal devicePixelRatio() const;
271
272 // flickableData property
273 static void data_append(QQmlListProperty<QObject> *, QObject *);
274 static int data_count(QQmlListProperty<QObject> *);
275 static QObject *data_at(QQmlListProperty<QObject> *, int);
276 static void data_clear(QQmlListProperty<QObject> *);
277};
278
279class QQuickFlickableVisibleArea : public QObject
280{
281 Q_OBJECT
282
283 Q_PROPERTY(qreal xPosition READ xPosition NOTIFY xPositionChanged)
284 Q_PROPERTY(qreal yPosition READ yPosition NOTIFY yPositionChanged)
285 Q_PROPERTY(qreal widthRatio READ widthRatio NOTIFY widthRatioChanged)
286 Q_PROPERTY(qreal heightRatio READ heightRatio NOTIFY heightRatioChanged)
287
288public:
289 QQuickFlickableVisibleArea(QQuickFlickable *parent=nullptr);
290
291 qreal xPosition() const;
292 qreal widthRatio() const;
293 qreal yPosition() const;
294 qreal heightRatio() const;
295
296 void updateVisible();
297
298Q_SIGNALS:
299 void xPositionChanged(qreal xPosition);
300 void yPositionChanged(qreal yPosition);
301 void widthRatioChanged(qreal widthRatio);
302 void heightRatioChanged(qreal heightRatio);
303
304private:
305 QQuickFlickable *flickable;
306 qreal m_xPosition;
307 qreal m_widthRatio;
308 qreal m_yPosition;
309 qreal m_heightRatio;
310};
311
312QT_END_NAMESPACE
313
314QML_DECLARE_TYPE(QQuickFlickableVisibleArea)
315
316#endif // QQUICKFLICKABLE_P_P_H
317