Skip to content

Commit e542cd8

Browse files
committed
macOS: Fix a big where the color of a transparent titlebar was off when running in the release build versus the build from source. Also fix using a transparent titlebar causing the background opacity to be darkened.
There were two issues. 1) Setting window background color to a non-zero opacity causes darkening (essentially there were two layers of blending) 2) The titlebar background view could end up in the wrong position because it was a child of the content view rather than its super view Fix both issues setting the window background to clear color and moving the background view into the super view while making sure it is positioned correctly using explicit constraints. Phew.
1 parent e024226 commit e542cd8

File tree

2 files changed

+30
-19
lines changed

2 files changed

+30
-19
lines changed

docs/changelog.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,13 @@ consumption to do the same tasks.
134134
Detailed list of changes
135135
-------------------------------------
136136

137+
0.43.1 [future]
138+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
139+
140+
- macOS: Fix a big where the color of a transparent titlebar was off when
141+
running in the release build versus the build from source. Also fix using a
142+
transparent titlebar causing the background opacity to be darkened.
143+
137144
0.43.0 [2025-09-28]
138145
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
139146

glfw/cocoa_window.m

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,27 +3280,30 @@ @implementation NSView (FindByIdentifier)
32803280
static
32813281
void clear_title_bar_background_views(NSWindow *window) {
32823282
#define tag @"kitty-for-transparent-titlebar"
3283-
NSView *contentView = window.contentView;
3284-
if (contentView) {
3285-
for (NSView *subview in [contentView viewsWithIdentifier:tag]) [subview removeFromSuperview];
3283+
NSView *contentView = window.contentView, *titlebarContainer = contentView ? contentView.superview : nil;
3284+
if (titlebarContainer) {
3285+
for (NSView *subview in [titlebarContainer viewsWithIdentifier:tag]) [subview removeFromSuperview];
32863286
}
32873287
}
32883288

32893289
static void
32903290
set_title_bar_background(NSWindow *window, NSColor *backgroundColor) {
3291+
// add an extra view that just renders the background color under the transparent titlebar
32913292
NSView *contentView = window.contentView, *titlebarContainer = contentView ? contentView.superview : nil;
32923293
if (!titlebarContainer) return;
3293-
for (NSView *subview in [contentView viewsWithIdentifier:tag]) [subview removeFromSuperview];
3294+
contentView.identifier = @"kitty-content-view";
3295+
for (NSView *subview in [titlebarContainer viewsWithIdentifier:tag]) [subview removeFromSuperview];
32943296
if (!backgroundColor) return;
3295-
32963297
const CGFloat height = title_bar_and_tool_bar_height(window);
32973298
debug_rendering("titlebar_height used for translucent titlebar view: %f\n", height);
32983299
NSView *bgView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, titlebarContainer.bounds.size.width, height)];
32993300
bgView.translatesAutoresizingMaskIntoConstraints = NO;
33003301
bgView.wantsLayer = YES;
33013302
bgView.layer.backgroundColor = backgroundColor.CGColor;
33023303
bgView.identifier = tag;
3303-
[contentView addSubview:bgView];
3304+
// position the background view above the content view but below the titlebar view
3305+
[titlebarContainer addSubview:bgView positioned:NSWindowAbove relativeTo:contentView];
3306+
// for (NSView *subview in titlebarContainer.subviews) NSLog(@"sv: %@", subview.identifier);
33043307
[NSLayoutConstraint activateConstraints:@[
33053308
// Pin to the top of the content view.
33063309
[bgView.topAnchor constraintEqualToAnchor:titlebarContainer.topAnchor],
@@ -3320,36 +3323,36 @@ GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool us
33203323
if (window->ns.layer_shell.is_active) return;
33213324
const bool is_transparent = _glfwPlatformFramebufferTransparent(window);
33223325
if (!is_transparent) { background_opacity = 1.0; background_blur = 0; }
3323-
NSColor *background = nil;
3326+
NSColor *window_background = [NSColor windowBackgroundColor];
3327+
if (background_opacity < 1.0) {
3328+
// use a clear color (fully transparent) so that the final color is just the color from the surface.
3329+
// prevent blurring of shadows at window corners with desktop background by setting a low alpha background
3330+
window_background = background_blur > 0 ? [NSColor colorWithWhite: 0 alpha: 0.001f] : [NSColor clearColor];
3331+
}
33243332
NSAppearance *appearance = nil;
33253333
bool titlebar_transparent = false;
3334+
NSColor *titlebar_color = nil;
33263335
const NSWindowStyleMask current_style_mask = [window->ns.object styleMask];
33273336
const bool in_fullscreen = ((current_style_mask & NSWindowStyleMaskFullScreen) != 0) || window->ns.in_traditional_fullscreen;
33283337
NSAppearance *light_appearance = is_transparent ? [NSAppearance appearanceNamed:NSAppearanceNameVibrantLight] : [NSAppearance appearanceNamed:NSAppearanceNameAqua];
33293338
NSAppearance *dark_appearance = is_transparent ? [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark] : [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
33303339
if (use_system_color) {
3331-
if (is_transparent) {
3332-
// prevent blurring of shadows at window corners with desktop background by setting a low alpha background
3333-
background = background_blur > 0 ? [NSColor colorWithWhite: 0 alpha: 0.001f] : [NSColor clearColor];
3334-
} else background = [NSColor windowBackgroundColor];
33353340
switch (system_color) {
33363341
case 1:
33373342
appearance = light_appearance; break;
33383343
case 2:
33393344
appearance = dark_appearance; break;
33403345
}
33413346
} else {
3342-
// set a background color and make the title bar transparent so the background color is visible
33433347
double red = ((color >> 16) & 0xFF) / 255.0;
33443348
double green = ((color >> 8) & 0xFF) / 255.0;
33453349
double blue = (color & 0xFF) / 255.0;
33463350
double luma = 0.2126 * red + 0.7152 * green + 0.0722 * blue;
3347-
CGFloat alpha = background_opacity < 1.0 ? background_opacity : 1.0;
3348-
background = [NSColor colorWithSRGBRed:red green:green blue:blue alpha:alpha];
33493351
appearance = luma < 0.5 ? dark_appearance : light_appearance;
3352+
titlebar_color = [NSColor colorWithSRGBRed:red green:green blue:blue alpha:background_opacity];
33503353
titlebar_transparent = true;
33513354
}
3352-
[window->ns.object setBackgroundColor:background];
3355+
[window->ns.object setBackgroundColor:window_background];
33533356
[window->ns.object setAppearance:appearance];
33543357
_glfwPlatformSetWindowBlur(window, background_blur);
33553358
bool has_shadow = false;
@@ -3395,12 +3398,13 @@ GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool us
33953398
debug(
33963399
"Window Chrome state:\n\tbackground: %s\n\tappearance: %s color_space: %s\n\t"
33973400
"blur: %d has_shadow: %d resizable: %d decorations: %s (%d)\n\t"
3398-
"titlebar_transparent: %d title_visibility: %d hidden: %d buttons_hidden: %d"
3401+
"titlebar_transparent: %d titlebar_color: %s title_visibility: %d hidden: %d buttons_hidden: %d"
33993402
"\n",
3400-
background ? [background.description UTF8String] : "<nil>",
3403+
window_background ? [window_background.description UTF8String] : "<nil>",
34013404
appearance ? [appearance.name UTF8String] : "<nil>",
34023405
cs ? (cs.localizedName ? [cs.localizedName UTF8String] : [cs.description UTF8String]) : "<nil>",
34033406
background_blur, has_shadow, resizable, decorations_desc, window->decorated, titlebar_transparent,
3407+
titlebar_color ? [titlebar_color.description UTF8String] : "<nil>",
34043408
show_text_in_titlebar, window->ns.titlebar_hidden, hide_titlebar_buttons
34053409
);
34063410
[window->ns.object setColorSpace:cs];
@@ -3416,8 +3420,8 @@ GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool us
34163420
} else {
34173421
[window->ns.object setStyleMask:window->ns.pre_full_screen_style_mask | fsmask];
34183422
}
3419-
if (background_opacity < 1.0 && !window->ns.titlebar_hidden && window->decorated) {
3420-
set_title_bar_background(window->ns.object, [background colorUsingColorSpace:(cs ? cs : [NSColorSpace deviceRGBColorSpace])]);
3423+
if (background_opacity < 1.0 && !window->ns.titlebar_hidden && window->decorated && titlebar_color != nil) {
3424+
set_title_bar_background(window->ns.object, titlebar_color);
34213425
} else clear_title_bar_background_views(window->ns.object);
34223426
// HACK: Changing the style mask can cause the first responder to be cleared
34233427
[window->ns.object makeFirstResponder:window->ns.view];

0 commit comments

Comments
 (0)