From 4a27d0fe0ade67938bb9ecb9bf2525dc3553e11c Mon Sep 17 00:00:00 2001 From: Johannes Grunenberg Date: Sun, 10 Nov 2024 18:09:45 +0100 Subject: [PATCH] QWidget: clamp own rect in pointInsideRectAndMask The rect of an empty widget (i.e. 0 width/height) will, after adjusting by -1, be invalid as it will have a width/height of -1. In turn, calling contains(p) on that rect can return true even though the rect is empty. Fixes: QTBUG-131001 Pick-to: 6.8.1 Change-Id: I604f5942589f1c1079cae90bd0d3b104344d2c55 Reviewed-by: Volker Hilsheimer Reviewed-by: David Faure (cherry picked from commit 1731d8af741a0a6cc6cd293be4aef52103d0899b) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/kernel/qwidget_p.h | 12 +++++++++--- .../auto/widgets/kernel/qwidget/tst_qwidget.cpp | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 9016532ba2c..9ea134b16f1 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -887,9 +887,15 @@ inline void QWidgetPrivate::setSharedPainter(QPainter *painter) inline bool QWidgetPrivate::pointInsideRectAndMask(const QPointF &p) const { Q_Q(const QWidget); - // Use QRectF::contains so that (0, -0.1) isn't in, with p.toPoint() it would be - // The adjusted matches QRect semantics: (160,160) isn't contained in QRect(0, 0, 160, 160) - return QRectF(q->rect().adjusted(0, 0, -1, -1)).contains(p) + + // Use QRectF::contains so that (0, -0.1) isn't in, with p.toPoint() it would be in. + // The -1 on right and bottom matches QRect semantics: + // (160,160) isn't contained in QRect(0, 0, 160, 160) + QRect r = q->rect(); + r.setRight(qMax(-1, r.right() - 1)); + r.setBottom(qMax(-1, r.bottom() - 1)); + + return r.toRectF().contains(p) && (!extra || !extra->hasMask || q->testAttribute(Qt::WA_MouseNoMask) || extra->mask.contains(p.toPoint() /* incorrect for the -0.1 case */)); } diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 0de06713e4c..8d06dae6d09 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -11803,11 +11803,27 @@ void tst_QWidget::childAt() grandChild->setAutoFillBackground(true); grandChild->setGeometry(-20, -20, 220, 220); + QWidget *emptyChild = new QWidget(child); + emptyChild->setPalette(Qt::green); + emptyChild->setAutoFillBackground(true); + emptyChild->setGeometry(0, 159, 160, 0); + QVERIFY(!parent.childAt(19, 19)); QVERIFY(!parent.childAt(180, 180)); QCOMPARE(parent.childAt(20, 20), grandChild); QCOMPARE(parent.childAt(179, 179), grandChild); + QCOMPARE(parent.childAt(120, 179), grandChild); + QCOMPARE(parent.childAt(QPointF(120.0, 178.9)), grandChild); + QVERIFY(!parent.childAt(120, 180)); + QVERIFY(!parent.childAt(QPointF(120, 179.1))); + + emptyChild->setGeometry(100, 0, 0, 160); + + QCOMPARE(parent.childAt(120, 120), grandChild); + QCOMPARE(parent.childAt(QPointF(120.5, 120.0)), grandChild); + QCOMPARE(parent.childAt(QPointF(119.5, 120.0)), grandChild); + grandChild->setAttribute(Qt::WA_TransparentForMouseEvents); QCOMPARE(parent.childAt(20, 20), child); QCOMPARE(parent.childAt(179, 179), child);