diff options
Diffstat (limited to 'src/location/declarativemaps/qquickgeomapgesturearea.cpp')
-rw-r--r-- | src/location/declarativemaps/qquickgeomapgesturearea.cpp | 173 |
1 files changed, 80 insertions, 93 deletions
diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp index 44f67469..bc37f2bc 100644 --- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp +++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp @@ -869,21 +869,6 @@ void QQuickGeoMapGestureArea::setFlickDeceleration(qreal deceleration) emit flickDecelerationChanged(); } -/*! - \internal -*/ -QTouchEvent::TouchPoint* createTouchPointFromMouseEvent(QMouseEvent *event, Qt::TouchPointState state) -{ - // this is only partially filled. But since it is only partially used it works - // more robust would be to store a list of QPointFs rather than TouchPoints - QTouchEvent::TouchPoint* newPoint = new QTouchEvent::TouchPoint(); - newPoint->setPos(event->position()); - newPoint->setScenePos(event->windowPos()); - newPoint->setScreenPos(event->screenPos()); - newPoint->setState(state); - newPoint->setId(0); - return newPoint; -} /*! \internal @@ -895,10 +880,7 @@ void QQuickGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event) return; } - m_mousePoint.reset(createTouchPointFromMouseEvent(event, QEventPoint::State::Pressed)); - if (m_touchPoints.isEmpty()) - update(); - event->accept(); + handleTouchEvent(event); } /*! @@ -911,10 +893,7 @@ void QQuickGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event) return; } - m_mousePoint.reset(createTouchPointFromMouseEvent(event, QEventPoint::State::Updated)); - if (m_touchPoints.isEmpty()) - update(); - event->accept(); + handleTouchEvent(event); } /*! @@ -927,28 +906,7 @@ void QQuickGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *event) return; } - if (!m_mousePoint.isNull()) { - //this looks super ugly , however is required in case we do not get synthesized MouseReleaseEvent - //and we reset the point already in handleTouchUngrabEvent - m_mousePoint.reset(createTouchPointFromMouseEvent(event, QEventPoint::State::Released)); - if (m_touchPoints.isEmpty()) - update(); - } - event->accept(); -} - -/*! - \internal -*/ -void QQuickGeoMapGestureArea::handleMouseUngrabEvent() -{ - - if (m_touchPoints.isEmpty() && !m_mousePoint.isNull()) { - m_mousePoint.reset(); - update(); - } else { - m_mousePoint.reset(); - } + handleTouchEvent(event); } /*! @@ -957,35 +915,69 @@ void QQuickGeoMapGestureArea::handleMouseUngrabEvent() void QQuickGeoMapGestureArea::handleTouchUngrabEvent() { m_touchPoints.clear(); - //this is needed since in some cases mouse release is not delivered - //(second touch point breaks mouse synthesized events) - m_mousePoint.reset(); update(); } /*! \internal */ -void QQuickGeoMapGestureArea::handleTouchEvent(QTouchEvent *event) +void QQuickGeoMapGestureArea::handleTouchEvent(QPointerEvent *event) { if (m_map && m_map->handleEvent(event)) { event->accept(); return; } - m_touchPoints.clear(); - m_mousePoint.reset(); + // m_touchPoints.clear(); + + // Update the points we are going to use ourselves. + for (const auto &point: event->points()){ + auto grabber = qobject_cast<QQuickItem*>(event->exclusiveGrabber(point)); + // qDebug() << event->type() << point.state() << point << grabber; + + bool canBeGrabbed = grabber == nullptr || grabber == m_declarativeMap || (!grabber->keepTouchGrab() && !grabber->keepMouseGrab()); + // if (canBeGrabbed) m_touchPoints << point; + + //TODO: Testing shows that events are not always propagated with full set of points. + // Therefore, it can happen that our first point is a different point for a moment + // and that will trigger pan or pinch right away. So we keep track of points by their states + // an IDs but then testing shows that sometimes not all points are finished with Release. + // They just dissapear. Child MouseArea will 'eat up' second touch point if first point + // is grabbed by child ListView, for example. Maybe it's a bug in 6.2 RC? + if (point.state() == QEventPoint::Released || !canBeGrabbed){ + for (int i = 0; i < m_touchPoints.count(); ++i) { + if (m_touchPoints.at(i).id() == point.id()){ + m_touchPoints.removeAt(i); + } + } + }else{ + bool replaced = false; + for (int i = 0; i < m_touchPoints.count(); ++i) { + if (m_touchPoints.at(i).id() == point.id()){ + m_touchPoints.replace(i, point); + replaced = true; + } + } + if (!replaced){ + m_touchPoints << point; + } + } - for (int i = 0; i < event->touchPoints().count(); ++i) { - auto point = event->touchPoints().at(i); - if (point.state() != QEventPoint::State::Released) - m_touchPoints << point; } - if (event->touchPoints().count() >= 2) - event->accept(); - else - event->ignore(); + // qDebug() << "m_touchPoints.count=" << m_touchPoints.count(); update(); + + if (isPanActive()){ + // In case we are pannin, we are using only the first point + // We let others to grab the second, if needed. + if (m_touchPoints.count() > 0){ + event->setExclusiveGrabber(m_touchPoints.at(0), m_declarativeMap); + } + }else if (isActive()){ + for (const auto &point: m_touchPoints) { + event->setExclusiveGrabber(point, m_declarativeMap); + } + } } #if QT_CONFIG(wheelevent) @@ -1026,7 +1018,7 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) if (preZoomPoint != postZoomPoint) // need to re-anchor the wheel geoPos to the event position m_declarativeMap->alignCoordinateToPoint(wheelGeoPos, preZoomPoint); } - event->accept(); + // event->accept(); } #endif @@ -1112,8 +1104,6 @@ void QQuickGeoMapGestureArea::update() //combine touch with mouse event m_allPoints.clear(); m_allPoints << m_touchPoints; - if (m_allPoints.isEmpty() && !m_mousePoint.isNull()) - m_allPoints << *m_mousePoint.data(); std::sort(m_allPoints.begin(), m_allPoints.end(), [](const QTouchEvent::TouchPoint &tp1, const QTouchEvent::TouchPoint &tp2) { return tp1.id() < tp2.id(); }); touchPointStateMachine(); @@ -1213,7 +1203,8 @@ void QQuickGeoMapGestureArea::startOneTouchPoint() */ void QQuickGeoMapGestureArea::updateOneTouchPoint() { - m_touchPointsCentroid = mapFromScene(m_allPoints.at(0).scenePos()); + m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePressPosition()); + m_touchPointsCentroid = mapFromScene(m_allPoints.at(0).scenePosition()); updateFlickParameters(m_touchPointsCentroid); } @@ -1222,8 +1213,8 @@ void QQuickGeoMapGestureArea::updateOneTouchPoint() */ void QQuickGeoMapGestureArea::startTwoTouchPoints() { - m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); - m_sceneStartPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePressPosition()); + m_sceneStartPoint2 = mapFromScene(m_allPoints.at(1).scenePressPosition()); QPointF startPos = (m_sceneStartPoint1 + m_sceneStartPoint2) * 0.5; m_lastPos = startPos; m_lastPosTime.start(); @@ -1242,8 +1233,10 @@ void QQuickGeoMapGestureArea::startTwoTouchPoints() */ void QQuickGeoMapGestureArea::updateTwoTouchPoints() { - QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); - QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePressPosition()); + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePosition()); + m_sceneStartPoint2 = mapFromScene(m_allPoints.at(1).scenePressPosition()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePosition()); m_distanceBetweenTouchPoints = distanceBetweenTouchPoints(p1, p2); m_touchPointsCentroid = (p1 + p2) / 2; updateFlickParameters(m_touchPointsCentroid); @@ -1262,7 +1255,6 @@ void QQuickGeoMapGestureArea::tiltStateMachine() case tiltInactive: if (m_allPoints.count() >= 2) { if (!isRotationActive() && !isPinchActive() && canStartTilt()) { // only gesture that can be overridden: pan/flick - m_declarativeMap->setKeepMouseGrab(true); m_declarativeMap->setKeepTouchGrab(true); startTilt(); setTiltState(tiltActive); @@ -1276,7 +1268,6 @@ void QQuickGeoMapGestureArea::tiltStateMachine() setTiltState(tiltInactive); } else { if (!isRotationActive() && !isPinchActive() && canStartTilt()) { // only gesture that can be overridden: pan/flick - m_declarativeMap->setKeepMouseGrab(true); m_declarativeMap->setKeepTouchGrab(true); startTilt(); setTiltState(tiltActive); @@ -1286,7 +1277,6 @@ void QQuickGeoMapGestureArea::tiltStateMachine() case tiltActive: if (m_allPoints.count() <= 1) { setTiltState(tiltInactive); - m_declarativeMap->setKeepMouseGrab(m_preventStealing); m_declarativeMap->setKeepTouchGrab(m_preventStealing); endTilt(); } @@ -1321,8 +1311,8 @@ bool validateTouchAngleForTilting(const qreal angle) bool QQuickGeoMapGestureArea::canStartTilt() { if (m_allPoints.count() >= 2) { - QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); - QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePosition()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePosition()); if (validateTouchAngleForTilting(m_twoTouchAngle) && movingParallelVertical(m_sceneStartPoint1, p1, m_sceneStartPoint2, p2) && qAbs(m_twoTouchPointsCentroidStart.y() - m_touchPointsCentroid.y()) > MinimumPanToTiltDelta) { @@ -1368,8 +1358,8 @@ void QQuickGeoMapGestureArea::updateTilt() m_pinch.m_event.setCenter(mapFromScene(m_touchPointsCentroid)); m_pinch.m_event.setAngle(m_twoTouchAngle); - m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); - m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePosition()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePosition()); m_pinch.m_event.setPoint1(m_pinch.m_lastPoint1); m_pinch.m_event.setPoint2(m_pinch.m_lastPoint2); m_pinch.m_event.setPointCount(m_allPoints.count()); @@ -1405,7 +1395,6 @@ void QQuickGeoMapGestureArea::rotationStateMachine() case rotationInactive: if (m_allPoints.count() >= 2) { if (!isTiltActive() && canStartRotation()) { - m_declarativeMap->setKeepMouseGrab(true); m_declarativeMap->setKeepTouchGrab(true); startRotation(); setRotationState(rotationActive); @@ -1419,7 +1408,6 @@ void QQuickGeoMapGestureArea::rotationStateMachine() setRotationState(rotationInactive); } else { if (!isTiltActive() && canStartRotation()) { - m_declarativeMap->setKeepMouseGrab(true); m_declarativeMap->setKeepTouchGrab(true); startRotation(); setRotationState(rotationActive); @@ -1429,7 +1417,6 @@ void QQuickGeoMapGestureArea::rotationStateMachine() case rotationActive: if (m_allPoints.count() <= 1) { setRotationState(rotationInactive); - m_declarativeMap->setKeepMouseGrab(m_preventStealing); m_declarativeMap->setKeepTouchGrab(m_preventStealing); endRotation(); } @@ -1459,8 +1446,8 @@ void QQuickGeoMapGestureArea::rotationStateMachine() bool QQuickGeoMapGestureArea::canStartRotation() { if (m_allPoints.count() >= 2) { - QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); - QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePosition()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePosition()); if (pointDragged(m_sceneStartPoint1, p1) || pointDragged(m_sceneStartPoint2, p2)) { qreal delta = angleDelta(m_twoTouchAngleStart, m_twoTouchAngle); if (qAbs(delta) < MinimumRotationStartingAngle) { @@ -1506,8 +1493,8 @@ void QQuickGeoMapGestureArea::updateRotation() m_pinch.m_event.setCenter(mapFromScene(m_touchPointsCentroid)); m_pinch.m_event.setAngle(m_twoTouchAngle); - m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); - m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePosition()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePosition()); m_pinch.m_event.setPoint1(m_pinch.m_lastPoint1); m_pinch.m_event.setPoint2(m_pinch.m_lastPoint2); m_pinch.m_event.setPointCount(m_allPoints.count()); @@ -1543,7 +1530,6 @@ void QQuickGeoMapGestureArea::pinchStateMachine() case pinchInactive: if (m_allPoints.count() >= 2) { if (!isTiltActive() && canStartPinch()) { - m_declarativeMap->setKeepMouseGrab(true); m_declarativeMap->setKeepTouchGrab(true); startPinch(); setPinchState(pinchActive); @@ -1557,7 +1543,6 @@ void QQuickGeoMapGestureArea::pinchStateMachine() setPinchState(pinchInactive); } else { if (!isTiltActive() && canStartPinch()) { - m_declarativeMap->setKeepMouseGrab(true); m_declarativeMap->setKeepTouchGrab(true); startPinch(); setPinchState(pinchActive); @@ -1567,7 +1552,6 @@ void QQuickGeoMapGestureArea::pinchStateMachine() case pinchActive: if (m_allPoints.count() <= 1) { // Once started, pinch goes off only when finger(s) are release setPinchState(pinchInactive); - m_declarativeMap->setKeepMouseGrab(m_preventStealing); m_declarativeMap->setKeepTouchGrab(m_preventStealing); endPinch(); } @@ -1597,8 +1581,8 @@ void QQuickGeoMapGestureArea::pinchStateMachine() bool QQuickGeoMapGestureArea::canStartPinch() { if (m_allPoints.count() >= 2) { - QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); - QPointF p2 = mapFromScene(m_allPoints.at(1).scenePos()); + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePosition()); + QPointF p2 = mapFromScene(m_allPoints.at(1).scenePosition()); if (qAbs(m_distanceBetweenTouchPoints - m_distanceBetweenTouchPointsStart) > MinimumPinchDelta) { m_pinch.m_event.setCenter(mapFromScene(m_touchPointsCentroid)); m_pinch.m_event.setAngle(m_twoTouchAngle); @@ -1622,8 +1606,8 @@ void QQuickGeoMapGestureArea::startPinch() m_pinch.m_zoom.m_previous = m_declarativeMap->zoomLevel(); m_pinch.m_lastAngle = m_twoTouchAngle; - m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); - m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePosition()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePosition()); m_pinch.m_zoom.m_start = m_declarativeMap->zoomLevel(); } @@ -1648,8 +1632,8 @@ void QQuickGeoMapGestureArea::updatePinch() m_pinch.m_event.setCenter(mapFromScene(m_touchPointsCentroid)); m_pinch.m_event.setAngle(m_twoTouchAngle); - m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); - m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePos()); + m_pinch.m_lastPoint1 = mapFromScene(m_allPoints.at(0).scenePosition()); + m_pinch.m_lastPoint2 = mapFromScene(m_allPoints.at(1).scenePosition()); m_pinch.m_event.setPoint1(m_pinch.m_lastPoint1); m_pinch.m_event.setPoint2(m_pinch.m_lastPoint2); m_pinch.m_event.setPointCount(m_allPoints.count()); @@ -1701,6 +1685,7 @@ void QQuickGeoMapGestureArea::panStateMachine() m_startCoord.setLongitude(newStartCoord.longitude()); m_startCoord.setLatitude(newStartCoord.latitude()); m_declarativeMap->setKeepMouseGrab(true); + m_declarativeMap->setKeepTouchGrab(true); setFlickState(panActive); } break; @@ -1712,6 +1697,7 @@ void QQuickGeoMapGestureArea::panStateMachine() // mark as inactive for use by camera if (m_pinchState == pinchInactive && m_rotationState == rotationInactive && m_tiltState == tiltInactive) { m_declarativeMap->setKeepMouseGrab(m_preventStealing); + m_declarativeMap->setKeepTouchGrab(m_preventStealing); m_map->prefetchData(); } emit panFinished(); @@ -1726,6 +1712,7 @@ void QQuickGeoMapGestureArea::panStateMachine() if (m_allPoints.count() > 0) { // re touched before movement ended stopFlick(); m_declarativeMap->setKeepMouseGrab(true); + m_declarativeMap->setKeepTouchGrab(true); setFlickState(panActive); } break; @@ -1753,18 +1740,18 @@ void QQuickGeoMapGestureArea::panStateMachine() */ bool QQuickGeoMapGestureArea::canStartPan() { - if (m_allPoints.count() == 0 || (m_acceptedGestures & PanGesture) == 0 - || (m_mousePoint && m_mousePoint->state() == QEventPoint::State::Released)) // mouseReleaseEvent handling does not clear m_mousePoint, only ungrabMouse does -- QTBUG-66534 + if (m_allPoints.count() == 0 || (m_acceptedGestures & PanGesture) == 0) return false; // Check if thresholds for normal panning are met. // (normal panning vs flicking: flicking will start from mouse release event). const int startDragDistance = qApp->styleHints()->startDragDistance() * 2; - QPointF p1 = mapFromScene(m_allPoints.at(0).scenePos()); + QPointF p1 = mapFromScene(m_allPoints.at(0).scenePosition()); int dyFromPress = int(p1.y() - m_sceneStartPoint1.y()); int dxFromPress = int(p1.x() - m_sceneStartPoint1.x()); if ((qAbs(dyFromPress) >= startDragDistance || qAbs(dxFromPress) >= startDragDistance)) return true; + return false; } |