5.15: fix for QTBUG-89133 & QTBUG-81452 using cherry pick (https://codereview.qt-project.org/c/qt/qtbase/+/327677)

This commit is contained in:
kleuter 2021-05-12 21:25:01 +02:00
parent 679fb5f237
commit 02f8fe67b8
3 changed files with 119 additions and 37 deletions

View File

@ -195,6 +195,10 @@ const int QMacStylePrivate::PushButtonLeftOffset = 6;
const int QMacStylePrivate::PushButtonRightOffset = 12;
const int QMacStylePrivate::PushButtonContentPadding = 6;
const int pushButtonBevelRectOffsets[3] = {
QMacStylePrivate::PushButtonLeftOffset, 5, 5
};
QVector<QPointer<QObject> > QMacStylePrivate::scrollBars;
// Title bar gradient colors for Lion were determined by inspecting PSDs exported
@ -1174,6 +1178,8 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
case SegmentedControl_Middle:
case TextField: {
auto innerRect = targetRect;
if (cw.type == Button_SquareButton)
innerRect = cw.adjustedControlFrame(targetRect.adjusted(hMargin, vMargin, -hMargin, -vMargin));
if (cw.type == TextField)
innerRect = innerRect.adjusted(hMargin, vMargin, -hMargin, -vMargin).adjusted(0.5, 0.5, -0.5, -0.5);
const auto outerRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth);
@ -1208,9 +1214,38 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
focusRingPath.addEllipse(rbOuterRect);
break;
}
case Button_PopupButton:
case Button_PullDown:
case Button_PushButton:
case Button_PushButton: {
const bool isBigSurOrAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSBigSur;
QRectF focusRect;
auto *pb = static_cast<NSButton *>(cocoaControl(cw));
const QRectF frameRect = cw.adjustedControlFrame(targetRect.adjusted(hMargin, vMargin, -hMargin, -vMargin));
pb.frame = frameRect.toCGRect();
focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]);
if (cw.type == QMacStylePrivate::Button_PushButton) {
focusRect -= pushButtonShadowMargins[cw.size];
}
else if (cw.type == QMacStylePrivate::Button_PullDown) {
focusRect -= pullDownButtonShadowMargins[cw.size];
//fix focus ring drawn slightly off for pull downs
if (cw.size == QStyleHelper::SizeLarge)
focusRect = focusRect.adjusted(0, 0, 0, -1);
else if (cw.size == QStyleHelper::SizeMini)
focusRect = focusRect.adjusted(0, -1, 0, 0);
}
if (isBigSurOrAbove)
focusRect = focusRect.translated(0, 1);
const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4;
const qreal outerRadius = innerRadius + focusRingWidth;
hOffset = focusRect.left();
vOffset = focusRect.top();
const auto innerRect = focusRect.translated(-focusRect.topLeft());
const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin);
focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius);
focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius);
break;
}
case Button_PopupButton:
case SegmentedControl_Single: {
const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4;
const qreal outerRadius = innerRadius + focusRingWidth;
@ -1568,7 +1603,8 @@ QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect)
const auto frameSize = defaultFrameSize();
if (type == QMacStylePrivate::Button_SquareButton) {
frameRect = rect.adjusted(3, 1, -3, -1)
.adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth);
.adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth)
.adjusted(-6.5, 0, 6.5, 0);
} else if (type == QMacStylePrivate::Button_PushButton) {
// Start from the style option's top-left corner.
frameRect = QRectF(rect.topLeft(),
@ -1577,6 +1613,8 @@ QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect)
frameRect = frameRect.translated(0, 1.5);
else if (size == QStyleHelper::SizeMini)
frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4);
frameRect = frameRect.adjusted(-pushButtonBevelRectOffsets[size], 0,
pushButtonBevelRectOffsets[size], 0);
} else {
// Center in the style option's rect.
frameRect = QRectF(QPointF(0, (rect.height() - frameSize.height()) / 2.0),
@ -1589,6 +1627,9 @@ QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect)
frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1);
else if (size == QStyleHelper::SizeMini)
frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0);
if (type == QMacStylePrivate::Button_PullDown)
frameRect = frameRect.adjusted(-pushButtonBevelRectOffsets[size], 0,
pushButtonBevelRectOffsets[size], 0);
} else if (type == QMacStylePrivate::ComboBox) {
frameRect = frameRect.adjusted(0, 0, -6, 0).translated(4, 0);
}
@ -3716,24 +3757,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
arrowOpt.rect = ar;
proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, w);
}
if (btn->state & State_HasFocus) {
// TODO Remove and use QFocusFrame instead.
const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w);
const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w);
QRectF focusRect;
if (cw.type == QMacStylePrivate::Button_SquareButton) {
focusRect = frameRect;
} else {
focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]);
if (cw.type == QMacStylePrivate::Button_PushButton)
focusRect -= pushButtonShadowMargins[cw.size];
else if (cw.type == QMacStylePrivate::Button_PullDown)
focusRect -= pullDownButtonShadowMargins[cw.size];
}
d->drawFocusRing(p, focusRect, hMargin, vMargin, cw);
}
}
break;
case CE_PushButtonLabel:
@ -3768,7 +3791,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QRect textRect = itemTextRect(
btn.fontMetrics, freeContentRect, Qt::AlignCenter, isEnabled, btn.text);
if (hasMenu) {
textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls
if (ct == QMacStylePrivate::Button_SquareButton)
textRect.moveTo(w ? 8 : 11, textRect.top());
else
textRect.moveTo(w ? (15 - pushButtonBevelRectOffsets[d->effectiveAquaSizeConstrain(b, w)])
: 11, textRect.top()); // Supports Qt Quick Controls
}
// Draw the icon:
if (hasIcon) {
@ -3988,8 +4015,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
rAdjusted.origin.x -= 3;
rAdjusted.size.width += 6;
if (isBigSurOrAbove) {
rAdjusted.origin.y -= 1;
rAdjusted.size.height += 1;
if (tp == QStyleOptionTab::End)
rAdjusted.origin.x -= 2;
}
@ -4166,6 +4191,15 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
return QMacStylePrivate::Button_RadioButton;
if (ffw->inherits("QLineEdit") || ffw->inherits("QTextEdit"))
return QMacStylePrivate::TextField;
if (const auto *pb = qobject_cast<const QPushButton *>(ffw)) {
if (pb->isFlat() || (pb->rect().height()
> pushButtonDefaultHeight[QStyleHelper::SizeLarge]
&& !(pb->testAttribute(Qt::WA_MacNormalSize))))
return QMacStylePrivate::Button_SquareButton;
if (pb->menu() != nullptr)
return QMacStylePrivate::Button_PullDown;
return QMacStylePrivate::Button_PushButton;
}
}
return QMacStylePrivate::Box; // Not really, just make it the default
@ -4909,14 +4943,24 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
= qstyleoption_cast<const QStyleOptionButton *>(opt)) {
if ((buttonOpt->features & QStyleOptionButton::Flat))
break; // leave rect alone
if ((buttonOpt->features & QStyleOptionButton::CommandLinkButton)) {
rect = opt->rect;
if (controlSize == QStyleHelper::SizeLarge)
rect.adjust(+6, +4, -6, -8);
else if (controlSize == QStyleHelper::SizeSmall)
rect.adjust(+5, +4, -5, -6);
else
rect.adjust(+1, 0, -1, -2);
break;
}
}
rect = opt->rect;
if (controlSize == QStyleHelper::SizeLarge) {
rect.adjust(+6, +4, -6, -8);
rect.adjust(0, +4, 0, -8);
} else if (controlSize == QStyleHelper::SizeSmall) {
rect.adjust(+5, +4, -5, -6);
rect.adjust(0, +4, 0, -6);
} else {
rect.adjust(+1, 0, -1, -2);
rect.adjust(0, 0, 0, -2);
}
break;
case SE_RadioButtonLayoutItem:
@ -6345,14 +6389,16 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
break;
#endif
case QStyle::CT_PushButton: {
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt))
bool isFlat = false;
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
if (btn->features & QStyleOptionButton::CommandLinkButton)
return QCommonStyle::sizeFromContents(ct, opt, sz, widget);
isFlat = btn->features & QStyleOptionButton::Flat;
}
// By default, we fit the contents inside a normal rounded push button.
// Do this by add enough space around the contents so that rounded
// borders (including highlighting when active) will show.
// TODO Use QFocusFrame and get rid of these horrors.
QSize macsz;
const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget, CT_PushButton, sz, &macsz);
// FIXME See comment in CT_PushButton case in qt_aqua_get_known_size().
@ -6363,12 +6409,24 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
// All values as measured from HIThemeGetButtonBackgroundBounds()
if (controlSize != QStyleHelper::SizeMini)
sz.rwidth() += 12; // We like 12 over here.
if (controlSize == QStyleHelper::SizeLarge && sz.height() > 16)
sz.rheight() += pushButtonDefaultHeight[QStyleHelper::SizeLarge] - 16;
else if (controlSize == QStyleHelper::SizeMini)
sz.setHeight(24); // FIXME Our previous HITheme-based logic returned this.
else
sz.setHeight(pushButtonDefaultHeight[controlSize]);
if (controlSize == QStyleHelper::SizeLarge) {
if (!isFlat)
sz.rwidth() -= 12;
if (sz.height() > 16)
sz.rheight() += pushButtonDefaultHeight[QStyleHelper::SizeLarge] - 16;
else
sz.setHeight(pushButtonDefaultHeight[QStyleHelper::SizeLarge]);
} else {
if (!isFlat)
sz.rwidth() -= 10;
if (controlSize == QStyleHelper::SizeMini)
sz.setHeight(24);
else
sz.setHeight(pushButtonDefaultHeight[QStyleHelper::SizeSmall]);
}
if (isFlat)
sz.rwidth() -= 13;
break;
}
case QStyle::CT_MenuItem:

View File

@ -332,6 +332,8 @@ void QPushButton::initStyleOption(QStyleOptionButton *option) const
option->state |= QStyle::State_On;
if (!d->flat && !d->down)
option->state |= QStyle::State_Raised;
if (underMouse() && hasMouseTracking())
option->state.setFlag(QStyle::State_MouseOver, d->hovering);
option->text = d->text;
option->icon = d->icon;
option->iconSize = iconSize();
@ -581,6 +583,13 @@ void QPushButton::showMenu()
d->_q_popupPressed();
}
void QPushButtonPrivate::init()
{
Q_Q(QPushButton);
q->setAttribute(Qt::WA_MacShowFocusRect);
resetLayoutItemMargins();
}
void QPushButtonPrivate::_q_popupPressed()
{
Q_Q(QPushButton);
@ -691,6 +700,18 @@ bool QPushButton::event(QEvent *e)
updateGeometry();
} else if (e->type() == QEvent::PolishRequest) {
updateGeometry();
} else if (e->type() == QEvent::MouseMove) {
const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(e);
if (testAttribute(Qt::WA_Hover)) {
bool hit = false;
if (underMouse())
hit = hitButton(mouseEvent->pos());
if (hit != d->hovering) {
update(rect());
d->hovering = hit;
}
}
}
return QAbstractButton::event(e);
}

View File

@ -69,9 +69,11 @@ public:
QPushButtonPrivate()
: QAbstractButtonPrivate(QSizePolicy::PushButton), autoDefault(Auto),
defaultButton(false), flat(false), menuOpen(false), lastAutoDefault(false) {}
defaultButton(false), flat(false), menuOpen(false), hovering(false),
lastAutoDefault(false)
{}
inline void init() { resetLayoutItemMargins(); }
void init();
static QPushButtonPrivate* get(QPushButton *b) { return b->d_func(); }
#if QT_CONFIG(menu)
QPoint adjustedMenuPosition();
@ -89,6 +91,7 @@ public:
uint defaultButton : 1;
uint flat : 1;
uint menuOpen : 1;
uint hovering : 1;
mutable uint lastAutoDefault : 1;
};