Skip to content

Commit

Permalink
macOS: Implement background blurring
Browse files Browse the repository at this point in the history
Uses a private API that allows us to control the amount of blurring.
While using a private API is obviously not ideal, it is used by both
iTerm.app and Apple's own Terminal.app, so hopefully it should stick
around. Fixes #6135
  • Loading branch information
kovidgoyal committed Jun 27, 2023
1 parent 326b81a commit 7a1bdb4
Show file tree
Hide file tree
Showing 15 changed files with 89 additions and 1 deletion.
1 change: 1 addition & 0 deletions glfw/cocoa_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ typedef struct _GLFWwindowNS
int width, height;
int fbWidth, fbHeight;
float xscale, yscale;
int blur_radius;

// The total sum of the distances the cursor has been warped
// since the last cursor motion event was processed
Expand Down
15 changes: 15 additions & 0 deletions glfw/cocoa_window.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include <string.h>


GLFWAPI int glfwCocoaSetBackgroundBlur(GLFWwindow *w, int radius);

static const char*
polymorphic_string_as_utf8(id string) {
if (string == nil) return "(nil)";
Expand Down Expand Up @@ -1835,6 +1837,7 @@ static bool createNativeWindow(_GLFWwindow* window,

_glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
_glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
if (wndconfig->ns.blur_radius > 0) glfwCocoaSetBackgroundBlur((GLFWwindow*)window, wndconfig->ns.blur_radius);

return true;
}
Expand Down Expand Up @@ -2969,6 +2972,18 @@ GLFWAPI void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun
requestRenderFrame((_GLFWwindow*)w, callback);
}

GLFWAPI int glfwCocoaSetBackgroundBlur(GLFWwindow *w, int radius) {
_GLFWwindow* window = (_GLFWwindow*)w;
int orig = window->ns.blur_radius;
if (radius > -1 && radius != window->ns.blur_radius) {
extern OSStatus CGSSetWindowBackgroundBlurRadius(void* connection, NSInteger windowNumber, int radius);
extern void* CGSDefaultConnectionForThread(void);
CGSSetWindowBackgroundBlurRadius(CGSDefaultConnectionForThread(), [window->ns.object windowNumber], radius);
window->ns.blur_radius = radius;
}
return orig;
}

GLFWAPI int glfwGetCurrentSystemColorTheme(void) {
int theme_type = 0;
NSAppearance *changedAppearance = NSApp.effectiveAppearance;
Expand Down
1 change: 1 addition & 0 deletions glfw/glfw.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ def generate_wrappers(glfw_header: str) -> None:
GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback)
uint32_t glfwGetCocoaKeyEquivalent(uint32_t glfw_key, int glfw_mods, int* cocoa_mods)
void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback)
int glfwCocoaSetBackgroundBlur(GLFWwindow *w, int blur_radius)
void* glfwGetX11Display(void)
int32_t glfwGetX11Window(GLFWwindow* window)
void glfwSetPrimarySelectionString(GLFWwindow* window, const char* string)
Expand Down
4 changes: 4 additions & 0 deletions glfw/glfw3.h
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,10 @@ typedef enum {
SRGB_COLORSPACE = 1,
DISPLAY_P3_COLORSPACE = 2,
} GlfwCocoaColorSpaces;
/*! @brief macOS specific
* [window hint](@ref GLFW_COCOA_BLUR_RADIUS_hint).
*/
#define GLFW_COCOA_BLUR_RADIUS 0x00023005

/*! @brief X11 specific
* [window hint](@ref GLFW_X11_CLASS_NAME_hint).
Expand Down
1 change: 1 addition & 0 deletions glfw/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ struct _GLFWwndconfig
struct {
bool retina;
int color_space;
int blur_radius;
char frameName[256];
} ns;
struct {
Expand Down
5 changes: 5 additions & 0 deletions glfw/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ void glfwDefaultWindowHints(void)
_glfw.hints.window.ns.retina = true;
// use the default colorspace assigned by the system
_glfw.hints.window.ns.color_space = 0;
// no blur
_glfw.hints.window.ns.blur_radius = 0;
}

GLFWAPI void glfwWindowHint(int hint, int value)
Expand Down Expand Up @@ -417,6 +419,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_COCOA_COLOR_SPACE:
_glfw.hints.window.ns.color_space = value;
return;
case GLFW_COCOA_BLUR_RADIUS:
_glfw.hints.window.ns.blur_radius = value;
return;
case GLFW_COCOA_GRAPHICS_SWITCHING:
_glfw.hints.context.nsgl.offline = value ? true : false;
return;
Expand Down
3 changes: 3 additions & 0 deletions kitty/glfw-wrapper.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions kitty/glfw-wrapper.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions kitty/glfw.c
Original file line number Diff line number Diff line change
Expand Up @@ -902,6 +902,11 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {

#ifdef __APPLE__
glfwWindowHint(GLFW_COCOA_COLOR_SPACE, OPT(macos_colorspace));
if (OPT(background_blur) > 0 && OPT(background_opacity) < 1.f) {
glfwWindowHint(GLFW_COCOA_BLUR_RADIUS, MIN(OPT(background_blur), 128));
} else {
glfwWindowHint(GLFW_COCOA_BLUR_RADIUS, 0);
}
#else
glfwWindowHintString(GLFW_X11_INSTANCE_NAME, wm_class_name);
glfwWindowHintString(GLFW_X11_CLASS_NAME, wm_class_class);
Expand Down Expand Up @@ -1081,6 +1086,17 @@ os_window_update_size_increments(OSWindow *window) {
}
}

void
update_background_blur(OSWindow *os_window) {
#ifdef __APPLE__
int new_blur_radius = 0;
if (os_window->background_opacity < 1.f && OPT(background_blur) > -1) new_blur_radius = OPT(background_blur);
glfwCocoaSetBackgroundBlur(os_window->handle, new_blur_radius);
#else
(void)os_window;
#endif
}

#ifdef __APPLE__
static bool
window_in_same_cocoa_workspace(void *w, size_t *source_workspaces, size_t source_workspace_count) {
Expand Down
11 changes: 11 additions & 0 deletions kitty/options/definition.py
Original file line number Diff line number Diff line change
Expand Up @@ -1371,6 +1371,17 @@
'''
)

opt('background_blur', '0', option_type='int', ctype='int',
long_text='''
Set to a positive value to enable background blur (blurring of the visuals
behind a transparent window) on platforms that support it. Only takes effect
when :opt:`background_opacity` is less than one. On macOS, this will also
control the :italic:`blur radius` (amount of blurring). Setting it to too high
a value will cause severe performance issues and/or rendering artifacts.
Usually, values up to 64 work well. Note that this might cause performance issues,
depending on how the platform implements it, so use with care.
''')

opt('background_image', 'none',
option_type='config_or_absolute_path', ctype='!background_image',
long_text='Path to a background image. Must be in PNG format.'
Expand Down
3 changes: 3 additions & 0 deletions kitty/options/parse.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions kitty/options/to-c-generated.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion kitty/options/types.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions kitty/state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,7 @@ PYWRAP0(apply_options_update) {
get_platform_dependent_config_values(os_window->handle);
os_window->background_opacity = OPT(background_opacity);
os_window->is_damaged = true;
update_background_blur(os_window);
for (size_t t = 0; t < os_window->num_tabs; t++) {
Tab *tab = os_window->tabs + t;
for (size_t w = 0; w < tab->num_windows; w++) {
Expand Down
2 changes: 2 additions & 0 deletions kitty/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ typedef struct {
float val; AdjustmentUnit unit;
} underline_position, underline_thickness, strikethrough_position, strikethrough_thickness, cell_width, cell_height, baseline;
bool show_hyperlink_targets;
int background_blur;
} Options;

typedef struct WindowLogoRenderData {
Expand Down Expand Up @@ -365,3 +366,4 @@ void update_ime_position(Window* w, Screen *screen);
bool update_ime_position_for_window(id_type window_id, bool force, int update_focus);
void set_ignore_os_keyboard_processing(bool enabled);
void update_menu_bar_title(PyObject *title UNUSED);
void update_background_blur(OSWindow *);

0 comments on commit 7a1bdb4

Please sign in to comment.