QMacStyle - workaround NSButtonCell (disclose button type)
Under the 'Dark' theme as a system one, in an application forcing 'Aqua' (and thus 'Light') appearance, disclose button (drawn as a triangle) can suddenly become transparent (apparently selecting a 'Dark' codepath internally). Different ways to fix this (attaching NSButton to a view, setting appearance on this button manually, etc.) - all seems to have no effect. We resort to manually drawing this button on macOS > 10.14 if 'effectiveAppearance' is 'Aqua'. Change-Id: I6f54c0c4cf8fdd1ba53263ba9535e3055be46d42 Fixes: QTBUG-74515 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
1a8aa81866
commit
a868942b11
@ -1156,6 +1156,66 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static NSColor *qt_convertColorForContext(CGContextRef context, NSColor *color)
|
||||||
|
{
|
||||||
|
Q_ASSERT(color);
|
||||||
|
Q_ASSERT(context);
|
||||||
|
|
||||||
|
CGColorSpaceRef targetCGColorSpace = CGBitmapContextGetColorSpace(context);
|
||||||
|
NSColorSpace *targetNSColorSpace = [[NSColorSpace alloc] initWithCGColorSpace:targetCGColorSpace];
|
||||||
|
NSColor *adjusted = [color colorUsingColorSpace:targetNSColorSpace];
|
||||||
|
[targetNSColorSpace release];
|
||||||
|
|
||||||
|
return adjusted;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSColor *qt_colorForContext(CGContextRef context, const CGFloat (&rgba)[4])
|
||||||
|
{
|
||||||
|
Q_ASSERT(context);
|
||||||
|
|
||||||
|
auto colorSpace = CGBitmapContextGetColorSpace(context);
|
||||||
|
if (!colorSpace)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
return qt_convertColorForContext(context, [NSColor colorWithSRGBRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qt_drawDisclosureButton(CGContextRef context, NSInteger state, bool selected, CGRect rect)
|
||||||
|
{
|
||||||
|
Q_ASSERT(context);
|
||||||
|
|
||||||
|
static const CGFloat gray[] = {0.55, 0.55, 0.55, 0.97};
|
||||||
|
static const CGFloat white[] = {1.0, 1.0, 1.0, 0.9};
|
||||||
|
|
||||||
|
NSColor *fillColor = qt_colorForContext(context, selected ? white : gray);
|
||||||
|
[fillColor setFill];
|
||||||
|
|
||||||
|
if (state == NSOffState) {
|
||||||
|
static NSBezierPath *triangle = [[NSBezierPath alloc] init];
|
||||||
|
[triangle removeAllPoints];
|
||||||
|
// In off state, a disclosure button is an equilateral triangle
|
||||||
|
// ('pointing' to the right) with a bound rect that can be described
|
||||||
|
// as NSMakeRect(0, 0, 8, 9). Inside the 'rect' it's translated by
|
||||||
|
// (2, 4).
|
||||||
|
[triangle moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4)];
|
||||||
|
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4 + 9)];
|
||||||
|
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2 + 8, rect.origin.y + 4 + 4.5)];
|
||||||
|
[triangle closePath];
|
||||||
|
[triangle fill];
|
||||||
|
} else {
|
||||||
|
static NSBezierPath *openTriangle = [[NSBezierPath alloc] init];
|
||||||
|
[openTriangle removeAllPoints];
|
||||||
|
// In 'on' state, the button is an equilateral triangle (looking down)
|
||||||
|
// with the bounding rect NSMakeRect(0, 0, 9, 8). Inside the 'rect'
|
||||||
|
// it's translated by (1, 4).
|
||||||
|
[openTriangle moveToPoint:NSMakePoint(rect.origin.x + 1, rect.origin.y + 4 + 8)];
|
||||||
|
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 9, rect.origin.y + 4 + 8)];
|
||||||
|
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 4.5, rect.origin.y + 4)];
|
||||||
|
[openTriangle closePath];
|
||||||
|
[openTriangle fill];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
|
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
|
||||||
{
|
{
|
||||||
QPainterPath focusRingPath;
|
QPainterPath focusRingPath;
|
||||||
@ -3241,8 +3301,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
|
|||||||
CGContextScaleCTM(cg, 1, -1);
|
CGContextScaleCTM(cg, 1, -1);
|
||||||
CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
|
CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
|
||||||
|
|
||||||
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
|
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) {
|
||||||
|
// When the real system theme is one of the 'Dark' themes, and an application forces the 'Aqua' theme,
|
||||||
|
// under some conditions (see QTBUG-74515 for more details) NSButtonCell seems to select the 'Dark'
|
||||||
|
// code path and is becoming transparent, thus 'invisible' on the white background. To workaround this,
|
||||||
|
// we draw the disclose triangle manually:
|
||||||
|
qt_drawDisclosureButton(cg, triangleCell.state, (opt->state & State_Selected) && viewHasFocus, rect);
|
||||||
|
} else {
|
||||||
|
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
|
||||||
|
}
|
||||||
d->restoreNSGraphicsContext(cg);
|
d->restoreNSGraphicsContext(cg);
|
||||||
break; }
|
break; }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user