498void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
500 QQuickMultiPointHandler::handlePointerEventImpl(event);
501 if (Q_UNLIKELY(lcPinchHandler().isDebugEnabled())) {
502 for (
const QQuickHandlerPoint &p : std::as_const(currentPoints()))
503 qCDebug(lcPinchHandler) << Qt::hex << p.id() << p.sceneGrabPosition() <<
"->" << p.scenePosition();
507#if QT_CONFIG(gestures)
508 if (event->type() == QEvent::NativeGesture) {
509 const auto gesture =
static_cast<
const QNativeGestureEvent *>(event);
510 mutableCentroid().reset(event, event->point(0));
511 switch (gesture->gestureType()) {
512 case Qt::BeginNativeGesture:
517 case Qt::EndNativeGesture:
518 mutableCentroid().reset();
522 case Qt::ZoomNativeGesture:
523 setActiveScale(m_scaleAxis.activeValue() * (1 + gesture->value()));
525 case Qt::RotateNativeGesture:
526 setActiveRotation(m_rotationAxis.activeValue() + gesture->value());
535 const bool containsReleasedPoints = event->isEndEvent();
536 QVector<QEventPoint> chosenPoints;
537 for (
const QQuickHandlerPoint &p : std::as_const(currentPoints())) {
538 auto ep = event->pointById(p.id());
544 int numberOfPointsDraggedOverThreshold = 0;
545 QVector2D accumulatedDrag;
546 const QVector2D currentCentroid(centroid().scenePosition());
547 const QVector2D pressCentroid(centroid().scenePressPosition());
549 const int dragThreshold = QQuickPointerHandler::dragThreshold();
550 const int dragThresholdSquared = dragThreshold * dragThreshold;
552 double accumulatedCentroidDistance = 0;
553 if (event->isBeginEvent())
554 m_accumulatedStartCentroidDistance = 0;
556 float accumulatedMovementMagnitude = 0;
558 for (
auto &point : chosenPoints) {
559 if (!containsReleasedPoints) {
560 accumulatedDrag += QVector2D(point.scenePressPosition() - point.scenePosition());
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594 QVector2D pressCentroidRelativePosition = QVector2D(point.scenePosition()) - currentCentroid;
595 QVector2D currentCentroidRelativePosition = QVector2D(point.scenePressPosition()) - pressCentroid;
596 QVector2D centroidRelativeMovement = currentCentroidRelativePosition - pressCentroidRelativePosition;
597 accumulatedMovementMagnitude += centroidRelativeMovement.length();
599 accumulatedCentroidDistance += qreal(pressCentroidRelativePosition.length());
600 if (event->isBeginEvent())
601 m_accumulatedStartCentroidDistance += qreal((QVector2D(point.scenePressPosition()) - pressCentroid).length());
603 setPassiveGrab(event, point);
605 if (point.state() == QEventPoint::Pressed) {
606 point.setAccepted(
false);
607 setPassiveGrab(event, point);
609 Q_D(QQuickMultiPointHandler);
610 if (d->dragOverThreshold(point))
611 ++numberOfPointsDraggedOverThreshold;
614 const bool requiredNumberOfPointsDraggedOverThreshold =
615 numberOfPointsDraggedOverThreshold >= minimumPointCount() &&
616 numberOfPointsDraggedOverThreshold <= maximumPointCount();
617 accumulatedMovementMagnitude /= currentPoints().size();
619 QVector2D avgDrag = accumulatedDrag / currentPoints().size();
620 if (!xAxis()->enabled())
622 if (!yAxis()->enabled())
625 const qreal centroidMovementDelta = qreal((currentCentroid - pressCentroid).length());
627 qreal distanceToCentroidDelta = qAbs(accumulatedCentroidDistance - m_accumulatedStartCentroidDistance);
628 if (numberOfPointsDraggedOverThreshold >= 1) {
629 if (requiredNumberOfPointsDraggedOverThreshold &&
630 avgDrag.lengthSquared() >= dragThresholdSquared && accumulatedMovementMagnitude < dragThreshold) {
632 if (grabPoints(event, chosenPoints))
634 }
else if (distanceToCentroidDelta > dragThreshold) {
636 if (grabPoints(event, chosenPoints))
638 }
else if (distanceToCentroidDelta < dragThreshold && (centroidMovementDelta < dragThreshold)) {
642 if (grabPoints(event, chosenPoints))
653 qreal activeScale = 1;
654 if (m_scaleAxis.enabled()) {
655 dist = averageTouchPointDistance(centroid().scenePosition());
656 activeScale = dist / m_startDistance;
657 activeScale = qBound(m_scaleAxis.minimum() / m_scaleAxis.m_startValue, activeScale,
658 m_scaleAxis.maximum() / m_scaleAxis.m_startValue);
659 setActiveScale(activeScale);
663 if (m_rotationAxis.enabled()) {
664 QVector<PointData> newAngles = angles(centroid().scenePosition());
665 const qreal angleDelta = averageAngleDelta(m_startAngles, newAngles);
666 setActiveRotation(m_rotationAxis.m_activeValue + angleDelta);
667 m_startAngles = std::move(newAngles);
670 if (!containsReleasedPoints)
671 acceptPoints(chosenPoints);
675 if (target() && target()->parentItem()) {
677 const QPointF centroidParentPos = t->parentItem()->mapFromScene(centroid().scenePosition());
679 const QPointF centroidStartParentPos = t->parentItem()->mapFromScene(centroid().sceneGrabPosition());
680 auto activeTranslation = centroidParentPos - centroidStartParentPos;
682 QPointF pos = QQuickItemPrivate::get(t)->adjustedPosForTransform(centroidParentPos,
683 m_startTargetPos, QVector2D(activeTranslation),
684 t->scale(), m_scaleAxis.persistentValue() / m_scaleAxis.m_startValue,
685 t->rotation(), m_rotationAxis.persistentValue() - m_rotationAxis.m_startValue);
687 if (xAxis()->enabled())
688 pos.setX(qBound(xAxis()->minimum(), pos.x(), xAxis()->maximum()));
690 pos.rx() -= qreal(activeTranslation.x());
691 if (yAxis()->enabled())
692 pos.setY(qBound(yAxis()->minimum(), pos.y(), yAxis()->maximum()));
694 pos.ry() -= qreal(activeTranslation.y());
696 const QVector2D delta(activeTranslation.x() - m_xAxis.activeValue(),
697 activeTranslation.y() - m_yAxis.activeValue());
698 m_xAxis.updateValue(activeTranslation.x(), m_xAxis.persistentValue() + delta.x(), delta.x());
699 m_yAxis.updateValue(activeTranslation.y(), m_yAxis.persistentValue() + delta.y(), delta.y());
700 emit translationChanged(delta);
708 if (m_rotationAxis.enabled())
709 t->setRotation(m_rotationAxis.persistentValue());
710 if (m_scaleAxis.enabled())
711 t->setScale(m_scaleAxis.persistentValue());
713 auto activeTranslation = centroid().scenePosition() - centroid().scenePressPosition();
714 auto accumulated = QPointF(m_xAxis.m_startValue, m_yAxis.m_startValue) + activeTranslation;
715 const QVector2D delta(activeTranslation.x() - m_xAxis.activeValue(),
716 activeTranslation.y() - m_yAxis.activeValue());
717 m_xAxis.updateValue(activeTranslation.x(), accumulated.x(), delta.x());
718 m_yAxis.updateValue(activeTranslation.y(), accumulated.y(), delta.y());
719 emit translationChanged(delta);
722 qCDebug(lcPinchHandler) <<
"centroid" << centroid().scenePressPosition() <<
"->" << centroid().scenePosition()
723 <<
", distance" << m_startDistance <<
"->" << dist
724 <<
", scale" << m_scaleAxis.m_startValue <<
"->" << m_scaleAxis.m_accumulatedValue
725 <<
", rotation" << m_rotationAxis.m_startValue <<
"->" << m_rotationAxis.m_accumulatedValue
726 <<
", translation" << persistentTranslation()
727 <<
" from " << event->device()->type();