QMacStyle: fix group box for macOS Mojave
This change is based on a patch started by Gabriel. It works around the apparently noop (on macOS Mojave, light theme) -drawRect: call on NSBox, replacing it with -displayRectIgnoringOpacity:inContext:. Unfortunately, this turns out to be extremely slow with dark theme, so we have to resort to a custom version of NSBox/-drawRect: which calls its super's -drawRect: and look more or less correct. Task-number: QTBUG-69650 Change-Id: I5a614d7cd8002b378c6c3804663b6559e227f628 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
This commit is contained in:
parent
0b4ab214db
commit
3c4f94b7cb
@ -238,6 +238,33 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView);
|
||||
}
|
||||
@end
|
||||
|
||||
// See render code in drawPrimitive(PE_FrameTabWidget)
|
||||
@interface QT_MANGLE_NAMESPACE(QDarkNSBox) : NSBox
|
||||
@end
|
||||
|
||||
QT_NAMESPACE_ALIAS_OBJC_CLASS(QDarkNSBox);
|
||||
|
||||
@implementation QDarkNSBox
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
self.title = @"";
|
||||
self.titlePosition = NSNoTitle;
|
||||
self.boxType = NSBoxCustom;
|
||||
self.cornerRadius = 3;
|
||||
self.borderColor = [NSColor.controlColor colorWithAlphaComponent:0.1];
|
||||
self.fillColor = [NSColor.darkGrayColor colorWithAlphaComponent:0.2];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
[super drawRect:rect];
|
||||
}
|
||||
@end
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
// The following constants are used for adjusting the size
|
||||
@ -1704,18 +1731,28 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
|
||||
|| widget.size == QStyleHelper::SizeDefault)
|
||||
return nil;
|
||||
|
||||
if (widget.type == Box) {
|
||||
if (__builtin_available(macOS 10.14, *)) {
|
||||
if (qt_mac_applicationIsInDarkMode()) {
|
||||
// See render code in drawPrimitive(PE_FrameTabWidget)
|
||||
widget.type = Box_Dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSView *bv = cocoaControls.value(widget, nil);
|
||||
if (!bv) {
|
||||
switch (widget.type) {
|
||||
case Box: {
|
||||
NSBox *bc = [[NSBox alloc] init];
|
||||
bc.title = @"";
|
||||
bc.titlePosition = NSNoTitle;
|
||||
bc.boxType = NSBoxPrimary;
|
||||
bc.borderType = NSBezelBorder;
|
||||
bv = bc;
|
||||
NSBox *box = [[NSBox alloc] init];
|
||||
bv = box;
|
||||
box.title = @"";
|
||||
box.titlePosition = NSNoTitle;
|
||||
break;
|
||||
}
|
||||
case Box_Dark:
|
||||
bv = [[QDarkNSBox alloc] init];
|
||||
break;
|
||||
case Button_CheckBox:
|
||||
case Button_Disclosure:
|
||||
case Button_PushButton:
|
||||
@ -2922,10 +2959,28 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
|
||||
{
|
||||
const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeLarge);
|
||||
auto *box = static_cast<NSBox *>(d->cocoaControl(cw));
|
||||
// FIXME Since macOS 10.14, simply calling drawRect: won't display anything anymore.
|
||||
// The AppKit team is aware of this and has proposed a couple of solutions.
|
||||
// The first solution was to call displayRectIgnoringOpacity:inContext: instead.
|
||||
// However, it doesn't seem to work on 10.13. More importantly, dark mode on 10.14
|
||||
// is extremely slow. Light mode works fine.
|
||||
// The second solution is to subclass NSBox and reimplement a trivial drawRect: which
|
||||
// would only call super. This works without any issue on 10.13, but a double border
|
||||
// shows on 10.14 in both light and dark modes.
|
||||
// The code below picks what works on each version and mode. On 10.13 and earlier, we
|
||||
// simply call drawRect: on a regular NSBox. On 10.14, we call displayRectIgnoringOpacity:
|
||||
// inContext:, but only in light mode. In dark mode, we use a custom NSBox subclass,
|
||||
// QDarkNSBox, of type NSBoxCustom. Its appearance is close enough to the real thing so
|
||||
// we can use this for now.
|
||||
d->drawNSViewInRect(box, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) {
|
||||
CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height);
|
||||
CGContextScaleCTM(ctx, 1, -1);
|
||||
[box drawRect:rect];
|
||||
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMojave
|
||||
|| [box isMemberOfClass:QDarkNSBox.class]) {
|
||||
[box drawRect:rect];
|
||||
} else {
|
||||
[box displayRectIgnoringOpacity:box.bounds inContext:NSGraphicsContext.currentContext];
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -187,6 +187,7 @@ public:
|
||||
enum CocoaControlType {
|
||||
NoControl, // For when there's no such a control in Cocoa
|
||||
Box, // QGroupBox
|
||||
Box_Dark, // FIXME See render code in drawPrimitive(PE_FrameTabWidget)
|
||||
Button_CheckBox,
|
||||
Button_Disclosure, // Disclosure triangle, like in QTreeView
|
||||
Button_PopupButton, // Non-editable QComboBox
|
||||
|
Loading…
x
Reference in New Issue
Block a user