diff options
author | Piotr WierciĆski <piotr.wiercinski@qt.io> | 2023-04-20 13:32:53 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2023-05-12 10:13:24 +0000 |
commit | f3b1d6135222e9ce41845a00831a3eb24cd36449 (patch) | |
tree | b977bdb2a52881d9d05d3a8d924c8871523196f7 | |
parent | e0c13e1138a1730047e627f4cb2087f6217b8d42 (diff) | |
download | qtdeclarative-f3b1d6135222e9ce41845a00831a3eb24cd36449.tar.gz |
QQuickText: Mark as a dirty node when its ClipRect changes
Make sure that any changes to ClipRect of QQuickText are properly
propagated.
Fixes: QTBUG-106164
Fixes: QTBUG-106205
Pick-to: 6.5
Change-Id: Id37099811cf8e10dd510dc5f8086d1323f92af9e
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r-- | src/quick/items/qquicktext.cpp | 5 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 28 | ||||
-rw-r--r-- | tests/auto/quick/qquicktext/data/qtbug_106205.qml | 28 | ||||
-rw-r--r-- | tests/auto/quick/qquicktext/tst_qquicktext.cpp | 23 |
4 files changed, 72 insertions, 12 deletions
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 02ae80b0b8..3a2fbfef0d 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -2538,6 +2538,11 @@ QSGNode *QQuickText::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data void QQuickText::updatePolish() { Q_D(QQuickText); + const bool clipNodeChanged = + d->componentComplete && d->clipNode() && d->clipNode()->rect() != clipRect(); + if (clipNodeChanged) + d->dirty(QQuickItemPrivate::Clip); + // If the fonts used for rendering are different from the ones used in the GUI thread, // it means we will get warnings and corrupted text. If this case is detected, we need // to update the text layout before creating the scenegraph nodes. diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index a9813d5187..68f3e6f8e0 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1954,19 +1954,14 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) itemPriv->itemNode()->setMatrix(matrix); } - bool clipEffectivelyChanged = (dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window)) && - ((item->clip() == false) != (itemPriv->clipNode() == nullptr)); - int effectRefCount = itemPriv->extra.isAllocated()?itemPriv->extra->effectRefCount:0; - bool effectRefEffectivelyChanged = (dirty & (QQuickItemPrivate::EffectReference | QQuickItemPrivate::Window)) && - ((effectRefCount == 0) != (itemPriv->rootNode() == nullptr)); - + const bool clipEffectivelyChanged = dirty & (QQuickItemPrivate::Clip | QQuickItemPrivate::Window); if (clipEffectivelyChanged) { - QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *) itemPriv->opacityNode() : - (QSGNode *) itemPriv->itemNode(); + QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *)itemPriv->opacityNode() + : (QSGNode *)itemPriv->itemNode(); QSGNode *child = itemPriv->rootNode(); - if (item->clip()) { - Q_ASSERT(itemPriv->clipNode() == nullptr); + if (bool initializeClipNode = item->clip() && itemPriv->clipNode() == nullptr; + initializeClipNode) { QQuickDefaultClipNode *clip = new QQuickDefaultClipNode(item->clipRect()); itemPriv->extra.value().clipNode = clip; clip->update(); @@ -1980,9 +1975,14 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) parent->appendChildNode(clip); } - } else { + } else if (bool updateClipNode = item->clip() && itemPriv->clipNode() != nullptr; + updateClipNode) { + QQuickDefaultClipNode *clip = itemPriv->clipNode(); + clip->setClipRect(item->clipRect()); + clip->update(); + } else if (bool removeClipNode = !item->clip() && itemPriv->clipNode() != nullptr; + removeClipNode) { QQuickDefaultClipNode *clip = itemPriv->clipNode(); - Q_ASSERT(clip); parent->removeChildNode(clip); if (child) { clip->removeChildNode(child); @@ -1996,6 +1996,10 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) } } + const int effectRefCount = itemPriv->extra.isAllocated() ? itemPriv->extra->effectRefCount : 0; + const bool effectRefEffectivelyChanged = + (dirty & (QQuickItemPrivate::EffectReference | QQuickItemPrivate::Window)) + && ((effectRefCount == 0) != (itemPriv->rootNode() == nullptr)); if (effectRefEffectivelyChanged) { if (dirty & QQuickItemPrivate::ChildrenUpdateMask) itemPriv->childContainerNode()->removeAllChildNodes(); diff --git a/tests/auto/quick/qquicktext/data/qtbug_106205.qml b/tests/auto/quick/qquicktext/data/qtbug_106205.qml new file mode 100644 index 0000000000..e4db73557a --- /dev/null +++ b/tests/auto/quick/qquicktext/data/qtbug_106205.qml @@ -0,0 +1,28 @@ +import QtQuick +import QtQuick.Controls + +Item { + id: root + objectName: "root" + visible: true + + anchors.fill: parent + property string text: "" + + ScrollView { + anchors.fill: parent + Rectangle { + x: 100 + width: 100 + height: 30 + color: "lightgray" + + Text { + objectName: "textOutsideViewport" + text: root.text + width: 50 + clip: true + } + } + } +} diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp index c8d9561803..8faace86c1 100644 --- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp +++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp @@ -53,6 +53,7 @@ private slots: void implicitElide_data(); void implicitElide(); void textFormat(); + void clipRectOutsideViewportDynamicallyChanged(); void baseUrl(); void embeddedImages_data(); @@ -827,6 +828,28 @@ void tst_qquicktext::textFormat() } } +void tst_qquicktext::clipRectOutsideViewportDynamicallyChanged() +{ + // QTBUG-106205 + QScopedPointer<QQuickView> view(createView(testFile("qtbug_106205.qml"))); + view->setWidth(100); + view->setHeight(200); + view->showNormal(); + QQuickItem *root = view->rootObject(); + QVERIFY(root); + QVERIFY(QTest::qWaitForWindowExposed(view.get())); + + auto clipRectMatches = [&]() -> bool { + auto *textOutsideInitialViewport = root->findChild<QQuickText *>("textOutsideViewport"); + if (!textOutsideInitialViewport) + return false; + auto *clipNode = QQuickItemPrivate::get(textOutsideInitialViewport)->clipNode(); + + return textOutsideInitialViewport->clipRect() == clipNode->clipRect(); + }; + QTRY_VERIFY(clipRectMatches()); +} + //the alignment tests may be trivial o.oa void tst_qquicktext::horizontalAlignment() { |