500void QQuickPinchHandler::handlePointerEventImpl(QPointerEvent *event)
502 QQuickMultiPointHandler::handlePointerEventImpl(event);
503 if (Q_UNLIKELY(lcPinchHandler().isDebugEnabled())) {
504 for (
const QQuickHandlerPoint &p : std::as_const(currentPoints()))
505 qCDebug(lcPinchHandler) << Qt::hex << p.id() << p.sceneGrabPosition() <<
"->" << p.scenePosition();
509#if QT_CONFIG(gestures)
510 if (event->type() == QEvent::NativeGesture) {
511 const auto gesture =
static_cast<
const QNativeGestureEvent *>(event);
512 mutableCentroid().reset(event, event->point(0));
513 switch (gesture->gestureType()) {
514 case Qt::BeginNativeGesture:
519 case Qt::EndNativeGesture:
520 mutableCentroid().reset();
524 case Qt::ZoomNativeGesture:
525 setActiveScale(m_scaleAxis.activeValue() * (1 + gesture->value()));
527 case Qt::RotateNativeGesture:
528 setActiveRotation(m_rotationAxis.activeValue() + gesture->value());
537 const bool containsReleasedPoints = event->isEndEvent();
538 QList<QEventPoint> chosenPoints;
539 for (
const QQuickHandlerPoint &p : std::as_const(currentPoints())) {
540 auto ep = event->pointById(p.id());
546 int numberOfPointsDraggedOverThreshold = 0;
547 QVector2D accumulatedDrag;
548 const QVector2D currentCentroid(centroid().scenePosition());
549 const QVector2D pressCentroid(centroid().scenePressPosition());
551 const int dragThreshold = QQuickPointerHandler::dragThreshold();
552 const int dragThresholdSquared = dragThreshold * dragThreshold;
554 double accumulatedCentroidDistance = 0;
555 if (event->isBeginEvent())
556 m_accumulatedStartCentroidDistance = 0;
558 float accumulatedMovementMagnitude = 0;
560 for (
auto &point : chosenPoints) {
561 if (!containsReleasedPoints) {
562 accumulatedDrag += QVector2D(point.scenePressPosition() - point.scenePosition());
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
595
596 QVector2D pressCentroidRelativePosition = QVector2D(point.scenePosition()) - currentCentroid;
597 QVector2D currentCentroidRelativePosition = QVector2D(point.scenePressPosition()) - pressCentroid;
598 QVector2D centroidRelativeMovement = currentCentroidRelativePosition - pressCentroidRelativePosition;
599 accumulatedMovementMagnitude += centroidRelativeMovement.length();
601 accumulatedCentroidDistance += qreal(pressCentroidRelativePosition.length());
602 if (event->isBeginEvent())
603 m_accumulatedStartCentroidDistance += qreal((QVector2D(point.scenePressPosition()) - pressCentroid).length());
605 setPassiveGrab(event, point);
607 if (point.state() == QEventPoint::Pressed) {
608 point.setAccepted(
false);
609 setPassiveGrab(event, point);
611 Q_D(QQuickMultiPointHandler);
612 if (d->dragOverThreshold(point))
613 ++numberOfPointsDraggedOverThreshold;
616 const bool requiredNumberOfPointsDraggedOverThreshold =
617 numberOfPointsDraggedOverThreshold >= minimumPointCount() &&
618 numberOfPointsDraggedOverThreshold <= maximumPointCount();
619 accumulatedMovementMagnitude /= currentPoints().size();
621 QVector2D avgDrag = accumulatedDrag / currentPoints().size();
622 if (!xAxis()->enabled())
624 if (!yAxis()->enabled())
627 const qreal centroidMovementDelta = qreal((currentCentroid - pressCentroid).length());
629 qreal distanceToCentroidDelta = qAbs(accumulatedCentroidDistance - m_accumulatedStartCentroidDistance);
630 if (numberOfPointsDraggedOverThreshold >= 1) {
631 if (requiredNumberOfPointsDraggedOverThreshold &&
632 avgDrag.lengthSquared() >= dragThresholdSquared && accumulatedMovementMagnitude < dragThreshold) {
634 if (grabPoints(event, chosenPoints))
636 }
else if (distanceToCentroidDelta > dragThreshold) {
638 if (grabPoints(event, chosenPoints))
640 }
else if (distanceToCentroidDelta < dragThreshold && (centroidMovementDelta < dragThreshold)) {
644 if (grabPoints(event, chosenPoints))
655 qreal activeScale = 1;
656 if (m_scaleAxis.enabled()) {
657 dist = averageTouchPointDistance(centroid().scenePosition());
658 activeScale = dist / m_startDistance;
659 activeScale = qBound(m_scaleAxis.minimum() / m_scaleAxis.m_startValue, activeScale,
660 m_scaleAxis.maximum() / m_scaleAxis.m_startValue);
661 setActiveScale(activeScale);
665 if (m_rotationAxis.enabled()) {
666 QList<PointData> newAngles = angles(centroid().scenePosition());
667 const qreal angleDelta = averageAngleDelta(m_startAngles, newAngles);
668 setActiveRotation(m_rotationAxis.m_activeValue + angleDelta);
669 m_startAngles = std::move(newAngles);
672 if (!containsReleasedPoints)
673 acceptPoints(chosenPoints);
677 if (target() && target()->parentItem()) {
679 const QPointF centroidParentPos = t->parentItem()->mapFromScene(centroid().scenePosition());
681 const QPointF centroidStartParentPos = t->parentItem()->mapFromScene(centroid().sceneGrabPosition());
682 auto activeTranslation = centroidParentPos - centroidStartParentPos;
684 QPointF pos = QQuickItemPrivate::get(t)->adjustedPosForTransform(centroidParentPos,
685 m_startTargetPos, QVector2D(activeTranslation),
686 t->scale(), m_scaleAxis.persistentValue() / m_scaleAxis.m_startValue,
687 t->rotation(), m_rotationAxis.persistentValue() - m_rotationAxis.m_startValue);
689 if (xAxis()->enabled())
690 pos.setX(qBound(xAxis()->minimum(), pos.x(), xAxis()->maximum()));
692 pos.rx() -= qreal(activeTranslation.x());
693 if (yAxis()->enabled())
694 pos.setY(qBound(yAxis()->minimum(), pos.y(), yAxis()->maximum()));
696 pos.ry() -= qreal(activeTranslation.y());
698 const QVector2D delta(activeTranslation.x() - m_xAxis.activeValue(),
699 activeTranslation.y() - m_yAxis.activeValue());
700 m_xAxis.updateValue(activeTranslation.x(), m_xAxis.persistentValue() + delta.x(), delta.x());
701 m_yAxis.updateValue(activeTranslation.y(), m_yAxis.persistentValue() + delta.y(), delta.y());
702 emit translationChanged(delta);
710 if (m_rotationAxis.enabled())
711 t->setRotation(m_rotationAxis.persistentValue());
712 if (m_scaleAxis.enabled())
713 t->setScale(m_scaleAxis.persistentValue());
715 auto activeTranslation = centroid().scenePosition() - centroid().scenePressPosition();
716 auto accumulated = QPointF(m_xAxis.m_startValue, m_yAxis.m_startValue) + activeTranslation;
717 const QVector2D delta(activeTranslation.x() - m_xAxis.activeValue(),
718 activeTranslation.y() - m_yAxis.activeValue());
719 m_xAxis.updateValue(activeTranslation.x(), accumulated.x(), delta.x());
720 m_yAxis.updateValue(activeTranslation.y(), accumulated.y(), delta.y());
721 emit translationChanged(delta);
724 qCDebug(lcPinchHandler) <<
"centroid" << centroid().scenePressPosition() <<
"->" << centroid().scenePosition()
725 <<
", distance" << m_startDistance <<
"->" << dist
726 <<
", scale" << m_scaleAxis.m_startValue <<
"->" << m_scaleAxis.m_accumulatedValue
727 <<
", rotation" << m_rotationAxis.m_startValue <<
"->" << m_rotationAxis.m_accumulatedValue
728 <<
", translation" << persistentTranslation()
729 <<
" from " << event->device()->type();