75void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QPointingDevice::GrabTransition transition, QPointerEvent *event, QEventPoint &point)
77 QQuickMultiPointHandler::onGrabChanged(grabber, transition, event, point);
78 if (grabber ==
this && transition == QPointingDevice::GrabExclusive && target()) {
81 auto isDescendant = [](QQuickItem *parent, QQuickItem *target) {
82 return parent && (target != parent) && !target->isAncestorOf(parent);
84 if (m_snapMode == SnapAlways
85 || (m_snapMode == SnapIfPressedOutsideTarget && !m_pressedInsideTarget)
86 || (m_snapMode == SnapAuto && !m_pressedInsideTarget && isDescendant(parentItem(), target()))
88 m_pressTargetPos = QPointF(target()->width(), target()->height()) / 2;
89 }
else if (m_pressTargetPos.isNull()) {
90 m_pressTargetPos = targetCentroidPosition();
122void QQuickDragHandler::onActiveChanged()
124 QQuickMultiPointHandler::onActiveChanged();
125 const bool curActive = active();
126 m_xAxis.onActiveChanged(curActive, 0);
127 m_yAxis.onActiveChanged(curActive, 0);
129 if (
auto parent = parentItem()) {
130 if (QQuickDeliveryAgentPrivate::isTouchEvent(currentEvent()))
131 parent->setKeepTouchGrab(
true);
135 parent->setKeepMouseGrab(
true);
138 m_pressTargetPos = QPointF();
139 m_pressedInsideTarget =
false;
140 m_pressedInsideParent =
false;
141 if (
auto parent = parentItem()) {
142 parent->setKeepTouchGrab(
false);
143 parent->setKeepMouseGrab(
false);
148bool QQuickDragHandler::wantsPointerEvent(QPointerEvent *event)
150 if (!QQuickMultiPointHandler::wantsPointerEvent(event))
152
153
154
155
159#if QT_CONFIG(gestures)
160 if (event->type() == QEvent::NativeGesture)
164 if (event->isBeginEvent()) {
166 if (event->isSinglePointEvent()) {
167 m_pressedInsideParent = parentContains(event->points().first());
169 for (
int i = 0; !m_pressedInsideParent && i < event->pointCount(); ++i) {
170 auto &p = event->point(i);
171 if (p.state() == QEventPoint::Pressed && parentContains(p))
172 m_pressedInsideParent =
true;
177 if (!m_pressedInsideParent)
183void QQuickDragHandler::handlePointerEventImpl(QPointerEvent *event)
185 if (active() && !QQuickMultiPointHandler::wantsPointerEvent(event))
188 QQuickMultiPointHandler::handlePointerEventImpl(event);
191 const auto mapFromScene = [
this](
const auto &scenePos) {
192 return target() ? target()->mapFromScene(scenePos) : scenePos;
198 QVector2D accumulatedDragDelta(mapFromScene(centroid().scenePosition())
199 - mapFromScene(centroid().scenePressPosition()));
200 if (!m_xAxis.enabled())
201 accumulatedDragDelta.setX(0);
202 if (!m_yAxis.enabled())
203 accumulatedDragDelta.setY(0);
204 setActiveTranslation(accumulatedDragDelta);
209 qreal minAngle = 361;
210 qreal maxAngle = -361;
211 bool allOverThreshold = QQuickDeliveryAgentPrivate::isTouchEvent(event) ?
212 static_cast<QTouchEvent *>(event)->touchPointStates() != QEventPoint::Released :
213 !event->isEndEvent();
214 QList<QEventPoint> chosenPoints;
216 if (event->isBeginEvent())
217 m_pressedInsideTarget = target() && currentPoints().size() > 0;
219 for (
const QQuickHandlerPoint &p : std::as_const(currentPoints())) {
220 if (!allOverThreshold)
222 auto point = event->pointById(p.id());
224 chosenPoints << *point;
225 setPassiveGrab(event, *point);
228 QVector2D accumulatedDragDelta = QVector2D(mapFromScene(point->scenePosition())
229 - mapFromScene(point->scenePressPosition()));
230 if (!m_xAxis.enabled()) {
233 if (qAbs(accumulatedDragDelta.x()) > qAbs(accumulatedDragDelta.y()))
234 accumulatedDragDelta.setY(0);
235 accumulatedDragDelta.setX(0);
237 if (!m_yAxis.enabled()) {
240 if (qAbs(accumulatedDragDelta.y()) > qAbs(accumulatedDragDelta.x()))
241 accumulatedDragDelta.setX(0);
242 accumulatedDragDelta.setY(0);
244 qreal angle = std::atan2(accumulatedDragDelta.y(), accumulatedDragDelta.x()) * 180 / M_PI;
245 bool overThreshold = d_func()->dragOverThreshold(accumulatedDragDelta);
246 qCDebug(lcDragHandler) <<
"movement" << accumulatedDragDelta <<
"angle" << angle <<
"of point" << point
247 <<
"pressed @" << point->scenePressPosition() <<
"over threshold?" << overThreshold;
248 minAngle = qMin(angle, minAngle);
249 maxAngle = qMax(angle, maxAngle);
250 if (allOverThreshold && !overThreshold)
251 allOverThreshold =
false;
253 if (event->isBeginEvent()) {
258 const QPointF localPressPos = target()->mapFromScene(point->scenePressPosition());
259 m_pressedInsideTarget &= target()->contains(localPressPos);
260 m_pressTargetPos = targetCentroidPosition();
266 if (QQuickDeliveryAgentPrivate::isMouseEvent(event))
267 point->setAccepted(
true);
270 if (allOverThreshold) {
271 qreal angleDiff = maxAngle - minAngle;
273 angleDiff = 360 - angleDiff;
274 qCDebug(lcDragHandler) <<
"angle min" << minAngle <<
"max" << maxAngle <<
"range" << angleDiff;
275 if (angleDiff < DragAngleToleranceDegrees && grabPoints(event, chosenPoints))
279 if (active() && target() && target()->parentItem()) {
280 const QPointF newTargetTopLeft = targetCentroidPosition() - m_pressTargetPos;
281 const QPointF xformOrigin = target()->transformOriginPoint();
282 const QPointF targetXformOrigin = newTargetTopLeft + xformOrigin;
283 QPointF pos = target()->parentItem()->mapFromItem(target(), targetXformOrigin);
285 QPointF targetItemPos = target()->position();
286 if (!m_xAxis.enabled())
287 pos.setX(targetItemPos.x());
288 if (!m_yAxis.enabled())
289 pos.setY(targetItemPos.y());
290 enforceAxisConstraints(&pos);
313void QQuickDragHandler::setActiveTranslation(
const QVector2D &trans)
315 if (trans == activeTranslation())
318 const QVector2D delta = trans - activeTranslation();
319 m_xAxis.updateValue(trans.x(), m_xAxis.persistentValue() + delta.x(), delta.x());
320 m_yAxis.updateValue(trans.y(), m_yAxis.persistentValue() + delta.y(), delta.y());
322 qCDebug(lcDragHandler) <<
"translation: delta" << delta
323 <<
"active" << trans <<
"accumulated" << persistentTranslation();
324 emit translationChanged(delta);