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);
756void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event)
758 Q_D(QQuickMouseArea);
759 d->stealMouse =
false;
760 d->overThreshold =
false;
761 if (!d->enabled && !d->pressed) {
762 QQuickItem::mouseReleaseEvent(event);
765 setPressed(event->button(),
false, event->source());
768#if QT_CONFIG(quick_draganddrop)
770 d->drag->setActive(
false);
773 bool resetHovered = !hoverEnabled();
774 if (!resetHovered && event->pointerType() == QPointingDevice::PointerType::Finger) {
780 auto *da = d->deliveryAgentPrivate();
781 resetHovered = !da || !da->isHoveredByHoveringDevice(
this);
785 QQuickWindow *w = window();
786 if (w && w->mouseGrabberItem() ==
this)
788 if (!d->preventStealing)
789 setKeepMouseGrab(
false);
792 d->doubleClick =
false;
795void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
797 Q_D(QQuickMouseArea);
800 QQuickMouseEvent &me = d->quickMouseEvent;
801 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
true,
802 false, event->flags());
803#if QT_DEPRECATED_SINCE(6
, 6
)
804 me.setSource(event->source());
806 me.setAccepted(d->isDoubleClickConnected());
807 emit
this->doubleClicked(&me);
808 if (!me.isAccepted())
809 d->propagate(&me, QQuickMouseAreaPrivate::DoubleClick);
811 d->doubleClick = d->isDoubleClickConnected() || me.isAccepted();
816 QQuickItem::mouseDoubleClickEvent(event);
819void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
821 Q_D(QQuickMouseArea);
822 if (!d->enabled && !d->pressed) {
831 QQuickItem::hoverEnterEvent(event);
833 d->lastPos = event->position();
834 d->lastModifiers = event->modifiers();
836 QQuickMouseEvent &me = d->quickMouseEvent;
837 me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers,
false,
false);
838 emit mouseXChanged(&me);
839 me.setPosition(d->lastPos);
840 emit mouseYChanged(&me);
841 me.setPosition(d->lastPos);
842 emit positionChanged(&me);
849void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
851 Q_D(QQuickMouseArea);
852 if (!d->enabled && !d->pressed) {
853 QQuickItem::hoverMoveEvent(event);
854 }
else if (d->lastPos != event->position()) {
855 d->lastPos = event->position();
856 d->lastModifiers = event->modifiers();
857 QQuickMouseEvent &me = d->quickMouseEvent;
858 me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers,
false,
false);
859 emit mouseXChanged(&me);
860 me.setPosition(d->lastPos);
861 emit mouseYChanged(&me);
862 me.setPosition(d->lastPos);
863 emit positionChanged(&me);
941bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
943 Q_D(QQuickMouseArea);
944 QPointF localPos = mapFromScene(event->scenePosition());
946 QQuickWindow *c = window();
947 QQuickItem *grabber = c ? c->mouseGrabberItem() :
nullptr;
948 bool stealThisEvent = d->stealMouse;
949 if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
950 QMouseEvent mouseEvent(event->type(), localPos, event->scenePosition(), event->globalPosition(),
951 event->button(), event->buttons(), event->modifiers());
952 mouseEvent.setAccepted(
false);
954 switch (event->type()) {
955 case QEvent::MouseMove:
956 mouseMoveEvent(&mouseEvent);
958 case QEvent::MouseButtonPress:
959 mousePressEvent(&mouseEvent);
961 case QEvent::MouseButtonRelease:
962 mouseReleaseEvent(&mouseEvent);
963 stealThisEvent = d->stealMouse;
968 grabber = c ? c->mouseGrabberItem() :
nullptr;
969 if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber !=
this)
972 return stealThisEvent;
974 if (event->type() == QEvent::MouseButtonRelease) {
976 d->pressed &= ~event->button();
977 emit pressedButtonsChanged();
980 d->stealMouse =
false;
981 d->overThreshold =
false;
982 if (c && c->mouseGrabberItem() ==
this)
985 emit pressedChanged();
986 emit containsPressChanged();
988 qCDebug(lcHoverTrace) <<
"losing hover: button released";
990 emit hoveredChanged();
998bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
1000 Q_D(QQuickMouseArea);
1002 (!d->enabled || !isVisible()
1003#if QT_CONFIG(quick_draganddrop)
1004 || !d->drag || !d->drag->filterChildren()
1008 return QQuickItem::childMouseEventFilter(i, e);
1009 switch (e->type()) {
1010 case QEvent::MouseButtonPress:
1011 case QEvent::MouseMove:
1012 case QEvent::MouseButtonRelease:
1013 return sendMouseEvent(
static_cast<QMouseEvent *>(e));
1018 return QQuickItem::childMouseEventFilter(i, e);
1021void QQuickMouseArea::timerEvent(QTimerEvent *event)
1023 Q_D(QQuickMouseArea);
1024 if (event->timerId() == d->pressAndHoldTimer.timerId()) {
1025 d->pressAndHoldTimer.stop();
1026#if QT_CONFIG(quick_draganddrop)
1027 bool dragged = d->drag && d->drag->active();
1029 bool dragged =
false;
1031 if (d->pressed && dragged ==
false && d->hovered ==
true) {
1032 d->longPress =
true;
1033 QQuickMouseEvent &me = d->quickMouseEvent;
1034 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers,
false, d->longPress, d->lastFlags);
1035#if QT_DEPRECATED_SINCE(6
, 6
)
1036 me.setSource(Qt::MouseEventSynthesizedByQt);
1038 me.setAccepted(d->isPressAndHoldConnected());
1039 emit pressAndHold(&me);
1040 if (!me.isAccepted())
1041 d->propagate(&me, QQuickMouseAreaPrivate::PressAndHold);
1042 if (!me.isAccepted())
1043 d->longPress =
false;
1059void QQuickMouseArea::itemChange(ItemChange change,
const ItemChangeData &value)
1061 Q_D(QQuickMouseArea);
1063 case ItemEnabledHasChanged:
1066 if (d->pressed && !d->effectiveEnable)
1069 case ItemVisibleHasChanged:
1070 if (d->effectiveEnable && d->enabled && hoverEnabled()
1071 && d->hovered != (isVisible() && isUnderMouse())) {
1080 QPointF globalPos{ QGuiApplicationPrivate::lastCursorPosition.toPoint() };
1081 QPointF scenePos{ d->window->mapFromGlobal(globalPos) };
1083 QQuickWindowPrivate *wd = QQuickWindowPrivate::get(d->window);
1084 QQuickDeliveryAgentPrivate *dap = wd->deliveryAgentPrivate();
1088 if (!dap->hoveredLeafItemFound) {
1089 dap->deliverHoverEvent(scenePos, scenePos, Qt::NoModifier,
1090 QDateTime::currentSecsSinceEpoch());
1095 if (dap->hoveredLeafItemFound) {
1096 for (
auto hoverItem : dap->hoverItems) {
1097 if (hoverItem.item ==
this) {
1099 d->lastScenePos = scenePos;
1100 d->lastPos = mapFromScene(d->lastScenePos);
1108 if (d->pressed && (!isVisible())) {
1119 QQuickItem::itemChange(change, value);
1240bool QQuickMouseArea::setPressed(Qt::MouseButton button,
bool p, Qt::MouseEventSource source)
1242 Q_D(QQuickMouseArea);
1245 if (p && !d->effectiveVisible)
1248#if QT_CONFIG(quick_draganddrop)
1249 bool dragged = d->drag && d->drag->active();
1251 bool dragged =
false;
1253 bool wasPressed = d->pressed & button;
1254 bool isclick = wasPressed && p ==
false && dragged ==
false && d->hovered ==
true;
1255 Qt::MouseButtons oldPressed = d->pressed;
1257 if (wasPressed != p) {
1258 QQuickMouseEvent &me = d->quickMouseEvent;
1259 me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress, d->lastFlags);
1260#if QT_DEPRECATED_SINCE(6
, 6
)
1261 me.setSource(source);
1264 d->pressed |= button;
1265 if (!d->doubleClick)
1267 me.setPosition(d->lastPos);
1268 emit mouseXChanged(&me);
1269 me.setPosition(d->lastPos);
1270 emit mouseYChanged(&me);
1272 if (!me.isAccepted()) {
1273 d->pressed = Qt::NoButton;
1274 if (!hoverEnabled())
1279 emit pressedChanged();
1280 emit containsPressChanged();
1282 emit pressedButtonsChanged();
1284 d->pressed &= ~button;
1286 me.setPosition(d->lastPos);
1288 emit pressedChanged();
1289 emit containsPressChanged();
1291 emit pressedButtonsChanged();
1292 if (isclick && !d->longPress && !d->doubleClick){
1293 me.setAccepted(d->isClickConnected());
1295 if (!me.isAccepted())
1296 d->propagate(&me, QQuickMouseAreaPrivate::Click);
1300 return me.isAccepted();
1473QSGNode *QQuickMouseArea::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
1476 Q_D(QQuickMouseArea);
1478 if (!qmlMaVisualTouchDebugging())
1481 QSGInternalRectangleNode *rectangle =
static_cast<QSGInternalRectangleNode *>(oldNode);
1482 if (!rectangle) rectangle = d->sceneGraphContext()->createInternalRectangleNode();
1484 rectangle->setRect(QRectF(0, 0, width(), height()));
1485 rectangle->setColor(QColor(255, 0, 0, 50));
1486 rectangle->update();