Fix breakage of QPushButton on macOS when a style sheet was set

Amends comment 6e1d70ae12, 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 <richard.gustavsen@qt.io>
This commit is contained in:
Volker Hilsheimer 2020-06-11 15:06:39 +02:00
parent cde86464df
commit f9940b15f7
3 changed files with 48 additions and 8 deletions

View File

@ -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<NSButton *>(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();
}

View File

@ -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<const QStyleOptionButton *>(opt)) {
if (rule.hasBox() || !rule.hasNativeBorder())

View File

@ -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"