aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquicktextedit.cpp
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2021-12-13 08:14:26 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-01-06 08:43:53 +0000
commit18ad8a7f17a6f49c0a93c0046c05578820732ccb (patch)
treec244c721b6a4bb75793f6535392a4b8e046ada3b /src/quick/items/qquicktextedit.cpp
parentcb28c76c40a9492d1a00baf61f71ad52c834ac25 (diff)
TextEdit: deal with scrolling backwards in rich text
A bug was introduced in 9db23e0e04906cf9ea33e23fa41f34955e5e6fe0 : when scrolling backwards in some kinds of rich text, updatePaintNode() failed to re-populate the nodes that had been scrolled out above the viewport. That was because those nodes had been removed from textNodeMap, and then firstDirtyPos was set from the first node in textNodeMap. For some reason this didn't happen with the markdown document that I was testing (maybe because it had a table and an image near the beginning), but showed up when viewing an html document similar to the one we ship with the rich text example. So now we iterate backwards from textNodeMap.begin() when this happens, to find all nodes in the current frame that intersect the viewport as rendered. In the autotest we now use font.pixelSize in an attempt to make the rendered text ranges more consistent across platforms in CI; and we need to wait for the rendering to be redone after scrolling. Change-Id: I70ef54c8d8facc439b9a6f8b5cb8e3a4a1c37e16 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> (cherry picked from commit cd083920b3b4f3a1ed7f2297058cf0d110d7cf10) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/quick/items/qquicktextedit.cpp')
-rw-r--r--src/quick/items/qquicktextedit.cpp23
1 files changed, 20 insertions, 3 deletions
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 9ef041bbb1..d0614bbeff 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -2087,7 +2087,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
QQuickTextNodeEngine engine;
QQuickTextNodeEngine frameDecorationsEngine;
- if (!oldNode || nodeIterator < d->textNodeMap.end()) {
+ if (!oldNode || nodeIterator < d->textNodeMap.end() || d->textNodeMap.isEmpty()) {
if (!oldNode)
rootNode = new RootNode;
@@ -2184,9 +2184,10 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
QTextFrame::iterator it = textFrame->begin();
while (!it.atEnd()) {
QTextBlock block = it.currentBlock();
- ++it;
- if (block.position() < firstDirtyPos)
+ if (block.position() < firstDirtyPos) {
+ ++it;
continue;
+ }
if (!engine.hasContents())
nodeOffset = d->document->documentLayout()->blockBoundingRect(block).topLeft();
@@ -2199,6 +2200,21 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
inView = coveredRegion.bottom() > viewport.top();
}
if (d->firstBlockInViewport < 0 && inView) {
+ // During backward scrolling, we need to iterate backwards from textNodeMap.begin() to fill the top of the viewport.
+ if (coveredRegion.top() > viewport.top() + 1) {
+ qCDebug(lcVP) << "checking backwards from block" << block.blockNumber() << "@" << nodeOffset.y() << coveredRegion;
+ while (it != textFrame->begin() && it.currentBlock().layout() &&
+ it.currentBlock().layout()->boundingRect().top() + nodeOffset.y() > viewport.top())
+ --it;
+ if (!it.currentBlock().layout())
+ ++it;
+ if (Q_LIKELY(it.currentBlock().layout())) {
+ block = it.currentBlock();
+ coveredRegion = block.layout()->boundingRect().adjusted(nodeOffset.x(), nodeOffset.y(), nodeOffset.x(), nodeOffset.y());
+ } else {
+ qCWarning(lcVP) << "failed to find a text block with layout during back-scrolling";
+ }
+ }
qCDebug(lcVP) << "first block in viewport" << block.blockNumber() << "@" << nodeOffset.y() << coveredRegion;
d->firstBlockInViewport = block.blockNumber();
if (block.layout())
@@ -2240,6 +2256,7 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
resetEngine(&engine, d->color, d->selectedTextColor, d->selectionColor);
nodeStart = block.next().position();
}
+ ++it;
}
}
if (Q_LIKELY(node && !node->parent()))