aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2023-09-06 17:18:42 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2023-09-12 21:03:21 +0200
commit584cd7239020e598df088a1b4669d3e69ff4650f (patch)
treee91d743576d8dd41ad9b25b2f7358bb6472abf4b /src
parent2bee7cf744f711df3b8ab9fa3905de086bb019bb (diff)
Loader: re-set ItemObservesViewport flag on child if already set
When QQuickLoaderPrivate::load() loads a Text item, its ctor calls QQuickTextPrivate::init(), which calls setFlag(ItemObservesViewport). QQuickItem::setFlag() tries to go up the parent hierarchy to get subtreeTransformChangedEnabled turned on; but at that time, the Text does not yet have a parent. If a Flickable contains a Loader that loads a Text with large content, QQuickTextPrivate::transformChanged() needs to get called during scrolling. Loader is not interested in these notifications for itself; so its parent's QQuickItemPrivate::transformChanged() detects that and turns off subtreeTransformChangedEnabled. After the child is loaded, QQuickLoader::itemChange() detects that the child's ItemObservesViewport is already set, and sets the same flag again. setFlag() doesn't have a guard, so the parent traversal happens again, and subtreeTransformChangedEnabled gets turned back on. If a different child were loaded, and that child did not want the notifications, the next QQuickItemPrivate::transformChanged() would detect it. If the child changed its own flag later on (e.g. because a small amount of text was replaced with a larger document, exceeding QQUICKTEXT_LARGETEXT_THRESHOLD), QQuickItem::setFlag() would be able to go up the parent chain at that time. For the autotest, long.qml has about 15KB of text. Maybe it will be reusable. At least it should compress well in git packfiles, since we have this license text elsewhere. Fixes: QTBUG-115687 Change-Id: I87b6a42f5735b8f9c2267f91a4112681da05de5d Reviewed-by: Santhosh Kumar <santhosh.kumar.selvaraj@qt.io> (cherry picked from commit 8c7c60fff37ea7bb7420d925e2f88e62764bf86b) Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/quick/items/qquickitem.cpp2
-rw-r--r--src/quick/items/qquickloader.cpp13
2 files changed, 14 insertions, 1 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 4c638e51f7..53276f6c49 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -6972,6 +6972,8 @@ void QQuickItem::setFlag(Flag flag, bool enabled)
else
setFlags((Flags)(d->flags & ~(quint32)flag));
+ // 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) {
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index fdee5d0b35..dad2e5a8a7 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -804,12 +804,23 @@ void QQuickLoader::componentComplete()
void QQuickLoader::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)
{
- if (change == ItemSceneChange) {
+ switch (change) {
+ case ItemSceneChange: {
QQuickWindow *loadedWindow = qmlobject_cast<QQuickWindow *>(item());
if (loadedWindow) {
qCDebug(lcTransient) << loadedWindow << "is transient for" << value.window;
loadedWindow->setTransientParent(value.window);
}
+ break;
+ }
+ case ItemChildAddedChange:
+ Q_ASSERT(value.item);
+ if (value.item->flags().testFlag(QQuickItem::ItemObservesViewport))
+ // Re-trigger the parent traversal to get subtreeTransformChangedEnabled turned on
+ value.item->setFlag(QQuickItem::ItemObservesViewport);
+ break;
+ default:
+ break;
}
QQuickItem::itemChange(change, value);
}