diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | src/imports/testlib/qmldir | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4bytecodegenerator.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 8 | ||||
-rw-r--r-- | src/qml/qml.pro | 33 | ||||
-rw-r--r-- | src/qmldevtools/qmldevtools.pro | 1 | ||||
-rw-r--r-- | src/quick/handlers/qquickdraghandler.cpp | 88 | ||||
-rw-r--r-- | src/quick/handlers/qquickdraghandler_p.h | 10 | ||||
-rw-r--r-- | src/quick/util/qquickimageprovider.cpp | 2 | ||||
-rw-r--r-- | src/src.pro | 2 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp | 86 | ||||
-rw-r--r-- | tests/auto/quick/qquickimage/tst_qquickimage.cpp | 5 |
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; } |