diff options
author | Liang Qi <liang.qi@qt.io> | 2018-10-08 10:50:52 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-10-08 10:52:26 +0200 |
commit | 86699cbccaa044adfd36a14453de8e5c0cefc226 (patch) | |
tree | ea5662ef8746842a765612f45a9f48f25b9c5d6a | |
parent | 2bcfb322df727abf96022830077d4ae8b30f644d (diff) | |
parent | 10095542d16fc9f5b2c585abf72fe00be9debff3 (diff) |
Merge remote-tracking branch 'origin/5.11' into 5.12
Conflicts:
src/3rdparty/masm/yarr/YarrJIT.h
src/quick/items/qquickwindow.cpp
Change-Id: I551404e1558d56c0b0626346ad1c86406bff0ec7
-rw-r--r-- | src/3rdparty/masm/runtime/MatchResult.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 4 | ||||
-rw-r--r-- | src/quick/doc/src/includes/item.qdocinc | 9 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 53 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 73 | ||||
-rw-r--r-- | src/quick/util/qquickanimatorjob.cpp | 6 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/tst_touchmouse.cpp | 104 |
8 files changed, 175 insertions, 77 deletions
diff --git a/src/3rdparty/masm/runtime/MatchResult.h b/src/3rdparty/masm/runtime/MatchResult.h index d87c8516b0..b7aaa6b6fc 100644 --- a/src/3rdparty/masm/runtime/MatchResult.h +++ b/src/3rdparty/masm/runtime/MatchResult.h @@ -35,6 +35,7 @@ struct MatchResult { { } +#if !CPU(X86_64) && !CPU(ARM64) explicit ALWAYS_INLINE MatchResult(EncodedMatchResult encoded) { union u { @@ -48,6 +49,7 @@ struct MatchResult { start = value.split.start; end = value.split.end; } +#endif ALWAYS_INLINE static MatchResult failed() { diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index c25e386131..49607256f9 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -206,6 +206,10 @@ public: bool isValid() const { return type != Invalid; } bool loadTriggersSideEffect() const { switch (type) { + case QmlScopeObject: + return capturePolicy != DontCapture; + case QmlContextObject: + return capturePolicy != DontCapture; case Name: case Member: case Subscript: diff --git a/src/quick/doc/src/includes/item.qdocinc b/src/quick/doc/src/includes/item.qdocinc index 12472cb928..4cb2652bbf 100644 --- a/src/quick/doc/src/includes/item.qdocinc +++ b/src/quick/doc/src/includes/item.qdocinc @@ -4,3 +4,12 @@ The following properties of the item are used in the mapping: \l x, \l y, \l scale, \l rotation, \l transformOrigin, and \l [QML]{Item::}{transform}. //! [mapping] + + +//! [accepting-events] + +The event is accepted by default, so it is not necessary to explicitly +accept the event if you reimplement this function. If you don't accept the +event, call \c event->ignore(). + +//! [accepting-events] diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index f7e7a1b773..eba3842c10 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3919,6 +3919,16 @@ void QQuickItemPrivate::addItemChangeListener(QQuickItemChangeListener *listener changeListeners.append(ChangeListener(listener, types)); } +void QQuickItemPrivate::updateOrAddItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types) +{ + const ChangeListener changeListener(listener, types); + const int index = changeListeners.indexOf(changeListener); + if (index > -1) + changeListeners[index].types = changeListener.types; + else + changeListeners.append(changeListener); +} + void QQuickItemPrivate::removeItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types) { ChangeListener change(listener, types); @@ -3953,6 +3963,8 @@ void QQuickItemPrivate::updateOrRemoveGeometryChangeListener(QQuickItemChangeLis This event handler can be reimplemented in a subclass to receive key press events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::keyPressEvent(QKeyEvent *event) { @@ -3963,6 +3975,8 @@ void QQuickItem::keyPressEvent(QKeyEvent *event) This event handler can be reimplemented in a subclass to receive key release events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::keyReleaseEvent(QKeyEvent *event) { @@ -3974,6 +3988,8 @@ void QQuickItem::keyReleaseEvent(QKeyEvent *event) This event handler can be reimplemented in a subclass to receive input method events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::inputMethodEvent(QInputMethodEvent *event) { @@ -3985,6 +4001,11 @@ void QQuickItem::inputMethodEvent(QInputMethodEvent *event) This event handler can be reimplemented in a subclass to receive focus-in events for an item. The event information is provided by the \c event parameter. + + \input item.qdocinc accepting-events + + If you do reimplement this function, you should call the base class + implementation. */ void QQuickItem::focusInEvent(QFocusEvent * /*event*/) { @@ -4002,6 +4023,8 @@ void QQuickItem::focusInEvent(QFocusEvent * /*event*/) This event handler can be reimplemented in a subclass to receive focus-out events for an item. The event information is provided by the \c event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::focusOutEvent(QFocusEvent * /*event*/) { @@ -4011,6 +4034,8 @@ void QQuickItem::focusOutEvent(QFocusEvent * /*event*/) This event handler can be reimplemented in a subclass to receive mouse press events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::mousePressEvent(QMouseEvent *event) { @@ -4021,6 +4046,8 @@ void QQuickItem::mousePressEvent(QMouseEvent *event) This event handler can be reimplemented in a subclass to receive mouse move events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::mouseMoveEvent(QMouseEvent *event) { @@ -4031,6 +4058,8 @@ void QQuickItem::mouseMoveEvent(QMouseEvent *event) This event handler can be reimplemented in a subclass to receive mouse release events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::mouseReleaseEvent(QMouseEvent *event) { @@ -4041,6 +4070,8 @@ void QQuickItem::mouseReleaseEvent(QMouseEvent *event) This event handler can be reimplemented in a subclass to receive mouse double-click events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::mouseDoubleClickEvent(QMouseEvent *) { @@ -4050,7 +4081,7 @@ void QQuickItem::mouseDoubleClickEvent(QMouseEvent *) This event handler can be reimplemented in a subclass to be notified when a mouse ungrab event has occurred on this item. - \sa ungrabMouse() + \input item.qdocinc accepting-events */ void QQuickItem::mouseUngrabEvent() { @@ -4060,6 +4091,8 @@ void QQuickItem::mouseUngrabEvent() /*! This event handler can be reimplemented in a subclass to be notified when a touch ungrab event has occurred on this item. + + \input item.qdocinc accepting-events */ void QQuickItem::touchUngrabEvent() { @@ -4071,6 +4104,8 @@ void QQuickItem::touchUngrabEvent() This event handler can be reimplemented in a subclass to receive wheel events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::wheelEvent(QWheelEvent *event) { @@ -4082,6 +4117,8 @@ void QQuickItem::wheelEvent(QWheelEvent *event) This event handler can be reimplemented in a subclass to receive touch events for an item. The event information is provided by the \a event parameter. + + \input item.qdocinc accepting-events */ void QQuickItem::touchEvent(QTouchEvent *event) { @@ -4094,6 +4131,8 @@ void QQuickItem::touchEvent(QTouchEvent *event) \a event parameter. Hover events are only provided if acceptHoverEvents() is true. + + \input item.qdocinc accepting-events */ void QQuickItem::hoverEnterEvent(QHoverEvent *event) { @@ -4106,6 +4145,8 @@ void QQuickItem::hoverEnterEvent(QHoverEvent *event) \a event parameter. Hover events are only provided if acceptHoverEvents() is true. + + \input item.qdocinc accepting-events */ void QQuickItem::hoverMoveEvent(QHoverEvent *event) { @@ -4118,6 +4159,8 @@ void QQuickItem::hoverMoveEvent(QHoverEvent *event) \a event parameter. Hover events are only provided if acceptHoverEvents() is true. + + \input item.qdocinc accepting-events */ void QQuickItem::hoverLeaveEvent(QHoverEvent *event) { @@ -4133,6 +4176,8 @@ void QQuickItem::hoverLeaveEvent(QHoverEvent *event) Drag and drop events are only provided if the ItemAcceptsDrops flag has been set for this item. + \input item.qdocinc accepting-events + \sa Drag, {Drag and Drop} */ void QQuickItem::dragEnterEvent(QDragEnterEvent *event) @@ -4148,6 +4193,8 @@ void QQuickItem::dragEnterEvent(QDragEnterEvent *event) Drag and drop events are only provided if the ItemAcceptsDrops flag has been set for this item. + \input item.qdocinc accepting-events + \sa Drag, {Drag and Drop} */ void QQuickItem::dragMoveEvent(QDragMoveEvent *event) @@ -4163,6 +4210,8 @@ void QQuickItem::dragMoveEvent(QDragMoveEvent *event) Drag and drop events are only provided if the ItemAcceptsDrops flag has been set for this item. + \input item.qdocinc accepting-events + \sa Drag, {Drag and Drop} */ void QQuickItem::dragLeaveEvent(QDragLeaveEvent *event) @@ -4178,6 +4227,8 @@ void QQuickItem::dragLeaveEvent(QDragLeaveEvent *event) Drag and drop events are only provided if the ItemAcceptsDrops flag has been set for this item. + \input item.qdocinc accepting-events + \sa Drag, {Drag and Drop} */ void QQuickItem::dropEvent(QDropEvent *event) diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 24941ab264..11b47114cf 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -415,6 +415,7 @@ public: QVector<QQuickItemPrivate::ChangeListener> changeListeners; void addItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types); + void updateOrAddItemChangeListener(QQuickItemChangeListener *listener, ChangeTypes types); void removeItemChangeListener(QQuickItemChangeListener *, ChangeTypes types); void updateOrAddGeometryChangeListener(QQuickItemChangeListener *listener, QQuickGeometryChange types); void updateOrRemoveGeometryChangeListener(QQuickItemChangeListener *listener, QQuickGeometryChange types); diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 8caa568a6c..059886f41c 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1738,48 +1738,49 @@ void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QQuic void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent) { + Q_Q(QQuickWindow); auto point = pointerEvent->point(0); lastMousePosition = point->scenePosition(); const bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton); + QQuickItem *grabberItem = point->grabberItem(); + if (!grabberItem && isDeliveringTouchAsMouse()) + grabberItem = q->mouseGrabberItem(); - if (point->exclusiveGrabber()) { - if (auto grabber = point->grabberItem()) { - bool handled = false; - hasFiltered.clear(); - if (sendFilteredPointerEvent(pointerEvent, grabber)) - handled = true; - // if the grabber is an Item: - // if the update consists of changing button state, don't accept it unless - // the button is one in which the grabber is interested - Qt::MouseButtons acceptedButtons = grabber->acceptedMouseButtons(); - if (!handled && pointerEvent->button() != Qt::NoButton && acceptedButtons - && !(acceptedButtons & pointerEvent->button())) { - pointerEvent->setAccepted(false); - handled = true; - } - - // send update - if (!handled) { - QPointF localPos = grabber->mapFromScene(lastMousePosition); - auto me = pointerEvent->asMouseEvent(localPos); - me->accept(); - QCoreApplication::sendEvent(grabber, me); - point->setAccepted(me->isAccepted()); - } + if (grabberItem) { + bool handled = false; + hasFiltered.clear(); + if (sendFilteredPointerEvent(pointerEvent, grabberItem)) + handled = true; + // if the grabber is an Item: + // if the update consists of changing button state, don't accept it unless + // the button is one in which the grabber is interested + Qt::MouseButtons acceptedButtons = grabberItem->acceptedMouseButtons(); + if (!handled && pointerEvent->button() != Qt::NoButton && acceptedButtons + && !(acceptedButtons & pointerEvent->button())) { + pointerEvent->setAccepted(false); + handled = true; + } - // release event: ungrab if no buttons are pressed anymore - if (mouseIsReleased) - removeGrabber(grabber, true, isDeliveringTouchAsMouse()); - } else { - // if the grabber is not an Item, it must be a PointerHandler - auto handler = point->grabberPointerHandler(); - pointerEvent->localize(handler->parentItem()); - hasFiltered.clear(); - if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem())) - handler->handlePointerEvent(pointerEvent); - if (mouseIsReleased) - point->setGrabberPointerHandler(nullptr, true); + // send update + if (!handled) { + QPointF localPos = grabberItem->mapFromScene(lastMousePosition); + auto me = pointerEvent->asMouseEvent(localPos); + me->accept(); + QCoreApplication::sendEvent(grabberItem, me); + point->setAccepted(me->isAccepted()); } + + // release event: ungrab if no buttons are pressed anymore + if (mouseIsReleased) + removeGrabber(grabberItem, true, isDeliveringTouchAsMouse()); + deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent); + } else if (auto handler = point->grabberPointerHandler()) { + pointerEvent->localize(handler->parentItem()); + hasFiltered.clear(); + if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem())) + handler->handlePointerEvent(pointerEvent); + if (mouseIsReleased) + point->setGrabberPointerHandler(nullptr, true); deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent); } else { bool delivered = false; diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 6574f8f67e..03be78ab15 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -217,8 +217,10 @@ void QQuickAnimatorProxyJob::setWindow(QQuickWindow *window) void QQuickAnimatorProxyJob::sceneGraphInitialized() { - disconnect(m_controller->window(), &QQuickWindow::sceneGraphInitialized, this, &QQuickAnimatorProxyJob::sceneGraphInitialized); - readyToAnimate(); + if (m_controller) { + disconnect(m_controller->window(), &QQuickWindow::sceneGraphInitialized, this, &QQuickAnimatorProxyJob::sceneGraphInitialized); + readyToAnimate(); + } } void QQuickAnimatorProxyJob::readyToAnimate() diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 052d81b6de..7fccb895db 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -28,6 +28,7 @@ #include <QtTest/QtTest> +#include <QDebug> #include <QtGui/qstylehints.h> #include <private/qdebug_p.h> @@ -47,6 +48,8 @@ #include "../../shared/util.h" #include "../shared/viewtestutil.h" +Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") + struct Event { Event(QEvent::Type t, QPoint mouse, QPoint global) @@ -703,14 +706,18 @@ void tst_TouchMouse::touchButtonOnFlickable() void tst_TouchMouse::buttonOnDelayedPressFlickable_data() { QTest::addColumn<bool>("scrollBeforeDelayIsOver"); + QTest::addColumn<bool>("releaseBeforeDelayIsOver"); // the item should never see the event, // due to the pressDelay which never delivers if we start moving - QTest::newRow("scroll before press delay is over") << true; + QTest::newRow("scroll before press delay is over") << true << false; + + // after release, the item should see the press and release via event replay (QTBUG-61144) + QTest::newRow("release before press delay is over") << false << true; // wait until the "button" sees the press but then // start moving: the button gets a press and cancel event - QTest::newRow("scroll after press delay is over") << false; + QTest::newRow("scroll after press delay is over") << false << false; } void tst_TouchMouse::buttonOnDelayedPressFlickable() @@ -719,6 +726,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() // - eventItem1 y: 100, height 100 // - eventItem2 y: 300, height 100 QFETCH(bool, scrollBeforeDelayIsOver); + QFETCH(bool, releaseBeforeDelayIsOver); qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true); filteredEventList.clear(); @@ -757,11 +765,12 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() // touch press QPoint p1 = QPoint(10, 110); + QPoint pEnd = p1; QTest::touchEvent(window.data(), device).press(0, p1, window.data()); QQuickTouchUtils::flush(window.data()); - if (scrollBeforeDelayIsOver) { - // no events, the flickable got scrolled, the button sees nothing + if (scrollBeforeDelayIsOver || releaseBeforeDelayIsOver) { + // no events yet: press is delayed QCOMPARE(eventItem1->eventList.size(), 0); } else { // wait until the button sees the press @@ -770,45 +779,64 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() QCOMPARE(filteredEventList.count(), 1); } - p1 += QPoint(0, -10); - QPoint p2 = p1 + QPoint(0, -10); - QPoint p3 = p2 + QPoint(0, -10); - QQuickTouchUtils::flush(window.data()); - QTest::touchEvent(window.data(), device).move(0, p1, window.data()); - QQuickTouchUtils::flush(window.data()); - QTest::touchEvent(window.data(), device).move(0, p2, window.data()); - QQuickTouchUtils::flush(window.data()); - QTest::touchEvent(window.data(), device).move(0, p3, window.data()); - QQuickTouchUtils::flush(window.data()); - QTRY_VERIFY(flickable->isMovingVertically()); + if (!releaseBeforeDelayIsOver) { + // move the touchpoint: try to flick + p1 += QPoint(0, -10); + QPoint p2 = p1 + QPoint(0, -10); + pEnd = p2 + QPoint(0, -10); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p1, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, p2, window.data()); + QQuickTouchUtils::flush(window.data()); + QTest::touchEvent(window.data(), device).move(0, pEnd, window.data()); + QQuickTouchUtils::flush(window.data()); + QTRY_VERIFY(flickable->isMovingVertically()); + + if (scrollBeforeDelayIsOver) { + QCOMPARE(eventItem1->eventList.size(), 0); + QCOMPARE(filteredEventList.count(), 0); + } else { + // see at least press, move and ungrab + QTRY_VERIFY(eventItem1->eventList.size() > 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); + QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse); + QCOMPARE(filteredEventList.count(), 1); + } - if (scrollBeforeDelayIsOver) { - QCOMPARE(eventItem1->eventList.size(), 0); - QCOMPARE(filteredEventList.count(), 0); - } else { - // see at least press, move and ungrab - QTRY_VERIFY(eventItem1->eventList.size() > 2); - QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); - QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse); - QCOMPARE(filteredEventList.count(), 1); + // flickable should have the mouse grab, and have moved the itemForTouchPointId + // for the touchMouseId to the new grabber. + QCOMPARE(window->mouseGrabberItem(), flickable); + QVERIFY(windowPriv->touchMouseId != -1); + auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0)); + QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable); } - // flickable should have the mouse grab, and have moved the itemForTouchPointId - // for the touchMouseId to the new grabber. - QCOMPARE(window->mouseGrabberItem(), flickable); - QVERIFY(windowPriv->touchMouseId != -1); - auto pointerEvent = windowPriv->pointerEventInstance(QQuickPointerDevice::touchDevices().at(0)); - QCOMPARE(pointerEvent->point(0)->grabberItem(), flickable); - - QTest::touchEvent(window.data(), device).release(0, p3, window.data()); + QTest::touchEvent(window.data(), device).release(0, pEnd, window.data()); QQuickTouchUtils::flush(window.data()); - // We should not have received any synthesised mouse events from Qt gui, - // just the delayed press. - if (scrollBeforeDelayIsOver) - QCOMPARE(filteredEventList.count(), 0); - else - QCOMPARE(filteredEventList.count(), 1); + if (releaseBeforeDelayIsOver) { + // when the touchpoint was released, the child saw the delayed press and the release in sequence + qCDebug(lcTests) << "expected delivered events: press, release, ungrab" << eventItem1->eventList; + qCDebug(lcTests) << "expected filtered events: delayed press, release" << filteredEventList; + QTRY_COMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease); + QCOMPARE(eventItem1->eventList.last().type, QEvent::UngrabMouse); + // QQuickWindow filters the delayed press and release + QCOMPARE(filteredEventList.count(), 2); + QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress); + QCOMPARE(filteredEventList.at(1).type, QEvent::MouseButtonRelease); + } else { + // QQuickWindow filters the delayed press if there was one; otherwise nothing + if (scrollBeforeDelayIsOver) { + QCOMPARE(filteredEventList.count(), 0); + } else { + qCDebug(lcTests) << "expected filtered event: delayed press" << filteredEventList; + QCOMPARE(filteredEventList.count(), 1); + QCOMPARE(filteredEventList.at(0).type, QEvent::MouseButtonPress); + } + } } void tst_TouchMouse::buttonOnTouch() |