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->effectivelyClipsEventHandlingChildren()) {
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())
626void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
628 Q_D(QQuickMouseArea);
630 d->stealMouse = d->preventStealing;
631 d->overThreshold =
false;
632 if (!d->enabled || !(event->button() & acceptedMouseButtons())) {
633 QQuickItem::mousePressEvent(event);
635 d->longPress =
false;
637#if QT_CONFIG(quick_draganddrop)
639 d->drag->setActive(
false);
642 d->startScene = event->scenePosition();
643 setKeepMouseGrab(d->stealMouse);
644 event->setAccepted(setPressed(event->button(),
true, event->source()));
645 if (event->isAccepted())
646 d->pressAndHoldTimer.start(pressAndHoldInterval(),
this);
650void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
652 Q_D(QQuickMouseArea);
653 if (!d->enabled && !d->pressed) {
654 QQuickItem::mouseMoveEvent(event);
660 setHovered(contains(event->position()));
662 if ((event->buttons() & acceptedMouseButtons()) == 0) {
663 QQuickItem::mouseMoveEvent(event);
670#if QT_CONFIG(quick_draganddrop)
671 if (d->drag && d->drag->target()) {
673 d->targetStartPos = d->drag->target()->parentItem()
674 ? d->drag->target()->parentItem()->mapToScene(d->drag->target()->position())
675 : d->drag->target()->position();
678 QPointF startLocalPos;
680 if (drag()->target()->parentItem()) {
681 startLocalPos = drag()->target()->parentItem()->mapFromScene(d->startScene);
682 curLocalPos = drag()->target()->parentItem()->mapFromScene(event->scenePosition());
684 startLocalPos = d->startScene;
685 curLocalPos = event->scenePosition();
688 if (keepMouseGrab() && d->stealMouse && d->overThreshold && !d->drag->active())
689 d->drag->setActive(
true);
691 QPointF startPos = d->drag->target()->parentItem()
692 ? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos)
695 bool dragX = drag()->axis() & QQuickDrag::XAxis;
696 bool dragY = drag()->axis() & QQuickDrag::YAxis;
698 QPointF dragPos = d->drag->target()->position();
699 QPointF boundedDragPos = dragPos;
701 dragPos.setX(startPos.x() + curLocalPos.x() - startLocalPos.x());
702 boundedDragPos.setX(qBound(
708 dragPos.setY(startPos.y() + curLocalPos.y() - startLocalPos.y());
709 boundedDragPos.setY(qBound(
715 QPointF targetPos = d->drag->target()->position();
717 if (d->drag->active()) {
718 d->drag->target()->setPosition(boundedDragPos);
719 d->lastPos = mapFromScene(d->lastScenePos);
722 bool dragOverThresholdX = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.x() - startPos.x(),
723 Qt::XAxis, event, d->drag->threshold());
724 bool dragOverThresholdY = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.y() - startPos.y(),
725 Qt::YAxis, event, d->drag->threshold());
727 if (!d->overThreshold && (((targetPos.x() != boundedDragPos.x()) && dragOverThresholdX) ||
728 ((targetPos.y() != boundedDragPos.y()) && dragOverThresholdY)))
730 d->overThreshold =
true;
731 if (d->drag->smoothed())
732 d->startScene = event->scenePosition();
735 if (!keepMouseGrab() && d->overThreshold) {
736 setKeepMouseGrab(
true);
737 d->stealMouse =
true;
744 QQuickMouseEvent &me = d->quickMouseEvent;
745 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
false, d->longPress, event->flags());
746#if QT_DEPRECATED_SINCE(6
, 6
)
747 me.setSource(event->source());
749 emit mouseXChanged(&me);
750 me.setPosition(d->lastPos);
751 emit mouseYChanged(&me);
752 me.setPosition(d->lastPos);
753 emit positionChanged(&me);
785void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
787 Q_D(QQuickMouseArea);
790 QQuickMouseEvent &me = d->quickMouseEvent;
791 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
true,
792 false, event->flags());
793#if QT_DEPRECATED_SINCE(6
, 6
)
794 me.setSource(event->source());
796 me.setAccepted(d->isDoubleClickConnected());
797 emit
this->doubleClicked(&me);
798 if (!me.isAccepted())
799 d->propagate(&me, QQuickMouseAreaPrivate::DoubleClick);
801 d->doubleClick = d->isDoubleClickConnected() || me.isAccepted();
806 QQuickItem::mouseDoubleClickEvent(event);
809void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
811 Q_D(QQuickMouseArea);
812 if (!d->enabled && !d->pressed) {
821 QQuickItem::hoverEnterEvent(event);
823 d->lastPos = event->position();
824 d->lastModifiers = event->modifiers();
826 QQuickMouseEvent &me = d->quickMouseEvent;
827 me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers,
false,
false);
828 emit mouseXChanged(&me);
829 me.setPosition(d->lastPos);
830 emit mouseYChanged(&me);
831 me.setPosition(d->lastPos);
832 emit positionChanged(&me);
839void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
841 Q_D(QQuickMouseArea);
842 if (!d->enabled && !d->pressed) {
843 QQuickItem::hoverMoveEvent(event);
844 }
else if (d->lastPos != event->position()) {
845 d->lastPos = event->position();
846 d->lastModifiers = event->modifiers();
847 QQuickMouseEvent &me = d->quickMouseEvent;
848 me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers,
false,
false);
849 emit mouseXChanged(&me);
850 me.setPosition(d->lastPos);
851 emit mouseYChanged(&me);
852 me.setPosition(d->lastPos);
853 emit positionChanged(&me);
931bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
933 Q_D(QQuickMouseArea);
934 QPointF localPos = mapFromScene(event->scenePosition());
936 QQuickWindow *c = window();
937 QQuickItem *grabber = c ? c->mouseGrabberItem() :
nullptr;
938 bool stealThisEvent = d->stealMouse;
939 if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
940 QMouseEvent mouseEvent(event->type(), localPos, event->scenePosition(), event->globalPosition(),
941 event->button(), event->buttons(), event->modifiers());
942 mouseEvent.setAccepted(
false);
944 switch (event->type()) {
945 case QEvent::MouseMove:
946 mouseMoveEvent(&mouseEvent);
948 case QEvent::MouseButtonPress:
949 mousePressEvent(&mouseEvent);
951 case QEvent::MouseButtonRelease:
952 mouseReleaseEvent(&mouseEvent);
953 stealThisEvent = d->stealMouse;
958 grabber = c ? c->mouseGrabberItem() :
nullptr;
959 if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber !=
this)
962 return stealThisEvent;
964 if (event->type() == QEvent::MouseButtonRelease) {
966 d->pressed &= ~event->button();
967 emit pressedButtonsChanged();
970 d->stealMouse =
false;
971 d->overThreshold =
false;
972 if (c && c->mouseGrabberItem() ==
this)
975 emit pressedChanged();
976 emit containsPressChanged();
978 qCDebug(lcHoverTrace) <<
"losing hover: button released";
980 emit hoveredChanged();
988bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
990 Q_D(QQuickMouseArea);
992 (!d->enabled || !isVisible()
993#if QT_CONFIG(quick_draganddrop)
994 || !d->drag || !d->drag->filterChildren()
998 return QQuickItem::childMouseEventFilter(i, e);
1000 case QEvent::MouseButtonPress:
1001 case QEvent::MouseMove:
1002 case QEvent::MouseButtonRelease:
1003 return sendMouseEvent(
static_cast<QMouseEvent *>(e));
1008 return QQuickItem::childMouseEventFilter(i, e);
1011void QQuickMouseArea::timerEvent(QTimerEvent *event)
1013 Q_D(QQuickMouseArea);
1014 if (event->timerId() == d->pressAndHoldTimer.timerId()) {
1015 d->pressAndHoldTimer.stop();
1016#if QT_CONFIG(quick_draganddrop)
1017 bool dragged = d->drag && d->drag->active();
1019 bool dragged =
false;
1021 if (d->pressed && dragged ==
false && d->hovered ==
true) {
1022 d->longPress =
true;
1023 QQuickMouseEvent &me = d->quickMouseEvent;
1024 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
false, d->longPress, d->lastFlags);
1025#if QT_DEPRECATED_SINCE(6
, 6
)
1026 me.setSource(Qt::MouseEventSynthesizedByQt);
1028 me.setAccepted(d->isPressAndHoldConnected());
1029 emit pressAndHold(&me);
1030 if (!me.isAccepted())
1031 d->propagate(&me, QQuickMouseAreaPrivate::PressAndHold);
1032 if (!me.isAccepted())
1033 d->longPress =
false;
1049void QQuickMouseArea::itemChange(ItemChange change,
const ItemChangeData &value)
1051 Q_D(QQuickMouseArea);
1053 case ItemEnabledHasChanged:
1056 if (d->pressed && !d->effectiveEnable)
1059 case ItemVisibleHasChanged:
1060 if (d->effectiveEnable && d->enabled && hoverEnabled()
1061 && d->hovered != (isVisible() && isUnderMouse())) {
1070 QPointF globalPos{ QGuiApplicationPrivate::lastCursorPosition.toPoint() };
1071 QPointF scenePos{ d->window->mapFromGlobal(globalPos) };
1073 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(d->window);
1074 QQuickDeliveryAgentPrivate *dap = wd->deliveryAgentPrivate();
1078 if (!dap->hoveredLeafItemFound) {
1079 dap->deliverHoverEvent(scenePos, scenePos, Qt::NoModifier,
1080 QDateTime::currentSecsSinceEpoch());
1085 if (dap->hoveredLeafItemFound) {
1086 for (
auto hoverItem : dap->hoverItems) {
1087 if (hoverItem.item ==
this) {
1089 d->lastScenePos = scenePos;
1090 d->lastPos = mapFromScene(d->lastScenePos);
1098 if (d->pressed && (!isVisible())) {
1109 QQuickItem::itemChange(change, value);
1230bool QQuickMouseArea::setPressed(Qt::MouseButton button,
bool p, Qt::MouseEventSource source)
1232 Q_D(QQuickMouseArea);
1235 if (p && !d->effectiveVisible)
1238#if QT_CONFIG(quick_draganddrop)
1239 bool dragged = d->drag && d->drag->active();
1241 bool dragged =
false;
1243 bool wasPressed = d->pressed & button;
1244 bool isclick = wasPressed && p ==
false && dragged ==
false && d->hovered ==
true;
1245 Qt::MouseButtons oldPressed = d->pressed;
1247 if (wasPressed != p) {
1248 QQuickMouseEvent &me = d->quickMouseEvent;
1249 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress, d->lastFlags);
1250#if QT_DEPRECATED_SINCE(6
, 6
)
1251 me.setSource(source);
1254 d->pressed |= button;
1255 if (!d->doubleClick)
1257 me.setPosition(d->lastPos);
1258 emit mouseXChanged(&me);
1259 me.setPosition(d->lastPos);
1260 emit mouseYChanged(&me);
1262 if (!me.isAccepted()) {
1263 d->pressed = Qt::NoButton;
1264 if (!hoverEnabled())
1269 emit pressedChanged();
1270 emit containsPressChanged();
1272 emit pressedButtonsChanged();
1274 d->pressed &= ~button;
1276 me.setPosition(d->lastPos);
1278 emit pressedChanged();
1279 emit containsPressChanged();
1281 emit pressedButtonsChanged();
1282 if (isclick && !d->longPress && !d->doubleClick){
1283 me.setAccepted(d->isClickConnected());
1285 if (!me.isAccepted())
1286 d->propagate(&me, QQuickMouseAreaPrivate::Click);
1290 return me.isAccepted();
1463QSGNode *QQuickMouseArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1466 Q_D(QQuickMouseArea);
1468 if (!qmlMaVisualTouchDebugging())
1471 QSGInternalRectangleNode *rectangle =
static_cast<QSGInternalRectangleNode *>(oldNode);
1472 if (!rectangle) rectangle = d->sceneGraphContext()->createInternalRectangleNode();
1474 rectangle->setRect(QRectF(0, 0, width(), height()));
1475 rectangle->setColor(QColor(255, 0, 0, 50));
1476 rectangle->update();