diff options
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/qquickdrag.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquickflickable.cpp | 16 | ||||
-rw-r--r-- | src/quick/items/qquickitem.cpp | 127 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 2 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 8 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea.cpp | 8 | ||||
-rw-r--r-- | src/quick/items/qquickmultipointtoucharea.cpp | 13 | ||||
-rw-r--r-- | src/quick/items/qquickpathview.cpp | 3 | ||||
-rw-r--r-- | src/quick/items/qquicktableview.cpp | 2 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 259 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.h | 4 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 143 |
12 files changed, 326 insertions, 261 deletions
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp index a980f83aba..e6ffcee2aa 100644 --- a/src/quick/items/qquickdrag.cpp +++ b/src/quick/items/qquickdrag.cpp @@ -240,7 +240,7 @@ void QQuickDragAttachedPrivate::deliverEvent(QQuickWindow *window, QEvent *event { Q_ASSERT(!inEvent); inEvent = true; - QQuickWindowPrivate::get(window)->deliverDragEvent(&dragGrabber, event); + QQuickWindowPrivate::get(window)->deliveryAgentPrivate()->deliverDragEvent(&dragGrabber, event); inEvent = false; } diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 62bc078f4d..b02840208d 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1341,9 +1341,9 @@ void QQuickFlickablePrivate::handleMoveEvent(QPointerEvent *event) QVector2D velocity = event->point(0).velocity(); if (q->yflick()) - overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.y(), Qt::YAxis, firstPoint); + overThreshold |= QQuickDeliveryAgentPrivate::dragOverThreshold(deltas.y(), Qt::YAxis, firstPoint); if (q->xflick()) - overThreshold |= QQuickWindowPrivate::dragOverThreshold(deltas.x(), Qt::XAxis, firstPoint); + overThreshold |= QQuickDeliveryAgentPrivate::dragOverThreshold(deltas.x(), Qt::XAxis, firstPoint); drag(currentTimestamp, event->type(), pos, deltas, overThreshold, false, false, velocity); } @@ -1518,7 +1518,7 @@ void QQuickFlickable::touchEvent(QTouchEvent *event) auto &firstPoint = event->point(0); if (auto grabber = qmlobject_cast<QQuickItem *>(event->exclusiveGrabber(firstPoint))) { const auto localPos = grabber->mapFromScene(firstPoint.scenePosition()); - QScopedPointer<QPointerEvent> localizedEvent(QQuickWindowPrivate::clonePointerEvent(event, localPos)); + QScopedPointer<QPointerEvent> localizedEvent(QQuickDeliveryAgentPrivate::clonePointerEvent(event, localPos)); QCoreApplication::sendEvent(window(), localizedEvent.data()); } @@ -1762,7 +1762,7 @@ void QQuickFlickablePrivate::captureDelayedPress(QQuickItem *item, QPointerEvent if (!isInnermostPressDelay(item)) return; - delayedPressEvent = QQuickWindowPrivate::clonePointerEvent(event); + delayedPressEvent = QQuickDeliveryAgentPrivate::clonePointerEvent(event); delayedPressEvent->setAccepted(false); delayedPressTimer.start(pressDelay, q); qCDebug(lcReplay) << "begin press delay" << pressDelay << "ms with" << delayedPressEvent; @@ -1789,8 +1789,8 @@ void QQuickFlickablePrivate::replayDelayedPress() // If we have the grab, release before delivering the event if (QQuickWindow *window = q->window()) { - QQuickWindowPrivate *wpriv = QQuickWindowPrivate::get(window); - wpriv->allowChildEventFiltering = false; // don't allow re-filtering during replay + auto da = deliveryAgentPrivate(); + da->allowChildEventFiltering = false; // don't allow re-filtering during replay replayingPressEvent = true; auto &firstPoint = event->point(0); // At first glance, it's weird for delayedPressEvent to already have a grabber; @@ -1813,7 +1813,7 @@ void QQuickFlickablePrivate::replayDelayedPress() // We're done with replay, go back to normal delivery behavior replayingPressEvent = false; - wpriv->allowChildEventFiltering = true; + da->allowChildEventFiltering = true; } } } @@ -2577,7 +2577,7 @@ bool QQuickFlickable::filterPointerEvent(QQuickItem *receiver, QPointerEvent *ev bool stealThisEvent = d->stealMouse; bool receiverKeepsGrab = receiver && (receiver->keepMouseGrab() || receiver->keepTouchGrab()); if ((stealThisEvent || contains(localPos)) && (!receiver || !receiverKeepsGrab || receiverDisabled)) { - QScopedPointer<QPointerEvent> localizedEvent(QQuickWindowPrivate::clonePointerEvent(event, localPos)); + QScopedPointer<QPointerEvent> localizedEvent(QQuickDeliveryAgentPrivate::clonePointerEvent(event, localPos)); localizedEvent->setAccepted(false); switch (firstPoint.state()) { case QEventPoint::State::Updated: diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 93512d70f8..f4eea2923a 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -91,6 +91,7 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcMouseTarget) Q_DECLARE_LOGGING_CATEGORY(lcHoverTrace) +Q_DECLARE_LOGGING_CATEGORY(lcPtr) Q_DECLARE_LOGGING_CATEGORY(lcTransient) Q_LOGGING_CATEGORY(lcHandlerParent, "qt.quick.handler.parent") @@ -2684,8 +2685,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) while (!scopeItem->isFocusScope() && scopeItem->parentItem()) scopeItem = scopeItem->parentItem(); if (d->window) { - QQuickWindowPrivate::get(d->window)->clearFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason, - QQuickWindowPrivate::DontChangeFocusProperty); + d->deliveryAgentPrivate()-> + clearFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason, + QQuickDeliveryAgentPrivate::DontChangeFocusProperty); if (scopeFocusedItem != this) QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, true); } else { @@ -2760,8 +2762,9 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) emit scopeFocusedItem->focusChanged(false); } else { if (d->window) { - QQuickWindowPrivate::get(d->window)->setFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason, - QQuickWindowPrivate::DontChangeFocusProperty); + d->deliveryAgentPrivate()-> + setFocusInScope(scopeItem, scopeFocusedItem, Qt::OtherFocusReason, + QQuickDeliveryAgentPrivate::DontChangeFocusProperty); } else { QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, true); } @@ -3037,7 +3040,6 @@ void QQuickItemPrivate::derefWindow() window->unsetCursor(); } #endif - c->hoverItems.removeAll(q); if (itemNodeInstance) c->cleanup(itemNodeInstance); if (!parentItem) @@ -3194,6 +3196,7 @@ QQuickItemPrivate::QQuickItemPrivate() , replayingPressEvent(false) , touchEnabled(false) , hasCursorHandler(false) + , hasSubsceneDeliveryAgent(false) , dirtyAttributes(0) , nextDirtyItem(nullptr) , prevDirtyItem(nullptr) @@ -5195,6 +5198,57 @@ QPointF QQuickItemPrivate::adjustedPosForTransform(const QPointF ¢roidParent return pos; } +/*! \internal + Returns the delivery agent for the narrowest subscene containing this item, + but falls back to QQuickWindowPrivate::deliveryAgent if there are no subscenes. + + \note When a Qt Quick scene is shown in the usual way in its own window, + subscenes are ignored, and QQuickWindowPrivate::deliveryAgent is used. + Subscene delivery agents are used only in QtQuick 3D so far. +*/ +QQuickDeliveryAgent *QQuickItemPrivate::deliveryAgent() +{ + // optimization: don't go up the parent hierarchy if this item is not aware of being in a subscene + if (hasSubsceneDeliveryAgent) { + QQuickItemPrivate *p = this; + do { + if (p->extra.isAllocated()) { + if (auto da = p->extra->subsceneDeliveryAgent) + return da; + p = p->parentItem ? QQuickItemPrivate::get(p->parentItem) : nullptr; + } + } while (p); + } + if (window) + return QQuickWindowPrivate::get(window)->deliveryAgent; + return nullptr; +} + +QQuickDeliveryAgentPrivate *QQuickItemPrivate::deliveryAgentPrivate() +{ + auto da = deliveryAgent(); + return da ? static_cast<QQuickDeliveryAgentPrivate *>(QQuickDeliveryAgentPrivate::get(da)) : nullptr; +} + +/*! \internal + Ensures that this item, presumably the root of a sub-scene (e.g. because it + is mapped onto a 3D object in Qt Quick 3D), has a delivery agent to be used + when delivering events to the subscene: i.e. when the viewport delivers an + event to the subscene, or when the outer delivery agent delivers an update + to an item that grabbed during a previous subscene delivery. Creates a new + agent if it was not already created, and returns a pointer to the instance. +*/ +QQuickDeliveryAgent *QQuickItemPrivate::ensureSubsceneDeliveryAgent() +{ + Q_Q(QQuickItem); + hasSubsceneDeliveryAgent = true; + if (extra.isAllocated() && extra->subsceneDeliveryAgent) + return extra->subsceneDeliveryAgent; + extra.value().subsceneDeliveryAgent = new QQuickDeliveryAgent(q); + qCDebug(lcPtr) << "created new" << extra->subsceneDeliveryAgent; + return extra->subsceneDeliveryAgent; +} + bool QQuickItemPrivate::filterKeyEvent(QKeyEvent *e, bool post) { if (!extra.isAllocated() || !extra->keyHandler) @@ -6089,12 +6143,10 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible) effectiveVisible = newEffectiveVisible; dirty(Visible); - if (parentItem) QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged); - - if (window) { - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - windowPriv->removeGrabber(q, true, true, true); - } + if (parentItem) + QQuickItemPrivate::get(parentItem)->dirty(ChildrenStackingChanged); + if (window) + deliveryAgentPrivate()->removeGrabber(q, true, true, true); bool childVisibilityChanged = false; for (int ii = 0; ii < childItems.count(); ++ii) @@ -6138,12 +6190,13 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec effectiveEnable = newEffectiveEnable; - if (window) { - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window); - windowPriv->removeGrabber(q, true, true, true); + QQuickDeliveryAgentPrivate *da = deliveryAgentPrivate(); + if (da) { + da->removeGrabber(q, true, true, true); if (scope && !effectiveEnable && activeFocus) { - windowPriv->clearFocusInScope( - scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem); + da->clearFocusInScope(scope, q, Qt::OtherFocusReason, + QQuickDeliveryAgentPrivate::DontChangeFocusProperty | + QQuickDeliveryAgentPrivate::DontChangeSubFocusItem); } } @@ -6152,9 +6205,10 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec (flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable); } - if (window && scope && effectiveEnable && focus) { - QQuickWindowPrivate::get(window)->setFocusInScope( - scope, q, Qt::OtherFocusReason, QQuickWindowPrivate::DontChangeFocusProperty | QQuickWindowPrivate::DontChangeSubFocusItem); + if (scope && effectiveEnable && focus && da) { + da->setFocusInScope(scope, q, Qt::OtherFocusReason, + QQuickDeliveryAgentPrivate::DontChangeFocusProperty | + QQuickDeliveryAgentPrivate::DontChangeSubFocusItem); } itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable); @@ -7252,10 +7306,12 @@ void QQuickItem::setFocus(bool focus, Qt::FocusReason reason) scope = scope->parentItem(); if (d->window) { if (reason != Qt::PopupFocusReason) { + auto da = d->deliveryAgentPrivate(); + Q_ASSERT(da); if (focus) - QQuickWindowPrivate::get(d->window)->setFocusInScope(scope, this, reason); + da->setFocusInScope(scope, this, reason); else - QQuickWindowPrivate::get(d->window)->clearFocusInScope(scope, this, reason); + da->clearFocusInScope(scope, this, reason); } } else { // do the focus changes from setFocusInScope/clearFocusInScope that are @@ -7276,7 +7332,7 @@ void QQuickItem::setFocus(bool focus, Qt::FocusReason reason) changed << this; emit focusChanged(focus); - QQuickWindowPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1); + QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1); } } else { QVarLengthArray<QQuickItem *, 20> changed; @@ -7291,7 +7347,7 @@ void QQuickItem::setFocus(bool focus, Qt::FocusReason reason) changed << this; emit focusChanged(focus); - QQuickWindowPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1); + QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1); } } @@ -7418,7 +7474,7 @@ bool QQuickItem::isUnderMouse() const // QQuickWindow handles QEvent::Leave to reset the lastMousePosition // FIXME: Using QPointF() as the reset value means an item will not be // under the mouse if the mouse is at 0,0 of the window. - if (QQuickWindowPrivate::get(d->window)->lastMousePosition == QPointF()) + if (const_cast<QQuickItemPrivate *>(d)->deliveryAgentPrivate()->lastMousePosition == QPointF()) return false; QPointF cursorPos = QGuiApplicationPrivate::lastCursorPosition; @@ -7703,13 +7759,14 @@ void QQuickItem::grabMouse() Q_D(QQuickItem); if (!d->window) return; - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window); - auto eventInDelivery = windowPriv->eventInDelivery(); + auto da = d->deliveryAgentPrivate(); + Q_ASSERT(da); + auto eventInDelivery = da->eventInDelivery(); if (!eventInDelivery) { qWarning() << "cannot grab mouse: no event is currently being delivered"; return; } - auto epd = windowPriv->mousePointData(); + auto epd = da->mousePointData(); eventInDelivery->setExclusiveGrabber(epd->eventPoint, this); } @@ -7729,14 +7786,15 @@ void QQuickItem::ungrabMouse() Q_D(QQuickItem); if (!d->window) return; - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window); - auto eventInDelivery = windowPriv->eventInDelivery(); + auto da = d->deliveryAgentPrivate(); + Q_ASSERT(da); + auto eventInDelivery = da->eventInDelivery(); if (!eventInDelivery) { // do it the expensive way - windowPriv->removeGrabber(this); + da->removeGrabber(this); return; } - const auto &eventPoint = windowPriv->mousePointData()->eventPoint; + const auto &eventPoint = da->mousePointData()->eventPoint; if (eventInDelivery->exclusiveGrabber(eventPoint) == this) eventInDelivery->setExclusiveGrabber(eventPoint, nullptr); } @@ -7785,8 +7843,8 @@ void QQuickItem::setKeepMouseGrab(bool keep) */ void QQuickItem::grabTouchPoints(const QList<int> &ids) { - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window()); - auto event = windowPriv->eventInDelivery(); + Q_D(QQuickItem); + auto event = d->deliveryAgentPrivate()->eventInDelivery(); if (Q_UNLIKELY(!event)) { qWarning() << "cannot grab: no event is currently being delivered"; return; @@ -7806,8 +7864,7 @@ void QQuickItem::ungrabTouchPoints() Q_D(QQuickItem); if (!d->window) return; - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(d->window); - windowPriv->removeGrabber(this, false, true); + d->deliveryAgentPrivate()->removeGrabber(this, false, true); } /*! diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index c7bc2f54c3..887318c23f 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -461,8 +461,8 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_resourceObjectDeleted(QObject *)) Q_PRIVATE_SLOT(d_func(), quint64 _q_createJSWrapper(QV4::ExecutionEngine *)) - friend class QQuickWindow; friend class QQuickWindowPrivate; + friend class QQuickDeliveryAgentPrivate; friend class QSGRenderer; friend class QAccessibleQuickItem; friend class QQuickAccessibleAttached; diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index b97b9cefd5..caa6edb15b 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -388,6 +388,8 @@ public: QSGOpacityNode *opacityNode; QQuickDefaultClipNode *clipNode; QSGRootNode *rootNode; + // subsceneDeliveryAgent is set only if this item is the root of a subscene, not on all items within. + QQuickDeliveryAgent *subsceneDeliveryAgent = nullptr; // Mask contains() method QMetaMethod maskContains; @@ -480,6 +482,8 @@ public: bool replayingPressEvent:1; bool touchEnabled:1; bool hasCursorHandler:1; + // set true when this item expects events via a subscene delivery agent; false otherwise + bool hasSubsceneDeliveryAgent:1; enum DirtyType { TransformOrigin = 0x00000001, @@ -607,6 +611,10 @@ public: qreal startScale, qreal activeScale, qreal startRotation, qreal activeRotation); + QQuickDeliveryAgent *deliveryAgent(); + QQuickDeliveryAgentPrivate *deliveryAgentPrivate(); + QQuickDeliveryAgent *ensureSubsceneDeliveryAgent(); + void deliverKeyEvent(QKeyEvent *); bool filterKeyEvent(QKeyEvent *, bool post); #if QT_CONFIG(im) diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index 037eddd6a8..1d4c707c76 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -752,10 +752,10 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) d->lastPos = mapFromScene(d->lastScenePos); } - bool dragOverThresholdX = QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), - Qt::XAxis, event, d->drag->threshold()); - bool dragOverThresholdY = QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), - Qt::YAxis, event, d->drag->threshold()); + bool dragOverThresholdX = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.x() - startPos.x(), + Qt::XAxis, event, d->drag->threshold()); + bool dragOverThresholdY = QQuickDeliveryAgentPrivate::dragOverThreshold(dragPos.y() - startPos.y(), + Qt::YAxis, event, d->drag->threshold()); if (!d->overThreshold && (((targetPos.x() != boundedDragPos.x()) && dragOverThresholdX) || ((targetPos.y() != boundedDragPos.y()) && dragOverThresholdY))) diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp index ed424a3763..642b5ca047 100644 --- a/src/quick/items/qquickmultipointtoucharea.cpp +++ b/src/quick/items/qquickmultipointtoucharea.cpp @@ -578,7 +578,6 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event) clearTouchLists(); QList<QEventPoint> touchPoints; - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window()); QPointingDevice *dev = nullptr; switch (event->type()) { @@ -590,10 +589,12 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event) dev = const_cast<QPointingDevice *>(te->pointingDevice()); break; } - case QEvent::MouseButtonPress: - _mouseQpaTouchPoint = QEventPoint(windowPriv->touchMouseId); - _touchMouseDevice = windowPriv->touchMouseDevice; + case QEvent::MouseButtonPress: { + auto da = QQuickItemPrivate::get(this)->deliveryAgentPrivate(); + _mouseQpaTouchPoint = QEventPoint(da->touchMouseId); + _touchMouseDevice = da->touchMouseDevice; Q_FALLTHROUGH(); + } case QEvent::MouseMove: case QEvent::MouseButtonRelease: { QMouseEvent *me = static_cast<QMouseEvent*>(event); @@ -950,11 +951,11 @@ bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *receiver, QEve return QQuickItem::childMouseEventFilter(receiver, event); switch (event->type()) { case QEvent::MouseButtonPress: { - QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window()); + auto da = QQuickItemPrivate::get(this)->deliveryAgentPrivate(); // If we already got a chance to filter the touchpoint that generated this synth-mouse-press, // and chose not to filter it, ignore it now, too. if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventSynthesizedByQt && - _lastFilterableTouchPointIds.contains(windowPriv->touchMouseId)) + _lastFilterableTouchPointIds.contains(da->touchMouseId)) return false; } Q_FALLTHROUGH(); case QEvent::MouseMove: diff --git a/src/quick/items/qquickpathview.cpp b/src/quick/items/qquickpathview.cpp index 3d0b1b97f9..4cde344dce 100644 --- a/src/quick/items/qquickpathview.cpp +++ b/src/quick/items/qquickpathview.cpp @@ -1705,7 +1705,8 @@ void QQuickPathViewPrivate::handleMouseMoveEvent(QMouseEvent *event) QPointF pathPoint = pointNear(event->position(), &newPc); if (!stealMouse) { QPointF posDelta = event->position() - startPos; - if (QQuickWindowPrivate::dragOverThreshold(posDelta.y(), Qt::YAxis, event) || QQuickWindowPrivate::dragOverThreshold(posDelta.x(), Qt::XAxis, event)) { + if (QQuickDeliveryAgentPrivate::dragOverThreshold(posDelta.y(), Qt::YAxis, event) || + QQuickDeliveryAgentPrivate::dragOverThreshold(posDelta.x(), Qt::XAxis, event)) { // The touch has exceeded the threshold. If the movement along the path is close to the drag threshold // then we'll assume that this gesture targets the PathView. This ensures PathView gesture grabbing // is in sync with other items. diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp index 1b71bd5a53..0d66f81b24 100644 --- a/src/quick/items/qquicktableview.cpp +++ b/src/quick/items/qquicktableview.cpp @@ -1295,7 +1295,7 @@ void QQuickTableViewPrivate::releaseItem(FxTableItem *fxTableItem, QQmlTableInst const bool hasFocus = item == focusItem || item->isAncestorOf(focusItem); if (hasFocus) { const auto focusChild = QQuickItemPrivate::get(q)->subFocusItem; - QQuickWindowPrivate::get(window)->clearFocusInScope(q, focusChild, Qt::OtherFocusReason); + deliveryAgentPrivate()->clearFocusInScope(q, focusChild, Qt::OtherFocusReason); } } } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 295ab9dc43..643e47c8a0 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -45,23 +45,16 @@ #include "qquickevents_p_p.h" #include "qquickgraphicsdevice_p.h" -#if QT_CONFIG(quick_draganddrop) -#include <private/qquickdrag_p.h> -#endif -#include <private/qquickhoverhandler_p.h> -#include <private/qquickpointerhandler_p.h> - #include <QtQuick/private/qsgrenderer_p.h> #include <QtQuick/private/qsgplaintexture_p.h> +#include <QtQuick/private/qquickpointerhandler_p.h> #include <private/qsgrenderloop_p.h> #include <private/qsgrhisupport_p.h> #include <private/qquickrendercontrol_p.h> #include <private/qquickanimatorcontroller_p.h> -#include <private/qquickpointerhandler_p_p.h> #include <private/qquickprofiler_p.h> #include <private/qguiapplication_p.h> -#include <QtGui/QInputMethod> #include <private/qabstractanimation_p.h> @@ -70,7 +63,6 @@ #include <QtGui/qmatrix4x4.h> #include <QtGui/private/qevent_p.h> #include <QtGui/private/qpointingdevice_p.h> -#include <QtGui/qpa/qplatformtheme.h> #include <QtCore/qvarlengtharray.h> #include <QtCore/qabstractanimation.h> #include <QtCore/QLibraryInfo> @@ -96,12 +88,11 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcTablet, "qt.quick.tablet") +Q_DECLARE_LOGGING_CATEGORY(lcMouse) +Q_DECLARE_LOGGING_CATEGORY(lcTouch) Q_LOGGING_CATEGORY(lcDirty, "qt.quick.dirty") Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient") -extern Q_GUI_EXPORT bool qt_sendShortcutOverrideEvent(QObject *o, ulong timestamp, int k, Qt::KeyboardModifiers mods, const QString &text = QString(), bool autorep = false, ushort count = 1); - bool QQuickWindowPrivate::defaultAlphaBuffer = false; #if defined(QT_QUICK_DEFAULT_TEXT_RENDER_TYPE) @@ -110,20 +101,6 @@ QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow: QQuickWindow::TextRenderType QQuickWindowPrivate::textRenderType = QQuickWindow::QtTextRendering; #endif -void QQuickWindowPrivate::updateFocusItemTransform() -{ -#if QT_CONFIG(im) - Q_Q(QQuickWindow); - QQuickItem *focus = q->activeFocusItem(); - if (focus && QGuiApplication::focusObject() == focus) { - QQuickItemPrivate *focusPrivate = QQuickItemPrivate::get(focus); - QGuiApplication::inputMethod()->setInputItemTransform(focusPrivate->itemToWindowTransform()); - QGuiApplication::inputMethod()->setInputItemRectangle(QRectF(0, 0, focusPrivate->width, focusPrivate->height)); - focus->updateInputMethod(Qt::ImInputItemClipRectangle); - } -#endif -} - class QQuickWindowIncubationController : public QObject, public QQmlIncubationController { Q_OBJECT @@ -280,9 +257,12 @@ void QQuickWindow::focusOutEvent(QFocusEvent *ev) void QQuickWindow::focusInEvent(QFocusEvent *ev) { Q_D(QQuickWindow); + if (d->inDestructor) + return; if (d->contentItem) d->contentItem->setFocus(true, ev->reason()); - d->updateFocusItemTransform(); + if (auto da = d->deliveryAgentPrivate()) + da->updateFocusItemTransform(); } #if QT_CONFIG(im) @@ -408,7 +388,7 @@ void QQuickWindowPrivate::polishItems() const bool isActiveFocusItem = (focusItem == QGuiApplication::focusObject()); const bool hasImEnabled = focusItem->inputMethodQuery(Qt::ImEnabled).toBool(); if (isActiveFocusItem && hasImEnabled && transformDirtyOnItemOrAncestor(focusItem)) - updateFocusItemTransform(); + deliveryAgentPrivate()->updateFocusItemTransform(); } #endif } @@ -719,47 +699,31 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size, const QSize &surfa QQuickWindowPrivate::QQuickWindowPrivate() : contentItem(nullptr) - , activeFocusItem(nullptr) -#if QT_CONFIG(cursor) - , cursorItem(nullptr) - , cursorHandler(nullptr) -#endif -#if QT_CONFIG(quick_draganddrop) - , dragGrabber(nullptr) -#endif - , touchMouseId(-1) - , touchMouseDevice(nullptr) - , touchMousePressTimestamp(0) , dirtyItemList(nullptr) , devicePixelRatio(0) , context(nullptr) , renderer(nullptr) , windowManager(nullptr) , renderControl(nullptr) - , pointerEventRecursionGuard(0) , clearColor(Qt::white) , persistentGraphics(true) , persistentSceneGraph(true) - , lastWheelEventAccepted(false) , componentCompleted(true) - , allowChildEventFiltering(true) - , allowDoubleClick(true) - , lastFocusReason(Qt::OtherFocusReason) + , inDestructor(false) , incubationController(nullptr) , hasActiveSwapchain(false) , hasRenderableSwapchain(false) , swapchainJustBecameRenderable(false) { -#if QT_CONFIG(quick_draganddrop) - dragGrabber = new QQuickDragGrabber; -#endif } QQuickWindowPrivate::~QQuickWindowPrivate() { + inDestructor = true; redirect.rt.reset(rhi, renderer); if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>()) service->removeWindow(q_func()); + deliveryAgent = nullptr; } void QQuickWindowPrivate::updateChildrenPalettes(const QPalette &parentPalette) @@ -780,6 +744,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) Q_Q(QQuickWindow); contentItem = new QQuickRootItem; + contentItem->setObjectName(q->objectName()); QQml_setParent_noEvent(contentItem, c); QQmlEngine::setObjectOwnership(contentItem, QQmlEngine::CppOwnership); QQuickItemPrivate *contentItemPrivate = QQuickItemPrivate::get(contentItem); @@ -787,6 +752,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) contentItemPrivate->windowRefCount = 1; contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope; contentItem->setSize(q->size()); + deliveryAgent = new QQuickDeliveryAgent(contentItem); visualizationMode = qgetenv("QSG_VISUALIZE"); renderControl = control; @@ -839,7 +805,7 @@ void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state) { Q_D(QQuickWindow); if (state != Qt::ApplicationActive && d->contentItem) - d->handleWindowDeactivate(); + d->deliveryAgentPrivate()->handleWindowDeactivate(this); } /*! @@ -871,8 +837,8 @@ void QQuickWindowPrivate::dirtyItem(QQuickItem *) QQuickItem *QQuickWindow::mouseGrabberItem() const { Q_D(const QQuickWindow); - auto epd = const_cast<QQuickWindowPrivate *>(d)->mousePointData(); - if (!epd && d->eventsInDelivery.isEmpty()) { + auto epd = const_cast<QQuickWindowPrivate *>(d)->deliveryAgentPrivate()->mousePointData(); + if (!epd && d->deliveryAgentPrivate()->eventsInDelivery.isEmpty()) { qCDebug(lcMouse, "mouse grabber ambiguous: no event is currently being delivered"); return qmlobject_cast<QQuickItem *>(QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice())-> firstPointExclusiveGrabber()); @@ -1134,7 +1100,7 @@ QQuickWindow::QQuickWindow(QQuickWindowPrivate &dd, QQuickRenderControl *control QQuickWindow::~QQuickWindow() { Q_D(QQuickWindow); - + d->inDestructor = true; if (d->renderControl) { QQuickRenderControlPrivate::get(d->renderControl)->windowDestroyed(); } else if (d->windowManager) { @@ -1143,12 +1109,11 @@ QQuickWindow::~QQuickWindow() } delete d->incubationController; d->incubationController = nullptr; -#if QT_CONFIG(quick_draganddrop) - delete d->dragGrabber; d->dragGrabber = nullptr; -#endif QQuickRootItem *root = d->contentItem; d->contentItem = nullptr; + root->setParent(nullptr); // avoid QChildEvent delivery during deletion delete root; + d->deliveryAgent = nullptr; // avoid forwarding events there during destruction d->renderJobMutex.lock(); qDeleteAll(d->beforeSynchronizingJobs); @@ -1305,9 +1270,6 @@ bool QQuickWindow::isPersistentSceneGraph() const return d->persistentSceneGraph; } - - - /*! \qmlattachedproperty Item Window::contentItem \since 5.4 @@ -1342,7 +1304,7 @@ QQuickItem *QQuickWindow::activeFocusItem() const { Q_D(const QQuickWindow); - return d->activeFocusItem; + return d->deliveryAgentPrivate()->activeFocusItem; } /*! @@ -1353,27 +1315,153 @@ QObject *QQuickWindow::focusObject() const { Q_D(const QQuickWindow); - if (d->activeFocusItem) - return d->activeFocusItem; + if (!d->inDestructor && d->deliveryAgentPrivate()->activeFocusItem) + return d->deliveryAgentPrivate()->activeFocusItem; return const_cast<QQuickWindow*>(this); } /*! \reimp */ +bool QQuickWindow::event(QEvent *e) +{ + Q_D(QQuickWindow); + + // bypass QWindow::event dispatching of input events: deliveryAgent takes care of it + QQuickDeliveryAgent *da = d->deliveryAgent; + if (e->isPointerEvent()) { + /* + When delivering update and release events to existing grabbers, + use the subscene delivery agent, if any. A possible scenario: + 1) Two touchpoints pressed on the main window: QQuickWindowPrivate::deliveryAgent delivers to QQuick3DViewport, + which does picking and finds two subscenes ("root" Items mapped onto two different 3D objects) to deliver it to. + 2) The QTouchEvent is split up so that each subscene sees points relevant to it. + 3) During delivery to either subscene, an item in the subscene grabs. + 4) The user moves finger(s) generating a move event: the correct grabber item needs to get the update + via the same subscene delivery agent from which it got the press, so that the coord transform will be done properly. + 5) Likewise with the touchpoint releases. + With single-point events (mouse, or only one finger) it's simplified: there can only be one subscene of interest; + for (pt : pe->points()) would only iterate once, so we might as well skip that logic. + */ + auto pe = static_cast<QPointerEvent *>(e); + if (pe->pointCount() > 1) { + bool ret = false; + Q_ASSERT(QQuickDeliveryAgentPrivate::isTouchEvent(pe)); + // Split up the multi-point event according to the relevant QQuickDeliveryAgent that should deliver to each existing grabber + // but send ungrabbed points to d->deliveryAgent() + QFlatMap<QQuickDeliveryAgent*, QList<QEventPoint>> deliveryAgentsNeedingPoints; + QEventPoint::States eventStates; + for (const auto &pt : pe->points()) { + eventStates |= pt.state(); + auto *ptda = QQuickDeliveryAgent::grabberAgent(pe, pt); + if (!ptda) + ptda = da; + if (ptda) { + auto danpit = deliveryAgentsNeedingPoints.find(ptda); + if (danpit == deliveryAgentsNeedingPoints.end()) { + deliveryAgentsNeedingPoints.insert(ptda, QList<QEventPoint>() << pt); + } else { + danpit.value().append(pt); + } + } + } + // Make new touch events for each subscene, the same way QQuickItemPrivate::localizedTouchEvent() does it + for (auto daAndPoints : deliveryAgentsNeedingPoints) { + // if all points have the same state, set the event type accordingly + QEvent::Type eventType = pe->type(); + switch (eventStates) { + case QEventPoint::State::Pressed: + eventType = QEvent::TouchBegin; + break; + case QEventPoint::State::Released: + eventType = QEvent::TouchEnd; + break; + default: + eventType = QEvent::TouchUpdate; + break; + } + QMutableTouchEvent te(eventType, pe->pointingDevice(), pe->modifiers(), daAndPoints.second); + te.setTimestamp(pe->timestamp()); + te.accept(); + qCDebug(lcTouch) << "subscene touch:" << daAndPoints.first << "shall now receive" << &te; + ret = daAndPoints.first->event(&te) || ret; + } + if (ret) + return true; + } else if (pe->pointCount()) { + // single-point event + if (auto *ptda = QQuickDeliveryAgent::grabberAgent(pe, pe->points().first())) + da = ptda; + } + // else if it has no points, it's probably a TouchCancel, and DeliveryAgent needs to handle it. + // TODO should we deliver to all DAs at once then, since we don't know which one should get it? + // or fix QTBUG-90851 so that the event always has points? + if (da && da->event(e)) + return true; + } else if (e->isInputEvent()) { + if (da && da->event(e)) + return true; + } + + switch (e->type()) { + // a few more types that are not QInputEvents, but QQuickDeliveryAgent needs to handle them anyway + case QEvent::FocusAboutToChange: + case QEvent::Enter: + case QEvent::Leave: + case QEvent::InputMethod: + case QEvent::InputMethodQuery: +#if QT_CONFIG(quick_draganddrop) + case QEvent::DragEnter: + case QEvent::DragLeave: + case QEvent::DragMove: + case QEvent::Drop: +#endif + if (d->inDestructor) + return false; + if (da && da->event(e)) + return true; + break; + case QEvent::LanguageChange: + if (d->contentItem) + QCoreApplication::sendEvent(d->contentItem, e); + break; + case QEvent::UpdateRequest: + if (d->windowManager) + d->windowManager->handleUpdateRequest(this); + break; + case QEvent::PlatformSurface: + if ((static_cast<QPlatformSurfaceEvent *>(e))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) { + // Ensure that the rendering thread is notified before + // the QPlatformWindow is destroyed. + if (d->windowManager) + d->windowManager->hide(this); + } + break; + case QEvent::WindowDeactivate: + d->deliveryAgentPrivate()->handleWindowDeactivate(this); + break; + default: + break; + } + + if (e->type() == QEvent::Type(QQuickWindowPrivate::FullUpdateRequest)) + update(); + else if (e->type() == QEvent::Type(QQuickWindowPrivate::TriggerContextCreationFailure)) + d->windowManager->handleContextCreationFailure(this); + + return QWindow::event(e); +} + +/*! \reimp */ void QQuickWindow::keyPressEvent(QKeyEvent *e) { Q_D(QQuickWindow); - Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyPress, e->key(), - e->modifiers()); - d->deliverKeyEvent(e); + d->deliveryAgentPrivate()->deliverKeyEvent(e); } /*! \reimp */ void QQuickWindow::keyReleaseEvent(QKeyEvent *e) { Q_D(QQuickWindow); - Q_QUICK_INPUT_PROFILE(QQuickProfiler::Key, QQuickProfiler::InputKeyRelease, e->key(), - e->modifiers()); - d->deliverKeyEvent(e); + d->deliveryAgentPrivate()->deliverKeyEvent(e); } #if QT_CONFIG(wheelevent) @@ -1381,18 +1469,7 @@ void QQuickWindow::keyReleaseEvent(QKeyEvent *e) void QQuickWindow::wheelEvent(QWheelEvent *event) { Q_D(QQuickWindow); - Q_QUICK_INPUT_PROFILE(QQuickProfiler::Mouse, QQuickProfiler::InputMouseWheel, - event->angleDelta().x(), event->angleDelta().y()); - - qCDebug(lcMouse) << event; - - //if the actual wheel event was accepted, accept the compatibility wheel event and return early - if (d->lastWheelEventAccepted && event->angleDelta().isNull() && event->phase() == Qt::ScrollUpdate) - return; - - event->ignore(); - d->deliverSinglePointEventUntilAccepted(event); - d->lastWheelEventAccepted = event->isAccepted(); + d->deliveryAgentPrivate()->deliverSinglePointEventUntilAccepted(event); } #endif // wheelevent @@ -1401,9 +1478,7 @@ void QQuickWindow::wheelEvent(QWheelEvent *event) void QQuickWindow::tabletEvent(QTabletEvent *event) { Q_D(QQuickWindow); - qCDebug(lcTablet) << event; - // TODO Qt 6: make sure TabletEnterProximity and TabletLeaveProximity are delivered here - d->deliverPointerEvent(event); + d->deliveryAgentPrivate()->deliverPointerEvent(event); } #endif // tabletevent @@ -1411,34 +1486,40 @@ void QQuickWindow::tabletEvent(QTabletEvent *event) void QQuickWindow::mousePressEvent(QMouseEvent *event) { Q_D(QQuickWindow); - d->handleMouseEvent(event); + d->deliveryAgentPrivate()->handleMouseEvent(event); } /*! \reimp */ void QQuickWindow::mouseMoveEvent(QMouseEvent *event) { Q_D(QQuickWindow); - d->handleMouseEvent(event); + d->deliveryAgentPrivate()->handleMouseEvent(event); } /*! \reimp */ void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event) { Q_D(QQuickWindow); - d->handleMouseEvent(event); + d->deliveryAgentPrivate()->handleMouseEvent(event); } /*! \reimp */ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event) { Q_D(QQuickWindow); - d->handleMouseEvent(event); + d->deliveryAgentPrivate()->handleMouseEvent(event); } -#if QT_CONFIG(cursor) -void QQuickWindowPrivate::updateCursor(const QPointF &scenePos) +void QQuickWindowPrivate::flushFrameSynchronousEvents() { Q_Q(QQuickWindow); + deliveryAgentPrivate()->flushFrameSynchronousEvents(q); +} - auto cursorItemAndHandler = findCursorItemAndHandler(contentItem, scenePos); - +#if QT_CONFIG(cursor) +void QQuickWindowPrivate::updateCursor(const QPointF &scenePos, QQuickItem *rootItem) +{ + Q_Q(QQuickWindow); + if (!rootItem) + rootItem = contentItem; + auto cursorItemAndHandler = findCursorItemAndHandler(rootItem, scenePos); if (cursorItem != cursorItemAndHandler.first || cursorHandler != cursorItemAndHandler.second) { QWindow *renderWindow = QQuickRenderControl::renderWindowFor(q); QWindow *window = renderWindow ? renderWindow : q; diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index 8700b5a141..7ee3be9b50 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -231,6 +231,9 @@ protected: void focusOutEvent(QFocusEvent *) override; bool event(QEvent *) override; + + // These overrides are no longer normal entry points for + // input events, but kept in case legacy code calls them. void keyPressEvent(QKeyEvent *) override; void keyReleaseEvent(QKeyEvent *) override; void mousePressEvent(QMouseEvent *) override; @@ -258,6 +261,7 @@ private: friend class QQuickRenderControl; friend class QQuickAnimatorController; friend class QQuickWidgetPrivate; + friend class QQuickDeliveryAgentPrivate; Q_DISABLE_COPY(QQuickWindow) }; diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 869324c317..30b5a36cb5 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtQuick/private/qquickdeliveryagent_p_p.h> #include <QtQuick/private/qquickevents_p_p.h> #include <QtQuick/private/qsgcontext_p.h> #include <QtQuick/private/qquickpaletteproviderprivatebase_p.h> @@ -100,6 +101,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickRootItem : public QQuickItem QML_ADDED_IN_VERSION(2, 0) public: QQuickRootItem(); + public Q_SLOTS: void setWidth(int w) {QQuickItem::setWidth(qreal(w));} void setHeight(int h) {QQuickItem::setHeight(qreal(h));} @@ -142,104 +144,25 @@ public: QSet<QQuickItem *> parentlessItems; QQmlListProperty<QObject> data(); - QQuickItem *activeFocusItem; - - void deliverKeyEvent(QKeyEvent *e); + // primary delivery agent for the whole scene, used by default for events that arrive in this window; + // but any subscene root can have a QQuickItemPrivate::ExtraData::subsceneDeliveryAgent + QQuickDeliveryAgent *deliveryAgent = nullptr; + QQuickDeliveryAgentPrivate *deliveryAgentPrivate() const + { return static_cast<QQuickDeliveryAgentPrivate *>(QQuickDeliveryAgentPrivate::get(deliveryAgent)); } - // Keeps track of the item currently receiving mouse events -#if QT_CONFIG(cursor) - QQuickItem *cursorItem; - QQuickPointerHandler *cursorHandler; -#endif -#if QT_CONFIG(quick_draganddrop) - QQuickDragGrabber *dragGrabber; -#endif - QQuickItem *lastUngrabbed = nullptr; - QStack<QPointerEvent *> eventsInDelivery; - - int touchMouseId; // only for obsolete stuff like QQuickItem::grabMouse() - // TODO get rid of these - const QPointingDevice *touchMouseDevice; - ulong touchMousePressTimestamp; - QPoint touchMousePressPos; // in screen coordiantes - bool isDeliveringTouchAsMouse() const { return touchMouseId != -1 && touchMouseDevice; } - void cancelTouchMouseSynthesis(); - - bool checkIfDoubleTapped(ulong newPressEventTimestamp, QPoint newPressPos); - QPointingDevicePrivate::EventPointData *mousePointData(); - QPointerEvent *eventInDelivery() const; - - // Mouse positions are saved in widget coordinates - QPointF lastMousePosition; - bool deliverTouchAsMouse(QQuickItem *item, QTouchEvent *pointerEvent); - void translateTouchEvent(QTouchEvent *touchEvent); - void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true, bool cancel = false); - void onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point); - static QPointerEvent *clonePointerEvent(QPointerEvent *event, std::optional<QPointF> transformedLocalPos = std::nullopt); - void deliverToPassiveGrabbers(const QVector<QPointer<QObject> > &passiveGrabbers, QPointerEvent *pointerEvent); - bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent); - bool sendFilteredPointerEvent(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr); - bool sendFilteredPointerEventImpl(QPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent); - bool deliverSinglePointEventUntilAccepted(QPointerEvent *); - - // entry point of events to the window - void handleTouchEvent(QTouchEvent *); - void handleMouseEvent(QMouseEvent *); - bool compressTouchEvent(QTouchEvent *); + // TODO remove these: they were moved to QQuickDeliveryAgentPrivate + static bool isMouseEvent(const QPointerEvent *ev) { return QQuickDeliveryAgentPrivate::isMouseEvent(ev); } + static bool isTouchEvent(const QPointerEvent *ev) { return QQuickDeliveryAgentPrivate::isTouchEvent(ev); } + static bool isTabletEvent(const QPointerEvent *ev) { return QQuickDeliveryAgentPrivate::isTabletEvent(ev); } void flushFrameSynchronousEvents(); - void deliverDelayedTouchEvent(); - void handleWindowDeactivate(); - - // utility functions that used to be in QQuickPointerEvent et al. - bool allUpdatedPointsAccepted(const QPointerEvent *ev); - static void localizePointerEvent(QPointerEvent *ev, const QQuickItem *dest); - QList<QObject *> exclusiveGrabbers(QPointerEvent *ev); - static bool isMouseEvent(const QPointerEvent *ev); - static bool isTouchEvent(const QPointerEvent *ev); - static bool isTabletEvent(const QPointerEvent *ev); - - // delivery of pointer events: - void touchToMouseEvent(QEvent::Type type, const QEventPoint &p, const QTouchEvent *touchEvent, QMutableSinglePointEvent *mouseEvent); - void ensureDeviceConnected(const QPointingDevice *dev); - void deliverPointerEvent(QPointerEvent *); - bool deliverTouchCancelEvent(QTouchEvent *); - bool deliverPressOrReleaseEvent(QPointerEvent *, bool handlersOnly = false); - void deliverUpdatedPoints(QPointerEvent *event); - void deliverMatchingPointsToItem(QQuickItem *item, bool isGrabber, QPointerEvent *pointerEvent, bool handlersOnly = false); - - QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointerEvent *event, const QEventPoint &point, - bool checkMouseButtons, bool checkAcceptsTouch) const; - QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const; - - // hover delivery - bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted); - bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, - Qt::KeyboardModifiers modifiers, ulong timestamp, bool accepted); - bool clearHover(ulong timestamp = 0); - -#if QT_CONFIG(quick_draganddrop) - void deliverDragEvent(QQuickDragGrabber *, QEvent *); - bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *, QVarLengthArray<QQuickItem*, 64> *currentGrabItems = nullptr); -#endif + #if QT_CONFIG(cursor) - void updateCursor(const QPointF &scenePos); + QQuickItem *cursorItem = nullptr; + QQuickPointerHandler *cursorHandler = nullptr; + void updateCursor(const QPointF &scenePos, QQuickItem *rootItem = nullptr); QPair<QQuickItem*, QQuickPointerHandler*> findCursorItemAndHandler(QQuickItem *item, const QPointF &scenePos) const; #endif - QList<QQuickItem*> hoverItems; - enum FocusOption { - DontChangeFocusProperty = 0x01, - DontChangeSubFocusItem = 0x02 - }; - Q_DECLARE_FLAGS(FocusOptions, FocusOption) - - void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { }); - void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { }); - static void notifyFocusChangesRecur(QQuickItem **item, int remaining); - void clearFocusObject() override; - - void updateFocusItemTransform(); - void dirtyItem(QQuickItem *); void cleanup(QSGNode *); @@ -272,8 +195,6 @@ public: QList<QSGNode *> cleanupNodeList; QVector<QQuickItem *> itemsToPolish; - QVector<QQuickItem *> hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called - QVector<QQuickItem *> skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary qreal devicePixelRatio; QMetaObject::Connection physicalDpiChangedConnection; @@ -295,23 +216,13 @@ public: QSGRenderLoop *windowManager; QQuickRenderControl *renderControl; QScopedPointer<QQuickAnimatorController> animationController; - QScopedPointer<QMutableTouchEvent> delayedTouch; - QList<const QPointingDevice *> knownPointingDevices; - - int pointerEventRecursionGuard; QColor clearColor; uint persistentGraphics : 1; uint persistentSceneGraph : 1; - - uint lastWheelEventAccepted : 1; - bool componentCompleted : 1; - - bool allowChildEventFiltering : 1; - bool allowDoubleClick : 1; - - Qt::FocusReason lastFocusReason; + uint componentCompleted : 1; + uint inDestructor : 1; // Storage for setRenderTarget(QQuickRenderTarget). // Gets baked into redirect.renderTarget by ensureCustomRenderTarget() when rendering the next frame. @@ -332,15 +243,18 @@ public: static bool defaultAlphaBuffer; static QQuickWindow::TextRenderType textRenderType; - static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1); - - static bool dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint &tp, int startDragThreshold = -1); - - // currently in use in Controls 2; TODO remove + // vvv currently in use in Controls 2; TODO remove static bool dragOverThreshold(qreal d, Qt::Axis axis, const QEventPoint *tp, int startDragThreshold = -1) - { return dragOverThreshold(d, axis, *tp, startDragThreshold); } - - static bool dragOverThreshold(QVector2D delta); + { return QQuickDeliveryAgentPrivate::dragOverThreshold(d, axis, *tp, startDragThreshold); } + static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1) + { return QQuickDeliveryAgentPrivate::dragOverThreshold(d, axis, event, startDragThreshold); } + void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason) + { deliveryAgentPrivate()->clearFocusInScope(scope, item, reason); } + void handleTouchEvent(QTouchEvent *e) + { deliveryAgentPrivate()->handleTouchEvent(e); } + void handleMouseEvent(QMouseEvent *e) + { deliveryAgentPrivate()->handleMouseEvent(e); } + // ^^^ currently in use in Controls 2; TODO remove // data property static void data_append(QQmlListProperty<QObject> *, QObject *); @@ -393,7 +307,6 @@ public: } }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickWindowPrivate::FocusOptions) Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickWindowPrivate::TextureFromNativeTextureFlags) QT_END_NAMESPACE |