diff options
-rw-r--r-- | src/quick/items/qquickflickable.cpp | 35 | ||||
-rw-r--r-- | tests/auto/quick/qquickflickable/data/contentXY.qml | 6 | ||||
-rw-r--r-- | tests/auto/quick/qquickflickable/tst_qquickflickable.cpp | 21 |
3 files changed, 53 insertions, 9 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 31581c0f07..0333f6b9bd 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -55,6 +55,8 @@ #include <QtCore/qmath.h> #include "qplatformdefs.h" +#include <cmath> + QT_BEGIN_NAMESPACE // FlickThreshold determines how far the "mouse" must have moved @@ -69,6 +71,21 @@ static const int RetainGrabVelocity = 100; static const int MovementEndingTimerInterval = 100; #endif +// Currently std::round can't be used on Android when using ndk g++, so +// use C version instead. We could just define two versions of Round, one +// for float and one for double, but then only one of them would be used +// and compiler would trigger a warning about unused function. +// +// See https://code.google.com/p/android/issues/detail?id=54418 +template<typename T> +static T Round(T t) { + return round(t); +} +template<> +Q_DECL_UNUSED float Round<float>(float f) { + return roundf(f); +} + static qreal EaseOvershoot(qreal t) { return qAtan(t); } @@ -351,7 +368,7 @@ bool QQuickFlickablePrivate::flick(AxisData &data, qreal minExtent, qreal maxExt qreal dist = v2 / (accel * 2.0); if (v > 0) dist = -dist; - qreal target = -qRound(-(data.move.value() - dist)); + qreal target = -Round(-(data.move.value() - dist)); dist = -target + data.move.value(); accel = v2 / (2.0f * qAbs(dist)); @@ -455,18 +472,18 @@ void QQuickFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal maxExt } else if (data.move.value() <= maxExtent) { resetTimeline(data); adjustContentPos(data, maxExtent); - } else if (-qRound(-data.move.value()) != data.move.value()) { + } else if (-Round(-data.move.value()) != data.move.value()) { // We could animate, but since it is less than 0.5 pixel it's probably not worthwhile. resetTimeline(data); qreal val = data.move.value(); - if (qAbs(-qRound(-val) - val) < 0.25) // round small differences - val = -qRound(-val); + if (std::abs(-Round(-val) - val) < 0.25) // round small differences + val = -Round(-val); else if (data.smoothVelocity.value() > 0) // continue direction of motion for larger - val = -qFloor(-val); + val = -std::floor(-val); else if (data.smoothVelocity.value() < 0) - val = -qCeil(-val); + val = -std::ceil(-val); else // otherwise round - val = -qRound(-val); + val = -Round(-val); timeline.set(data.move, val); } data.inOvershoot = false; @@ -1553,12 +1570,12 @@ void QQuickFlickablePrivate::replayDelayedPress() //XXX pixelAligned ignores the global position of the Flickable, i.e. assumes Flickable itself is pixel aligned. void QQuickFlickablePrivate::setViewportX(qreal x) { - contentItem->setX(pixelAligned ? -qRound(-x) : x); + contentItem->setX(pixelAligned ? -Round(-x) : x); } void QQuickFlickablePrivate::setViewportY(qreal y) { - contentItem->setY(pixelAligned ? -qRound(-y) : y); + contentItem->setY(pixelAligned ? -Round(-y) : y); } void QQuickFlickable::timerEvent(QTimerEvent *event) diff --git a/tests/auto/quick/qquickflickable/data/contentXY.qml b/tests/auto/quick/qquickflickable/data/contentXY.qml new file mode 100644 index 0000000000..8215976949 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/contentXY.qml @@ -0,0 +1,6 @@ +import QtQuick 2.0 + +Flickable { + width: 400; height: 400 + contentWidth: 1e11; contentHeight: 1e11 +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index e1678b9acd..a03e3b8170 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -91,6 +91,7 @@ private slots: void cleanup(); void contentSize(); void ratios_smallContent(); + void contentXYNotTruncatedToInt(); private: void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to); @@ -1841,6 +1842,26 @@ void tst_qquickflickable::ratios_smallContent() QCOMPARE(obj->property("widthRatioIs").toDouble(), 1.); } +// QTBUG-48018 +void tst_qquickflickable::contentXYNotTruncatedToInt() +{ + QScopedPointer<QQuickView> window(new QQuickView); + window->setSource(testFileUrl("contentXY.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + QQuickViewTestUtil::centerOnScreen(window.data()); + QQuickViewTestUtil::moveMouseAway(window.data()); + window->show(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + + QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject()); + QVERIFY(flickable); + + flickable->setContentX(1e10); + flick(window.data(), QPoint(200, 100), QPoint(100, 100), 50); + + // make sure we are not clipped at 2^31 + QVERIFY(flickable->contentX() > qreal(1e10)); +} QTEST_MAIN(tst_qquickflickable) |