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);
194 QVector2D accumulatedDragDelta = QVector2D(centroid().scenePosition() - centroid().scenePressPosition());
195 if (!m_xAxis.enabled())
196 accumulatedDragDelta.setX(0);
197 if (!m_yAxis.enabled())
198 accumulatedDragDelta.setY(0);
199 setActiveTranslation(accumulatedDragDelta);
204 qreal minAngle = 361;
205 qreal maxAngle = -361;
206 bool allOverThreshold = QQuickDeliveryAgentPrivate::isTouchEvent(event) ?
207 static_cast<QTouchEvent *>(event)->touchPointStates() != QEventPoint::Released :
208 !event->isEndEvent();
209 QVector<QEventPoint> chosenPoints;
211 if (event->isBeginEvent())
212 m_pressedInsideTarget = target() && currentPoints().size() > 0;
214 for (
const QQuickHandlerPoint &p : std::as_const(currentPoints())) {
215 if (!allOverThreshold)
217 auto point = event->pointById(p.id());
219 chosenPoints << *point;
220 setPassiveGrab(event, *point);
223 auto const mapFromScene = [
this](
auto const &scenePos) {
224 return target() ? target()->mapFromScene(scenePos) : scenePos;
226 QVector2D accumulatedDragDelta = QVector2D(mapFromScene(point->scenePosition())
227 - mapFromScene(point->scenePressPosition()));
228 if (!m_xAxis.enabled()) {
231 if (qAbs(accumulatedDragDelta.x()) > qAbs(accumulatedDragDelta.y()))
232 accumulatedDragDelta.setY(0);
233 accumulatedDragDelta.setX(0);
235 if (!m_yAxis.enabled()) {
238 if (qAbs(accumulatedDragDelta.y()) > qAbs(accumulatedDragDelta.x()))
239 accumulatedDragDelta.setX(0);
240 accumulatedDragDelta.setY(0);
242 qreal angle = std::atan2(accumulatedDragDelta.y(), accumulatedDragDelta.x()) * 180 / M_PI;
243 bool overThreshold = d_func()->dragOverThreshold(accumulatedDragDelta);
244 qCDebug(lcDragHandler) <<
"movement" << accumulatedDragDelta <<
"angle" << angle <<
"of point" << point
245 <<
"pressed @" << point->scenePressPosition() <<
"over threshold?" << overThreshold;
246 minAngle = qMin(angle, minAngle);
247 maxAngle = qMax(angle, maxAngle);
248 if (allOverThreshold && !overThreshold)
249 allOverThreshold =
false;
251 if (event->isBeginEvent()) {
256 const QPointF localPressPos = target()->mapFromScene(point->scenePressPosition());
257 m_pressedInsideTarget &= target()->contains(localPressPos);
258 m_pressTargetPos = targetCentroidPosition();
264 if (QQuickDeliveryAgentPrivate::isMouseEvent(event))
265 point->setAccepted(
true);
268 if (allOverThreshold) {
269 qreal angleDiff = maxAngle - minAngle;
271 angleDiff = 360 - angleDiff;
272 qCDebug(lcDragHandler) <<
"angle min" << minAngle <<
"max" << maxAngle <<
"range" << angleDiff;
273 if (angleDiff < DragAngleToleranceDegrees && grabPoints(event, chosenPoints))
277 if (active() && target() && target()->parentItem()) {
278 const QPointF newTargetTopLeft = targetCentroidPosition() - m_pressTargetPos;
279 const QPointF xformOrigin = target()->transformOriginPoint();
280 const QPointF targetXformOrigin = newTargetTopLeft + xformOrigin;
281 QPointF pos = target()->parentItem()->mapFromItem(target(), targetXformOrigin);
283 QPointF targetItemPos = target()->position();
284 if (!m_xAxis.enabled())
285 pos.setX(targetItemPos.x());
286 if (!m_yAxis.enabled())
287 pos.setY(targetItemPos.y());
288 enforceAxisConstraints(&pos);
311void QQuickDragHandler::setActiveTranslation(
const QVector2D &trans)
313 if (trans == activeTranslation())
316 const QVector2D delta = trans - activeTranslation();
317 m_xAxis.updateValue(trans.x(), m_xAxis.persistentValue() + delta.x(), delta.x());
318 m_yAxis.updateValue(trans.y(), m_yAxis.persistentValue() + delta.y(), delta.y());
320 qCDebug(lcDragHandler) <<
"translation: delta" << delta
321 <<
"active" << trans <<
"accumulated" << persistentTranslation();
322 emit translationChanged(delta);