QMacStyle: Fix push buttons focus ring on Yosemite
HITheme renders the focus ring in a way that diminishes contrast on the focused button edges. The same issue seems to affect combo boxes, check boxes, and radio buttons. We refactor the code that was used to draw CE_FocusFrame into qt_drawFocusRingOnPath(). We use it to render our own path for the push button contour. This should also allow us to implement the focus ring animation in the future. As a side note, notice how the square button part (kThemeBevelButton) is a complete joke. Not only we impose the wrong button kind and let HITheme do what it can with it, but we also prevent ourselves from using it by never adding padding for the focus ring. Hopefully, we can fix this whole button sizing and padding mess in 5.5 or 6.0, whatever breaks less apps around. Task-number: QTBUG-40833 Change-Id: Ib9e7829d99b38dc926c55b31c3d6d5d32b691867 Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
This commit is contained in:
parent
63f48d00aa
commit
e94642a9b0
@ -1098,6 +1098,19 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz
|
||||
}
|
||||
#endif
|
||||
|
||||
static void qt_drawFocusRingOnPath(CGContextRef cg, NSBezierPath *focusRingPath)
|
||||
{
|
||||
CGContextSaveGState(cg);
|
||||
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
|
||||
graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]];
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
NSSetFocusRingStyle(NSFocusRingOnly);
|
||||
[focusRingPath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos
|
||||
[focusRingPath fill];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
CGContextRestoreGState(cg);
|
||||
}
|
||||
|
||||
QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
|
||||
QStyle::ContentsType ct, QSize szHint, QSize *insz) const
|
||||
{
|
||||
@ -3573,6 +3586,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
|
||||
d->initHIThemePushButton(btn, w, tds, &bdi);
|
||||
|
||||
if (yosemiteOrLater) {
|
||||
// HITheme is not drawing a nice focus frame around buttons.
|
||||
// We'll do it ourselves further down.
|
||||
bdi.adornment &= ~kThemeAdornmentFocus;
|
||||
|
||||
// We can't rely on an animation existing to test for the default look. That means a bit
|
||||
// more logic (notice that the logic is slightly different for the bevel and the label).
|
||||
if (tds == kThemeStateActive
|
||||
@ -3625,6 +3642,37 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
|
||||
else
|
||||
HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
|
||||
|
||||
if (yosemiteOrLater && btn->state & State_HasFocus) {
|
||||
CGRect focusRect = newRect;
|
||||
if (bdi.kind == kThemePushButton)
|
||||
focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about.
|
||||
else if (bdi.kind == kThemePushButtonMini)
|
||||
focusRect.size.height = 15; // Our QPushButton sizes are really weird
|
||||
|
||||
if (bdi.adornment & kThemeAdornmentDefault || bdi.state == kThemeStatePressed) {
|
||||
if (bdi.kind == kThemePushButtonSmall) {
|
||||
focusRect = CGRectInset(focusRect, -1, 0);
|
||||
} else if (bdi.kind == kThemePushButtonMini) {
|
||||
focusRect = CGRectInset(focusRect, 1, 0);
|
||||
}
|
||||
} else {
|
||||
if (bdi.kind == kThemePushButton) {
|
||||
focusRect = CGRectInset(focusRect, 1, 1);
|
||||
} else if (bdi.kind == kThemePushButtonSmall) {
|
||||
focusRect = CGRectInset(focusRect, 0, 2);
|
||||
} else if (bdi.kind == kThemePushButtonMini) {
|
||||
focusRect = CGRectInset(focusRect, 2, 1);
|
||||
}
|
||||
}
|
||||
|
||||
NSBezierPath *pushButtonFocusRingPath;
|
||||
if (bdi.kind == kThemeBevelButton)
|
||||
pushButtonFocusRingPath = [NSBezierPath bezierPathWithRect:focusRect];
|
||||
else
|
||||
pushButtonFocusRingPath = [NSBezierPath bezierPathWithRoundedRect:focusRect xRadius:4 yRadius:4];
|
||||
qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath);
|
||||
}
|
||||
|
||||
if (hasMenu) {
|
||||
int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
|
||||
QRect ir = btn->rect;
|
||||
@ -4089,16 +4137,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
|
||||
int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w);
|
||||
NSRect rect = NSMakeRect(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff,
|
||||
opt->rect.height() - 2 * yOff);
|
||||
CGContextSaveGState(cg);
|
||||
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
|
||||
graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]];
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
NSSetFocusRingStyle(NSFocusRingOnly);
|
||||
NSBezierPath *focusFramePath = [NSBezierPath bezierPathWithRect:rect];
|
||||
[focusFramePath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos
|
||||
[focusFramePath fill];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
CGContextRestoreGState(cg);
|
||||
qt_drawFocusRingOnPath(cg, focusFramePath);
|
||||
break; }
|
||||
case CE_MenuItem:
|
||||
case CE_MenuEmptyArea:
|
||||
|
Loading…
Reference in New Issue
Block a user