98void QQuickPointerHandler::setMargin(qreal pointDistanceThreshold)
100 Q_D(QQuickPointerHandler);
101 if (d->m_margin == pointDistanceThreshold)
104 d->m_margin = pointDistanceThreshold;
105 if (
auto *parent = parentItem()) {
106 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
108 itemPriv->extra.value().biggestPointerHandlerMarginCache = -1;
110 emit marginChanged();
132void QQuickPointerHandler::setDragThreshold(
int t)
134 Q_D(QQuickPointerHandler);
135 if (d->dragThreshold == t)
138 if (t > std::numeric_limits<qint16>::max())
139 qWarning() <<
"drag threshold cannot exceed" << std::numeric_limits<qint16>::max();
140 d->dragThreshold = qint16(t);
141 emit dragThresholdChanged();
267void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition,
268 QPointerEvent *event, QEventPoint &point)
271 qCDebug(lcPointerHandlerGrab) << point << transition << grabber;
272 if (grabber ==
this) {
273 bool wasCanceled =
false;
274 switch (transition) {
275 case QPointingDevice::GrabPassive:
276 case QPointingDevice::GrabExclusive:
278 case QPointingDevice::CancelGrabPassive:
279 case QPointingDevice::CancelGrabExclusive:
282 case QPointingDevice::UngrabPassive:
283 case QPointingDevice::UngrabExclusive:
285 point.setAccepted(
false);
286 if (
auto par = parentItem()) {
287 Q_D(
const QQuickPointerHandler);
288 par->setKeepMouseGrab(d->hadKeepMouseGrab);
289 par->setKeepTouchGrab(d->hadKeepTouchGrab);
292 case QPointingDevice::OverrideGrabPassive:
298 emit canceled(point);
299 emit grabChanged(transition, point);
318void QQuickPointerHandler::setPassiveGrab(QPointerEvent *event,
const QEventPoint &point,
bool grab)
320 qCDebug(lcPointerHandlerGrab) <<
this << point << grab <<
"via"
321 << QQuickDeliveryAgentPrivate::currentOrItemDeliveryAgent(parentItem());
323 event->addPassiveGrabber(point,
this);
325 event->removePassiveGrabber(point,
this);
340bool QQuickPointerHandler::canGrab(QPointerEvent *event,
const QEventPoint &point)
342 QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point));
343 return approveGrabTransition(event, point,
this) &&
344 (existingPhGrabber ? existingPhGrabber->approveGrabTransition(event, point,
this) :
true);
353bool QQuickPointerHandler::approveGrabTransition(QPointerEvent *event,
const QEventPoint &point, QObject *proposedGrabber)
355 Q_D(
const QQuickPointerHandler);
356 bool allowed =
false;
357 QObject* existingGrabber = event->exclusiveGrabber(point);
358 if (proposedGrabber ==
this) {
359 allowed = (existingGrabber ==
nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
360 if (existingGrabber) {
361 if (QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(event->exclusiveGrabber(point))) {
362 if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfDifferentType) &&
363 existingPhGrabber->metaObject()->className() != metaObject()->className())
365 if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfSameType) &&
366 existingPhGrabber->metaObject()->className() == metaObject()->className())
368 }
else if ((d->grabPermissions & CanTakeOverFromItems)) {
370 QQuickItem * existingItemGrabber = qobject_cast<QQuickItem *>(event->exclusiveGrabber(point));
371 auto da = parentItem() ? QQuickItemPrivate::get(parentItem())->deliveryAgentPrivate()
372 : QQuickDeliveryAgentPrivate::currentEventDeliveryAgent ?
static_cast<QQuickDeliveryAgentPrivate *>(
373 QQuickDeliveryAgentPrivate::get(QQuickDeliveryAgentPrivate::currentEventDeliveryAgent)) :
nullptr;
374 const bool isTouchMouse = (da && da->isDeliveringTouchAsMouse());
375 if (existingItemGrabber &&
376 ((existingItemGrabber->keepMouseGrab() &&
377 (QQuickDeliveryAgentPrivate::isMouseEvent(event) || isTouchMouse)) ||
378 (existingItemGrabber->keepTouchGrab() && QQuickDeliveryAgentPrivate::isTouchEvent(event)))) {
388 if (existingItemGrabber->isAncestorOf(parentItem())) {
390 if ((existingItemGrabber->keepMouseGrab() &&
391 (QQuickDeliveryAgentPrivate::isMouseEvent(event) || (isTouchMouse && point.id() == da->touchMouseId))) ||
392 (existingItemGrabber->keepTouchGrab() && QQuickDeliveryAgentPrivate::isTouchEvent(event))) {
393 qCDebug(lcPointerHandlerGrab) <<
this <<
"steals from ancestor"
394 << existingItemGrabber <<
"despite keep-grab flags"
395 << existingItemGrabber->keepMouseGrab() << existingItemGrabber->keepTouchGrab();
400 qCDebug(lcPointerHandlerGrab) <<
this <<
"wants to grab point" << point.id()
401 <<
"but declines to steal from grabber" << existingItemGrabber
402 <<
"with keepMouseGrab=" << existingItemGrabber->keepMouseGrab()
403 <<
"keepTouchGrab=" << existingItemGrabber->keepTouchGrab();
410 if (proposedGrabber) {
411 if ((d->grabPermissions & ApprovesTakeOverByAnything) == ApprovesTakeOverByAnything)
413 if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfDifferentType) &&
414 proposedGrabber->metaObject()->className() != metaObject()->className())
416 if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfSameType) &&
417 proposedGrabber->metaObject()->className() == metaObject()->className())
419 if (!allowed && (d->grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits(
"QQuickItem"))
422 if (d->grabPermissions & ApprovesCancellation)
426 qCDebug(lcPointerHandlerGrab) <<
"point" << Qt::hex << point.id() <<
"permission" <<
427 QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) <<
428 ':' <<
this << (allowed ?
"approved from" :
"denied from") <<
429 existingGrabber <<
"to" << proposedGrabber;
495void QQuickPointerHandler::componentComplete()
497 Q_D(
const QQuickPointerHandler);
498 if (
auto *parent = parentItem()) {
499 QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
500 itemPriv->addPointerHandler(
this);
502 itemPriv->hasCursorHandler =
true;
503 itemPriv->setHasCursorInChild(
true);
528bool QQuickPointerHandler::setExclusiveGrab(QPointerEvent *ev,
const QEventPoint &point,
bool grab)
533 if ((grab && ev->exclusiveGrabber(point) ==
this) || (!grab && ev->exclusiveGrabber(point) !=
this))
538 allowed = canGrab(ev, point);
540 QQuickPointerHandler *existingPhGrabber = qobject_cast<QQuickPointerHandler *>(ev->exclusiveGrabber(point));
542 if (existingPhGrabber && existingPhGrabber !=
this && !existingPhGrabber->approveGrabTransition(ev, point,
nullptr))
545 qCDebug(lcPointerHandlerGrab) << point << (grab ?
"grab" :
"ungrab") << (allowed ?
"allowed" :
"forbidden") <<
546 ev->exclusiveGrabber(point) <<
"->" << (grab ?
this :
nullptr);
548 ev->setExclusiveGrabber(point, grab ?
this :
nullptr);
555void QQuickPointerHandler::cancelAllGrabs(QPointerEvent *event, QEventPoint &point)
557 qCDebug(lcPointerHandlerGrab) << point;
558 if (event->exclusiveGrabber(point) ==
this) {
559 event->setExclusiveGrabber(point,
nullptr);
560 onGrabChanged(
this, QPointingDevice::CancelGrabExclusive, event, point);
562 if (event->removePassiveGrabber(point,
this))
563 onGrabChanged(
this, QPointingDevice::CancelGrabPassive, event, point);
590bool QQuickPointerHandler::parentContains(
const QPointF &localPosition,
const QPointF &scenePosition)
const
592 if (QQuickItem *par = parentItem()) {
594 QRectF windowGeometry = par->window()->geometry();
595 if (!par->window()->isTopLevel())
596 windowGeometry = QRectF(QWindowPrivate::get(par->window())->globalPosition(), par->window()->size());
597 QPointF screenPosition = par->window()->mapToGlobal(scenePosition);
598 if (!windowGeometry.contains(screenPosition))
603 return localPosition.x() >= -m && localPosition.y() >= -m &&
604 localPosition.x() <= par->width() + m && localPosition.y() <= par->height() + m;
605 return par->contains(localPosition);
606 }
else if (parent() && parent()->inherits(
"QQuick3DModel")) {
703void QQuickPointerHandler::setParentItem(QQuickItem *p)
705 Q_D(QQuickPointerHandler);
706 if (QObject::parent() == p)
709 qCDebug(lcHandlerParent) <<
"reparenting handler" <<
this <<
":" << parent() <<
"->" << p;
710 auto *oldParent =
static_cast<QQuickItem *>(QObject::parent());
712 QQuickItemPrivate::get(oldParent)->removePointerHandler(
this);
715 QQuickItemPrivate::get(p)->addPointerHandler(
this);
716 d->onParentChanged(oldParent, p);
717 emit parentChanged();
747void QQuickPointerHandler::handlePointerEvent(QPointerEvent *event)
749 Q_D(QQuickPointerHandler);
750 bool wants = wantsPointerEvent(event);
751 qCDebug(lcPointerHandlerDispatch) << metaObject()->className() << objectName()
752 <<
"on" << parent()->metaObject()->className() << parent()->objectName()
753 << (wants ?
"WANTS" :
"DECLINES") << event;
754 d->currentEvent = event;
756 handlePointerEventImpl(event);
757 d->lastEventTime = event->timestamp();
759#if QT_CONFIG(gestures)
760 if (event->type() != QEvent::NativeGesture)
763 for (
int i = 0; i < event->pointCount(); ++i) {
764 auto &pt = event->point(i);
765 if (event->exclusiveGrabber(pt) ==
this && pt.state() != QEventPoint::Stationary)
766 event->setExclusiveGrabber(pt,
nullptr);
769 d->currentEvent =
nullptr;
770 QQuickPointerHandlerPrivate::deviceDeliveryTargets(event->device()).append(
this);
823bool QQuickPointerHandler::wantsEventPoint(
const QPointerEvent *event,
const QEventPoint &point)
826 bool ret = event->exclusiveGrabber(point) ==
this ||
827 event->passiveGrabbers(point).contains(
this) || parentContains(point);
828 qCDebug(lcPointerHandlerDispatch) << Qt::hex << point.id() <<
"@" << point.scenePosition()
829 << metaObject()->className() << objectName() << ret;
914QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
915 : grabPermissions(QQuickPointerHandler::CanTakeOverFromItems |
916 QQuickPointerHandler::CanTakeOverFromHandlersOfDifferentType |
917 QQuickPointerHandler::ApprovesTakeOverByAnything)
918 , cursorShape(Qt::ArrowCursor)
921 , targetExplicitlySet(
false)
922 , hadKeepMouseGrab(
false)
923 , hadKeepTouchGrab(
false)
937bool QQuickPointerHandlerPrivate::dragOverThreshold(qreal d, Qt::Axis axis,
const TEventPoint &p)
const
939 Q_Q(
const QQuickPointerHandler);
940 QStyleHints *styleHints = qApp->styleHints();
941 bool overThreshold = qAbs(d) > q->dragThreshold();
942 const bool dragVelocityLimitAvailable = (styleHints->startDragVelocity() > 0);
943 if (!overThreshold && dragVelocityLimitAvailable) {
944 qreal velocity = qreal(axis == Qt::XAxis ? p.velocity().x() : p.velocity().y());
945 overThreshold |= qAbs(velocity) > styleHints->startDragVelocity();
947 return overThreshold;
970bool QQuickPointerHandlerPrivate::dragOverThreshold(
const QEventPoint &point)
const
972 QPointF delta = point.scenePosition() - point.scenePressPosition();
973 return (dragOverThreshold(delta.x(), Qt::XAxis, point) ||
974 dragOverThreshold(delta.y(), Qt::YAxis, point));