43 #include "private/qflickgesture_p.h"
44 #include "private/qscroller_p.h"
46 #include "private/qscrollerproperties_p.h"
51 #include <QElapsedTimer>
53 #include <QApplication>
54 #include <QAbstractScrollArea>
55 #if QT_CONFIG(graphicsview)
56 #include <QGraphicsObject>
57 #include <QGraphicsScene>
58 #include <QGraphicsView>
61 #include <QtCore/qmath.h>
62 #include <QtGui/qevent.h>
75 #ifdef QSCROLLER_DEBUG
76 # define qScrollerDebug qDebug
78 # define qScrollerDebug while (false) qDebug
83 dbg <<
"\n Time: start:" <<
s.startTime <<
" duration:" <<
s.deltaTime <<
" stop progress:" <<
s.stopProgress;
84 dbg <<
"\n Pos: start:" <<
s.startPos <<
" delta:" <<
s.deltaPos <<
" stop:" <<
s.stopPos;
85 dbg <<
"\n Curve: type:" <<
s.curve.type() <<
"\n";
146 return (
r < 0) ? -1 : ((
r > 0) ? 1 : 0);
154 const qreal dx = 0.01;
171 qWarning(
"progressForValue(): QEasingCurves of type %d do not have an inverse, since they are not injective.", curve.
type());
192 #if QT_CONFIG(animation)
211 ignoreUpdate =
false;
219 if (++skip >=
d->frameRateSkip()) {
300 qWarning(
"QScroller::scroller() was called with a null target.");
305 return qt_allScrollers()->value(
target);
308 qt_allScrollers()->insert(
target,
s);
328 return *qt_activeScrollers();
358 return d->properties;
364 if (
d->properties !=
sp) {
370 d->recalcScrollingSegments(
true);
374 #ifndef QT_NO_GESTURES
409 switch (scrollGestureType) {
420 if (
target->isWidgetType()) {
425 #if QT_CONFIG(graphicsview)
428 go->setAcceptTouchEvents(
true);
429 go->grabGesture(
sp->recognizerType);
432 return sp->recognizerType;
445 return s->d_ptr->recognizerType;
466 if (
target->isWidgetType()) {
469 #if QT_CONFIG(graphicsview)
471 go->ungrabGesture(
sp->recognizerType);
477 sp->recognizer =
nullptr;
497 QScroller::~QScroller()
500 #ifndef QT_NO_GESTURES
503 d->recognizer =
nullptr;
505 qt_allScrollers()->remove(
d->target);
506 qt_activeScrollers()->removeOne(
this);
547 d->contentPosition = snap;
548 d->overshootPosition =
QPointF(0, 0);
568 #if QT_CONFIG(graphicsview)
572 if (
const auto *
scene = go->scene()) {
574 if (!views.isEmpty())
575 viewtr = views.first()->viewportTransform();
578 if (
tr.isScaling()) {
605 return d->releaseVelocity;
610 if (!
d->xSegments.isEmpty()) {
617 if (!
d->ySegments.isEmpty()) {
689 qScrollerDebug() <<
"QScroller::scrollTo(req:" <<
pos <<
" [pix] / snap:" << newpos <<
", " << scrollTime <<
" [ms])";
691 if (newpos ==
d->contentPosition +
d->overshootPosition)
704 d->setContentPositionHelperScrolling();
748 rect.width() + 2 * xmargin,
rect.height() + 2 * ymargin);
750 QSizeF visible =
d->viewportSize;
751 QRectF visibleRect(startPos, visible);
753 qScrollerDebug() <<
"QScroller::ensureVisible(" <<
rect <<
" [pix], " << xmargin <<
" [pix], " << ymargin <<
" [pix], " << scrollTime <<
"[ms])";
756 if (visibleRect.
contains(marginRect))
761 if (visibleRect.
width() <
rect.width()) {
763 if (
rect.left() > visibleRect.
left())
765 else if (
rect.right() < visibleRect.
right())
768 }
else if (visibleRect.
width() < marginRect.
width()) {
770 }
else if (marginRect.
left() > visibleRect.
left()) {
772 }
else if (marginRect.
right() < visibleRect.
right()) {
778 if (
rect.top() > visibleRect.
top())
780 else if (
rect.bottom() < visibleRect.
bottom())
783 }
else if (visibleRect.
height() < marginRect.
height()) {
785 }
else if (marginRect.
top() > visibleRect.
top()) {
787 }
else if (marginRect.
bottom() < visibleRect.
bottom()) {
793 if (newPos == startPos)
809 d->prepareScrolling(
d->pressPosition);
820 d->snapPositionsX = positions;
821 d->snapIntervalX = 0.0;
823 d->recalcScrollingSegments();
837 d->snapIntervalX = interval;
838 d->snapPositionsX.clear();
840 d->recalcScrollingSegments();
851 d->snapPositionsY = positions;
852 d->snapIntervalY = 0.0;
854 d->recalcScrollingSegments();
867 d->snapIntervalY = interval;
868 d->snapPositionsY.clear();
870 d->recalcScrollingSegments();
879 #ifndef QT_NO_GESTURES
892 , scrollTimer(new QScrollTimer(
this))
917 default:
return "(invalid)";
927 default:
return "(invalid)";
933 #if QT_CONFIG(animation)
944 timerhandler_t handler;
947 timerevent timerevents[] = {
952 for (
int i = 0;
i < int(
sizeof(timerevents) /
sizeof(*timerevents)); ++
i) {
953 timerevent *te = timerevents +
i;
955 if (
state == te->state) {
956 (this->*te->handler)();
961 #if QT_CONFIG(animation)
987 inputhandler_t handler;
990 statechange statechanges[] = {
999 for (
int i = 0;
i < int(
sizeof(statechanges) /
sizeof(*statechanges)); ++
i) {
1000 statechange *sc = statechanges +
i;
1002 if (
d->state == sc->state &&
input == sc->input)
1003 return (
d->*sc->handler)(
position -
d->overshootPosition, timestamp);
1049 QPointF deltaPixel = deltaPixelRaw;
1051 qScrollerDebug() <<
"QScroller::updateVelocity(" << deltaPixelRaw <<
" [delta pix], " << deltaTime <<
" [delta ms])";
1054 if (((deltaPixelRaw /
qreal(deltaTime)).manhattanLength() / ((ppm.
x() + ppm.
y()) / 2) * 1000) >
qreal(2.5))
1055 deltaPixel = deltaPixelRaw *
qreal(2.5) * ppm / 1000 / (deltaPixelRaw /
qreal(deltaTime)).manhattanLength();
1084 if (startPos == stopPos || deltaPos == 0)
1089 const auto &lastX =
xSegments.constLast();
1090 s.startTime = lastX.startTime + lastX.deltaTime * lastX.stopProgress;
1092 const auto &lastY =
ySegments.constLast();
1093 s.startTime = lastY.startTime + lastY.deltaTime * lastY.stopProgress;
1098 s.startPos = startPos;
1099 s.deltaPos = deltaPos;
1100 s.stopPos = stopPos;
1101 s.deltaTime = deltaTime * 1000;
1102 s.stopProgress = stopProgress;
1103 s.curve.setType(curve);
1178 (stopPos != minPos && stopPos != maxPos))
1181 if (stopPos < minPos || stopPos > maxPos)
1184 if (stopPos == minPos || stopPos == maxPos)
1188 if (!
qIsNaN(nextSnap) && stopPos != nextSnap)
1206 qScrollerDebug() <<
"+++ createScrollToSegments: t:" << deltaTime <<
"ep:" << endPos <<
"o:" << int(orientation);
1212 qreal deltaPos = (endPos - startPos) / 2;
1215 pushSegment(
type, deltaTime *
qreal(0.7),
qreal(1.0), startPos + deltaPos, deltaPos, endPos,
sp->scrollingCurve.type(), orientation);
1247 bool canOvershoot = !noOvershoot && (alwaysOvershoot || maxPos);
1249 qScrollerDebug() <<
"+++ createScrollingSegments: s:" << startPos <<
"maxPos:" << maxPos <<
"o:" << int(orientation);
1251 qScrollerDebug() <<
"v = " <<
v <<
", decelerationFactor = " <<
sp->decelerationFactor <<
", curveType = " <<
sp->scrollingCurve.type();
1253 qreal endPos = startPos + deltaPos;
1258 if ((startPos < minPos && endPos < minPos) ||
1259 (startPos > maxPos && endPos > maxPos)) {
1260 qreal stopPos = endPos < minPos ? minPos : maxPos;
1261 qreal oDeltaTime =
sp->overshootScrollTime;
1272 qScrollerDebug() <<
" Real Delta:" << lowerSnapPos <<
'-' << nextSnap <<
'-' <<higherSnapPos;
1275 if (nextSnap > higherSnapPos ||
qIsNaN(higherSnapPos))
1276 higherSnapPos = nextSnap;
1277 if (nextSnap < lowerSnapPos ||
qIsNaN(lowerSnapPos))
1278 lowerSnapPos = nextSnap;
1280 if (
qAbs(
v) <
sp->minimumVelocity) {
1285 if (
qIsNaN(nextSnap) || nextSnap == startPos)
1290 qreal snapDistance = higherSnapPos - lowerSnapPos;
1297 if (
sp->snapPositionRatio == 0.0 ||
qAbs(pressDistance /
sp->snapPositionRatio) > snapDistance)
1299 else if (pressDistance < 0.0)
1300 endPos = lowerSnapPos;
1302 endPos = higherSnapPos;
1304 deltaPos = endPos - startPos;
1305 qreal midPos = startPos + deltaPos *
qreal(0.3);
1312 if (
v > 0 && !
qIsNaN(higherSnapPos)) {
1314 if (endPos - startPos)
1315 deltaTime *=
qAbs((higherSnapPos - startPos) / (endPos - startPos));
1316 if (deltaTime >
sp->snapTime)
1317 deltaTime =
sp->snapTime;
1318 endPos = higherSnapPos;
1320 }
else if (
v < 0 && !
qIsNaN(lowerSnapPos)) {
1322 if (endPos - startPos)
1323 deltaTime *=
qAbs((lowerSnapPos - startPos) / (endPos - startPos));
1324 if (deltaTime >
sp->snapTime)
1325 deltaTime =
sp->snapTime;
1326 endPos = lowerSnapPos;
1329 }
else if (endPos < minPos || endPos > maxPos) {
1330 qreal stopPos = endPos < minPos ? minPos : maxPos;
1334 qreal stopProgress = progressForValue(
sp->scrollingCurve,
qAbs((stopPos - startPos) / deltaPos));
1336 if (!canOvershoot) {
1341 qreal oDeltaTime =
sp->overshootScrollTime;
1342 qreal oStopProgress = qMin(stopProgress + oDeltaTime *
qreal(0.3) / deltaTime,
qreal(1));
1343 qreal oDistance = startPos + deltaPos *
sp->scrollingCurve.valueForProgress(oStopProgress) - stopPos;
1344 qreal oMaxDistance =
qSign(oDistance) * (viewSize *
sp->overshootScrollDistanceFactor);
1346 qScrollerDebug() <<
"1 oDistance:" << oDistance <<
"Max:" << oMaxDistance <<
"stopP/oStopP" << stopProgress << oStopProgress;
1348 if (
qAbs(oDistance) >
qAbs(oMaxDistance)) {
1349 oStopProgress = progressForValue(
sp->scrollingCurve,
qAbs((stopPos + oMaxDistance - startPos) / deltaPos));
1350 oDistance = oMaxDistance;
1351 qScrollerDebug() <<
"2 oDistance:" << oDistance <<
"Max:" << oMaxDistance <<
"stopP/oStopP" << stopProgress << oStopProgress;
1354 pushSegment(
ScrollTypeFlick, deltaTime, oStopProgress, startPos, deltaPos, stopPos + oDistance,
sp->scrollingCurve.type(), orientation);
1385 qreal deltaTime = (
qreal(2) * vel.
length()) / (
sp->decelerationFactor * differentialForProgress(
sp->scrollingCurve, 0));
1419 if (contentDelta !=
QPointF(0, 0)) {
1430 #if QT_CONFIG(graphicsview)
1433 if (
const auto *
scene = go->scene()) {
1435 if (!views.isEmpty())
1457 if (
sp->axisLockThreshold) {
1458 int dx =
qAbs(deltaPixel.
x());
1459 int dy =
qAbs(deltaPixel.
y());
1461 bool vertical = (dy > dx);
1539 bool moveAborted =
false;
1540 bool moveStarted = (((deltaPixel / ppm).manhattanLength()) >
sp->dragStartDistance);
1545 bool canScrollX = (max.
width() > 0);
1546 bool canScrollY = (max.
height() > 0);
1553 if (
qAbs(deltaPixel.
x() / ppm.
x()) <
qAbs(deltaPixel.
y() / ppm.
y())) {
1564 moveStarted =
false;
1566 }
else if (moveStarted) {
1570 deltaPixel = deltaPixel - deltaPixel * (
sp->dragStartDistance / deltaPixel.
manhattanLength());
1572 if (deltaPixel !=
QPointF(0, 0)) {
1608 if (((deltaPixel /
q->pixelPerMeter()).manhattanLength()) >
sp->dragStartDistance) {
1615 int signX = 0, signY = 0;
1624 sp->maximumVelocity));
1628 sp->maximumVelocity));
1677 bool sendLastScroll =
false;
1679 if (
state == newstate)
1686 #if QT_CONFIG(animation)
1687 scrollTimer->stop();
1692 sendLastScroll =
true;
1698 #if QT_CONFIG(animation)
1699 scrollTimer->stop();
1708 #if QT_CONFIG(animation)
1710 scrollTimer->start();
1715 #if QT_CONFIG(animation)
1716 scrollTimer->start();
1723 if (sendLastScroll) {
1730 qt_activeScrollers()->push_back(
q);
1732 qt_activeScrollers()->removeOne(
q);
1754 if (
sp->overshootDragResistanceFactor)
1758 QPointF newPos = oldPos + deltaPos;
1760 qScrollerDebug() <<
"QScroller::setContentPositionHelperDragging(" << deltaPos <<
" [pix])";
1770 !
sp->overshootDragDistanceFactor;
1773 !
sp->overshootDragDistanceFactor;
1777 qreal newOvershootX = (canOvershootX) ? newPos.
x() - newClampedPos.
x() : 0;
1778 qreal newOvershootY = (canOvershootY) ? newPos.
y() - newClampedPos.
y() : 0;
1783 qScrollerDebug() <<
" --> noOs:" << noOvershootX <<
"drf:" <<
sp->overshootDragResistanceFactor <<
"mdf:" <<
sp->overshootScrollDistanceFactor <<
"ossP:"<<
sp->hOvershootPolicy;
1784 qScrollerDebug() <<
" --> canOS:" << canOvershootX <<
"newOS:" << newOvershootX <<
"maxOS:" << maxOvershootX;
1786 if (
sp->overshootDragResistanceFactor) {
1787 newOvershootX *=
sp->overshootDragResistanceFactor;
1788 newOvershootY *=
sp->overshootDragResistanceFactor;
1793 newOvershootX = qBound(-maxOvershootX, newOvershootX, maxOvershootX);
1794 newOvershootY = qBound(-maxOvershootY, newOvershootY, maxOvershootY);
1817 if ((
s.startTime +
s.deltaTime *
s.stopProgress) <=
now) {
1820 }
else if (
s.startTime <=
now) {
1822 pos =
s.startPos +
s.deltaPos *
s.curve.valueForProgress(progress);
1823 if (
s.deltaPos > 0 ?
pos >
s.stopPos :
pos <
s.stopPos) {
1845 qScrollerDebug() <<
"QScroller::setContentPositionHelperScrolling()\n"
1887 qreal snapPosDist = snapPos -
p;
1888 if ((
dir > 0 && snapPosDist < 0) ||
1889 (dir < 0 && snapPosDist > 0))
1891 if (snapPos < minPos || snapPos > maxPos )
1894 if (
qIsNaN(bestSnapPos) ||
1895 qAbs(snapPosDist) < bestSnapPosDist ) {
1896 bestSnapPos = snapPos;
1897 bestSnapPosDist =
qAbs(snapPosDist);
1920 if (snapPos >=
first && snapPos <= maxPos ) {
1921 qreal snapPosDist = snapPos -
p;
1923 if (
qIsNaN(bestSnapPos) ||
1924 qAbs(snapPosDist) < bestSnapPosDist ) {
1925 bestSnapPos = snapPos;
1926 bestSnapPosDist =
qAbs(snapPosDist);
1934 qreal snapPosDist = snapPos -
p;
1935 if ((
dir > 0 && snapPosDist < 0) ||
1936 (dir < 0 && snapPosDist > 0))
1938 if (snapPos < minPos || snapPos > maxPos )
1941 if (
qIsNaN(bestSnapPos) ||
1942 qAbs(snapPosDist) < bestSnapPosDist) {
1943 bestSnapPos = snapPos;
1944 bestSnapPosDist =
qAbs(snapPosDist);
1967 if (snapPos >=
first && snapPos <= maxPos ) {
1968 qreal snapPosDist = snapPos -
p;
1970 if (
qIsNaN(bestSnapPos) ||
1971 qAbs(snapPosDist) < bestSnapPosDist) {
1972 bestSnapPos = snapPos;
1973 bestSnapPosDist =
qAbs(snapPosDist);
2024 #include "moc_qscroller.cpp"
2025 #include "moc_qscroller_p.cpp"
small capitals from c petite p scientific i
[1]
The QAbstractAnimation class is the base of all animations.
virtual void updateCurrentTime(int currentTime)=0
void start(QAbstractAnimation::DeletionPolicy policy=KeepWhenStopped)
int duration
the duration of the animation.
bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event)
operator<<(QDataStream &ds, qfloat16 f)
The QDebug class provides an output stream for debugging information.
The QEasingCurve class provides easing curves for controlling animation.
qreal valueForProgress(qreal progress) const
bool operator<(const QElapsedTimer &lhs, const QElapsedTimer &rhs) noexcept
qint64 elapsed() const noexcept
The QEvent class is the base class of all event classes. Event objects contain event parameters.
static void unregisterRecognizer(Qt::GestureType type)
static Qt::GestureType registerRecognizer(QGestureRecognizer *recognizer)
The QGraphicsObject class provides a base class for all graphics items that require signals,...
QList< QGraphicsView * > views() const
QScreen * primaryScreen
the primary (or default) screen of the application.
The QLineF class provides a two-dimensional vector using floating point precision.
QMargins operator*(const QMargins &margins, int factor)
QMargins operator/(const QMargins &margins, int divisor)
The QObject class is the base class of all Qt objects.
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
void setParent(QObject *parent)
void destroyed(QObject *=nullptr)
The QPointF class defines a point in the plane using floating point precision.
constexpr qreal & ry() noexcept
constexpr qreal x() const noexcept
constexpr qreal manhattanLength() const
constexpr qreal y() const noexcept
constexpr qreal & rx() noexcept
constexpr void setY(qreal y) noexcept
constexpr void setX(qreal x) noexcept
The QQueue class is a generic container that provides a queue.
The QRectF class defines a finite rectangle in the plane using floating point precision.
constexpr qreal bottom() const noexcept
constexpr qreal height() const noexcept
constexpr qreal width() const noexcept
bool contains(const QRectF &r) const noexcept
constexpr qreal left() const noexcept
constexpr void setWidth(qreal w) noexcept
constexpr bool isNull() const noexcept
constexpr qreal top() const noexcept
constexpr void setHeight(qreal h) noexcept
constexpr qreal right() const noexcept
T * data() const noexcept
The QScreen class is used to query screen properties. \inmodule QtGui.
qreal physicalDotsPerInchY
the number of physical dots or pixels per inch in the vertical direction
qreal physicalDotsPerInchX
the number of physical dots or pixels per inch in the horizontal direction
The QSizeF class defines the size of a two-dimensional object using floating point precision.
constexpr qreal width() const noexcept
constexpr qreal height() const noexcept
bool operator<=(const QUuid &lhs, const QUuid &rhs)
bool operator>=(const QUuid &lhs, const QUuid &rhs)
The QVector2D class represents a vector or vertex in 2D space.
float length() const noexcept
QVector2D normalized() const noexcept
QHighDpiScaling::Point position(T, QHighDpiScaling::Point::Kind)
Q_WIDGETS_EXPORT qreal dpi(const QStyleOption *option)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
[3]
EGLOutputLayerEXT EGLint EGLAttrib value
bool qIsNaN(qfloat16 f) noexcept
int qRound(qfloat16 d) noexcept
QT_END_INCLUDE_NAMESPACE typedef double qreal
#define QT_CONFIG(feature)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLdouble GLdouble GLdouble GLdouble q
GLfloat GLfloat GLfloat alpha
GLenum GLenum GLenum input
QPropertyAnimation * animation
[0]