summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2018-10-12 15:45:27 +0200
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2018-10-19 13:23:51 +0000
commit3c4f94b7cb3f319f24fda6502e49bdd199c0f77d (patch)
tree3922c05849764f77af54b32b78c0bf60c7f64d6b
parent0b4ab214db5f0368b33d4cfdfcaadf137070b7a8 (diff)
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>
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm69
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h1
2 files changed, 63 insertions, 7 deletions
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 1aab0309c9..94d048ca7e 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -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;
}
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 8c712e838a..dd99cf4bb5 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -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