105bool QQuickMouseAreaPrivate::propagateHelper(QQuickMouseEvent *ev, QQuickItem *item,
const QPointF &sp, PropagateType sig)
109 Q_Q(
const QQuickMouseArea);
110 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
112 if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) {
113 QPointF p = item->mapFromScene(sp);
114 if (!item->contains(p))
118 QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
119 for (
int ii = children.size() - 1; ii >= 0; --ii) {
120 QQuickItem *child = children.at(ii);
121 if (!child->isVisible() || !child->isEnabled())
123 if (propagateHelper(ev, child, sp, sig))
127 QQuickMouseArea* ma = qobject_cast<QQuickMouseArea*>(item);
128 if (ma && ma != q && ma->isEnabled() && itemPrivate->acceptedMouseButtons() & ev->button()) {
131 if (!ma->d_func()->isClickConnected())
135 if (!ma->d_func()->isDoubleClickConnected())
139 if (!ma->d_func()->isPressAndHoldConnected())
143 QPointF p = item->mapFromScene(sp);
144 if (item->contains(p)) {
147 ev->setAccepted(
true);
149 case Click: emit ma->clicked(ev);
break;
150 case DoubleClick: emit ma->doubleClicked(ev);
break;
151 case PressAndHold: emit ma->pressAndHold(ev);
break;
153 if (ev->isAccepted())
625void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
627 Q_D(QQuickMouseArea);
629 d->stealMouse = d->preventStealing;
630 d->overThreshold =
false;
631 if (!d->enabled || !(event->button() & acceptedMouseButtons())) {
632 QQuickItem::mousePressEvent(event);
634 d->longPress =
false;
636#if QT_CONFIG(quick_draganddrop)
638 d->drag->setActive(
false);
641 d->startScene = event->scenePosition();
642 setKeepMouseGrab(d->stealMouse);
643 event->setAccepted(setPressed(event->button(),
true, event->source()));
644 if (event->isAccepted())
645 d->pressAndHoldTimer.start(pressAndHoldInterval(),
this);
649void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
651 Q_D(QQuickMouseArea);
652 if (!d->enabled && !d->pressed) {
653 QQuickItem::mouseMoveEvent(event);
659 setHovered(contains(event->position()));
661 if ((event->buttons() & acceptedMouseButtons()) == 0) {
662 QQuickItem::mouseMoveEvent(event);
669#if QT_CONFIG(quick_draganddrop)
670 if (d->drag && d->drag->target()) {
672 d->targetStartPos = d->drag->target()->parentItem()
673 ? d->drag->target()->parentItem()->mapToScene(d->drag->target()->position())
674 : d->drag->target()->position();
677 QPointF startLocalPos;
679 if (drag()->target()->parentItem()) {
680 startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
681 curLocalPos = drag()->target()->parentItem()->mapFromScene(event->scenePosition());
683 startLocalPos = d->startScene;
684 curLocalPos = event->scenePosition();
687 if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active())
688 d->drag->setActive(
true);
690 QPointF startPos = d->drag->target()->parentItem()
691 ? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos)
694 bool dragX = drag()->axis() & QQuickDrag::XAxis;
695 bool dragY = drag()->axis() & QQuickDrag::YAxis;
697 QPointF dragPos = d->drag->target()->position();
698 QPointF boundedDragPos = dragPos;
700 dragPos.setX(startPos.x() + curLocalPos.x() - startLocalPos.x());
701 boundedDragPos.setX(qBound(
707 dragPos.setY(startPos.y() + curLocalPos.y() - startLocalPos.y());
708 boundedDragPos.setY(qBound(
714 QPointF targetPos = d->drag->target()->position();
716 if (d->drag->active()) {
717 d->drag->target()->setPosition(boundedDragPos);
718 d->lastPos = mapFromScene(d->lastScenePos);
721 bool dragOverThresholdX = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.x() - startPos.x(),
722 Qt::XAxis, event, d->drag->threshold());
723 bool dragOverThresholdY = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.y() - startPos.y(),
724 Qt::YAxis, event, d->drag->threshold());
726 if (!d->overThreshold && (((targetPos.x() != boundedDragPos.x()) && dragOverThresholdX) ||
727 ((targetPos.y() != boundedDragPos.y()) && dragOverThresholdY)))
729 d->overThreshold =
true;
730 if (d->drag->smoothed())
731 d->startScene = event->scenePosition();
734 if (!keepMouseGrab() && d->overThreshold) {
735 setKeepMouseGrab(
true);
736 d->stealMouse =
true;
743 QQuickMouseEvent &me = d->quickMouseEvent;
744 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
false, d->longPress, event->flags());
745#if QT_DEPRECATED_SINCE(6
, 6
)
746 me.setSource(event->source());
748 emit mouseXChanged(&me);
749 me.setPosition(d->lastPos);
750 emit mouseYChanged(&me);
751 me.setPosition(d->lastPos);
752 emit positionChanged(&me);
784void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
786 Q_D(QQuickMouseArea);
789 QQuickMouseEvent &me = d->quickMouseEvent;
790 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
true,
791 false, event->flags());
792#if QT_DEPRECATED_SINCE(6
, 6
)
793 me.setSource(event->source());
795 me.setAccepted(d->isDoubleClickConnected());
796 emit
this->doubleClicked(&me);
797 if (!me.isAccepted())
798 d->propagate(&me, QQuickMouseAreaPrivate::DoubleClick);
800 d->doubleClick = d->isDoubleClickConnected() || me.isAccepted();
805 QQuickItem::mouseDoubleClickEvent(event);
808void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
810 Q_D(QQuickMouseArea);
811 if (!d->enabled && !d->pressed) {
820 QQuickItem::hoverEnterEvent(event);
822 d->lastPos = event->position();
823 d->lastModifiers = event->modifiers();
825 QQuickMouseEvent &me = d->quickMouseEvent;
826 me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers,
false,
false);
827 emit mouseXChanged(&me);
828 me.setPosition(d->lastPos);
829 emit mouseYChanged(&me);
830 me.setPosition(d->lastPos);
831 emit positionChanged(&me);
838void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
840 Q_D(QQuickMouseArea);
841 if (!d->enabled && !d->pressed) {
842 QQuickItem::hoverMoveEvent(event);
843 }
else if (d->lastPos != event->position()) {
844 d->lastPos = event->position();
845 d->lastModifiers = event->modifiers();
846 QQuickMouseEvent &me = d->quickMouseEvent;
847 me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers,
false,
false);
848 emit mouseXChanged(&me);
849 me.setPosition(d->lastPos);
850 emit mouseYChanged(&me);
851 me.setPosition(d->lastPos);
852 emit positionChanged(&me);
930bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
932 Q_D(QQuickMouseArea);
933 QPointF localPos = mapFromScene(event->scenePosition());
935 QQuickWindow *c = window();
936 QQuickItem *grabber = c ? c->mouseGrabberItem() :
nullptr;
937 bool stealThisEvent = d->stealMouse;
938 if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
939 QMouseEvent mouseEvent(event->type(), localPos, event->scenePosition(), event->globalPosition(),
940 event->button(), event->buttons(), event->modifiers());
941 mouseEvent.setAccepted(
false);
943 switch (event->type()) {
944 case QEvent::MouseMove:
945 mouseMoveEvent(&mouseEvent);
947 case QEvent::MouseButtonPress:
948 mousePressEvent(&mouseEvent);
950 case QEvent::MouseButtonRelease:
951 mouseReleaseEvent(&mouseEvent);
952 stealThisEvent = d->stealMouse;
957 grabber = c ? c->mouseGrabberItem() :
nullptr;
958 if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber !=
this)
961 return stealThisEvent;
963 if (event->type() == QEvent::MouseButtonRelease) {
965 d->pressed &= ~event->button();
966 emit pressedButtonsChanged();
969 d->stealMouse =
false;
970 d->overThreshold =
false;
971 if (c && c->mouseGrabberItem() ==
this)
974 emit pressedChanged();
975 emit containsPressChanged();
977 qCDebug(lcHoverTrace) <<
"losing hover: button released";
979 emit hoveredChanged();
987bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
989 Q_D(QQuickMouseArea);
991 (!d->enabled || !isVisible()
992#if QT_CONFIG(quick_draganddrop)
993 || !d->drag || !d->drag->filterChildren()
997 return QQuickItem::childMouseEventFilter(i, e);
999 case QEvent::MouseButtonPress:
1000 case QEvent::MouseMove:
1001 case QEvent::MouseButtonRelease:
1002 return sendMouseEvent(
static_cast<QMouseEvent *>(e));
1007 return QQuickItem::childMouseEventFilter(i, e);
1010void QQuickMouseArea::timerEvent(QTimerEvent *event)
1012 Q_D(QQuickMouseArea);
1013 if (event->timerId() == d->pressAndHoldTimer.timerId()) {
1014 d->pressAndHoldTimer.stop();
1015#if QT_CONFIG(quick_draganddrop)
1016 bool dragged = d->drag && d->drag->active();
1018 bool dragged =
false;
1020 if (d->pressed && dragged ==
false && d->hovered ==
true) {
1021 d->longPress =
true;
1022 QQuickMouseEvent &me = d->quickMouseEvent;
1023 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
false, d->longPress, d->lastFlags);
1024#if QT_DEPRECATED_SINCE(6
, 6
)
1025 me.setSource(Qt::MouseEventSynthesizedByQt);
1027 me.setAccepted(d->isPressAndHoldConnected());
1028 emit pressAndHold(&me);
1029 if (!me.isAccepted())
1030 d->propagate(&me, QQuickMouseAreaPrivate::PressAndHold);
1031 if (!me.isAccepted())
1032 d->longPress =
false;
1048void QQuickMouseArea::itemChange(ItemChange change,
const ItemChangeData &value)
1050 Q_D(QQuickMouseArea);
1052 case ItemEnabledHasChanged:
1055 if (d->pressed && !d->effectiveEnable)
1058 case ItemVisibleHasChanged:
1059 if (d->effectiveEnable && d->enabled && hoverEnabled()
1060 && d->hovered != (isVisible() && isUnderMouse())) {
1069 QPointF globalPos{ QGuiApplicationPrivate::lastCursorPosition.toPoint() };
1070 QPointF scenePos{ d->window->mapFromGlobal(globalPos) };
1072 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(d->window);
1073 QQuickDeliveryAgentPrivate *dap = wd->deliveryAgentPrivate();
1077 if (!dap->hoveredLeafItemFound) {
1078 dap->deliverHoverEvent(scenePos, scenePos, Qt::NoModifier,
1079 QDateTime::currentSecsSinceEpoch());
1084 if (dap->hoveredLeafItemFound) {
1085 for (
auto hoverItem : dap->hoverItems) {
1086 if (hoverItem.first ==
this) {
1088 d->lastScenePos = scenePos;
1089 d->lastPos = mapFromScene(d->lastScenePos);
1097 if (d->pressed && (!isVisible())) {
1108 QQuickItem::itemChange(change, value);
1229bool QQuickMouseArea::setPressed(Qt::MouseButton button,
bool p, Qt::MouseEventSource source)
1231 Q_D(QQuickMouseArea);
1234 if (p && !d->effectiveVisible)
1237#if QT_CONFIG(quick_draganddrop)
1238 bool dragged = d->drag && d->drag->active();
1240 bool dragged =
false;
1242 bool wasPressed = d->pressed & button;
1243 bool isclick = wasPressed && p ==
false && dragged ==
false && d->hovered ==
true;
1244 Qt::MouseButtons oldPressed = d->pressed;
1246 if (wasPressed != p) {
1247 QQuickMouseEvent &me = d->quickMouseEvent;
1248 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress, d->lastFlags);
1249#if QT_DEPRECATED_SINCE(6
, 6
)
1250 me.setSource(source);
1253 d->pressed |= button;
1254 if (!d->doubleClick)
1256 me.setPosition(d->lastPos);
1257 emit mouseXChanged(&me);
1258 me.setPosition(d->lastPos);
1259 emit mouseYChanged(&me);
1261 if (!me.isAccepted()) {
1262 d->pressed = Qt::NoButton;
1263 if (!hoverEnabled())
1268 emit pressedChanged();
1269 emit containsPressChanged();
1271 emit pressedButtonsChanged();
1273 d->pressed &= ~button;
1275 me.setPosition(d->lastPos);
1277 emit pressedChanged();
1278 emit containsPressChanged();
1280 emit pressedButtonsChanged();
1281 if (isclick && !d->longPress && !d->doubleClick){
1282 me.setAccepted(d->isClickConnected());
1284 if (!me.isAccepted())
1285 d->propagate(&me, QQuickMouseAreaPrivate::Click);
1289 return me.isAccepted();
1462QSGNode *QQuickMouseArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1465 Q_D(QQuickMouseArea);
1467 if (!qmlMaVisualTouchDebugging())
1470 QSGInternalRectangleNode *rectangle =
static_cast<QSGInternalRectangleNode *>(oldNode);
1471 if (!rectangle) rectangle = d->sceneGraphContext()->createInternalRectangleNode();
1473 rectangle->setRect(QRectF(0, 0, width(), height()));
1474 rectangle->setColor(QColor(255, 0, 0, 50));
1475 rectangle->update();