diff options
author | Tarja Sundqvist <[email protected]> | 2024-07-23 13:25:53 +0300 |
---|---|---|
committer | Tarja Sundqvist <[email protected]> | 2024-07-23 13:25:53 +0300 |
commit | 7c32569ad27b743b6cb50e2bcb67c9ca1674f238 (patch) | |
tree | 15b39c35a96707029dbd352e0e74cb78c59b3952 | |
parent | 5f4570b5164a828b20514b938957ce06b105ff3e (diff) | |
parent | e6e266221555bf3c5554427f7402f6e7e3087fa5 (diff) |
Merge tag 'v5.15.15-lts' into tqtc/lts-5.15-opensourcev5.15.15-lts-lgpl
Qt 5.15.15-lts release
Change-Id: I0272e1ec4b55be362e13e36cd48f532fe4b7c770
-rw-r--r-- | .qmake.conf | 2 | ||||
-rw-r--r-- | src/qml/common/qqmljsmemorypool_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arraydata.cpp | 38 | ||||
-rw-r--r-- | src/qml/qml/ftw/qintrusivelist_p.h | 5 | ||||
-rw-r--r-- | src/qml/qml/ftw/qrecyclepool_p.h | 9 | ||||
-rw-r--r-- | src/quick/doc/images/qml-item-canvas-startAngle.png | bin | 5099 -> 5826 bytes | |||
-rw-r--r-- | src/quick/doc/src/examples.qdoc | 1 | ||||
-rw-r--r-- | src/quick/items/context2d/qquickcontext2d.cpp | 4 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 10 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 22 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgrenderloop.cpp | 7 | ||||
-rw-r--r-- | src/quick/scenegraph/qsgthreadedrenderloop.cpp | 11 | ||||
-rw-r--r-- | tests/auto/qml/qjsengine/tst_qjsengine.cpp | 77 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml | 36 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml | 80 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp | 107 | ||||
-rw-r--r-- | tools/qml/main.cpp | 13 |
17 files changed, 385 insertions, 39 deletions
diff --git a/.qmake.conf b/.qmake.conf index 831517bb0e..e78597cf64 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean DEFINES += QT_NO_LINKED_LIST DEFINES += QT_NO_JAVA_STYLE_ITERATORS -MODULE_VERSION = 5.15.14 +MODULE_VERSION = 5.15.15 diff --git a/src/qml/common/qqmljsmemorypool_p.h b/src/qml/common/qqmljsmemorypool_p.h index 0cf7ea84e6..1b81a87a2c 100644 --- a/src/qml/common/qqmljsmemorypool_p.h +++ b/src/qml/common/qqmljsmemorypool_p.h @@ -87,7 +87,7 @@ public: inline void *allocate(size_t size) { size = (size + 7) & ~size_t(7); - if (Q_LIKELY(_ptr && (_ptr + size < _end))) { + if (Q_LIKELY(_ptr && size < size_t(_end - _ptr))) { void *addr = _ptr; _ptr += size; return addr; diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 0eea3345c5..9816a646de 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -670,8 +670,8 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const return p1s->toQString() < p2s->toQString(); } -template <typename RandomAccessIterator, typename T, typename LessThan> -void sortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan) +template <typename RandomAccessIterator, typename LessThan> +void sortHelper(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan) { top: int span = int(end - start); @@ -716,7 +716,7 @@ top: ++low; qSwap(*end, *low); - sortHelper(start, low, t, lessThan); + sortHelper(start, low, lessThan); start = low + 1; ++end; @@ -816,8 +816,36 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c ArrayElementLessThan lessThan(engine, static_cast<const FunctionObject &>(comparefn)); - Value *begin = thisObject->arrayData()->values.values; - sortHelper(begin, begin + len, *begin, lessThan); + const auto thisArrayData = thisObject->arrayData(); + uint startIndex = thisArrayData->mappedIndex(0); + uint endIndex = thisArrayData->mappedIndex(len - 1) + 1; + if (startIndex < endIndex) { + // Values are contiguous. Sort right away. + sortHelper( + thisArrayData->values.values + startIndex, + thisArrayData->values.values + endIndex, + lessThan); + } else { + // Values wrap around the end of the allocation. Close the gap to form a contiguous array. + // We're going to sort anyway. So we don't need to care about order. + + // ArrayElementLessThan sorts empty and undefined to the end of the array anyway, but we + // probably shouldn't rely on the unused slots to be actually undefined or empty. + + const uint gap = startIndex - endIndex; + const uint allocEnd = thisArrayData->values.alloc - 1; + for (uint i = 0; i < gap; ++i) { + const uint from = allocEnd - i; + const uint to = endIndex + i; + if (from < startIndex) + break; + + std::swap(thisArrayData->values.values[from], thisArrayData->values.values[to]); + } + + thisArrayData->offset = 0; + sortHelper(thisArrayData->values.values, thisArrayData->values.values + len, lessThan); + } #ifdef CHECK_SPARSE_ARRAYS thisObject->initSparseArray(); diff --git a/src/qml/qml/ftw/qintrusivelist_p.h b/src/qml/qml/ftw/qintrusivelist_p.h index 8992be9f93..e7ae83c38d 100644 --- a/src/qml/qml/ftw/qintrusivelist_p.h +++ b/src/qml/qml/ftw/qintrusivelist_p.h @@ -241,7 +241,12 @@ typename QIntrusiveList<N, member>::iterator QIntrusiveList<N, member>::end() template<class N, QIntrusiveListNode N::*member> N *QIntrusiveList<N, member>::nodeToN(QIntrusiveListNode *node) { + QT_WARNING_PUSH +#if defined(Q_CC_CLANG) && ((__clang_major__ * 100) + __clang_minor__) >= 1300 + QT_WARNING_DISABLE_CLANG("-Wnull-pointer-subtraction") +#endif return (N *)((char *)node - ((char *)&(((N *)nullptr)->*member) - (char *)nullptr)); + QT_WARNING_POP } QIntrusiveListNode::QIntrusiveListNode() diff --git a/src/qml/qml/ftw/qrecyclepool_p.h b/src/qml/qml/ftw/qrecyclepool_p.h index 39f4f88512..c963e1878e 100644 --- a/src/qml/qml/ftw/qrecyclepool_p.h +++ b/src/qml/qml/ftw/qrecyclepool_p.h @@ -130,8 +130,7 @@ template<typename T, int Step> T *QRecyclePool<T, Step>::New() { T *rv = d->allocate(); - new (rv) T; - return rv; + return new (rv) T; } template<typename T, int Step> @@ -139,8 +138,7 @@ template<typename T1> T *QRecyclePool<T, Step>::New(const T1 &a) { T *rv = d->allocate(); - new (rv) T(a); - return rv; + return new (rv) T(a); } template<typename T, int Step> @@ -148,8 +146,7 @@ template<typename T1> T *QRecyclePool<T, Step>::New(T1 &a) { T *rv = d->allocate(); - new (rv) T(a); - return rv; + return new (rv) T(a); } template<typename T, int Step> diff --git a/src/quick/doc/images/qml-item-canvas-startAngle.png b/src/quick/doc/images/qml-item-canvas-startAngle.png Binary files differindex bf82c3aa4b..7930284896 100644 --- a/src/quick/doc/images/qml-item-canvas-startAngle.png +++ b/src/quick/doc/images/qml-item-canvas-startAngle.png diff --git a/src/quick/doc/src/examples.qdoc b/src/quick/doc/src/examples.qdoc index 9a1308440f..1675136817 100644 --- a/src/quick/doc/src/examples.qdoc +++ b/src/quick/doc/src/examples.qdoc @@ -124,7 +124,6 @@ Creator. \list \li \l{Qt Quick Controls - Gallery}{Controls Gallery} \li \l{Qt Quick System Dialog Examples}{Dialog Examples} - \li \l{Calendar Example} \li \l{tableview/gameoflife}{TableView} \li \l{Qt Quick Examples - Text}{Text and Fonts} \li \l{Qt Quick Examples - Toggle Switch}{Custom Toggle Switch} diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp index 28c62bd4f2..f6b3fafcda 100644 --- a/src/quick/items/context2d/qquickcontext2d.cpp +++ b/src/quick/items/context2d/qquickcontext2d.cpp @@ -2350,8 +2350,8 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_strokeRect(const QV4::Func \image qml-item-canvas-startAngle.png - The \a anticlockwise parameter is \c true for each arc in the figure above - because they are all drawn in the anticlockwise direction. + The \a anticlockwise parameter is \c false for each arc in the figure above + because they are all drawn in the clockwise direction. \sa arcTo, {http://www.w3.org/TR/2dcontext/#dom-context-2d-arc}{W3C's 2D Context Standard for arc()} diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index ec55fb2998..540d12c84a 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -70,6 +70,7 @@ #include <QtQuick/private/qquickaccessibleattached_p.h> #include <QtQuick/private/qquickhoverhandler_p.h> #include <QtQuick/private/qquickpointerhandler_p.h> +#include <QtQuick/private/qquickpointerhandler_p_p.h> #include <private/qv4engine_p.h> #include <private/qv4object_p.h> @@ -6341,6 +6342,15 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt } case QQuickItem::ItemSceneChange: q->itemChange(change, data); + if (hasPointerHandlers()) { + for (QQuickPointerHandler *handler : qAsConst(extra->pointerHandlers)) { + if (auto *currentEvent = handler->currentEvent()) { + for (int i = 0; i < currentEvent->pointCount(); ++i) + currentEvent->point(i)->cancelAllGrabs(handler); + } + } + } + break; case QQuickItem::ItemVisibleHasChanged: { q->itemChange(change, data); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 8ab69603ad..7bc5d97060 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -591,15 +591,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa renderer->setDevicePixelRatio(1); } } else { - QSize pixelSize; - QSizeF logicalSize; - if (surfaceSize.isEmpty()) { - pixelSize = size * devicePixelRatio; - logicalSize = size; - } else { - pixelSize = surfaceSize; - logicalSize = QSizeF(surfaceSize) / devicePixelRatio; - } + const QSize pixelSize = surfaceSize.isEmpty() ? size * devicePixelRatio : surfaceSize; QRect rect(QPoint(0, 0), pixelSize); renderer->setDeviceRect(rect); renderer->setViewportRect(rect); @@ -607,7 +599,7 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa QSGAbstractRenderer::MatrixTransformFlags matrixFlags; if (flipY) matrixFlags |= QSGAbstractRenderer::MatrixTransformFlipY; - renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), logicalSize), matrixFlags); + renderer->setProjectionMatrixToRect(QRectF(QPoint(0, 0), size), matrixFlags); renderer->setDevicePixelRatio(devicePixelRatio); } @@ -2673,7 +2665,7 @@ QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, QQui QPointF itemPos = item->mapFromScene(point->scenePosition()); // if the item clips, we can potentially return early if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { - if (!item->contains(itemPos)) + if (!item->clipRect().contains(itemPos)) return targets; } @@ -2901,6 +2893,14 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo if (itemPrivate->wasDeleted) return; #endif + // QTBUG-114475 - handlers shouldn't get events if their item was taken out of the scene + // by a previous event-handling mechanism. + if (item->window() != q) { + qCDebug(DBG_TOUCH) << "Not delivering " << pointerEvent << " to " << item + << "- item has been parented away"; + return; + } + pointerEvent->localize(item); // Let the Item's handlers (if any) have the event first. diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index ee01211545..d98a3b0f4d 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -672,7 +672,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) return; } - QSize effectiveOutputSize; // always prefer what the surface tells us, not the QWindow + QSize effectiveOutputSize; // always prefer what the surface or platform window tells us, not the QWindow if (cd->swapchain) { effectiveOutputSize = cd->swapchain->surfacePixelSize(); // An update request could still be delivered right before we get an @@ -680,6 +680,11 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) // leads to failures at this stage since the surface size is already 0. if (effectiveOutputSize.isEmpty()) return; + } else { + // Use platform window geometry to avoid introducing rounding errors + // due to fractonal Qt Gui scale factors. + QPlatformWindow *pw = window->handle(); + effectiveOutputSize = pw->geometry().size() * pw->devicePixelRatio(); } Q_TRACE_SCOPE(QSG_renderWindow); diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index d47b0d72a5..f5e3f2e864 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -368,6 +368,7 @@ public: QQuickWindow *window; // Will be 0 when window is not exposed QSize windowSize; + QSize windowPixelSize; float dpr = 1; int rhiSampleCount = 1; bool rhiDeviceLost = false; @@ -406,6 +407,13 @@ bool QSGRenderThread::event(QEvent *e) stopEventProcessing = true; window = se->window; windowSize = se->size; + if (window) { + // Use platform window geometry to avoid introducing rounding errors + // due to fractonal Qt Gui scale factors. + QPlatformWindow *pw = window->handle(); + windowPixelSize = pw->geometry().size() * pw->devicePixelRatio(); + } + dpr = se->dpr; pendingUpdate |= SyncRequest; @@ -833,7 +841,8 @@ void QSGRenderThread::syncAndRender(QImage *grabImage) } } if (current) { - d->renderSceneGraph(windowSize, rhi ? cd->swapchain->currentPixelSize() : QSize()); + const QSize surfaceSize = rhi ? cd->swapchain->currentPixelSize() : windowPixelSize; + d->renderSceneGraph(windowSize, surfaceSize); if (profileFrames) renderTime = threadTimer.nsecsElapsed(); diff --git a/tests/auto/qml/qjsengine/tst_qjsengine.cpp b/tests/auto/qml/qjsengine/tst_qjsengine.cpp index f1c34e6142..8e7958c3ef 100644 --- a/tests/auto/qml/qjsengine/tst_qjsengine.cpp +++ b/tests/auto/qml/qjsengine/tst_qjsengine.cpp @@ -105,6 +105,8 @@ private slots: void collectGarbageNestedWrappersTwoEngines(); void gcWithNestedDataStructure(); void stacktrace(); + void unshiftAndSort(); + void unshiftAndPushAndSort(); void numberParsing_data(); void numberParsing(); void automaticSemicolonInsertion(); @@ -1982,6 +1984,81 @@ void tst_QJSEngine::stacktrace() } } +void tst_QJSEngine::unshiftAndSort() +{ + QJSEngine engine; + QJSValue func = engine.evaluate(R"""( + (function (objectArr, currIdx) { + objectArr.unshift({"sortIndex": currIdx}); + objectArr.sort(function(a, b) { + if (a.sortIndex > b.sortIndex) + return 1; + if (a.sortIndex < b.sortIndex) + return -1; + return 0; + }); + return objectArr; + }) + )"""); + QVERIFY(func.isCallable()); + QJSValue objectArr = engine.newArray(); + + for (int i = 0; i < 5; ++i) { + objectArr = func.call({objectArr, i}); + QVERIFY2(!objectArr.isError(), qPrintable(objectArr.toString())); + const int length = objectArr.property("length").toInt(); + + // It did add one element + QCOMPARE(length, i + 1); + + for (int x = 0; x < length; ++x) { + // We didn't sort cruft into the array. + QVERIFY(!objectArr.property(x).isUndefined()); + + // The array is actually sorted. + QCOMPARE(objectArr.property(x).property("sortIndex").toInt(), x); + } + } +} + +void tst_QJSEngine::unshiftAndPushAndSort() +{ + QJSEngine engine; + QJSValue func = engine.evaluate(R"""( + (function (objectArr, currIdx) { + objectArr.unshift({"sortIndex": currIdx}); + objectArr.push({"sortIndex": currIdx + 1}); + objectArr.sort(function(a, b) { + if (a.sortIndex > b.sortIndex) + return 1; + if (a.sortIndex < b.sortIndex) + return -1; + return 0; + }); + return objectArr; + }) + )"""); + QVERIFY(func.isCallable()); + QJSValue objectArr = engine.newArray(); + + for (int i = 0; i < 20; i += 2) { + objectArr = func.call({objectArr, i}); + QVERIFY2(!objectArr.isError(), qPrintable(objectArr.toString())); + const int length = objectArr.property("length").toInt(); + + // It did add 2 elements + QCOMPARE(length, i + 2); + + for (int x = 0; x < length; ++x) { + // We didn't sort cruft into the array. + QVERIFY(!objectArr.property(x).isUndefined()); + + // The array is actually sorted. + QCOMPARE(objectArr.property(x).property("sortIndex").toInt(), x); + } + } +} + void tst_QJSEngine::numberParsing_data() { QTest::addColumn<QString>("string"); diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml new file mode 100644 index 0000000000..63bc94ae5c --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/clip.qml @@ -0,0 +1,36 @@ +import QtQuick 2.12 +import Qt.test 1.0 + +Item { + width: 200 + height: 200 + + Rectangle { + id: circle + y: 0 + width: 100 + height: width + radius: width/2 + color: "#3e1" + clip: true + + // Rectangle contains() is not affected by its 'radius' property + containmentMask: QtObject { + property alias radius: circle.radius + function contains(point: point) : bool { + return (Math.pow(point.x - radius, 2) + Math.pow(point.y - radius, 2)) < Math.pow(radius, 2) + } + } + EventHandler { + objectName: "circle eventHandler" + } + Rectangle { + width: circle.width/2 + height: width + color: "red" + EventHandler { + objectName: "eventHandler" + } + } + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml new file mode 100644 index 0000000000..166f7d4618 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/grabberSceneChange.qml @@ -0,0 +1,80 @@ +import QtQuick 2.12 +import QtQuick.Window 2.12 +import Qt.test 1.0 + +Window { + id: root + visible: true + objectName: "root" + width: 320 + height: 480 + + property bool useTimer : false + property int grabChangedCounter : 0 + + Item { + id: back + anchors.fill: parent + + Rectangle { + id: background + anchors.fill: parent + color: "blue" + } + + Rectangle { + id: container + objectName: "container" + anchors.fill: parent + anchors.margins: 50 + z: 2 + + Rectangle { + id: likeButton + color: "gray" + anchors.centerIn: parent + width: 200 + height: 200 + + DragHandler { + id: handler + objectName: "dragHandler" + grabPermissions: PointerHandler.CanTakeOverFromItems + onGrabChanged: { + ++grabChangedCounter + } + } + } + } + + Timer { + id: reparentTimer + running: false + interval: 100 + repeat: false + onTriggered: { + container.parent = null + } + } + + Rectangle { + id: likeButton2 + color: "yellow" + anchors.centerIn: parent + width: 100 + height: 100 + z: 3 + + MultiPointTouchArea { + id: press + anchors.fill: parent + onPressed: { + if (useTimer) + reparentTimer.running = true + else + container.parent = null + } + } + } + } +} diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp index 2b6482465c..7be2198197 100644 --- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp @@ -244,6 +244,9 @@ private slots: void dynamicCreation(); void handlerInWindow(); void dynamicCreationInWindow(); + void grabberSceneChange_data(); + void grabberSceneChange(); + void clip(); protected: bool eventFilter(QObject *, QEvent *event) @@ -679,6 +682,110 @@ void tst_PointerHandlers::dynamicCreationInWindow() QTRY_COMPARE(handler->releaseEventCount, 1); } +/*! + Verify that removing an item that has a grabbing handler from the scene + does not result in crashes in our event dispatching code. The item's window() + pointer will be nullptr, so the handler must have released the grab, or never + gotten the grab, depending on when the item gets removed. + + See QTBUG-114475. +*/ +void tst_PointerHandlers::grabberSceneChange_data() +{ + QTest::addColumn<bool>("useTimer"); + QTest::addColumn<int>("grabChangedCount"); + + QTest::addRow("Immediately") << false << 0; + QTest::addRow("Delayed") << true << 2; +} + +void tst_PointerHandlers::grabberSceneChange() +{ + QFETCH(const bool, useTimer); + QFETCH(const int, grabChangedCount); + + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("grabberSceneChange.qml")); + QQuickWindow *window = qobject_cast<QQuickWindow*>(component.create()); + QScopedPointer<QQuickWindow> cleanup(window); + QVERIFY(window); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + window->setProperty("useTimer", useTimer); + + QQuickItem *container = window->findChild<QQuickItem *>("container"); + + QPoint p1 = QPoint(window->width() / 2, window->height() / 2); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + // The container gets removed from this window, either immediately on + // press, or through a timer. + QTRY_COMPARE(container->parentItem(), nullptr); + + QCOMPARE(window->property("grabChangedCounter").toInt(), grabChangedCount); + + // this should not crash + QTest::mouseMove(window, p1 + QPoint(5, 5)); +} + +void tst_PointerHandlers::clip() +{ + QScopedPointer<QQuickView> windowPtr; + createView(windowPtr, "clip.qml"); + QQuickView * window = windowPtr.data(); + QVERIFY(window); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + EventHandler *handler = window->contentItem()->findChild<EventHandler*>("eventHandler"); + EventHandler *circleHandler = window->contentItem()->findChild<EventHandler*>("circle eventHandler"); + + QCOMPARE(handler->pressEventCount, 0); + QCOMPARE(circleHandler->pressEventCount, 0); + QCOMPARE(handler->releaseEventCount, 0); + QCOMPARE(circleHandler->releaseEventCount, 0); + + const QPoint rectPt = QPoint(1, 1); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, rectPt); + QCOMPARE(handler->pressEventCount, 1); + QCOMPARE(circleHandler->pressEventCount, 0); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, rectPt); + QCOMPARE(handler->releaseEventCount, 1); + QCOMPARE(circleHandler->releaseEventCount, 0); + + + handler->pressEventCount = 0; + circleHandler->pressEventCount = 0; + handler->releaseEventCount = 0; + circleHandler->releaseEventCount = 0; + + const QPoint rectAndCirclePt = QPoint(49 ,49); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, rectAndCirclePt); + QCOMPARE(handler->pressEventCount, 1); + QCOMPARE(circleHandler->pressEventCount, 1); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, rectAndCirclePt); + QCOMPARE(handler->releaseEventCount, 1); + QCOMPARE(circleHandler->releaseEventCount, 1); + + + handler->pressEventCount = 0; + circleHandler->pressEventCount = 0; + handler->releaseEventCount = 0; + circleHandler->releaseEventCount = 0; + + const QPoint circlePt = QPoint(51 ,51); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, circlePt); + QCOMPARE(handler->pressEventCount, 0); + QCOMPARE(circleHandler->pressEventCount, 1); + + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, circlePt); + QCOMPARE(handler->releaseEventCount, 0); + QCOMPARE(circleHandler->releaseEventCount, 1); +} + QTEST_MAIN(tst_PointerHandlers) #include "tst_qquickpointerhandler.moc" diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index beeec88f07..2cb7653d65 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -446,8 +446,8 @@ int main(int argc, char *argv[]) QCommandLineParser parser; parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments); - const QCommandLineOption helpOption = parser.addHelpOption(); - const QCommandLineOption versionOption = parser.addVersionOption(); + parser.addHelpOption(); + parser.addVersionOption(); #ifdef QT_GUI_LIB QCommandLineOption apptypeOption(QStringList() << QStringLiteral("a") << QStringLiteral("apptype"), QCoreApplication::translate("main", "Select which application class to use. Default is gui."), @@ -522,14 +522,7 @@ int main(int argc, char *argv[]) parser.addPositionalArgument("args", QCoreApplication::translate("main", "Arguments after '--' are ignored, but passed through to the application.arguments variable in QML."), "[-- args...]"); - if (!parser.parse(QCoreApplication::arguments())) { - qWarning() << parser.errorText(); - exit(1); - } - if (parser.isSet(versionOption)) - parser.showVersion(); - if (parser.isSet(helpOption)) - parser.showHelp(); + parser.process(*app); if (parser.isSet(listConfOption)) listConfFiles(); if (applicationType == QmlApplicationTypeUnknown) { |