aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/items/qquickflickable.cpp35
-rw-r--r--tests/auto/quick/qquickflickable/data/contentXY.qml6
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp21
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)