aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--src/imports/testlib/qmldir1
-rw-r--r--src/qml/compiler/qv4bytecodegenerator.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp7
-rw-r--r--src/qml/jsruntime/qv4engine.cpp6
-rw-r--r--src/qml/jsruntime/qv4engine_p.h8
-rw-r--r--src/qml/qml.pro33
-rw-r--r--src/qmldevtools/qmldevtools.pro1
-rw-r--r--src/quick/handlers/qquickdraghandler.cpp88
-rw-r--r--src/quick/handlers/qquickdraghandler_p.h10
-rw-r--r--src/quick/util/qquickimageprovider.cpp2
-rw-r--r--src/src.pro2
-rw-r--r--tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp86
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp5
14 files changed, 193 insertions, 59 deletions
diff --git a/.gitignore b/.gitignore
index da9552c8e6..2cffe24ff0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -286,6 +286,7 @@ tests/auto/*/*/*/*.moc
src/qml/RegExpJitTables.h
src/qml/udis86_itab.c
src/qml/udis86_itab.h
+src/qml/qml_compile_hash_p.h
# Generated HLSL bytecode headers
*.hlslh
diff --git a/src/imports/testlib/qmldir b/src/imports/testlib/qmldir
index e5757f6a88..be9039abbb 100644
--- a/src/imports/testlib/qmldir
+++ b/src/imports/testlib/qmldir
@@ -5,3 +5,4 @@ typeinfo plugins.qmltypes
TestCase 1.0 TestCase.qml
TestCase 1.2 TestCase.qml
SignalSpy 1.0 SignalSpy.qml
+depends QtQuick.Window 2.0
diff --git a/src/qml/compiler/qv4bytecodegenerator.cpp b/src/qml/compiler/qv4bytecodegenerator.cpp
index 0978e23b17..4d50654d27 100644
--- a/src/qml/compiler/qv4bytecodegenerator.cpp
+++ b/src/qml/compiler/qv4bytecodegenerator.cpp
@@ -74,7 +74,7 @@ void BytecodeGenerator::packInstruction(I &i)
Q_ASSERT(type >= MOTH_NUM_INSTRUCTIONS());
if (type >= MOTH_NUM_INSTRUCTIONS())
type -= MOTH_NUM_INSTRUCTIONS();
- int instructionsAsInts[sizeof(Instr)/sizeof(int)];
+ int instructionsAsInts[sizeof(Instr)/sizeof(int)] = {};
int nMembers = Moth::InstrInfo::argumentCount[static_cast<int>(i.type)];
for (int j = 0; j < nMembers; ++j) {
instructionsAsInts[j] = qFromLittleEndian<qint32>(i.packed + 1 + j * sizeof(int));
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 86200d7df7..05869c3287 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -65,6 +65,9 @@
#include <QCryptographicHash>
#include <QSaveFile>
+// generated by qmake:
+#include "qml_compile_hash_p.h"
+
#include <algorithm>
#if defined(QT_BUILD_INTERNAL)
@@ -703,10 +706,8 @@ static QByteArray ownLibraryChecksum()
libraryChecksum = hash.result();
}
}
-#elif defined(QML_COMPILE_HASH)
- libraryChecksum = QByteArray(QT_STRINGIFY(QML_COMPILE_HASH));
#else
- // Not implemented.
+ libraryChecksum = QByteArray(QML_COMPILE_HASH);
#endif
return libraryChecksum;
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 06b71c5cf7..903633df90 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -126,9 +126,6 @@ QQmlEngine *ExecutionEngine::qmlEngine() const
#endif // V4_BOOTSTRAP
qint32 ExecutionEngine::maxCallDepth = -1;
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
-const bool ExecutionEngine::canAllocateExecutableMemory = OSAllocator::canAllocateExecutableMemory();
-#endif
ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
: executableAllocator(new QV4::ExecutableAllocator)
@@ -144,6 +141,9 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
, m_engineId(engineSerial.fetchAndAddOrdered(1))
, regExpCache(0)
, m_multiplyWrappedQObjects(0)
+#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+ , m_canAllocateExecutableMemory(OSAllocator::canAllocateExecutableMemory())
+#endif
{
memoryManager = new QV4::MemoryManager(this);
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index c955d1ab9e..da404b748f 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -372,6 +372,9 @@ public:
// but any time a QObject is wrapped a second time in another engine, we have to do
// bookkeeping.
MultiplyWrappedQObjectMap *m_multiplyWrappedQObjects;
+#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+ const bool m_canAllocateExecutableMemory;
+#endif
int internalClassIdCount = 0;
@@ -491,7 +494,7 @@ public:
bool canJIT(Function *f = nullptr)
{
#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
- if (!canAllocateExecutableMemory)
+ if (!m_canAllocateExecutableMemory)
return false;
if (f)
return f->interpreterCallCount >= jitCallCountThreshold;
@@ -510,9 +513,6 @@ private:
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
int jitCallCountThreshold;
-#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
- static const bool canAllocateExecutableMemory;
-#endif
};
// This is a trick to tell the code generators that functions taking a NoThrowContext won't
diff --git a/src/qml/qml.pro b/src/qml/qml.pro
index adfaf38e9f..eabca59836 100644
--- a/src/qml/qml.pro
+++ b/src/qml/qml.pro
@@ -16,17 +16,28 @@ gcc:isEqual(QT_ARCH, "mips"): QMAKE_CXXFLAGS += -fno-reorder-blocks
DEFINES += QT_NO_FOREACH
-tagFile=$$PWD/../../.tag
-tag=
-exists($$tagFile) {
- tag=$$cat($$tagFile, singleline)
- QMAKE_INTERNAL_INCLUDED_FILES += $$tagFile
-}
-!equals(tag, "$${LITERAL_DOLLAR}Format:%H$${LITERAL_DOLLAR}") {
- DEFINES += QML_COMPILE_HASH="$$tag"
-} else:exists($$PWD/../../.git) {
- commit=$$system(git describe --tags --always --long --dirty)
- DEFINES += QML_COMPILE_HASH="$$commit"
+!build_pass {
+ # Create a header containing a hash that describes this library. For a
+ # released version of Qt, we'll use the .tag file that is updated by git
+ # archive with the commit hash. For unreleased versions, we'll ask git
+ # describe. Note that it won't update unless qmake is run again, even if
+ # the commit change also changed something in this library.
+ tagFile = $$PWD/../../.tag
+ tag =
+ exists($$tagFile) {
+ tag = $$cat($$tagFile, singleline)
+ QMAKE_INTERNAL_INCLUDED_FILES += $$tagFile
+ }
+ !equals(tag, "$${LITERAL_DOLLAR}Format:%H$${LITERAL_DOLLAR}") {
+ QML_COMPILE_HASH = $$tag
+ } else:exists($$PWD/../../.git) {
+ commit = $$system(git describe --tags --always --long --dirty)
+ QML_COMPILE_HASH = $$commit
+ }
+ compile_hash_contents = \
+ "// Generated file, DO NOT EDIT" \
+ "$${LITERAL_HASH}define QML_COMPILE_HASH \"$$QML_COMPILE_HASH\""
+ write_file("$$OUT_PWD/qml_compile_hash_p.h", compile_hash_contents)|error()
}
exists("qqml_enable_gcov") {
diff --git a/src/qmldevtools/qmldevtools.pro b/src/qmldevtools/qmldevtools.pro
index 5ee97776b8..23b7cf651e 100644
--- a/src/qmldevtools/qmldevtools.pro
+++ b/src/qmldevtools/qmldevtools.pro
@@ -4,6 +4,7 @@ QT = core-private
CONFIG += minimal_syncqt internal_module qmldevtools_build
MODULE_INCNAME = QtQml
+INCLUDEPATH += $$OUT_PWD/../qml
# 2415: variable "xx" of static storage duration was declared but never referenced
# unused variable 'xx' [-Werror,-Wunused-const-variable]
diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp
index d4a8f06db8..5180a840ca 100644
--- a/src/quick/handlers/qquickdraghandler.cpp
+++ b/src/quick/handlers/qquickdraghandler.cpp
@@ -91,20 +91,44 @@ bool QQuickDragHandler::wantsEventPoint(QQuickEventPoint *point)
|| QQuickSinglePointHandler::wantsEventPoint(point));
}
+bool QQuickDragHandler::targetContains(QQuickEventPoint *point)
+{
+ Q_ASSERT(parentItem() && target());
+ return target()->contains(localTargetPosition(point));
+}
+
+QPointF QQuickDragHandler::localTargetPosition(QQuickEventPoint *point)
+{
+ QPointF pos = point->position();
+ if (target() != parentItem())
+ pos = parentItem()->mapToItem(target(), pos);
+ return pos;
+}
+
void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point)
{
- if (grabber == this && stateChange == QQuickEventPoint::GrabExclusive && m_targetStartPos.isNull())
- // In case the grab got handled over from another grabber, we might not get the Press.
- // Therefore, prefer the m_targetStartPos we got when it got Pressed.
- initializeTargetStartPos(point);
- enforceConstraints();
+ if (!target() || !target()->parentItem())
+ return;
+ if (grabber == this && stateChange == QQuickEventPoint::GrabExclusive) {
+ // In case the grab got handed over from another grabber, we might not get the Press.
+ if (!m_pressedInsideTarget) {
+ m_pressTargetPos = QPointF(target()->width(), target()->height()) / 2;
+ m_pressScenePos = point->scenePosition();
+ } else if (m_pressTargetPos.isNull()) {
+ m_pressTargetPos = localTargetPosition(point);
+ m_pressScenePos = point->scenePosition();
+ }
+ }
QQuickSinglePointHandler::onGrabChanged(grabber, stateChange, point);
}
void QQuickDragHandler::onActiveChanged()
{
- if (!active())
- m_targetStartPos = QPointF();
+ if (!active()) {
+ m_pressTargetPos = QPointF();
+ m_pressScenePos = m_pressTargetPos;
+ m_pressedInsideTarget = false;
+ }
}
void QQuickDragHandler::handleEventPoint(QQuickEventPoint *point)
@@ -112,25 +136,38 @@ void QQuickDragHandler::handleEventPoint(QQuickEventPoint *point)
point->setAccepted();
switch (point->state()) {
case QQuickEventPoint::Pressed:
- initializeTargetStartPos(point);
+ m_pressedInsideTarget = targetContains(point);
+ m_pressTargetPos = localTargetPosition(point);
+ m_pressScenePos = point->scenePosition();
setPassiveGrab(point);
break;
case QQuickEventPoint::Updated: {
- QPointF delta = point->scenePosition() - point->scenePressPosition();
- if (!m_xAxis.enabled())
- delta.setX(0);
- if (!m_yAxis.enabled())
- delta.setY(0);
+ QVector2D accumulatedDragDelta = QVector2D(point->scenePosition() - m_pressScenePos);
if (active()) {
- setTranslation(QVector2D(delta));
+ // update translation property. Make sure axis is respected for it.
+ if (!m_xAxis.enabled())
+ accumulatedDragDelta.setX(0);
+ if (!m_yAxis.enabled())
+ accumulatedDragDelta.setY(0);
+ setTranslation(accumulatedDragDelta);
+
if (target() && target()->parentItem()) {
- QPointF pos = target()->parentItem()->mapFromScene(m_targetStartPos + delta);
+ const QPointF newTargetTopLeft = localTargetPosition(point) - m_pressTargetPos;
+ const QPointF xformOrigin = target()->transformOriginPoint();
+ const QPointF targetXformOrigin = newTargetTopLeft + xformOrigin;
+ QPointF pos = target()->parentItem()->mapFromItem(target(), targetXformOrigin);
+ pos -= xformOrigin;
+ QPointF targetItemPos = target()->position();
+ if (!m_xAxis.enabled())
+ pos.setX(targetItemPos.x());
+ if (!m_yAxis.enabled())
+ pos.setY(targetItemPos.y());
enforceAxisConstraints(&pos);
moveTarget(pos, point);
}
} else if (!point->exclusiveGrabber() &&
- ((m_xAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point)) ||
- (m_yAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point)))) {
+ ((m_xAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(accumulatedDragDelta.x(), Qt::XAxis, point)) ||
+ (m_yAxis.enabled() && QQuickWindowPrivate::dragOverThreshold(accumulatedDragDelta.y(), Qt::YAxis, point)))) {
setExclusiveGrab(point);
if (auto parent = parentItem()) {
if (point->pointerEvent()->asPointerTouchEvent())
@@ -166,23 +203,6 @@ void QQuickDragHandler::enforceAxisConstraints(QPointF *localPos)
localPos->setY(qBound(m_yAxis.minimum(), localPos->y(), m_yAxis.maximum()));
}
-void QQuickDragHandler::initializeTargetStartPos(QQuickEventPoint *point)
-{
- if (target() && target()->parentItem()) {
- m_targetStartPos = target()->parentItem()->mapToScene(target()->position());
- if (!target()->contains(point->position())) {
- // If pressed outside of target item, move the target item so that the touchpoint is in its center,
- // while still respecting the axis constraints.
- const QPointF center = target()->parentItem()->mapFromScene(point->scenePosition());
- const QPointF pointCenteredInItemPos = target()->parentItem()->mapToScene(center - QPointF(target()->width(), target()->height())/2);
- if (m_xAxis.enabled())
- m_targetStartPos.setX(pointCenteredInItemPos.x());
- if (m_yAxis.enabled())
- m_targetStartPos.setY(pointCenteredInItemPos.y());
- }
- }
-}
-
void QQuickDragHandler::setTranslation(const QVector2D &trans)
{
if (trans == m_translation) // fuzzy compare?
diff --git a/src/quick/handlers/qquickdraghandler_p.h b/src/quick/handlers/qquickdraghandler_p.h
index d10084c654..50f56d78a4 100644
--- a/src/quick/handlers/qquickdraghandler_p.h
+++ b/src/quick/handlers/qquickdraghandler_p.h
@@ -118,13 +118,19 @@ protected:
private:
void ungrab();
void enforceAxisConstraints(QPointF *localPos);
- void initializeTargetStartPos(QQuickEventPoint *point);
+ bool targetContains(QQuickEventPoint *point);
+ QPointF localTargetPosition(QQuickEventPoint *point);
private:
- QPointF m_targetStartPos;
+ QPointF m_pressScenePos;
+ QPointF m_pressTargetPos; // We must also store the local targetPos, because we cannot deduce
+ // the press target pos from the scene pos in case there was e.g a
+ // flick in one of the ancestors during the drag.
QVector2D m_translation;
+
QQuickDragAxis m_xAxis;
QQuickDragAxis m_yAxis;
+ bool m_pressedInsideTarget = false;
friend class QQuickDragAxis;
};
diff --git a/src/quick/util/qquickimageprovider.cpp b/src/quick/util/qquickimageprovider.cpp
index a1513336a5..4003b88d09 100644
--- a/src/quick/util/qquickimageprovider.cpp
+++ b/src/quick/util/qquickimageprovider.cpp
@@ -684,7 +684,7 @@ QSize QQuickImageProviderWithOptions::loadSize(const QSize &originalSize, const
const bool preserveAspectCropOrFit = options.preserveAspectRatioCrop() || options.preserveAspectRatioFit();
- if (!preserveAspectCropOrFit && (format == "svg" || format == "svgz"))
+ if (!preserveAspectCropOrFit && (format == "svg" || format == "svgz") && !requestedSize.isEmpty())
return requestedSize;
qreal ratio = 0.0;
diff --git a/src/src.pro b/src/src.pro
index 8ff4d4af10..867e243523 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -22,6 +22,8 @@ SUBDIRS += \
qtConfig(qml-devtools): SUBDIRS += qmldevtools
+qmldevtools.depends = qml
+
qtConfig(qml-network) {
QT_FOR_CONFIG += network
qtConfig(localserver):qtConfig(qml-debug): SUBDIRS += qmldebug
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
index c0b34f8246..f3513881cd 100644
--- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
+++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp
@@ -75,6 +75,7 @@ private slots:
void touchDragFlickableBehindItemWithHandlers();
void mouseDragFlickableBehindItemWithHandlers_data();
void mouseDragFlickableBehindItemWithHandlers();
+ void touchDragSliderAndFlickable();
private:
void createView(QScopedPointer<QQuickView> &window, const char *fileName);
@@ -560,6 +561,91 @@ void tst_FlickableInterop::mouseDragFlickableBehindItemWithHandlers()
QCOMPARE(originP1, rect->mapToScene(rect->clipRect().center()).toPoint());
}
+void tst_FlickableInterop::touchDragSliderAndFlickable()
+{
+ const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
+ QScopedPointer<QQuickView> windowPtr;
+ createView(windowPtr, "flickableWithHandlers.qml");
+ QQuickView * window = windowPtr.data();
+
+ QQuickItem *slider = window->rootObject()->findChild<QQuickItem*>("Slider");
+ QVERIFY(slider);
+ QQuickDragHandler *drag = slider->findChild<QQuickDragHandler*>();
+ QVERIFY(drag);
+ QQuickItem *knob = slider->findChild<QQuickItem*>("Slider Knob");
+ QVERIFY(knob);
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>();
+ QVERIFY(flickable);
+
+ // The knob is initially centered over the slider's "groove"
+ qreal initialXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).x() - slider->mapToScene
+ (slider->clipRect().center()).x());
+ QVERIFY(initialXOffset <= 1);
+
+ // Drag the slider in the allowed (vertical) direction with one finger
+ QPoint p1 = knob->mapToScene(knob->clipRect().center()).toPoint();
+ QTest::touchEvent(window, touchDevice).press(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(0, dragThreshold);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(0, dragThreshold);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(0, dragThreshold);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(slider->property("value").toInt() < 49);
+ QVERIFY(!flickable->isMoving());
+
+ // Drag the Flickable with a second finger
+ QPoint p2(300,300);
+ QTest::touchEvent(window, touchDevice).stationary(1).press(2, p2, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).move(1, p1, window).stationary(2);
+ QQuickTouchUtils::flush(window);
+ p1 += QPoint(-10, -10);
+ p2 += QPoint(dragThreshold, 0);
+ QTest::touchEvent(window, touchDevice).stationary(1).move(2, p2, window);
+ QQuickTouchUtils::flush(window);
+ QTRY_VERIFY(flickable->isMoving());
+ qreal knobSliderXOffset = qAbs(knob->mapToScene(knob->clipRect().center()).toPoint().x() -
+ slider->mapToScene(slider->clipRect().center()).toPoint().x()) - initialXOffset;
+ if (knobSliderXOffset > 1)
+ qDebug() << "knob has slipped out of groove by" << knobSliderXOffset << "pixels";
+ // See if the knob is still centered over the slider's "groove"
+ QVERIFY(qAbs(knobSliderXOffset) <= 1);
+
+ // Release
+ QTest::touchEvent(window, touchDevice).release(1, p1, window).release(2, p2, window);
+}
+
QTEST_MAIN(tst_FlickableInterop)
#include "tst_flickableinterop.moc"
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 783e4aab4c..ec0ec6c2b6 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -418,6 +418,11 @@ void tst_qquickimage::svg()
QCOMPARE(obj->width(), 200.0);
QCOMPARE(obj->height(), 200.0);
+ obj->setSourceSize(QSize(100,0));
+ QCOMPARE(obj->width(), 100.0);
+ // Due to aspect ratio calculations we can't get a precise
+ // check for all setups, so we allow a small margin of error
+ QVERIFY(qAbs(obj->height() - 141) < 1);
delete obj;
}