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
Pick-to: 6.4 6.3 6.2
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>
bb10
Tang Haixiang 2021-10-27 18:59:33 +08:00 committed by Volker Hilsheimer
parent ff92c4c3d8
commit 8aae49019d
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"