diff options
-rw-r--r-- | src/quick/items/qquickpincharea.cpp | 99 | ||||
-rw-r--r-- | src/quick/items/qquickpincharea_p.h | 10 | ||||
-rw-r--r-- | src/quick/items/qquickpincharea_p_p.h | 29 |
3 files changed, 69 insertions, 69 deletions
diff --git a/src/quick/items/qquickpincharea.cpp b/src/quick/items/qquickpincharea.cpp index 8de9071b21..8ed92de051 100644 --- a/src/quick/items/qquickpincharea.cpp +++ b/src/quick/items/qquickpincharea.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtSG module of the Qt Toolkit. @@ -337,25 +337,25 @@ void QQuickPinchArea::touchEvent(QTouchEvent *event) d->touchPoints.clear(); for (int i = 0; i < event->pointCount(); ++i) { auto &tp = event->point(i); - if (!(tp.state() & QEventPoint::State::Released)) { + if (tp.state() != QEventPoint::State::Released) { d->touchPoints << tp; tp.setAccepted(); } } - updatePinch(); + updatePinch(event, false); break; case QEvent::TouchEnd: - clearPinch(); + clearPinch(event); break; case QEvent::TouchCancel: - cancelPinch(); + cancelPinch(event); break; default: QQuickItem::touchEvent(event); } } -void QQuickPinchArea::clearPinch() +void QQuickPinchArea::clearPinch(QTouchEvent *event) { Q_D(QQuickPinchArea); @@ -380,15 +380,17 @@ void QQuickPinchArea::clearPinch() d->pinchActivated = false; d->initPinch = false; d->pinchRejected = false; - d->stealMouse = false; d->id1 = -1; - QQuickWindow *win = window(); - if (win && win->mouseGrabberItem() == this) - ungrabMouse(); - setKeepMouseGrab(false); + if (event) { + for (const auto &point : event->points()) { + if (event->exclusiveGrabber(point) == this) + event->setExclusiveGrabber(point, nullptr); + } + } + setKeepTouchGrab(false); } -void QQuickPinchArea::cancelPinch() +void QQuickPinchArea::cancelPinch(QTouchEvent *event) { Q_D(QQuickPinchArea); @@ -421,25 +423,29 @@ void QQuickPinchArea::cancelPinch() d->pinchActivated = false; d->initPinch = false; d->pinchRejected = false; - d->stealMouse = false; d->id1 = -1; - QQuickWindow *win = window(); - if (win && win->mouseGrabberItem() == this) - ungrabMouse(); - setKeepMouseGrab(false); + for (const auto &point : event->points()) { + if (event->exclusiveGrabber(point) == this) + event->setExclusiveGrabber(point, nullptr); + } + setKeepTouchGrab(false); } -void QQuickPinchArea::updatePinch() +void QQuickPinchArea::updatePinch(QTouchEvent *event, bool filtering) { Q_D(QQuickPinchArea); - QQuickWindow *win = window(); - if (d->touchPoints.count() < 2) { - setKeepMouseGrab(false); - QQuickWindow *c = window(); - if (c && c->mouseGrabberItem() == this) - ungrabMouse(); + // A pinch gesture is not occurring, so stealing the grab is permitted. + setKeepTouchGrab(false); + // During filtering, there's no need to hold a grab for one point, + // because filtering happens for every event anyway. + // But if we receive the event via direct delivery, and give up the grab, + // not only will we not see any more updates, but any filtering parent + // (such as Flickable) will also not get a chance to filter them. + // Continuing to hold the grab in this case keeps tst_TouchMouse::pinchOnFlickable() working. + if (filtering && !d->touchPoints.isEmpty() && event->exclusiveGrabber(d->touchPoints.first()) == this) + event->setExclusiveGrabber(d->touchPoints.first(), nullptr); } if (d->touchPoints.count() == 0) { @@ -463,7 +469,6 @@ void QQuickPinchArea::updatePinch() } d->initPinch = false; d->pinchRejected = false; - d->stealMouse = false; return; } @@ -481,18 +486,13 @@ void QQuickPinchArea::updatePinch() // AND one or more of the points has just now been pressed (wasn't pressed already) // AND both points are inside the bounds. if (d->touchPoints.count() == 2 - && (touchPoint1.state() & QEventPoint::State::Pressed || touchPoint2.state() & QEventPoint::State::Pressed) && + && (touchPoint1.state() == QEventPoint::State::Pressed || touchPoint2.state() == QEventPoint::State::Pressed) && bounds.contains(touchPoint1.position()) && bounds.contains(touchPoint2.position())) { d->id1 = touchPoint1.id(); d->pinchActivated = true; d->initPinch = true; - - int touchMouseId = QQuickWindowPrivate::get(win)->touchMouseId; - if (touchPoint1.id() == touchMouseId || touchPoint2.id() == touchMouseId) { - if (win && win->mouseGrabberItem() != this) { - grabMouse(); - } - } + event->setExclusiveGrabber(touchPoint1, this); + event->setExclusiveGrabber(touchPoint2, this); } if (d->pinchActivated && !d->pinchRejected) { const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); @@ -550,13 +550,10 @@ void QQuickPinchArea::updatePinch() emit pinchStarted(&pe); if (pe.accepted()) { d->inPinch = true; - d->stealMouse = true; - if (win && win->mouseGrabberItem() != this) - grabMouse(); - setKeepMouseGrab(true); - grabTouchPoints(QList<int>() << touchPoint1.id() << touchPoint2.id()); + event->setExclusiveGrabber(touchPoint1, this); + event->setExclusiveGrabber(touchPoint2, this); + setKeepTouchGrab(true); d->inPinch = true; - d->stealMouse = true; if (d->pinch && d->pinch->target()) { d->pinchStartPos = pinch()->target()->position(); d->pinchStartScale = d->pinch->target()->scale(); @@ -631,28 +628,38 @@ void QQuickPinchArea::updatePinchTarget() } } +/*! \internal + PinchArea needs to filter touch events going to its children: in case + one of them stops event propagation by accepting the touch event, filtering + is the only way PinchArea can see the touch event. + + This method is called childMouseEventFilter instead of childPointerEventFilter + for historical reasons, but actually filters all pointer events (and the + occasional QEvent::UngrabMouse). +*/ bool QQuickPinchArea::childMouseEventFilter(QQuickItem *i, QEvent *e) { Q_D(QQuickPinchArea); if (!d->enabled || !isVisible()) return QQuickItem::childMouseEventFilter(i, e); + auto *te = static_cast<QTouchEvent*>(e); switch (e->type()) { case QEvent::TouchBegin: - clearPinch(); + clearPinch(te); Q_FALLTHROUGH(); case QEvent::TouchUpdate: { - const auto &points = static_cast<QTouchEvent*>(e)->points(); + const auto &points = te->points(); d->touchPoints.clear(); for (auto &tp : points) { - if (!(tp.state() & QEventPoint::State::Released)) + if (tp.state() != QEventPoint::State::Released) d->touchPoints << tp; } - updatePinch(); + updatePinch(te, true); } e->setAccepted(d->inPinch); return d->inPinch; case QEvent::TouchEnd: - clearPinch(); + clearPinch(te); break; default: break; @@ -683,7 +690,7 @@ bool QQuickPinchArea::event(QEvent *event) QNativeGestureEvent *gesture = static_cast<QNativeGestureEvent *>(event); switch (gesture->gestureType()) { case Qt::BeginNativeGesture: - clearPinch(); // probably not necessary; JIC + clearPinch(nullptr); // probably not necessary; JIC d->pinchStartCenter = gesture->position(); d->pinchStartAngle = 0.0; d->pinchStartRotation = 0.0; @@ -703,7 +710,7 @@ bool QQuickPinchArea::event(QEvent *event) } break; case Qt::EndNativeGesture: - clearPinch(); + clearPinch(nullptr); break; case Qt::ZoomNativeGesture: { qreal scale = d->pinchLastScale * (1.0 + gesture->value()); diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h index b488f436df..124f0fe5d3 100644 --- a/src/quick/items/qquickpincharea_p.h +++ b/src/quick/items/qquickpincharea_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtSG module of the Qt Toolkit. @@ -300,12 +300,10 @@ protected: bool event(QEvent *) override; private: - void clearPinch(); - void cancelPinch(); - void updatePinch(); + void clearPinch(QTouchEvent *event); + void cancelPinch(QTouchEvent *event); + void updatePinch(QTouchEvent *event, bool filtering); void updatePinchTarget(); - void handlePress(); - void handleRelease(); private: Q_DISABLE_COPY(QQuickPinchArea) diff --git a/src/quick/items/qquickpincharea_p_p.h b/src/quick/items/qquickpincharea_p_p.h index 986aa53900..fdba06f070 100644 --- a/src/quick/items/qquickpincharea_p_p.h +++ b/src/quick/items/qquickpincharea_p_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtSG module of the Qt Toolkit. @@ -64,11 +64,7 @@ class QQuickPinchAreaPrivate : public QQuickItemPrivate Q_DECLARE_PUBLIC(QQuickPinchArea) public: QQuickPinchAreaPrivate() - : enabled(true), stealMouse(false), inPinch(false) - , pinchRejected(false), pinchActivated(false), initPinch(false) - , pinch(0), pinchStartDist(0), pinchStartScale(1.0) - , pinchLastScale(1.0), pinchStartRotation(0.0), pinchStartAngle(0.0) - , pinchLastAngle(0.0), pinchRotation(0.0) + : enabled(true), inPinch(false), pinchRejected(false), pinchActivated(false), initPinch(false) { } @@ -77,34 +73,33 @@ public: void init() { Q_Q(QQuickPinchArea); - q->setAcceptedMouseButtons(Qt::LeftButton); + q->setAcceptTouchEvents(true); q->setFiltersChildMouseEvents(true); } bool enabled : 1; - bool stealMouse : 1; bool inPinch : 1; bool pinchRejected : 1; bool pinchActivated : 1; bool initPinch : 1; - QQuickPinch *pinch; + int id1 = -1; + QQuickPinch *pinch = nullptr; QPointF sceneStartPoint1; QPointF sceneStartPoint2; QPointF lastPoint1; QPointF lastPoint2; - qreal pinchStartDist; - qreal pinchStartScale; - qreal pinchLastScale; - qreal pinchStartRotation; - qreal pinchStartAngle; - qreal pinchLastAngle; - qreal pinchRotation; + qreal pinchStartDist = 0; + qreal pinchStartScale = 1; + qreal pinchLastScale = 1; + qreal pinchStartRotation = 0; + qreal pinchStartAngle = 0; + qreal pinchLastAngle = 0; + qreal pinchRotation = 0; QPointF sceneStartCenter; QPointF pinchStartCenter; QPointF sceneLastCenter; QPointF pinchStartPos; QList<QEventPoint> touchPoints; - int id1; }; QT_END_NAMESPACE |