From f9940b15f7f0fde731431626172939b9821fd660 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 11 Jun 2020 15:06:39 +0200 Subject: Fix breakage of QPushButton on macOS when a style sheet was set Amends comment 6e1d70ae12baae4610356ec7b69635ad75a97b4e, which introduced SE_PushButtonBevel so that QPushButton could ignore clicks outside of the button's bevel. In the macOS style, make sure that the framerect we pass to NSButton::alignmentRectForFrame is the rect we receive from QPushButton in the style options. The frame property of the shared NSButton* object might not be initialized. In the style sheet style, handle SE_PushButtonBevel the same ways as Contents and FocusRect, as it is not a separately styleable property. Change-Id: I12eb1b046c864a02b34d276e6352e2e16d44231e Fixes: QTBUG-84852 Fixes: QTBUG-84879 Task-number: QTBUG-81452 Pick-to: 5.15 Reviewed-by: Richard Moe Gustavsen --- src/plugins/styles/mac/qmacstyle_mac.mm | 14 ++++---- src/widgets/styles/qstylesheetstyle.cpp | 1 + .../widgets/qpushbutton/tst_qpushbutton.cpp | 41 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 58061b1ae4..01d4a06c61 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -4642,15 +4642,13 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, auto frameRect = cw.adjustedControlFrame(btn->rect); if (sr == SE_PushButtonContents) { frameRect -= cw.titleMargins(); - } else { + } else if (cw.type != QMacStylePrivate::Button_SquareButton) { auto *pb = static_cast(d->cocoaControl(cw)); - if (cw.type != QMacStylePrivate::Button_SquareButton) { - frameRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); - if (cw.type == QMacStylePrivate::Button_PushButton) - frameRect -= pushButtonShadowMargins[cw.size]; - else if (cw.type == QMacStylePrivate::Button_PullDown) - frameRect -= pullDownButtonShadowMargins[cw.size]; - } + frameRect = QRectF::fromCGRect([pb alignmentRectForFrame:frameRect.toCGRect()]); + if (cw.type == QMacStylePrivate::Button_PushButton) + frameRect -= pushButtonShadowMargins[cw.size]; + else if (cw.type == QMacStylePrivate::Button_PullDown) + frameRect -= pullDownButtonShadowMargins[cw.size]; } rect = frameRect.toRect(); } diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index a9989dcd3e..412bf27f3a 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -5826,6 +5826,7 @@ QRect QStyleSheetStyle::subElementRect(SubElement se, const QStyleOption *opt, c switch (se) { case SE_PushButtonContents: + case SE_PushButtonBevel: case SE_PushButtonFocusRect: if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { if (rule.hasBox() || !rule.hasNativeBorder()) diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp index 51eb7d2020..634497f22f 100644 --- a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp +++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp @@ -71,6 +71,7 @@ private slots: void taskQTBUG_20191_shortcutWithKeypadModifer(); #endif void emitReleasedAfterChange(); + void hitButton(); protected slots: void resetCounters(); @@ -662,5 +663,45 @@ void tst_QPushButton::emitReleasedAfterChange() QCOMPARE(spy.count(), 1); } +/* + Test that QPushButton::hitButton returns true for points that + are certainly inside the bevel, also when a style sheet is set. +*/ +void tst_QPushButton::hitButton() +{ + class PushButton : public QPushButton + { + public: + PushButton(const QString &text = {}) + : QPushButton(text) + {} + + bool hitButton(const QPoint &point) const override + { + return QPushButton::hitButton(point); + } + }; + + QDialog dialog; + QVBoxLayout *layout = new QVBoxLayout; + PushButton *button1 = new PushButton("Ok"); + PushButton *button2 = new PushButton("Cancel"); + button2->setStyleSheet("QPushButton { margin: 10px; border-radius: 4px; border: 1px solid black; }"); + + layout->addWidget(button1); + layout->addWidget(button2); + + dialog.setLayout(layout); + dialog.show(); + QVERIFY(QTest::qWaitForWindowExposed(&dialog)); + + const QPoint button1Center = button1->rect().center(); + QVERIFY(button1->hitButton(button1Center)); + + const QPoint button2Center = button2->rect().center(); + QVERIFY(button2->hitButton(button2Center)); + QVERIFY(!button2->hitButton(QPoint(0, 0))); +} + QTEST_MAIN(tst_QPushButton) #include "tst_qpushbutton.moc" -- cgit v1.2.3