diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-12-02 00:10:22 +0100 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2023-12-07 06:49:26 +0100 |
commit | 5b5c8aa4615fb8fb5fa27374479f0807fa73d64b (patch) | |
tree | 4f2855ee4db868cab592597be6554c0a25001ebe /src | |
parent | 6eba6dd95082d5087662f9755d2f01ecb741ddc6 (diff) |
Ensure ItemObservesViewport works when item is moved to new ancestor
When an item has ItemObservesViewport set, it will receive
transformChanged callbacks when any of its ancestors changes their
position, size, etc.
This relies on every ancestor having the subtreeTransformChangedEnabled
flag set, which was previously ensured when the item called setFlag().
But when the item then moved to a different ancestor hierarchy, we
would only set subtreeTransformChangedEnabled on the new parent,
but not any of its ancestors, which meant that the item would
no longer pick up changes beyond the immediate parent.
We would also not send a transformChanged in response to the reparenting
itself, which is critical, as the item's clip or scene positions may
have changed in response to the new parent.
Both of these cases are now handled as part of the ItemChildAddedChange
of the new parent.
Change-Id: I5000fb46d7638ce9674d4879890cf4344e5ce538
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 38 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 2 |
2 files changed, 29 insertions, 11 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 8b1188e4d4..968c44e997 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6727,8 +6727,18 @@ void QQuickItemPrivate::itemChange(QQuickItem::ItemChange change, const QQuickIt switch (change) { case QQuickItem::ItemChildAddedChange: { q->itemChange(change, data); - if (!subtreeTransformChangedEnabled) - subtreeTransformChangedEnabled = true; + // The newly added child or any of its descendants may have + // ItemObservesViewport set, in which case we need to both + // inform the item that the transform has changed, and re-apply + // subtreeTransformChangedEnabled to both this item and its + // ancestors. + if (QQuickItemPrivate::get(data.item)->transformChanged(q)) { + if (!subtreeTransformChangedEnabled) { + qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << q; + subtreeTransformChangedEnabled = true; + } + enableSubtreeChangeNotificationsForParentHierachy(); + } notifyChangeListeners(QQuickItemPrivate::Children, &QQuickItemChangeListener::itemChildAdded, q, data.item); break; } @@ -6958,15 +6968,21 @@ void QQuickItem::setFlag(Flag flag, bool enabled) // We don't return early if the flag did not change. That's useful in case // we need to intentionally trigger this parent-chain traversal again. - if (enabled && flag == ItemObservesViewport) { - QQuickItem *par = parentItem(); - while (par) { - auto parPriv = QQuickItemPrivate::get(par); - if (!parPriv->subtreeTransformChangedEnabled) - qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << par; - parPriv->subtreeTransformChangedEnabled = true; - par = par->parentItem(); - } + if (enabled && flag == ItemObservesViewport) + d->enableSubtreeChangeNotificationsForParentHierachy(); +} + +void QQuickItemPrivate::enableSubtreeChangeNotificationsForParentHierachy() +{ + Q_Q(QQuickItem); + + QQuickItem *par = q->parentItem(); + while (par) { + auto parPriv = QQuickItemPrivate::get(par); + if (!parPriv->subtreeTransformChangedEnabled) + qCDebug(lcVP) << "turned on transformChanged notification for subtree of" << par; + parPriv->subtreeTransformChangedEnabled = true; + par = par->parentItem(); } } diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 205169066a..63c8896680 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -685,6 +685,8 @@ public: void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &); + void enableSubtreeChangeNotificationsForParentHierachy(); + virtual void mirrorChange() {} void setHasCursorInChild(bool hasCursor); |