568void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints remap)
572 bool started =
false;
575 QList<QEventPoint> touchPoints;
576 bool touchPointsFromEvent =
false;
577 QPointingDevice *dev =
nullptr;
579 switch (event->type()) {
580 case QEvent::TouchBegin:
581 case QEvent::TouchUpdate:
582 case QEvent::TouchEnd: {
583 QTouchEvent* te =
static_cast<QTouchEvent*>(event);
584 touchPoints = te->points();
585 touchPointsFromEvent =
true;
586 dev =
const_cast<QPointingDevice *>(te->pointingDevice());
589 case QEvent::MouseButtonPress: {
590 auto da = QQuickItemPrivate::get(
this)->deliveryAgentPrivate();
591 _mouseQpaTouchPoint = QEventPoint(da->touchMouseId);
592 _touchMouseDevice = da->touchMouseDevice;
595 case QEvent::MouseMove:
596 case QEvent::MouseButtonRelease: {
597 QMouseEvent *me =
static_cast<QMouseEvent*>(event);
598 _mouseQpaTouchPoint = me->points().first();
599 dev =
const_cast<QPointingDevice *>(me->pointingDevice());
600 if (event->type() == QEvent::MouseButtonPress) {
604 touchPoints << _mouseQpaTouchPoint;
608 qWarning(
"updateTouchData: unhandled event type %d", event->type());
612 int numTouchPoints = touchPoints.size();
614 for (
const QEventPoint &p : std::as_const(touchPoints)) {
615 QEventPoint::State touchPointState = p.state();
617 if (touchPointState & QEventPoint::State::Released) {
618 QQuickTouchPoint* dtp =
static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
621 updateTouchPoint(dtp, &p);
622 dtp->setPressed(
false);
623 _releasedTouchPoints.append(dtp);
624 _touchPoints.remove(id);
628 if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
629 for (QEventPoint &p : touchPoints) {
630 QPointF oldPos = p.position();
631 auto transformBack = qScopeGuard([&] { QMutableEventPoint::setPosition(p, oldPos); });
632 if (touchPointsFromEvent && remap == RemapEventPoints::ToLocal)
633 QMutableEventPoint::setPosition(p, mapFromScene(p.scenePosition()));
634 QEventPoint::State touchPointState = p.state();
636 if (touchPointState & QEventPoint::State::Released) {
638 }
else if (!_touchPoints.contains(id)) {
642 }
else if ((touchPointState & QEventPoint::State::Updated) ||
643 (touchPointState & QEventPoint::State::Stationary)) {
645 QQuickTouchPoint* dtp =
static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
647 _movedTouchPoints.append(dtp);
648 updateTouchPoint(dtp,&p);
651 QQuickTouchPoint* dtp =
static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
653 updateTouchPoint(dtp,&p);
659 bool offerGrab =
false;
660 const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
661 for (
const QEventPoint &p : std::as_const(touchPoints)) {
662 if (p.state() == QEventPoint::State::Released)
664 const QPointF currentPos = mapFromScene(p.scenePosition());
665 const QPointF startPos = mapFromScene(p.scenePressPosition());
666 if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
668 else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
675 QQuickGrabGestureEvent event;
676 event._touchPoints = _touchPoints.values();
677 emit gestureStarted(&event);
678 if (event.wantsGrab() && dev)
684 emit released(_releasedTouchPoints);
686 emit updated(_movedTouchPoints);
687 if (started && !_pressedTouchPoints.isEmpty())
688 emit pressed(_pressedTouchPoints);
689 if (ended || moved || started) emit touchUpdated(_touchPoints.values());
791void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp,
const QEventPoint *p)
795 dtp->setUniqueId(p->uniqueId());
796 dtp->setPosition(p->position());
797 dtp->setEllipseDiameters(p->ellipseDiameters());
798 dtp->setPressure(p->pressure());
799 dtp->setRotation(p->rotation());
800 dtp->setVelocity(p->velocity());
801 QRectF area(QPointF(), p->ellipseDiameters());
802 area.moveCenter(p->position());
804 dtp->setStartX(p->pressPosition().x());
805 dtp->setStartY(p->pressPosition().y());
806 dtp->setPreviousX(p->lastPosition().x());
807 dtp->setPreviousY(p->lastPosition().y());
808 dtp->setSceneX(p->scenePosition().x());
809 dtp->setSceneY(p->scenePosition().y());
812void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp,
const QMouseEvent *e)
814 dtp->setPreviousX(dtp->x());
815 dtp->setPreviousY(dtp->y());
816 dtp->setPosition(e->position());
817 if (e->type() == QEvent::MouseButtonPress) {
818 dtp->setStartX(e->position().x());
819 dtp->setStartY(e->position().y());
821 dtp->setSceneX(e->scenePosition().x());
822 dtp->setSceneY(e->scenePosition().y());
915bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
917 const QPointF localPos = mapFromScene(event->scenePosition());
919 QQuickWindow *c = window();
920 QQuickItem *grabber = c ? c->mouseGrabberItem() :
nullptr;
921 bool stealThisEvent = _stealMouse;
922 if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
923 QMutableSinglePointEvent mouseEvent(*event);
924 const auto oldPosition = mouseEvent.position();
925 QMutableEventPoint::setPosition(mouseEvent.point(0), localPos);
926 mouseEvent.setSource(Qt::MouseEventSynthesizedByQt);
927 mouseEvent.setAccepted(
false);
928 QMouseEvent *pmouseEvent =
static_cast<QMouseEvent *>(
static_cast<QSinglePointEvent *>(&mouseEvent));
930 switch (mouseEvent.type()) {
931 case QEvent::MouseMove:
932 mouseMoveEvent(pmouseEvent);
934 case QEvent::MouseButtonPress:
935 mousePressEvent(pmouseEvent);
937 case QEvent::MouseButtonRelease:
938 mouseReleaseEvent(pmouseEvent);
943 grabber = c ? c->mouseGrabberItem() :
nullptr;
944 if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber !=
this)
947 QMutableEventPoint::setPosition(mouseEvent.point(0), oldPosition);
948 return stealThisEvent;
950 if (event->type() == QEvent::MouseButtonRelease) {
952 if (c && c->mouseGrabberItem() ==
this)
954 setKeepMouseGrab(
false);
959bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *receiver, QEvent *event)
961 if (!isEnabled() || !isVisible())
962 return QQuickItem::childMouseEventFilter(receiver, event);
963 switch (event->type()) {
964 case QEvent::MouseButtonPress: {
965 auto da = QQuickItemPrivate::get(
this)->deliveryAgentPrivate();
968 if (
static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventSynthesizedByQt &&
969 _lastFilterableTouchPointIds.contains(da->touchMouseId))
972 case QEvent::MouseMove:
973 case QEvent::MouseButtonRelease:
974 return sendMouseEvent(
static_cast<QMouseEvent *>(event));
975 case QEvent::TouchBegin:
976 _lastFilterableTouchPointIds.clear();
978 case QEvent::TouchUpdate:
979 for (
const auto &tp :
static_cast<QTouchEvent*>(event)->points()) {
980 if (tp.state() == QEventPoint::State::Pressed)
981 _lastFilterableTouchPointIds << tp.id();
983 if (!shouldFilter(event))
985 updateTouchData(event, RemapEventPoints::ToLocal);
987 case QEvent::TouchEnd: {
988 if (!shouldFilter(event))
990 updateTouchData(event, RemapEventPoints::ToLocal);
997 return QQuickItem::childMouseEventFilter(receiver, event);
1000bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
1002 QQuickWindow *c = window();
1003 QQuickItem *grabber = c ? c->mouseGrabberItem() :
nullptr;
1004 bool disabledItem = grabber && !grabber->isEnabled();
1005 bool stealThisEvent = _stealMouse;
1006 bool containsPoint =
false;
1007 if (!stealThisEvent) {
1008 switch (event->type()) {
1009 case QEvent::MouseButtonPress:
1010 case QEvent::MouseMove:
1011 case QEvent::MouseButtonRelease: {
1012 QMouseEvent *me =
static_cast<QMouseEvent*>(event);
1013 containsPoint = contains(mapFromScene(me->scenePosition()));
1016 case QEvent::TouchBegin:
1017 case QEvent::TouchUpdate:
1018 case QEvent::TouchEnd: {
1019 QTouchEvent *te =
static_cast<QTouchEvent*>(event);
1020 for (
const QEventPoint &point : te->points()) {
1021 if (contains(mapFromScene(point.scenePosition()))) {
1022 containsPoint =
true;
1032 if ((stealThisEvent || containsPoint) && (!grabber || !grabber->keepMouseGrab() || disabledItem)) {
1039QSGNode *QQuickMultiPointTouchArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1043 if (!qmlMptaVisualTouchDebugging())
1046 QSGInternalRectangleNode *rectangle =
static_cast<QSGInternalRectangleNode *>(oldNode);
1047 if (!rectangle) rectangle = QQuickItemPrivate::get(
this)->sceneGraphContext()->createInternalRectangleNode();
1049 rectangle->setRect(QRectF(0, 0, width(), height()));
1050 rectangle->setColor(QColor(255, 0, 0, 50));
1051 rectangle->update();