Search code examples
macoscalayernswindowtheming

Drawing correct CALayer colors honoring NSAppearance


I am looking into theming my app by setting window.appearance. In my app, I draw some stuff inside layers. I also use Core Plot, which renders its charts in layers.

For the default aqua appearance, I just use the system colors (such as NSColor.textColor and NSColor.gridColor) and they are drawn in the correct color in CALayer. But changing the window's appearance to vibrant dark causes colors to be drawn incorrectly. Is there any way to obtain the correct color for a givenNSAppearance? Private API is acceptable too.


If the question is not clear, here is a very simple example to show the problem.

I set up a CATextLayer that is added as a sublayer of the main view's sublayers and an NSTextFied that is added as a subview:

CATextLayer* textLayer = [CATextLayer new];
textLayer.string = @"Is this colored correctly? (Layer)";
textLayer.foregroundColor = NSColor.textColor.CGColor;
textLayer.contentsScale = 2.0;
textLayer.frame = (CGRect){0,0, [textLayer preferredFrameSize]};

NSTextField* textField = [NSTextField new];
textField.stringValue = @"Is this colored correctly? (View)";
textField.textColor = NSColor.textColor;
textField.font = (__bridge id)textLayer.font;
textField.editable = NO;
textField.selectable = NO;
textField.bezeled = NO;
textField.backgroundColor = nil;
[textField sizeToFit];
textField.frame = (CGRect){0, 60, textField.bounds.size};

[self.view.layer addSublayer:textLayer];
[self.view addSubview:textField];

On an Aqua window, both appear correctly:

enter image description here

However, on a dark vibrant window, the layer does not, while the text field does:

enter image description here

I'd like to know how to get the correct color for a given NSAppearance.


Solution

  • So I had an incorrect approach.

    The right way to do it, is to implement -updateLayer in the view and take the colors' CGColor snapshot there. -updateLayer is called when the appearance changes, so the view can update it with the correct color values.