QTextDocumentLayout: Account for topMargin when hit-testing

When TopMargin is set in TextBlock and the mouse click position is
between Margin (the mouse is not on the textrect), the cursor will
usually jump to the end. So topMargin should be considered when
hitTest() calculates coordinates.

Fixes: QTBUG-91774
Change-Id: I231377263855b9cd7152684203fc4ed2e9299bb9
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Tang Haixiang <tanghaixiang@uniontech.com>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
(cherry picked from commit 8aae49019d7386c1abd6cd32f7ccb68c264c0288)
This commit is contained in:
Tang Haixiang 2021-10-27 18:59:33 +08:00 committed by Volker Hilsheimer
parent 16dcd2abe6
commit b3bb20b8bc
2 changed files with 38 additions and 1 deletions

View File

@ -794,7 +794,7 @@ QTextDocumentLayoutPrivate::hitTest(const QTextBlock &bl, const QFixedPoint &poi
textrect.translate(tl->position());
qCDebug(lcHit) << " checking block" << bl.position() << "point=" << point.toPointF() << " tlrect" << textrect;
*position = bl.position();
if (point.y.toReal() < textrect.top()) {
if (point.y.toReal() < textrect.top() - bl.blockFormat().topMargin()) {
qCDebug(lcHit) << " before pos=" << *position;
return PointBefore;
} else if (point.y.toReal() > textrect.bottom()) {

View File

@ -33,6 +33,7 @@ private slots:
void floatingTablePageBreak();
void imageAtRightAlignedTab();
void blockVisibility();
void testHitTest();
void largeImage();
@ -380,5 +381,41 @@ void tst_QTextDocumentLayout::largeImage()
}
}
void tst_QTextDocumentLayout::testHitTest()
{
QTextDocument document;
QTextCursor cur(&document);
int topMargin = 20;
//insert 500 blocks into textedit
for (int i = 0; i < 500; i++) {
cur.insertBlock();
cur.insertHtml(QString("block %1").arg(i));
}
//randomly set half the blocks invisible
QTextBlock blk=document.begin();
for (int i = 0; i < 500; i++) {
if (i % 7)
blk.setVisible(0);
blk = blk.next();
}
//set margin for all blocks (not strictly necessary, but makes easier to click in between blocks)
QTextBlockFormat blkfmt;
blkfmt.setTopMargin(topMargin);
cur.movePosition(QTextCursor::Start);
cur.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
cur.mergeBlockFormat(blkfmt);
for (int y = cur.selectionStart(); y < cur.selectionEnd(); y += 10) {
QPoint mousePoint(1, y);
int cursorPos = document.documentLayout()->hitTest(mousePoint, Qt::FuzzyHit);
int positionY = document.findBlock(cursorPos).layout()->position().toPoint().y();
//mousePoint is in the rect of the current Block
QVERIFY(positionY - topMargin <= y);
}
}
QTEST_MAIN(tst_QTextDocumentLayout)
#include "tst_qtextdocumentlayout.moc"