diff options
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 258 |
1 files changed, 153 insertions, 105 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 53c0231f87..4f14eedd39 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -46,6 +46,7 @@ #include "qquickevents_p_p.h" #include <private/qquickdrag_p.h> +#include <private/qquickhoverhandler_p.h> #include <private/qquickpointerhandler_p.h> #include <QtQuick/private/qsgrenderer_p.h> @@ -88,6 +89,8 @@ Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch") Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target") Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse") Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target") +Q_LOGGING_CATEGORY(lcWheelTarget, "qt.quick.wheel.target") +Q_LOGGING_CATEGORY(lcGestureTarget, "qt.quick.gesture.target") Q_LOGGING_CATEGORY(DBG_HOVER_TRACE, "qt.quick.hover.trace") Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus") Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty") @@ -256,14 +259,16 @@ void QQuickWindow::hideEvent(QHideEvent *) void QQuickWindow::focusOutEvent(QFocusEvent *ev) { Q_D(QQuickWindow); - d->contentItem->setFocus(false, ev->reason()); + if (d->contentItem) + d->contentItem->setFocus(false, ev->reason()); } /*! \reimp */ void QQuickWindow::focusInEvent(QFocusEvent *ev) { Q_D(QQuickWindow); - d->contentItem->setFocus(true, ev->reason()); + if (d->contentItem) + d->contentItem->setFocus(true, ev->reason()); d->updateFocusItemTransform(); } @@ -610,6 +615,7 @@ QQmlListProperty<QObject> QQuickWindowPrivate::data() static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::TouchPoint &p, QTouchEvent *event, QQuickItem *item, bool transformNeeded = true) { + Q_ASSERT(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)); // The touch point local position and velocity are not yet transformed. QMouseEvent *me = new QMouseEvent(type, transformNeeded ? item->mapFromScene(p.scenePos()) : p.pos(), p.scenePos(), p.screenPos(), Qt::LeftButton, (type == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton), event->modifiers()); @@ -651,6 +657,7 @@ bool QQuickWindowPrivate::checkIfDoubleClicked(ulong newPressEventTimestamp) bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEvent *pointerEvent) { + Q_ASSERT(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)); Q_Q(QQuickWindow); auto device = pointerEvent->device(); @@ -767,6 +774,7 @@ bool QQuickWindowPrivate::deliverTouchAsMouse(QQuickItem *item, QQuickPointerEve void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> &ids) { + QQuickPointerEvent *ev = nullptr; for (int i = 0; i < ids.count(); ++i) { int id = ids.at(i); if (Q_UNLIKELY(id < 0)) { @@ -786,15 +794,26 @@ void QQuickWindowPrivate::grabTouchPoints(QObject *grabber, const QVector<int> & qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: mouse grabber changed due to grabTouchPoints:" << touchMouseGrabber << "-> null"; } + // optimization to avoid the loop over devices below: + // all ids are probably from the same event, so we don't have to search + if (ev) { + auto point = ev->pointById(id); + if (point && point->exclusiveGrabber() != grabber) { + point->setExclusiveGrabber(grabber); + continue; // next id in the ids loop + } + } + // search all devices for a QQuickPointerEvent instance that is delivering the point with id const auto touchDevices = QQuickPointerDevice::touchDevices(); for (auto device : touchDevices) { - auto point = pointerEventInstance(device)->pointById(id); - if (!point) - continue; - QObject *oldGrabber = point->exclusiveGrabber(); - if (oldGrabber == grabber) - continue; - point->setExclusiveGrabber(grabber); + QQuickPointerEvent *pev = pointerEventInstance(device); + auto point = pev->pointById(id); + if (point) { + ev = pev; + if (point->exclusiveGrabber() != grabber) + point->setExclusiveGrabber(grabber); + break; // out of touchDevices loop + } } } } @@ -1315,7 +1334,9 @@ QQuickWindow::~QQuickWindow() #if QT_CONFIG(draganddrop) delete d->dragGrabber; d->dragGrabber = nullptr; #endif - delete d->contentItem; d->contentItem = nullptr; + QQuickRootItem *root = d->contentItem; + d->contentItem = nullptr; + delete root; qDeleteAll(d->pointerEventInstances); d->pointerEventInstances.clear(); @@ -1540,8 +1561,20 @@ bool QQuickWindowPrivate::clearHover(ulong timestamp) QPointF pos = q->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint()); bool accepted = false; - for (QQuickItem* item : qAsConst(hoverItems)) + for (QQuickItem* item : qAsConst(hoverItems)) { accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), timestamp, true) || accepted; + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + if (itemPrivate->hasPointerHandlers()) { + pos = q->mapFromGlobal(QCursor::pos()); + QQuickPointerEvent *pointerEvent = pointerEventInstance(QQuickPointerDevice::genericMouseDevice(), QEvent::MouseMove); + pointerEvent->point(0)->reset(Qt::TouchPointMoved, pos, quint64(1) << 24 /* mouse has device ID 1 */, timestamp, QVector2D()); + pointerEvent->point(0)->setAccepted(true); + pointerEvent->localize(item); + for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers) + if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h)) + hh->handlePointerEvent(pointerEvent); + } + } hoverItems.clear(); return accepted; } @@ -1571,6 +1604,8 @@ bool QQuickWindow::event(QEvent *e) return d->deliverTouchCancelEvent(static_cast<QTouchEvent*>(e)); break; case QEvent::Enter: { + if (!d->contentItem) + return false; QEnterEvent *enter = static_cast<QEnterEvent*>(e); bool accepted = enter->isAccepted(); bool delivered = d->deliverHoverEvent(d->contentItem, enter->windowPos(), d->lastMousePosition, @@ -1592,7 +1627,8 @@ bool QQuickWindow::event(QEvent *e) break; #endif case QEvent::WindowDeactivate: - contentItem()->windowDeactivateEvent(); + if (d->contentItem) + d->contentItem->windowDeactivateEvent(); break; case QEvent::Close: { // TOOD Qt 6 (binary incompatible) @@ -1617,7 +1653,7 @@ bool QQuickWindow::event(QEvent *e) } #if QT_CONFIG(gestures) case QEvent::NativeGesture: - d->deliverNativeGestureEvent(d->contentItem, static_cast<QNativeGestureEvent*>(e)); + d->deliverSinglePointEventUntilAccepted(d->pointerEventInstance(e)); break; #endif case QEvent::ShortcutOverride: @@ -1684,6 +1720,7 @@ void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector<QPointer <QQuic { const QVector<QQuickPointerHandler *> &eventDeliveryTargets = pointerEvent->device()->eventDeliveryTargets(); QVarLengthArray<QPair<QQuickItem *, bool>, 4> sendFilteredPointerEventResult; + hasFiltered.clear(); for (auto handler : passiveGrabbers) { // a null pointer in passiveGrabbers is unlikely, unless the grabbing handler was deleted dynamically if (Q_LIKELY(handler) && !eventDeliveryTargets.contains(handler)) { @@ -1723,6 +1760,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven if (grabberItem) { bool handled = false; + hasFiltered.clear(); if (sendFilteredPointerEvent(pointerEvent, grabberItem)) handled = true; // if the grabber is an Item: @@ -1747,8 +1785,10 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven // release event: ungrab if no buttons are pressed anymore if (mouseIsReleased) removeGrabber(grabberItem, true, isDeliveringTouchAsMouse()); - } else if (auto handler = point->grabberPointerHandler()) { + deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent); + } else if (auto handler = point->grabberPointerHandler()) { pointerEvent->localize(handler->parentItem()); + hasFiltered.clear(); if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem())) handler->handlePointerEvent(pointerEvent); if (mouseIsReleased) @@ -1767,12 +1807,13 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order if (!pointerEvent->allPointsGrabbed() && pointerEvent->buttons()) { - QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePosition(), false, false); + QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point, false, false); for (QQuickItem *item : targetItems) { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (!itemPrivate->extra.isAllocated() || itemPrivate->extra->pointerHandlers.isEmpty()) continue; pointerEvent->localize(item); + hasFiltered.clear(); if (!sendFilteredPointerEvent(pointerEvent, item)) { if (itemPrivate->handlePointerEvent(pointerEvent, true)) // avoid re-delivering to grabbers delivered = true; @@ -1834,6 +1875,16 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce } } + if (itemPrivate->hasPointerHandlers()) { + QQuickPointerEvent *pointerEvent = pointerEventInstance(QQuickPointerDevice::genericMouseDevice(), QEvent::MouseMove); + pointerEvent->point(0)->reset(Qt::TouchPointMoved, scenePos, quint64(1) << 24 /* mouse has device ID 1 */, timestamp, QVector2D()); + pointerEvent->point(0)->setAccepted(true); + pointerEvent->localize(item); + for (QQuickPointerHandler *h : itemPrivate->extra->pointerHandlers) + if (QQuickHoverHandler *hh = qmlobject_cast<QQuickHoverHandler *>(h)) + hh->handlePointerEvent(pointerEvent); + } + if (itemPrivate->hoverEnabled) { QPointF p = item->mapFromScene(scenePos); if (item->contains(p)) { @@ -1886,43 +1937,57 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce return false; } -#if QT_CONFIG(wheelevent) -bool QQuickWindowPrivate::deliverWheelEvent(QQuickItem *item, QWheelEvent *event) +// Simple delivery of non-mouse, non-touch Pointer Events: visit the items and handlers +// in the usual reverse-paint-order until propagation is stopped +bool QQuickWindowPrivate::deliverSinglePointEventUntilAccepted(QQuickPointerEvent *event) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + Q_ASSERT(event->pointCount() == 1); + QQuickEventPoint *point = event->point(0); + QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point, false, false); - if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { - QPointF p = item->mapFromScene(event->posF()); - if (!item->contains(p)) - return false; - } - - QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); - for (int ii = children.count() - 1; ii >= 0; --ii) { - QQuickItem *child = children.at(ii); - if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) - continue; - if (deliverWheelEvent(child, event)) - return true; - } - - QPointF p = item->mapFromScene(event->posF()); - - if (item->contains(p)) { - QWheelEvent wheel(p, event->globalPosF(), event->pixelDelta(), event->angleDelta(), event->delta(), - event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted()); - wheel.setTimestamp(event->timestamp()); - wheel.accept(); - QCoreApplication::sendEvent(item, &wheel); - if (wheel.isAccepted()) { - event->accept(); + for (QQuickItem *item : targetItems) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + event->localize(item); + // Let Pointer Handlers have the first shot + itemPrivate->handlePointerEvent(event); + if (point->isAccepted()) return true; + QPointF g = item->window()->mapToGlobal(point->scenePosition().toPoint()); +#if QT_CONFIG(wheelevent) + // Let the Item have a chance to handle it + if (QQuickPointerScrollEvent *pse = event->asPointerScrollEvent()) { + QWheelEvent wheel(point->position(), g, pse->pixelDelta().toPoint(), pse->angleDelta().toPoint(), + pse->buttons(), pse->modifiers(), pse->phase(), + pse->isInverted(), pse->synthSource()); + wheel.setTimestamp(pse->timestamp()); + wheel.accept(); + QCoreApplication::sendEvent(item, &wheel); + if (wheel.isAccepted()) { + qCDebug(lcWheelTarget) << &wheel << "->" << item; + event->setAccepted(true); + return true; + } + } +#endif +#if QT_CONFIG(gestures) + if (QQuickPointerNativeGestureEvent *pnge = event->asPointerNativeGestureEvent()) { + QNativeGestureEvent nge(pnge->type(), pnge->device()->qTouchDevice(), point->position(), point->scenePosition(), g, + pnge->value(), 0L, 0L); // TODO can't copy things I can't access + nge.accept(); + QCoreApplication::sendEvent(item, &nge); + if (nge.isAccepted()) { + qCDebug(lcGestureTarget) << &nge << "->" << item; + event->setAccepted(true); + return true; + } } +#endif // gestures } - return false; + return false; // it wasn't handled } +#if QT_CONFIG(wheelevent) /*! \reimp */ void QQuickWindow::wheelEvent(QWheelEvent *event) { @@ -1937,55 +2002,11 @@ void QQuickWindow::wheelEvent(QWheelEvent *event) return; event->ignore(); - d->deliverWheelEvent(d->contentItem, event); + d->deliverPointerEvent(d->pointerEventInstance(event)); d->lastWheelEventAccepted = event->isAccepted(); } #endif // wheelevent -#if QT_CONFIG(gestures) -bool QQuickWindowPrivate::deliverNativeGestureEvent(QQuickItem *item, QNativeGestureEvent *event) -{ - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - - QPointF p = item->mapFromScene(event->windowPos()); - if ((itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) && !item->contains(p)) - return false; - - QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); - for (int ii = children.count() - 1; ii >= 0; --ii) { - QQuickItem *child = children.at(ii); - if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) - continue; - if (deliverNativeGestureEvent(child, event)) - return true; - } - - // Try the Item's pointer handlers first - QQuickPointerEvent *pointerEvent = pointerEventInstance(event); - pointerEvent->localize(item); - if (itemPrivate->handlePointerEvent(pointerEvent, false)) { - if (pointerEvent->allPointsAccepted()) { - event->accept(); - return true; - } - } - - // If still not accepted, try direct delivery to the item - if (item->contains(p)) { - QNativeGestureEvent copy(event->gestureType(), event->device(), p, event->windowPos(), event->screenPos(), - event->value(), 0L, 0L); // TODO can't copy things I can't access - event->accept(); - item->event(©); - if (copy.isAccepted()) { - event->accept(); - return true; - } - } - - return false; -} -#endif // gestures - bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event) { qCDebug(DBG_TOUCH) << event; @@ -2229,6 +2250,8 @@ QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointer if (eventType == QEvent::NativeGesture && !qobject_cast<QQuickPointerNativeGestureEvent*>(e)) continue; #endif + if (eventType == QEvent::Wheel && !qobject_cast<QQuickPointerScrollEvent*>(e)) + continue; // Otherwise we assume there's only one event type per device. // More disambiguation tests might need to be added above if that changes later. if (e->device() == device) @@ -2248,7 +2271,10 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevic // QWindowSystemInterface::handleMouseEvent() does not take a device parameter: // we assume all mouse events come from one mouse (the "core pointer"). // So when the event is a mouse event, device == QQuickPointerDevice::genericMouseDevice() - ev = new QQuickPointerMouseEvent(q, device); + if (eventType == QEvent::Wheel) + ev = new QQuickPointerScrollEvent(q, device); + else + ev = new QQuickPointerMouseEvent(q, device); break; case QQuickPointerDevice::TouchPad: case QQuickPointerDevice::TouchScreen: @@ -2282,6 +2308,7 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) con case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: + case QEvent::Wheel: dev = QQuickPointerDevice::genericMouseDevice(); break; case QEvent::TouchBegin: @@ -2324,7 +2351,7 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) } else if (event->asPointerTouchEvent()) { deliverTouchEvent(event->asPointerTouchEvent()); } else { - Q_ASSERT(false); + deliverSinglePointEventUntilAccepted(event); } event->reset(nullptr); @@ -2332,16 +2359,16 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) --pointerEventRecursionGuard; } -// check if item or any of its child items contain the point +// check if item or any of its child items contain the point, or if any pointer handler "wants" the point // FIXME: should this be iterative instead of recursive? // If checkMouseButtons is true, it means we are finding targets for a mouse event, so no item for which acceptedMouseButtons() is NoButton will be added. // If checkAcceptsTouch is true, it means we are finding targets for a touch event, so either acceptTouchEvents() must return true OR // it must accept a synth. mouse event, thus if acceptTouchEvents() returns false but acceptedMouseButtons() is true, gets added; if not, it doesn't. -QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, const QPointF &scenePos, bool checkMouseButtons, bool checkAcceptsTouch) const +QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, QQuickEventPoint *point, bool checkMouseButtons, bool checkAcceptsTouch) const { QVector<QQuickItem *> targets; auto itemPrivate = QQuickItemPrivate::get(item); - QPointF itemPos = item->mapFromScene(scenePos); + QPointF itemPos = item->mapFromScene(point->scenePosition()); // if the item clips, we can potentially return early if (itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) { if (!item->contains(itemPos)) @@ -2355,11 +2382,15 @@ QVector<QQuickItem *> QQuickWindowPrivate::pointerTargets(QQuickItem *item, cons auto childPrivate = QQuickItemPrivate::get(child); if (!child->isVisible() || !child->isEnabled() || childPrivate->culled) continue; - targets << pointerTargets(child, scenePos, checkMouseButtons, checkAcceptsTouch); + targets << pointerTargets(child, point, checkMouseButtons, checkAcceptsTouch); } bool relevant = item->contains(itemPos); - if (!(itemPrivate->hasPointerHandlers())) { + if (itemPrivate->hasPointerHandlers()) { + if (!relevant) + if (itemPrivate->anyPointerHandlerWants(point)) + relevant = true; + } else { if (relevant && checkMouseButtons && item->acceptedMouseButtons() == Qt::NoButton) relevant = false; if (relevant && checkAcceptsTouch && !(item->acceptTouchEvents() || item->acceptedMouseButtons())) @@ -2440,6 +2471,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve // The grabber is not an item? It's a handler then. Let it have the event first. QQuickPointerHandler *handler = static_cast<QQuickPointerHandler *>(grabber); receiver = static_cast<QQuickPointerHandler *>(grabber)->parentItem(); + hasFiltered.clear(); if (sendFilteredPointerEvent(event, receiver)) done = true; event->localize(receiver); @@ -2469,7 +2501,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve QQuickEventPoint *point = event->point(i); if (point->state() == QQuickEventPoint::Pressed) continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints - QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), false, false); + QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, false, false); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2494,12 +2526,20 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, int pointCount = event->pointCount(); QVector<QQuickItem *> targetItems; bool isTouchEvent = (event->asPointerTouchEvent() != nullptr); + if (isTouchEvent && event->isPressEvent()) { + // When a second point is pressed, we're starting over with delivery, so + // don't let prior conception of which one is acting as a mouse interfere + touchMouseId = -1; + touchMouseDevice = nullptr; + } for (int i = 0; i < pointCount; ++i) { auto point = event->point(i); + if (point->state() == QQuickEventPoint::Pressed && !event->isDoubleClickEvent()) + point->clearPassiveGrabbers(); point->setAccepted(false); // because otherwise touchEventForItem will ignore it if (point->grabberPointerHandler() && point->state() == QQuickEventPoint::Released) point->setGrabberPointerHandler(nullptr, true); - QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), !isTouchEvent, isTouchEvent); + QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point, !isTouchEvent, isTouchEvent); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2512,6 +2552,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, qWarning("event went missing during delivery! (nested sendEvent() is not allowed)"); break; } + hasFiltered.clear(); if (!handlersOnly && sendFilteredPointerEvent(event, item)) { if (event->isAccepted()) { for (int i = 0; i < event->pointCount(); ++i) @@ -2567,7 +2608,6 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo // synthetic events - flickable sends one when setPressDelay is used. auto oldMouseGrabber = q->mouseGrabberItem(); QPointF localPos = item->mapFromScene(point->scenePosition()); - Q_ASSERT(item->contains(localPos)); // transform is checked already QMouseEvent *me = event->asMouseEvent(localPos); me->accept(); QCoreApplication::sendEvent(item, me); @@ -2595,6 +2635,7 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo bool eventAccepted = false; // If any parent filters the event, we're done. + hasFiltered.clear(); if (sendFilteredPointerEvent(pointerEvent, item)) return; @@ -2604,10 +2645,12 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo eventAccepted = touchEvent->isAccepted(); // If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it. - if (!eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) { - // send mouse event - if (deliverTouchAsMouse(item, ptEvent)) - eventAccepted = true; + if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) { + if (!eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) { + // send mouse event + if (deliverTouchAsMouse(item, ptEvent)) + eventAccepted = true; + } } if (eventAccepted) { @@ -2811,7 +2854,6 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent) { - hasFiltered.clear(); return sendFilteredPointerEventImpl(event, receiver, filteringParent ? filteringParent : receiver->parentItem()); } @@ -2872,7 +2914,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event pt->setGrabberItem(filteringParent); } return true; - } else { + } else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) { // filteringParent didn't filter the touch event. Give it a chance to filter a synthetic mouse event. for (int i = 0; i < filteringParentTouchEvent->touchPoints().size(); ++i) { const QTouchEvent::TouchPoint &tp = filteringParentTouchEvent->touchPoints().at(i); @@ -2971,6 +3013,12 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent return overThreshold; } +bool QQuickWindowPrivate::dragOverThreshold(QVector2D delta) +{ + int threshold = qApp->styleHints()->startDragDistance(); + return qAbs(delta.x()) > threshold || qAbs(delta.y()) > threshold; +} + /*! \qmlproperty list<Object> Window::data \default |