99void QQuickPointerHandler::setMargin(qreal pointDistanceThreshold)
101 Q_D(QQuickPointerHandler);
102 if (d->m_margin == pointDistanceThreshold)
105 d->m_margin = pointDistanceThreshold;
106 if (
auto *parent = parentItem()) {
107 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
109 itemPriv->extra.value().biggestPointerHandlerMarginCache = -1;
111 emit marginChanged();
133void QQuickPointerHandler::setDragThreshold(
int t)
135 Q_D(QQuickPointerHandler);
136 if (d->dragThreshold == t)
139 if (t > std::numeric_limits<qint16>::max())
140 qWarning() <<
"drag threshold cannot exceed" << std::numeric_limits<qint16>::max();
141 d->dragThreshold = qint16(t);
142 emit dragThresholdChanged();
268void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition,
269 QPointerEvent *event, QEventPoint &point)
272 qCDebug(lcPointerHandlerGrab) << point << transition << grabber;
273 if (grabber ==
this) {
274 bool wasCanceled =
false;
275 switch (transition) {
276 case QPointingDevice::GrabPassive:
277 case QPointingDevice::GrabExclusive:
279 case QPointingDevice::CancelGrabPassive:
280 case QPointingDevice::CancelGrabExclusive:
283 case QPointingDevice::UngrabPassive:
284 case QPointingDevice::UngrabExclusive:
286 point.setAccepted(
false);
287 if (
auto par = parentItem()) {
288 Q_D(
const QQuickPointerHandler);
289 par->setKeepMouseGrab(d->hadKeepMouseGrab);
290 par->setKeepTouchGrab(d->hadKeepTouchGrab);
293 case QPointingDevice::OverrideGrabPassive:
299 emit canceled(point);
300 emit grabChanged(transition, point);
319void QQuickPointerHandler::setPassiveGrab(QPointerEvent *event,
const QEventPoint &point,
bool grab)
321 qCDebug(lcPointerHandlerGrab) <<
this << point << grab <<
"via"
322 << QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(parentItem());
324 event->addPassiveGrabber(point,
this);
326 event->removePassiveGrabber(point,
this);
341bool QQuickPointerHandler::canGrab(QPointerEvent *event,
const QEventPoint &point)
343 QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point));
344 return approveGrabTransition(event, point,
this) &&
345 (existingPhGrabber ? existingPhGrabber->approveGrabTransition(event, point,
this) :
true);
354bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event,
const QEventPoint &point, QObject *proposedGrabber)
356 Q_D(
const QQuickPointerHandler);
357 bool allowed =
false;
358 QObject* existingGrabber = event->exclusiveGrabber(point);
359 if (proposedGrabber ==
this) {
360 allowed = (existingGrabber ==
nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
361 if (existingGrabber) {
362 if (QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point))) {
363 if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfDifferentType) &&
364 existingPhGrabber->metaObject()->className() != metaObject()->className())
366 if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfSameType) &&
367 existingPhGrabber->metaObject()->className() == metaObject()->className())
369 }
else if ((d->grabPermissions & CanTakeOverFromItems)) {
371 QQuickItem * existingItemGrabber = qobject_cast<QQuickItem *>(event->exclusiveGrabber(point));
372 auto da = parentItem() ? QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate()
373 : QQuickDeliveryAgentPrivate::currentEventDeliveryAgent ?
static_cast<QQuickDeliveryAgentPrivate *>(
374 QQuickDeliveryAgentPrivate::get(QQuickDeliveryAgentPrivate::currentEventDeliveryAgent)) :
nullptr;
375 const bool isTouchMouse = (da && da->isDeliveringTouchAsMouse());
376 if (existingItemGrabber &&
377 ((existingItemGrabber->keepMouseGrab() &&
378 (QQuickDeliveryAgentPrivate::isMouseEvent(event) || isTouchMouse)) ||
379 (existingItemGrabber->keepTouchGrab() && QQuickDeliveryAgentPrivate::isTouchEvent(event)))) {
389 if (existingItemGrabber->isAncestorOf(parentItem())) {
391 if ((existingItemGrabber->keepMouseGrab() &&
392 (QQuickDeliveryAgentPrivate::isMouseEvent(event) || (isTouchMouse && point.id() == da->touchMouseId))) ||
393 (existingItemGrabber->keepTouchGrab() && QQuickDeliveryAgentPrivate::isTouchEvent(event))) {
394 qCDebug(lcPointerHandlerGrab) <<
this <<
"steals from ancestor"
395 << existingItemGrabber <<
"despite keep-grab flags"
396 << existingItemGrabber->keepMouseGrab() << existingItemGrabber->keepTouchGrab();
401 qCDebug(lcPointerHandlerGrab) <<
this <<
"wants to grab point" << point.id()
402 <<
"but declines to steal from grabber" << existingItemGrabber
403 <<
"with keepMouseGrab=" << existingItemGrabber->keepMouseGrab()
404 <<
"keepTouchGrab=" << existingItemGrabber->keepTouchGrab();
411 if (proposedGrabber) {
412 if ((d->grabPermissions & ApprovesTakeOverByAnything) == ApprovesTakeOverByAnything)
414 if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfDifferentType) &&
415 proposedGrabber->metaObject()->className() != metaObject()->className())
417 if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfSameType) &&
418 proposedGrabber->metaObject()->className() == metaObject()->className())
420 if (!allowed && (d->grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits(
"QQuickItem"))
423 if (d->grabPermissions & ApprovesCancellation)
427 qCDebug(lcPointerHandlerGrab) <<
"point" << Qt::hex << point.id() <<
"permission" <<
428 QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) <<
429 ':' <<
this << (allowed ?
"approved from" :
"denied from") <<
430 existingGrabber <<
"to" << proposedGrabber;
496void QQuickPointerHandler::componentComplete()
498 Q_D(
const QQuickPointerHandler);
499 if (
auto *parent = parentItem()) {
500 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
501 itemPriv->addPointerHandler(
this);
503 itemPriv->hasCursorHandler =
true;
504 itemPriv->setHasCursorInChild(
true);
529bool QQuickPointerHandler::setExclusiveGrab(QPointerEvent *ev,
const QEventPoint &point,
bool grab)
534 if ((grab && ev->exclusiveGrabber(point) ==
this) || (!grab && ev->exclusiveGrabber(point) !=
this))
539 allowed = canGrab(ev, point);
541 QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(ev->exclusiveGrabber(point));
543 if (existingPhGrabber && existingPhGrabber !=
this && !existingPhGrabber->approveGrabTransition(ev, point,
nullptr))
546 qCDebug(lcPointerHandlerGrab) << point << (grab ?
"grab" :
"ungrab") << (allowed ?
"allowed" :
"forbidden") <<
547 ev->exclusiveGrabber(point) <<
"->" << (grab ?
this :
nullptr);
549 ev->setExclusiveGrabber(point, grab ?
this :
nullptr);
556void QQuickPointerHandler::cancelAllGrabs(QPointerEvent *event, QEventPoint &point)
558 qCDebug(lcPointerHandlerGrab) << point;
559 if (event->exclusiveGrabber(point) ==
this) {
560 event->setExclusiveGrabber(point,
nullptr);
561 onGrabChanged(
this, QPointingDevice::CancelGrabExclusive, event, point);
563 if (event->removePassiveGrabber(point,
this))
564 onGrabChanged(
this, QPointingDevice::CancelGrabPassive, event, point);
591bool QQuickPointerHandler::parentContains(
const QPointF &localPosition,
const QPointF &scenePosition)
const
593 if (QQuickItem *par = parentItem()) {
595 QRectF windowGeometry = par->window()->geometry();
596 if (!par->window()->isTopLevel())
597 windowGeometry = QRectF(QWindowPrivate::get(par->window())->globalPosition(), par->window()->size());
598 QPointF screenPosition = par->window()->mapToGlobal(scenePosition);
599 if (!windowGeometry.contains(screenPosition))
604 return localPosition.x() >= -m && localPosition.y() >= -m &&
605 localPosition.x() <= par->width() + m && localPosition.y() <= par->height() + m;
606 return par->contains(localPosition);
607 }
else if (parent() && parent()->inherits(
"QQuick3DModel")) {
704void QQuickPointerHandler::setParentItem(QQuickItem *p)
706 Q_D(QQuickPointerHandler);
707 if (QObject::parent() == p)
710 qCDebug(lcHandlerParent) <<
"reparenting handler" <<
this <<
":" << parent() <<
"->" << p;
711 auto *oldParent =
static_cast<QQuickItem *>(QObject::parent());
713 QQuickItemPrivate::get(oldParent)->removePointerHandler(
this);
716 QQuickItemPrivate::get(p)->addPointerHandler(
this);
717 d->onParentChanged(oldParent, p);
718 emit parentChanged();
748void QQuickPointerHandler::handlePointerEvent(QPointerEvent *event)
750 Q_D(QQuickPointerHandler);
751 bool wants = wantsPointerEvent(event);
752 qCDebug(lcPointerHandlerDispatch) << metaObject()->className() << objectName()
753 <<
"on" << parent()->metaObject()->className() << parent()->objectName()
754 << (wants ?
"WANTS" :
"DECLINES") << event;
755 d->currentEvent = event;
757 handlePointerEventImpl(event);
758 d->lastEventTime = event->timestamp();
760#if QT_CONFIG(gestures)
761 if (event->type() != QEvent::NativeGesture)
764 for (
int i = 0; i < event->pointCount(); ++i) {
765 auto &pt = event->point(i);
766 if (event->exclusiveGrabber(pt) ==
this && pt.state() != QEventPoint::Stationary)
767 event->setExclusiveGrabber(pt,
nullptr);
770 d->currentEvent =
nullptr;
771 QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->device()).append(
this);
824bool QQuickPointerHandler::wantsEventPoint(
const QPointerEvent *event,
const QEventPoint &point)
827 bool ret = event->exclusiveGrabber(point) ==
this ||
828 event->passiveGrabbers(point).contains(
this) || parentContains(point);
829 qCDebug(lcPointerHandlerDispatch) << Qt::hex << point.id() <<
"@" << point.scenePosition()
830 << metaObject()->className() << objectName() << ret;
915QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
916 : grabPermissions(QQuickPointerHandler::CanTakeOverFromItems |
917 QQuickPointerHandler::CanTakeOverFromHandlersOfDifferentType |
918 QQuickPointerHandler::ApprovesTakeOverByAnything)
919 , cursorShape(Qt::ArrowCursor)
922 , targetExplicitlySet(
false)
923 , hadKeepMouseGrab(
false)
924 , hadKeepTouchGrab(
false)
938bool QQuickPointerHandlerPrivate::dragOverThreshold(qreal d, Qt::Axis axis,
const TEventPoint &p)
const
940 Q_Q(
const QQuickPointerHandler);
941 QStyleHints *styleHints = qApp->styleHints();
942 bool overThreshold = qAbs(d) > q->dragThreshold();
943 const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
944 if (!overThreshold && dragVelocityLimitAvailable) {
945 qreal velocity = qreal(axis == Qt::XAxis ? p.velocity().x() : p.velocity().y());
946 overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
948 return overThreshold;
971bool QQuickPointerHandlerPrivate::dragOverThreshold(
const QEventPoint &point)
const
973 QPointF delta = point.scenePosition() - point.scenePressPosition();
974 return (dragOverThreshold(delta.x(), Qt::XAxis, point) ||
975 dragOverThreshold(delta.y(), Qt::YAxis, point));