From 630101204b3a9d7c13e1df069991f45181235e5c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 22 Jul 2023 11:20:37 +0530 Subject: [PATCH] macOS: Disable OS window shadows for transparent windows as they cause rendering artifacts due to Cocoa bugs Fixes #6439 --- docs/changelog.rst | 2 ++ glfw/cocoa_window.m | 3 +++ kitty/cocoa_window.m | 15 --------------- kitty/glfw.c | 18 ------------------ kitty/state.h | 2 +- 5 files changed, 6 insertions(+), 34 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 636dd938d..d8b3353db 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -40,6 +40,8 @@ Detailed list of changes - macOS: Fix a performance regression on M1 machines using outdated macOS versions (:iss:`6479`) +- macOS: Disable OS window shadows for transparent windows as they cause rendering artifacts due to Cocoa bugs (:iss:`6439`) + 0.29.1 [2023-07-17] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 890bad574..cfc3377c6 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -3029,6 +3029,9 @@ GLFWAPI void glfwCocoaSetWindowChrome(GLFWwindow *w, unsigned int color, bool us has_shadow = true; break; } + // shadow causes burn-in/ghosting because cocoa doesnt invalidate it on OS window resize/minimize/restore. + // https://github.com/kovidgoyal/kitty/issues/6439 + if (is_transparent) has_shadow = false; bool hide_titlebar_buttons = !in_fullscreen && window->ns.titlebar_hidden; [window->ns.object setTitlebarAppearsTransparent:titlebar_transparent]; [window->ns.object setHasShadow:has_shadow]; diff --git a/kitty/cocoa_window.m b/kitty/cocoa_window.m index 1d3297970..be4d37b18 100644 --- a/kitty/cocoa_window.m +++ b/kitty/cocoa_window.m @@ -737,21 +737,6 @@ cocoa_focus_window(void *w) { [window makeKeyWindow]; } -bool -cocoa_set_shadow(void *w, bool has_shadow) { - NSWindow *window = (NSWindow*)w; - bool current = window.hasShadow; - [window setHasShadow:has_shadow]; - if (has_shadow) { // invalidate the shadow to clear the ghosting - [window invalidateShadow]; - // invalidateShadow does not work with layer backed views, see http://www.openradar.me/34184270 - // so do the frame resize dance to force AppKit to invalidate the shadow even with the layer - [window setFrame:NSMakeRect(NSMinX(window.frame), NSMinY(window.frame), NSWidth(window.frame)+1, NSHeight(window.frame)) display:NO animate:NO]; - [window setFrame:NSMakeRect(NSMinX(window.frame), NSMinY(window.frame), NSWidth(window.frame)-1, NSHeight(window.frame)) display:NO animate:NO]; - } - return current; -} - long cocoa_window_number(void *w) { NSWindow *window = (NSWindow*)w; diff --git a/kitty/glfw.c b/kitty/glfw.c index 97b16f3ff..db73487dd 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -320,24 +320,6 @@ change_live_resize_state(OSWindow *w, bool in_progress) { w->live_resize.num_of_resize_events = 0; apply_swap_interval(in_progress ? 0 : -1); #ifdef __APPLE__ - extern bool cocoa_set_shadow(void*, bool); - if (w->is_semi_transparent && w->handle) { - // shadow with transparency during resize causes burn-in of window contents - // aka ghosting of the text after resize is completed. So avoid that by turning - // the shadow on and off. - if (in_progress) { - bool had_shadow = cocoa_set_shadow(glfwGetCocoaWindow(w->handle), false); - w->has_cocoa_shadow = had_shadow; - } else { - if (w->has_cocoa_shadow) { - // turning on the shadow will cause a resize event which will be delivered before cocoa_set_shadow returns - w->ignore_resize_events = true; - cocoa_set_shadow(glfwGetCocoaWindow(w->handle), true); - w->ignore_resize_events = false; - w->has_cocoa_shadow = false; - } - } - } cocoa_out_of_sequence_render(w); #endif } diff --git a/kitty/state.h b/kitty/state.h index 8d9ff007f..507d3fa76 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -229,7 +229,7 @@ typedef struct { bool viewport_size_dirty, viewport_updated_at_least_once; monotonic_t viewport_resized_at; LiveResizeInfo live_resize; - bool has_pending_resizes, is_semi_transparent, shown_once, is_damaged, has_cocoa_shadow, ignore_resize_events; + bool has_pending_resizes, is_semi_transparent, shown_once, is_damaged, ignore_resize_events; unsigned int clear_count; WindowChromeState last_window_chrome; float background_opacity;