QMacStyle: use the 'momentary push in' type for push buttons

In the past, we were using different hacks to emulate the 'default' button
and a normal button (and them in a pressed/not pressed active/non-active
states). In macOS 12 old trick stopped working and UI looks a bit different:
non-default buttons never get accent color even if pressed. Instead of relying
on a combination of 'push on-push off' type's states and highlight, we can
use the 'momentary push in' (highlighted == YES gives an impression of a pressed
button) + setting a key equivalent (thanks to Tor Arne for the hint) gives
the desired 'default button' look.

Pick-to: 6.2 6.3 5.15
Task-number: QTBUG-98483
Change-Id: If7d665d217420b7732b556d98d9e0313258ff93e
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
bb10
Timur Pocheptsov 2021-12-30 09:06:10 +01:00 committed by Tor Arne Vestbø
parent 9ea1f0f8b9
commit eabaa8a08e
1 changed files with 22 additions and 8 deletions

View File

@ -1689,7 +1689,7 @@ bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonTyp
*bezelStyle = NSBezelStyleShadowlessSquare;
break;
case Button_PushButton:
*buttonType = NSButtonTypePushOnPushOff;
*buttonType = NSButtonTypeMomentaryPushIn;
*bezelStyle = NSBezelStyleRounded;
break;
default:
@ -3716,8 +3716,16 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
pb.frame = frameRect.toCGRect();
pb.enabled = isEnabled;
// With the 'momentary push in' type this gives an impression of a
// button in a 'pressed' state (the 'momentary push in' does
// not show its state otherwise):
[pb highlight:isPressed];
pb.state = isHighlighted && !isPressed ? NSControlStateValueOn : NSControlStateValueOff;
// For default/checked button this will give the required
// button accent color:
pb.keyEquivalent = isHighlighted ? @"\r" : @"";
d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef, const CGRect &r) {
[pb.cell drawBezelWithFrame:r inView:pb.superview];
});
@ -3759,6 +3767,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const bool hasText = !btn.text.isEmpty();
const bool isActive = btn.state & State_Active;
const bool isPressed = btn.state & State_Sunken;
const bool isDefault = (btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton)
|| d->autoDefaultButton == btn.styleObject;
// cocoaControlType evaluates the type based on the control's geometry, not on the
// label's geometry
@ -3769,12 +3779,16 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
btn.rect = oldRect;
if (!hasMenu && ct != QMacStylePrivate::Button_SquareButton) {
if (isPressed
|| (isActive && isEnabled
&& ((btn.state & State_On)
|| ((btn.features & QStyleOptionButton::DefaultButton) && !d->autoDefaultButton)
|| d->autoDefaultButton == btn.styleObject)))
btn.palette.setColor(QPalette::ButtonText, Qt::white);
if (isPressed || (isActive && isEnabled && ((btn.state & State_On) || isDefault)))
btn.palette.setColor(QPalette::ButtonText, Qt::white);
}
if (!isDarkMode() && QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur) {
if (!isDefault && !(btn.state & State_On)) {
// On macOS 12 it's a gray button, white text color (if set in the
// previous statement) would be almost invisible.
btn.palette.setColor(QPalette::ButtonText, Qt::black);
}
}
if ((!hasIcon && !hasMenu) || (hasIcon && !hasText)) {