569void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints remap)
573 bool started =
false;
576 QList<QEventPoint> touchPoints;
577 bool touchPointsFromEvent =
false;
578 QPointingDevice *dev =
nullptr;
580 switch (event->type()) {
581 case QEvent::TouchBegin:
582 case QEvent::TouchUpdate:
583 case QEvent::TouchEnd: {
584 QTouchEvent* te =
static_cast<QTouchEvent*>(event);
585 touchPoints = te->points();
586 touchPointsFromEvent =
true;
587 dev =
const_cast<QPointingDevice *>(te->pointingDevice());
590 case QEvent::MouseButtonPress: {
591 auto da = QQuickItemPrivate::get(
this)->deliveryAgentPrivate();
592 _mouseQpaTouchPoint = QEventPoint(da->touchMouseId);
593 _touchMouseDevice = da->touchMouseDevice;
596 case QEvent::MouseMove:
597 case QEvent::MouseButtonRelease: {
598 QMouseEvent *me =
static_cast<QMouseEvent*>(event);
599 _mouseQpaTouchPoint = me->points().first();
600 dev =
const_cast<QPointingDevice *>(me->pointingDevice());
601 if (event->type() == QEvent::MouseButtonPress) {
605 touchPoints << _mouseQpaTouchPoint;
609 qWarning(
"updateTouchData: unhandled event type %d", event->type());
613 int numTouchPoints = touchPoints.size();
615 for (
const QEventPoint &p : std::as_const(touchPoints)) {
616 QEventPoint::State touchPointState = p.state();
618 if (touchPointState & QEventPoint::State::Released) {
619 QQuickTouchPoint* dtp =
static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
622 updateTouchPoint(dtp, &p);
623 dtp->setPressed(
false);
624 _releasedTouchPoints.append(dtp);
625 _touchPoints.remove(id);
629 if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
630 for (QEventPoint &p : touchPoints) {
631 QPointF oldPos = p.position();
632 auto transformBack = qScopeGuard([&] { QMutableEventPoint::setPosition(p, oldPos); });
633 if (touchPointsFromEvent && remap == RemapEventPoints::ToLocal)
634 QMutableEventPoint::setPosition(p, mapFromScene(p.scenePosition()));
635 QEventPoint::State touchPointState = p.state();
637 if (touchPointState & QEventPoint::State::Released) {
639 }
else if (!_touchPoints.contains(id)) {
643 }
else if ((touchPointState & QEventPoint::State::Updated) ||
644 (touchPointState & QEventPoint::State::Stationary)) {
646 QQuickTouchPoint* dtp =
static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
648 _movedTouchPoints.append(dtp);
649 updateTouchPoint(dtp,&p);
652 QQuickTouchPoint* dtp =
static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
654 updateTouchPoint(dtp,&p);
660 bool offerGrab =
false;
661 const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
662 for (
const QEventPoint &p : std::as_const(touchPoints)) {
663 if (p.state() == QEventPoint::State::Released)
665 const QPointF currentPos = mapFromScene(p.scenePosition());
666 const QPointF startPos = mapFromScene(p.scenePressPosition());
667 if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
669 else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
676 QQuickGrabGestureEvent event;
677 event._touchPoints = _touchPoints.values();
678 emit gestureStarted(&event);
679 if (event.wantsGrab() && dev)
685 emit released(_releasedTouchPoints);
687 emit updated(_movedTouchPoints);
688 if (started && !_pressedTouchPoints.isEmpty())
689 emit pressed(_pressedTouchPoints);
690 if (ended || moved || started) emit touchUpdated(_touchPoints.values());
792void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp,
const QEventPoint *p)
796 dtp->setUniqueId(p->uniqueId());
797 dtp->setPosition(p->position());
798 dtp->setEllipseDiameters(p->ellipseDiameters());
799 dtp->setPressure(p->pressure());
800 dtp->setRotation(p->rotation());
801 dtp->setVelocity(p->velocity());
802 QRectF area(QPointF(), p->ellipseDiameters());
803 area.moveCenter(p->position());
806 if (p->state() == QEventPoint::State::Pressed) {
810 dtp->setStartX(p->position().x());
811 dtp->setStartY(p->position().y());
813 dtp->setPreviousX(p->lastPosition().x());
814 dtp->setPreviousY(p->lastPosition().y());
815 dtp->setSceneX(p->scenePosition().x());
816 dtp->setSceneY(p->scenePosition().y());
819void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp,
const QMouseEvent *e)
821 dtp->setPreviousX(dtp->x());
822 dtp->setPreviousY(dtp->y());
823 dtp->setPosition(e->position());
824 if (e->type() == QEvent::MouseButtonPress) {
825 dtp->setStartX(e->position().x());
826 dtp->setStartY(e->position().y());
828 dtp->setSceneX(e->scenePosition().x());
829 dtp->setSceneY(e->scenePosition().y());
922bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
924 const QPointF localPos = mapFromScene(event->scenePosition());
926 QQuickWindow *c = window();
927 QQuickItem *grabber = c ? c->mouseGrabberItem() :
nullptr;
928 bool stealThisEvent = _stealMouse;
929 if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
930 QMutableSinglePointEvent mouseEvent(*event);
931 const auto oldPosition = mouseEvent.position();
932 QMutableEventPoint::setPosition(mouseEvent.point(0), localPos);
933 mouseEvent.setSource(Qt::MouseEventSynthesizedByQt);
934 mouseEvent.setAccepted(
false);
935 QMouseEvent *pmouseEvent =
static_cast<QMouseEvent *>(
static_cast<QSinglePointEvent *>(&mouseEvent));
937 switch (mouseEvent.type()) {
938 case QEvent::MouseMove:
939 mouseMoveEvent(pmouseEvent);
941 case QEvent::MouseButtonPress:
942 mousePressEvent(pmouseEvent);
944 case QEvent::MouseButtonRelease:
945 mouseReleaseEvent(pmouseEvent);
950 grabber = c ? c->mouseGrabberItem() :
nullptr;
951 if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber !=
this)
954 QMutableEventPoint::setPosition(mouseEvent.point(0), oldPosition);
955 return stealThisEvent;
957 if (event->type() == QEvent::MouseButtonRelease) {
959 if (c && c->mouseGrabberItem() ==
this)
961 setKeepMouseGrab(
false);
966bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *receiver, QEvent *event)
968 if (!isEnabled() || !isVisible())
969 return QQuickItem::childMouseEventFilter(receiver, event);
970 switch (event->type()) {
971 case QEvent::MouseButtonPress: {
972 auto da = QQuickItemPrivate::get(
this)->deliveryAgentPrivate();
975 if (
static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventSynthesizedByQt &&
976 _lastFilterableTouchPointIds.contains(da->touchMouseId))
979 case QEvent::MouseMove:
980 case QEvent::MouseButtonRelease:
981 return sendMouseEvent(
static_cast<QMouseEvent *>(event));
982 case QEvent::TouchBegin:
983 _lastFilterableTouchPointIds.clear();
985 case QEvent::TouchUpdate:
986 for (
const auto &tp :
static_cast<QTouchEvent*>(event)->points()) {
987 if (tp.state() == QEventPoint::State::Pressed)
988 _lastFilterableTouchPointIds << tp.id();
990 if (!shouldFilter(event))
992 updateTouchData(event, RemapEventPoints::ToLocal);
994 case QEvent::TouchEnd: {
995 if (!shouldFilter(event))
997 updateTouchData(event, RemapEventPoints::ToLocal);
1004 return QQuickItem::childMouseEventFilter(receiver, event);
1007bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
1009 QQuickWindow *c = window();
1010 QQuickItem *grabber = c ? c->mouseGrabberItem() :
nullptr;
1011 bool disabledItem = grabber && !grabber->isEnabled();
1012 bool stealThisEvent = _stealMouse;
1013 bool containsPoint =
false;
1014 if (!stealThisEvent) {
1015 switch (event->type()) {
1016 case QEvent::MouseButtonPress:
1017 case QEvent::MouseMove:
1018 case QEvent::MouseButtonRelease: {
1019 QMouseEvent *me =
static_cast<QMouseEvent*>(event);
1020 containsPoint = contains(mapFromScene(me->scenePosition()));
1023 case QEvent::TouchBegin:
1024 case QEvent::TouchUpdate:
1025 case QEvent::TouchEnd: {
1026 QTouchEvent *te =
static_cast<QTouchEvent*>(event);
1027 for (
const QEventPoint &point : te->points()) {
1028 if (contains(mapFromScene(point.scenePosition()))) {
1029 containsPoint =
true;
1039 if ((stealThisEvent || containsPoint) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
1046QSGNode *QQuickMultiPointTouchArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1050 if (!qmlMptaVisualTouchDebugging())
1053 QSGInternalRectangleNode *rectangle =
static_cast<QSGInternalRectangleNode *>(oldNode);
1054 if (!rectangle) rectangle = QQuickItemPrivate::get(
this)->sceneGraphContext()->createInternalRectangleNode();
1056 rectangle->setRect(QRectF(0, 0, width(), height()));
1057 rectangle->setColor(QColor(255, 0, 0, 50));
1058 rectangle->update();