diff options
-rw-r--r-- | src/widgets/widgets/qwidgettextcontrol.cpp | 25 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp | 82 |
2 files changed, 100 insertions, 7 deletions
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 1b78442ed1..28d07dd6c8 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -1818,25 +1818,36 @@ void QWidgetTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton but } if (interactionFlags & Qt::LinksAccessibleByMouse) { - if (!(button & Qt::LeftButton)) + + // Ignore event unless left button has been pressed + if (!(button & Qt::LeftButton)) { + e->ignore(); return; + } const QString anchor = q->anchorAt(pos); - if (anchor.isEmpty()) + // Ignore event without selection anchor + if (anchor.isEmpty()) { + e->ignore(); return; + } if (!cursor.hasSelection() || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) { const int anchorPos = q->hitTest(pos, Qt::ExactHit); - if (anchorPos != -1) { - cursor.setPosition(anchorPos); - QString anchor = anchorOnMousePress; - anchorOnMousePress = QString(); - activateLinkUnderCursor(anchor); + // Ignore event without valid anchor position + if (anchorPos < 0) { + e->ignore(); + return; } + + cursor.setPosition(anchorPos); + QString anchor = anchorOnMousePress; + anchorOnMousePress = QString(); + activateLinkUnderCursor(anchor); } } } diff --git a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp index 891f22c1c9..77613341dd 100644 --- a/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp +++ b/tests/auto/widgets/widgets/qlabel/tst_qlabel.cpp @@ -83,6 +83,8 @@ private Q_SLOTS: void taskQTBUG_48157_dprMovie(); void resourceProvider(); + void mouseEventPropagation_data(); + void mouseEventPropagation(); private: QLabel *testWidget; @@ -600,5 +602,85 @@ void tst_QLabel::resourceProvider() QVERIFY(providerCalled > 0); } +// Test if mouse events are correctly propagated to the parent widget, +// even if a label contains rich text (QTBUG-110055) +void tst_QLabel::mouseEventPropagation_data() +{ + QTest::addColumn<const QString>("text"); + QTest::addColumn<const Qt::TextInteractionFlag>("interaction"); + QTest::addColumn<const bool>("expectPropagation"); + + + QTest::newRow("RichText") + << QString("<b>This is a rich text propagating mouse events</b>") + << Qt::LinksAccessibleByMouse + << true; + QTest::newRow("PlainText") + << QString("This is a plain text propagating mouse events") + << Qt::LinksAccessibleByMouse + << true; + QTest::newRow("PlainTextConsume") + << QString("This is a plain text consuming mouse events") + << Qt::TextSelectableByMouse + << false; + QTest::newRow("RichTextConsume") + << QString("<b>This is a rich text consuming mouse events</b>") + << Qt::TextSelectableByMouse + << false; + QTest::newRow("PlainTextNoInteraction") + << QString("This is a text not interacting with mouse") + << Qt::NoTextInteraction + << true; + QTest::newRow("RichTextNoInteraction") + << QString("<b>This is a rich text not interacting with mouse</b>") + << Qt::NoTextInteraction + << true; +} + +void tst_QLabel::mouseEventPropagation() +{ + class MouseEventWidget : public QWidget + { + public: + uint pressed() const { return m_pressed; } + uint released() const { return m_released; } + + private: + uint m_pressed = 0; + uint m_released = 0; + void mousePressEvent(QMouseEvent *event) override + { + ++m_pressed; + return QWidget::mousePressEvent(event); + } + + void mouseReleaseEvent(QMouseEvent *event) override + { + ++m_released; + return QWidget::mouseReleaseEvent(event); + } + }; + + QFETCH(const QString, text); + QFETCH(const Qt::TextInteractionFlag, interaction); + QFETCH(const bool, expectPropagation); + + MouseEventWidget widget; + auto *layout = new QVBoxLayout(&widget); + auto *label = new QLabel(text); + label->setTextInteractionFlags(interaction); + const uint count = expectPropagation ? 1 : 0; + + layout->addWidget(label); + widget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&widget)); + + const QPoint labelCenter = label->rect().center(); + QTest::mouseClick(label, Qt::LeftButton, Qt::KeyboardModifiers(), labelCenter); + + QTRY_COMPARE(widget.pressed(), count); + QTRY_COMPARE(widget.released(), count); +} + QTEST_MAIN(tst_QLabel) #include "tst_qlabel.moc" |