aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-12-20 08:32:22 +0100
committerLiang Qi <liang.qi@qt.io>2017-12-20 08:50:58 +0100
commit9a38fdcf8f9b734808bb54422e306872f3bfa944 (patch)
tree20fd361db6c505d99a40ab7a695511b97dcdcbd3 /src/quick/items
parent1db9405128972d5ba77e33181bee40356f718cea (diff)
parent4fff2bb14e55484eacec0a1b49a2b02958f75eca (diff)
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts: tests/auto/quick/pointerhandlers/flickableinterop/data/FlashAnimation.qml tests/auto/quick/pointerhandlers/flickableinterop/data/Slider.qml tests/auto/quick/pointerhandlers/flickableinterop/data/TapHandlerButton.qml tests/auto/quick/pointerhandlers/flickableinterop/data/flickableWithHandlers.qml tests/auto/quick/pointerhandlers/multipointtoucharea_interop/data/pinchDragMPTA.qml tests/auto/quick/pointerhandlers/qquickdraghandler/data/DragAnywhereSlider.qml tests/auto/quick/pointerhandlers/qquickdraghandler/data/FlashAnimation.qml tests/auto/quick/pointerhandlers/qquickdraghandler/data/Slider.qml tests/auto/quick/pointerhandlers/qquickdraghandler/data/draggables.qml tests/auto/quick/pointerhandlers/qquickdraghandler/data/multipleSliders.qml tests/auto/quick/pointerhandlers/qquicktaphandler/data/Button.qml tests/auto/quick/pointerhandlers/qquicktaphandler/data/FlashAnimation.qml tests/auto/quick/pointerhandlers/qquicktaphandler/data/buttons.qml tests/manual/pointer/content/FakeFlickable.qml tests/manual/pointer/content/FlashAnimation.qml tests/manual/pointer/content/MomentumAnimation.qml tests/manual/pointer/content/MouseAreaButton.qml tests/manual/pointer/content/MouseAreaSlider.qml tests/manual/pointer/content/MptaButton.qml tests/manual/pointer/content/MultiButton.qml tests/manual/pointer/content/ScrollBar.qml tests/manual/pointer/content/Slider.qml tests/manual/pointer/content/TapHandlerButton.qml tests/manual/pointer/fakeFlickable.qml tests/manual/pointer/flickableWithHandlers.qml tests/manual/pointer/flingAnimation.qml tests/manual/pointer/joystick.qml tests/manual/pointer/main.cpp tests/manual/pointer/main.qml tests/manual/pointer/map.qml tests/manual/pointer/map2.qml tests/manual/pointer/mixer.qml tests/manual/pointer/multibuttons.qml tests/manual/pointer/photosurface.qml tests/manual/pointer/pinchDragFlingMPTA.qml tests/manual/pointer/pinchHandler.qml tests/manual/pointer/singlePointHandlerProperties.qml tests/manual/pointer/tapHandler.qml tests/manual/pointer/tapWithModifiers.qml tests/manual/shapestest/main.cpp Change-Id: I4f233a521305fab1ebfecbac801da192434ed524
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickevents.cpp32
-rw-r--r--src/quick/items/qquickevents_p_p.h1
-rw-r--r--src/quick/items/qquickflickable.cpp56
-rw-r--r--src/quick/items/qquickitem.cpp2
-rw-r--r--src/quick/items/qquickitemview.cpp48
-rw-r--r--src/quick/items/qquickopenglshadereffect.cpp2
-rw-r--r--src/quick/items/qquickwindow.cpp172
-rw-r--r--src/quick/items/qquickwindow_p.h1
8 files changed, 172 insertions, 142 deletions
diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp
index 8653d758de..4a786d5569 100644
--- a/src/quick/items/qquickevents.cpp
+++ b/src/quick/items/qquickevents.cpp
@@ -790,17 +790,19 @@ QQuickItem *QQuickEventPoint::grabberItem() const
void QQuickEventPoint::setGrabberItem(QQuickItem *grabber)
{
if (grabber != m_exclusiveGrabber.data()) {
+ QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
+ if (oldGrabberHandler && !oldGrabberHandler->approveGrabTransition(this, grabber))
+ return;
if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this)
<< ": grab" << m_exclusiveGrabber << "->" << grabber;
}
- QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
- QQuickItem *oldGrabberItem = grabberItem();
m_exclusiveGrabber = QPointer<QObject>(grabber);
m_grabberIsHandler = false;
m_sceneGrabPos = m_scenePos;
+ QQuickItem *oldGrabberItem = grabberItem();
if (oldGrabberHandler)
- oldGrabberHandler->onGrabChanged(oldGrabberHandler, CancelGrabExclusive, this);
+ oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this);
else if (oldGrabberItem && oldGrabberItem != grabber && grabber && pointerEvent()->asPointerTouchEvent())
oldGrabberItem->touchUngrabEvent();
for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers)
@@ -837,26 +839,24 @@ void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, b
}
if (exclusive) {
if (grabber != m_exclusiveGrabber.data()) {
+ QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
+ QQuickItem *oldGrabberItem = grabberItem();
+ m_exclusiveGrabber = QPointer<QObject>(grabber);
+ m_grabberIsHandler = true;
+ m_sceneGrabPos = m_scenePos;
if (grabber) {
- // set variables before notifying the new grabber
- m_exclusiveGrabber = QPointer<QObject>(grabber);
- m_grabberIsHandler = true;
- m_sceneGrabPos = m_scenePos;
grabber->onGrabChanged(grabber, GrabExclusive, this);
for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers) {
if (passiveGrabber != grabber)
passiveGrabber->onGrabChanged(grabber, OverrideGrabPassive, this);
}
- } else if (QQuickPointerHandler *oldGrabberPointerHandler = qmlobject_cast<QQuickPointerHandler *>(m_exclusiveGrabber.data())) {
- oldGrabberPointerHandler->onGrabChanged(oldGrabberPointerHandler, UngrabExclusive, this);
- } else if (!m_exclusiveGrabber.isNull()) {
- // If there is a previous grabber and it's not a PointerHandler, it must be an Item.
- QQuickItem *oldGrabberItem = static_cast<QQuickItem *>(m_exclusiveGrabber.data());
- // If this point came from a touchscreen, notify that previous grabber Item that it's losing its touch grab.
- if (pointerEvent()->asPointerTouchEvent())
- oldGrabberItem->touchUngrabEvent();
}
- // set variables after notifying the old grabber
+ if (oldGrabberHandler)
+ oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this);
+ else if (oldGrabberItem && pointerEvent()->asPointerTouchEvent())
+ oldGrabberItem->touchUngrabEvent();
+ // touchUngrabEvent() can result in the grabber being set to null (MPTA does that, for example).
+ // So set it again to ensure that final state is what we want.
m_exclusiveGrabber = QPointer<QObject>(grabber);
m_grabberIsHandler = true;
m_sceneGrabPos = m_scenePos;
diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h
index 09a63febdc..af5857cf63 100644
--- a/src/quick/items/qquickevents_p_p.h
+++ b/src/quick/items/qquickevents_p_p.h
@@ -306,7 +306,6 @@ public:
void setExclusiveGrabber(QObject *exclusiveGrabber);
QQuickItem *grabberItem() const;
- Q_DECL_DEPRECATED QQuickItem *grabber() const { return grabberItem(); }
void setGrabberItem(QQuickItem *exclusiveGrabber);
QQuickPointerHandler *grabberPointerHandler() const;
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index cd918cef5f..bec5f06d72 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -725,7 +725,19 @@ QQuickFlickable::~QQuickFlickable()
These properties hold the surface coordinate currently at the top-left
corner of the Flickable. For example, if you flick an image up 100 pixels,
- \c contentY will be 100.
+ \c contentY will increase by 100.
+
+ \note If you flick back to the origin (the top-left corner), after the
+ rebound animation, \c contentX will settle to the same value as \c originX,
+ and \c contentY to \c originY. These are usually (0,0), however ListView
+ and GridView may have an arbitrary origin due to delegate size variation,
+ or item insertion/removal outside the visible region. So if you want to
+ implement something like a vertical scrollbar, one way is to use
+ \c {y: (contentY - originY) * (height / contentHeight)}
+ for the position; another way is to use the normalized values in
+ \l {QtQuick::Flickable::visibleArea}{visibleArea}.
+
+ \sa originX, originY
*/
qreal QQuickFlickable::contentX() const
{
@@ -739,7 +751,8 @@ void QQuickFlickable::setContentX(qreal pos)
d->hData.explicitValue = true;
d->resetTimeline(d->hData);
d->hData.vTime = d->timeline.time();
- movementEnding(true, false);
+ if (isMoving() || isFlicking())
+ movementEnding(true, false);
if (-pos != d->hData.move.value())
d->hData.move.setValue(-pos);
}
@@ -756,7 +769,8 @@ void QQuickFlickable::setContentY(qreal pos)
d->vData.explicitValue = true;
d->resetTimeline(d->vData);
d->vData.vTime = d->timeline.time();
- movementEnding(false, true);
+ if (isMoving() || isFlicking())
+ movementEnding(false, true);
if (-pos != d->vData.move.value())
d->vData.move.setValue(-pos);
}
@@ -2150,6 +2164,8 @@ void QQuickFlickable::setRightMargin(qreal m)
This is usually (0,0), however ListView and GridView may have an arbitrary
origin due to delegate size variation, or item insertion/removal outside
the visible region.
+
+ \sa contentX, contentY
*/
qreal QQuickFlickable::originY() const
@@ -2180,25 +2196,25 @@ qreal QQuickFlickable::originX() const
void QQuickFlickable::resizeContent(qreal w, qreal h, QPointF center)
{
Q_D(QQuickFlickable);
- if (w != d->hData.viewSize) {
- qreal oldSize = d->hData.viewSize;
- d->hData.viewSize = w;
- d->contentItem->setWidth(w);
+ const qreal oldHSize = d->hData.viewSize;
+ const qreal oldVSize = d->vData.viewSize;
+ const bool needToUpdateWidth = w != oldHSize;
+ const bool needToUpdateHeight = h != oldVSize;
+ d->hData.viewSize = w;
+ d->vData.viewSize = h;
+ d->contentItem->setSize(QSizeF(w, h));
+ if (needToUpdateWidth)
emit contentWidthChanged();
- if (center.x() != 0) {
- qreal pos = center.x() * w / oldSize;
- setContentX(contentX() + pos - center.x());
- }
- }
- if (h != d->vData.viewSize) {
- qreal oldSize = d->vData.viewSize;
- d->vData.viewSize = h;
- d->contentItem->setHeight(h);
+ if (needToUpdateHeight)
emit contentHeightChanged();
- if (center.y() != 0) {
- qreal pos = center.y() * h / oldSize;
- setContentY(contentY() + pos - center.y());
- }
+
+ if (center.x() != 0) {
+ qreal pos = center.x() * w / oldHSize;
+ setContentX(contentX() + pos - center.x());
+ }
+ if (center.y() != 0) {
+ qreal pos = center.y() * h / oldVSize;
+ setContentY(contentY() + pos - center.y());
}
d->updateBeginningEnd();
}
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index f8374bdbc2..2009d76677 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -3253,7 +3253,7 @@ void QQuickItemPrivate::data_append(QQmlListProperty<QObject> *prop, QObject *o)
// because there can be multiple handlers...
that->setAcceptedMouseButtons(Qt::AllButtons);
QQuickItemPrivate *p = QQuickItemPrivate::get(that);
- p->extra.value().pointerHandlers.append(pointerHandler);
+ p->extra.value().pointerHandlers.prepend(pointerHandler);
} else {
QQuickWindow *thisWindow = qmlobject_cast<QQuickWindow *>(o);
QQuickItem *item = that;
diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp
index 1d0d042839..c203f389ae 100644
--- a/src/quick/items/qquickitemview.cpp
+++ b/src/quick/items/qquickitemview.cpp
@@ -926,7 +926,6 @@ void QQuickItemView::setDisplacedTransition(QQuickTransition *transition)
void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
{
- Q_Q(QQuickItemView);
if (!isValid())
return;
if (mode < QQuickItemView::Beginning || mode > QQuickItemView::SnapPosition)
@@ -953,11 +952,16 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
item = visibleItem(idx);
}
if (item) {
+ const bool stickyHeader = hasStickyHeader();
+ const bool stickyFooter = hasStickyFooter();
+ const qreal stickyHeaderSize = stickyHeader ? headerSize() : 0;
+ const qreal stickyFooterSize = stickyFooter ? footerSize() : 0;
+
const qreal itemPos = item->position();
switch (mode) {
case QQuickItemView::Beginning:
pos = itemPos;
- if (header && (index < 0 || hasStickyHeader()))
+ if (header && (index < 0 || stickyHeader))
pos -= headerSize();
break;
case QQuickItemView::Center:
@@ -965,30 +969,29 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
break;
case QQuickItemView::End:
pos = itemPos - viewSize + item->size();
- if (footer && (index >= modelCount || hasStickyFooter()))
+ if (footer && (index >= modelCount || stickyFooter))
pos += footerSize();
break;
case QQuickItemView::Visible:
- if (itemPos > pos + viewSize)
- pos = itemPos - viewSize + item->size();
- else if (item->endPosition() <= pos)
- pos = itemPos;
+ if (itemPos > pos + viewSize - stickyFooterSize)
+ pos = item->endPosition() - viewSize + stickyFooterSize;
+ else if (item->endPosition() <= pos - stickyHeaderSize)
+ pos = itemPos - stickyHeaderSize;
break;
case QQuickItemView::Contain:
- if (item->endPosition() >= pos + viewSize)
- pos = itemPos - viewSize + item->size();
- if (itemPos < pos)
- pos = itemPos;
+ if (item->endPosition() >= pos + viewSize + stickyFooterSize)
+ pos = itemPos - viewSize + item->size() + stickyFooterSize;
+ if (itemPos - stickyHeaderSize < pos)
+ pos = itemPos - stickyHeaderSize;
break;
case QQuickItemView::SnapPosition:
- pos = itemPos - highlightRangeStart;
+ pos = itemPos - highlightRangeStart - stickyHeaderSize;
break;
}
pos = qMin(pos, maxExtent);
qreal minExtent = calculatedMinExtent();
pos = qMax(pos, minExtent);
moveReason = QQuickItemViewPrivate::Other;
- q->cancelFlick();
setPosition(pos);
if (highlight) {
@@ -1246,16 +1249,26 @@ void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometry
void QQuickItemView::destroyRemoved()
{
Q_D(QQuickItemView);
+
+ bool hasRemoveTransition = false;
+ bool hasRemoveTransitionAsTarget = false;
+ if (d->transitioner) {
+ hasRemoveTransition = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false);
+ hasRemoveTransitionAsTarget = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true);
+ }
+
for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
it != d->visibleItems.end();) {
FxViewItem *item = *it;
if (item->index == -1 && (!item->attached || item->attached->delayRemove() == false)) {
- if (d->transitioner && d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) {
+ if (hasRemoveTransitionAsTarget) {
// don't remove from visibleItems until next layout()
d->runDelayedRemoveTransition = true;
QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()));
++it;
} else {
+ if (hasRemoveTransition)
+ d->runDelayedRemoveTransition = true;
d->releaseItem(item);
it = d->visibleItems.erase(it);
}
@@ -1384,7 +1397,6 @@ void QQuickItemView::trackedPositionChanged()
pos = qMax(trackedPos, toItemPos);
}
if (viewPos != pos) {
- cancelFlick();
d->calcVelocity = true;
d->setPosition(pos);
d->calcVelocity = false;
@@ -1934,8 +1946,9 @@ void QQuickItemViewPrivate::layout()
if (transitioner) {
// items added in the last refill() may need to be transitioned in - e.g. a remove
// causes items to slide up into view
- if (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, false)
- || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
+ if (lastIndexInView != -1 &&
+ (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, false)
+ || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false))) {
translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges);
}
@@ -1978,7 +1991,6 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult
}
updateUnrequestedIndexes();
- moveReason = QQuickItemViewPrivate::Other;
FxViewItem *prevVisibleItemsFirst = visibleItems.count() ? *visibleItems.constBegin() : 0;
int prevItemCount = itemCount;
diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp
index c3e0ba05bd..94a5b6a646 100644
--- a/src/quick/items/qquickopenglshadereffect.cpp
+++ b/src/quick/items/qquickopenglshadereffect.cpp
@@ -896,7 +896,7 @@ QSGNode *QQuickOpenGLShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuic
bool geometryUsesTextureSubRect = false;
if (m_supportsAtlasTextures && material->textureProviders.size() == 1) {
QSGTextureProvider *provider = material->textureProviders.at(0);
- if (provider->texture()) {
+ if (provider && provider->texture()) {
srcRect = provider->texture()->normalizedTextureSubRect();
geometryUsesTextureSubRect = true;
}
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index caae188ed8..db7a80ee9a 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -762,19 +762,18 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
auto point = pointerEventInstance(touchMouseDevice)->pointById(touchMouseId);
if (point) {
auto originalEvent = pointerEventInstance(point->pointerEvent()->device());
- for (int i = 0; i < originalEvent->pointCount(); ++i)
- originalEvent->point(i)->cancelExclusiveGrab();
+ for (int i = 0; i < originalEvent->pointCount(); ++i) {
+ QQuickEventPoint *pt = originalEvent->point(i);
+ if (pt->exclusiveGrabber())
+ pt->cancelExclusiveGrab();
+ }
point->setGrabberItem(grabber);
- for (auto handler : point->passiveGrabbers())
- point->cancelPassiveGrab(handler);
}
} else {
QQuickPointerEvent *event = pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
Q_ASSERT(event->pointCount() == 1);
auto point = event->point(0);
point->setGrabberItem(grabber);
- for (auto handler : point->passiveGrabbers())
- point->cancelPassiveGrab(handler);
}
@@ -840,11 +839,12 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to
bool ungrab = false;
const auto touchDevices = QQuickPointerDevice::touchDevices();
for (auto device : touchDevices) {
- auto pointerEvent = pointerEventInstance(device);
- for (int i = 0; i < pointerEvent->pointCount(); ++i) {
- if (pointerEvent->point(i)->exclusiveGrabber() == grabber) {
- pointerEvent->point(i)->setGrabberItem(nullptr);
- ungrab = true;
+ if (auto pointerEvent = queryPointerEventInstance(device)) {
+ for (int i = 0; i < pointerEvent->pointCount(); ++i) {
+ if (pointerEvent->point(i)->exclusiveGrabber() == grabber) {
+ pointerEvent->point(i)->setGrabberItem(nullptr);
+ ungrab = true;
+ }
}
}
}
@@ -1309,6 +1309,8 @@ QQuickWindow::~QQuickWindow()
delete d->dragGrabber; d->dragGrabber = 0;
#endif
delete d->contentItem; d->contentItem = 0;
+ qDeleteAll(d->pointerEventInstances);
+ d->pointerEventInstances.clear();
d->renderJobMutex.lock();
qDeleteAll(d->beforeSynchronizingJobs);
@@ -1510,14 +1512,15 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const
Q_D(const QQuickWindow);
if (d->touchMouseId != -1 && d->touchMouseDevice) {
- QQuickPointerEvent *event = d->pointerEventInstance(d->touchMouseDevice);
- auto point = event->pointById(d->touchMouseId);
- return point ? point->grabberItem() : nullptr;
+ if (QQuickPointerEvent *event = d->queryPointerEventInstance(d->touchMouseDevice)) {
+ auto point = event->pointById(d->touchMouseId);
+ return point ? point->grabberItem() : nullptr;
+ }
+ } else if (QQuickPointerEvent *event = d->queryPointerEventInstance(QQuickPointerDevice::genericMouseDevice())) {
+ Q_ASSERT(event->pointCount());
+ return event->point(0)->grabberItem();
}
-
- QQuickPointerEvent *event = d->pointerEventInstance(QQuickPointerDevice::genericMouseDevice());
- Q_ASSERT(event->pointCount());
- return event->point(0)->grabberItem();
+ return nullptr;
}
@@ -1691,8 +1694,10 @@ void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QQuic
alreadyFiltered = sendFilteredPointerEvent(pointerEvent, par);
sendFilteredPointerEventResult << qMakePair<QQuickItem*, bool>(par, alreadyFiltered);
}
- if (!alreadyFiltered)
+ if (!alreadyFiltered) {
+ pointerEvent->localize(handler->parentItem());
handler->handlePointerEvent(pointerEvent);
+ }
}
}
}
@@ -1707,24 +1712,27 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
if (point->exclusiveGrabber()) {
if (auto grabber = point->grabberItem()) {
+ bool handled = false;
if (sendFilteredPointerEvent(pointerEvent, grabber))
- return;
+ 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 (pointerEvent->button() != Qt::NoButton && acceptedButtons
+ if (!handled && pointerEvent->button() != Qt::NoButton && acceptedButtons
&& !(acceptedButtons & pointerEvent->button())) {
pointerEvent->setAccepted(false);
- return;
+ handled = true;
}
// send update
- QPointF localPos = grabber->mapFromScene(lastMousePosition);
- auto me = pointerEvent->asMouseEvent(localPos);
- me->accept();
- QCoreApplication::sendEvent(grabber, me);
- point->setAccepted(me->isAccepted());
+ if (!handled) {
+ QPointF localPos = grabber->mapFromScene(lastMousePosition);
+ auto me = pointerEvent->asMouseEvent(localPos);
+ me->accept();
+ QCoreApplication::sendEvent(grabber, me);
+ point->setAccepted(me->isAccepted());
+ }
// release event: ungrab if no buttons are pressed anymore
if (mouseIsReleased)
@@ -1738,6 +1746,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
if (mouseIsReleased)
point->setGrabberPointerHandler(nullptr, true);
}
+ deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent);
} else {
bool delivered = false;
if (pointerEvent->isPressEvent()) {
@@ -1929,7 +1938,8 @@ bool QQuickWindowPrivate::deliverNativeGestureEvent(QQuickItem *item, QNativeGes
{
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- if ((itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) && !item->contains(event->localPos()))
+ QPointF p = item->mapFromScene(event->windowPos());
+ if ((itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) && !item->contains(p))
return false;
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
@@ -1952,7 +1962,6 @@ bool QQuickWindowPrivate::deliverNativeGestureEvent(QQuickItem *item, QNativeGes
}
// If still not accepted, try direct delivery to the item
- QPointF p = item->mapFromScene(event->localPos());
if (item->contains(p)) {
QNativeGestureEvent copy(event->gestureType(), event->device(), p, event->windowPos(), event->screenPos(),
event->value(), 0L, 0L); // TODO can't copy things I can't access
@@ -1973,15 +1982,16 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event)
qCDebug(DBG_TOUCH) << event;
Q_Q(QQuickWindow);
+ if (q->mouseGrabberItem())
+ q->mouseGrabberItem()->ungrabMouse();
+ touchMouseId = -1;
+ touchMouseDevice = nullptr;
+
// A TouchCancel event will typically not contain any points.
// Deliver it to all items and handlers that have active touches.
QQuickPointerEvent *pointerEvent = pointerEventInstance(QQuickPointerDevice::touchDevice(event->device()));
for (int i = 0; i < pointerEvent->pointCount(); ++i)
pointerEvent->point(i)->cancelExclusiveGrabImpl(event);
- touchMouseId = -1;
- touchMouseDevice = nullptr;
- if (q->mouseGrabberItem())
- q->mouseGrabberItem()->ungrabMouse();
// The next touch event can only be a TouchBegin, so clean up.
pointerEvent->clearGrabbers();
@@ -2200,7 +2210,7 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents()
}
}
-QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType) const
+QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType) const
{
// Search for a matching reusable event object.
for (QQuickPointerEvent *e : pointerEventInstances) {
@@ -2213,9 +2223,14 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevic
if (e->device() == device)
return e;
}
+ return nullptr;
+}
- // Not found: we have to create a suitable event instance.
- QQuickPointerEvent *ev = nullptr;
+QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType) const
+{
+ QQuickPointerEvent *ev = queryPointerEventInstance(device, eventType);
+ if (ev)
+ return ev;
QQuickWindow *q = const_cast<QQuickWindow*>(q_func());
switch (device->type()) {
case QQuickPointerDevice::Mouse:
@@ -2397,6 +2412,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event)
// Deliver touch points to existing grabbers
void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event)
{
+ bool done = false;
const auto grabbers = event->exclusiveGrabbers();
for (auto grabber : grabbers) {
// The grabber is guaranteed to be either an item or a handler.
@@ -2406,52 +2422,52 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
QQuickPointerHandler *handler = static_cast<QQuickPointerHandler *>(grabber);
receiver = static_cast<QQuickPointerHandler *>(grabber)->parentItem();
if (sendFilteredPointerEvent(event, receiver))
- return;
+ done = true;
event->localize(receiver);
handler->handlePointerEvent(event);
if (event->allPointsAccepted())
- return;
+ done = true;
}
+ if (done)
+ break;
// If the grabber is an item or the grabbing handler didn't handle it,
// then deliver the event to the item (which may have multiple handlers).
deliverMatchingPointsToItem(receiver, event);
}
- // If some points weren't grabbed, deliver only to non-grabber PointerHandlers
- if (!event->allPointsGrabbed()) {
- int pointCount = event->pointCount();
+ // Deliver to each eventpoint's passive grabbers (but don't visit any handler more than once)
+ int pointCount = event->pointCount();
+ for (int i = 0; i < pointCount; ++i) {
+ QQuickEventPoint *point = event->point(i);
+ deliverToPassiveGrabbers(point->passiveGrabbers(), event);
+ }
+
+ if (done)
+ return;
- // Deliver to each eventpoint's passive grabbers (but don't visit any handler more than once)
+ // If some points weren't grabbed, deliver only to non-grabber PointerHandlers in reverse paint order
+ if (!event->allPointsGrabbed()) {
+ QVector<QQuickItem *> targetItems;
for (int i = 0; i < pointCount; ++i) {
QQuickEventPoint *point = event->point(i);
- deliverToPassiveGrabbers(point->passiveGrabbers(), event);
- }
-
- // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order
- if (!event->allPointsGrabbed()) {
- QVector<QQuickItem *> targetItems;
- for (int i = 0; i < pointCount; ++i) {
- QQuickEventPoint *point = event->point(i);
- if (point->state() == QQuickEventPoint::Pressed)
- continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), false, false);
- if (targetItems.count()) {
- targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
- } else {
- targetItems = targetItemsForPoint;
- }
- }
-
- for (QQuickItem *item: targetItems) {
- if (grabbers.contains(item))
- continue;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- event->localize(item);
- itemPrivate->handlePointerEvent(event, true); // avoid re-delivering to grabbers
- if (event->allPointsGrabbed())
- break;
+ if (point->state() == QQuickEventPoint::Pressed)
+ continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), false, false);
+ if (targetItems.count()) {
+ targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
+ } else {
+ targetItems = targetItemsForPoint;
}
}
+ for (QQuickItem *item : targetItems) {
+ if (grabbers.contains(item))
+ continue;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ event->localize(item);
+ itemPrivate->handlePointerEvent(event, true); // avoid re-delivering to grabbers
+ if (event->allPointsGrabbed())
+ break;
+ }
}
}
@@ -2490,7 +2506,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
continue;
deliverMatchingPointsToItem(item, event, handlersOnly);
if (event->allPointsAccepted())
- break;
+ handlersOnly = true;
}
return event->allPointsAccepted();
@@ -2505,8 +2521,9 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
// Let the Item's handlers (if any) have the event first.
// However, double click should never be delivered to handlers.
if (!pointerEvent->isDoubleClickEvent()) {
+ bool wasAccepted = pointerEvent->allPointsAccepted();
itemPrivate->handlePointerEvent(pointerEvent);
- allowDoubleClick = !(pointerEvent->asPointerMouseEvent() && pointerEvent->isPressEvent() && pointerEvent->allPointsAccepted());
+ allowDoubleClick = wasAccepted || !(pointerEvent->asPointerMouseEvent() && pointerEvent->isPressEvent() && pointerEvent->allPointsAccepted());
}
if (handlersOnly)
return;
@@ -2818,17 +2835,10 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event
// get a touch event customized for delivery to filteringParent
QScopedPointer<QTouchEvent> filteringParentTouchEvent(pte->touchEventForItem(receiver, true));
if (filteringParentTouchEvent) {
- QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel;
if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) {
qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent;
skipDelivery.append(filteringParent);
for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) {
- auto pointerEventPoint = pte->pointById(point.id());
- for (auto handler : pointerEventPoint->passiveGrabbers()) {
- QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint);
- if (!passiveGrabsToCancel.contains(grab))
- passiveGrabsToCancel.append(grab);
- }
QQuickEventPoint *pt = event->pointById(point.id());
pt->setAccepted();
pt->setGrabberItem(filteringParent);
@@ -2874,12 +2884,6 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event
touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set
if (mouseEvent->isAccepted())
filteringParent->grabMouse();
- auto pointerEventPoint = pte->pointById(tp.id());
- for (auto handler : pointerEventPoint->passiveGrabbers()) {
- QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint);
- if (!passiveGrabsToCancel.contains(grab))
- passiveGrabsToCancel.append(grab);
- }
}
filtered = true;
}
@@ -2895,8 +2899,6 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event
}
}
}
- for (auto grab : passiveGrabsToCancel)
- grab.second->cancelPassiveGrab(grab.first);
}
}
}
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 06891406ab..87d7f63c8b 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -167,6 +167,7 @@ public:
// the device-specific event instances which are reused during event delivery
mutable QVector<QQuickPointerEvent *> pointerEventInstances;
+ QQuickPointerEvent *queryPointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType = QEvent::None) const;
QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device, QEvent::Type eventType = QEvent::None) const;
// delivery of pointer events: