aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items')
-rw-r--r--src/quick/items/qquickdrag.cpp2
-rw-r--r--src/quick/items/qquickflickable.cpp16
-rw-r--r--src/quick/items/qquickitem.cpp127
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h8
-rw-r--r--src/quick/items/qquickmousearea.cpp8
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp13
-rw-r--r--src/quick/items/qquickpathview.cpp3
-rw-r--r--src/quick/items/qquicktableview.cpp2
-rw-r--r--src/quick/items/qquickwindow.cpp259
-rw-r--r--src/quick/items/qquickwindow.h4
-rw-r--r--src/quick/items/qquickwindow_p.h143
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 &centroidParent
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