aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanthosh Kumar <santhosh.kumar.selvaraj@qt.io>2023-12-21 13:46:52 +0100
committerSanthosh Kumar <santhosh.kumar.selvaraj@qt.io>2024-01-26 15:40:09 +0100
commitd548077d205d22610ceeb623006f7fa54d4c72c7 (patch)
tree90eb43d56c2ddceb76d70dfd51a200be4daa9b13
parent34f39f670281fdce22a402508b1a8e55be6e9fa2 (diff)
Force text layout update in the thread where its created
The text layout gets updated while invalidating font data. This creates an issue when quick text instance was created and invalidated across different threads. It mainly affects QQuickText::lineLaidOut() signal as QQuickTextLine is designed to provide information only about current line and its to be noted that the current line provided by QQuickTextPrivate was from stack. Thus, triggering this signal across thread provide invalid line information. Its possible to keep line in heap but that doesn't help as the ultimate purpose of QQuickText::lineLaidOut() signal is to provide current line information which user can hook to modify its geometry. This patch makes updateLayout() to be happening in same thread where the quick text object was created. Fixes: QTBUG-113039 Pick-to: 6.7 6.6 6.5 Change-Id: Ic0737cb514f663f87ac1cf21506ad76fee03643e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
-rw-r--r--src/quick/items/qquicktext.cpp2
-rw-r--r--tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml25
-rw-r--r--tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttfbin0 -> 24544 bytes
-rw-r--r--tests/auto/quick/qquicktext/tst_qquicktext.cpp24
4 files changed, 50 insertions, 1 deletions
diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp
index 8a8b36bea3..6abb30de56 100644
--- a/src/quick/items/qquicktext.cpp
+++ b/src/quick/items/qquicktext.cpp
@@ -3211,7 +3211,7 @@ void QQuickText::invalidate()
{
Q_D(QQuickText);
d->textHasChanged = true;
- d->updateLayout();
+ QMetaObject::invokeMethod(this,[&]{q_updateLayout();});
}
bool QQuickTextPrivate::transformChanged(QQuickItem *transformedItem)
diff --git a/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml b/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml
new file mode 100644
index 0000000000..d018e31d29
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/lineLayoutFontUpdate.qml
@@ -0,0 +1,25 @@
+import QtQuick
+
+Item {
+ width: 640
+ height: 480
+
+ FontLoader {
+ id: fontIcons
+ source: "tarzeau_ocr_a.ttf"
+ }
+
+ Text {
+ id: exampleText
+ objectName: "exampleText"
+ text: "Example multiline text"
+ wrapMode: Text.WordWrap
+ width: 100
+ onLineLaidOut: (line) => {
+ if (line.number < 1) {
+ line.x += 40;
+ line.width -= 40;
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf b/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf
new file mode 100644
index 0000000000..cf93f9651f
--- /dev/null
+++ b/tests/auto/quick/qquicktext/data/tarzeau_ocr_a.ttf
Binary files differ
diff --git a/tests/auto/quick/qquicktext/tst_qquicktext.cpp b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
index 218d1d47ac..257dc678b6 100644
--- a/tests/auto/quick/qquicktext/tst_qquicktext.cpp
+++ b/tests/auto/quick/qquicktext/tst_qquicktext.cpp
@@ -110,6 +110,7 @@ private slots:
void largeTextInDelayedLoader();
void lineLaidOut();
void lineLaidOutRelayout();
+ void lineLaidOutFontUpdate();
void lineLaidOutHAlign();
void lineLaidOutImplicitWidth();
@@ -3121,6 +3122,29 @@ void tst_qquicktext::lineLaidOutRelayout()
}
}
+void tst_qquicktext::lineLaidOutFontUpdate()
+{
+ QScopedPointer<QQuickView> window(createView(testFile("lineLayoutFontUpdate.qml")));
+
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+
+ auto *myText = window->rootObject()->findChild<QQuickText*>("exampleText");
+ QVERIFY(myText != nullptr);
+
+ QQuickTextPrivate *textPrivate = QQuickTextPrivate::get(myText);
+ QVERIFY(textPrivate != nullptr);
+
+ QCOMPARE(textPrivate->layout.lineCount(), 2);
+
+ QTextLine firstLine = textPrivate->layout.lineAt(0);
+ QTextLine secondLine = textPrivate->layout.lineAt(1);
+
+ QCOMPARE(firstLine.rect().x(), secondLine.rect().x() + 40);
+ QCOMPARE(firstLine.rect().width(), secondLine.rect().width() - 40);
+}
+
void tst_qquicktext::lineLaidOutHAlign()
{
QScopedPointer<QQuickView> window(createView(testFile("lineLayoutHAlign.qml")));