From 64b2f514f846027f9c730ddf9bc8ae0ab2cf6fc7 Mon Sep 17 00:00:00 2001 From: yorhodes Date: Sun, 2 Jan 2022 01:58:01 -0500 Subject: [PATCH] Add window blur --- makefile | 2 +- src/message.c | 35 ++++++++++++ src/osax/payload.m | 123 +++++++++++++++++++++---------------------- src/sa.h | 1 + src/sa.m | 7 +++ src/window.c | 3 ++ src/window.h | 1 + src/window_manager.c | 25 +++++++++ src/window_manager.h | 9 ++++ 9 files changed, 141 insertions(+), 65 deletions(-) diff --git a/makefile b/makefile index d955f3ba..1ec7d93b 100644 --- a/makefile +++ b/makefile @@ -21,7 +21,7 @@ install: clean-build $(BINS) $(OSAX_SRC): $(OSAX_PATH)/loader.m $(OSAX_PATH)/payload.m xcrun clang $(OSAX_PATH)/loader.m -shared -O2 -mmacosx-version-min=10.13 -arch x86_64 -o $(OSAX_PATH)/loader -framework Foundation - xcrun clang $(OSAX_PATH)/payload.m -shared -fPIC -O2 -mmacosx-version-min=10.13 -arch x86_64 -arch arm64e -o $(OSAX_PATH)/payload -framework Foundation -framework Carbon + xcrun clang $(OSAX_PATH)/payload.m -shared -fPIC -O2 -mmacosx-version-min=10.13 -arch x86_64 -arch arm64e -o $(OSAX_PATH)/payload -framework Foundation -framework Carbon -F/System/Library/PrivateFrameworks -framework SkyLight xcrun clang $(OSAX_PATH)/mach_loader.m -O2 -mmacosx-version-min=10.13 -arch x86_64 -arch arm64e -o $(OSAX_PATH)/mach_loader -framework Cocoa xxd -i -a $(OSAX_PATH)/loader $(OSAX_PATH)/loader_bin.c xxd -i -a $(OSAX_PATH)/payload $(OSAX_PATH)/payload_bin.c diff --git a/src/message.c b/src/message.c index dc5ebfe6..4a5407a8 100644 --- a/src/message.c +++ b/src/message.c @@ -28,6 +28,8 @@ extern bool g_verbose; #define COMMAND_CONFIG_TOPMOST "window_topmost" #define COMMAND_CONFIG_OPACITY "window_opacity" #define COMMAND_CONFIG_OPACITY_DURATION "window_opacity_duration" +#define COMMAND_CONFIG_BLUR "window_blur" +#define COMMAND_CONFIG_BLUR_RADIUS "window_blur_radius" #define COMMAND_CONFIG_BORDER "window_border" #define COMMAND_CONFIG_BORDER_WIDTH "window_border_width" #define COMMAND_CONFIG_BORDER_ACTIVE_COLOR "active_window_border_color" @@ -128,6 +130,7 @@ extern bool g_verbose; #define COMMAND_WINDOW_CLOSE "--close" #define COMMAND_WINDOW_LAYER "--layer" #define COMMAND_WINDOW_OPACITY "--opacity" +#define COMMAND_WINDOW_BLUR "--blur" #define COMMAND_WINDOW_TOGGLE "--toggle" #define COMMAND_WINDOW_DISPLAY "--display" #define COMMAND_WINDOW_SPACE "--space" @@ -174,6 +177,7 @@ extern bool g_verbose; #define ARGUMENT_RULE_KEY_DISPLAY "display" #define ARGUMENT_RULE_KEY_SPACE "space" #define ARGUMENT_RULE_KEY_ALPHA "opacity" +#define ARGUMENT_RULE_KEY_BLUR "blur" #define ARGUMENT_RULE_KEY_MANAGE "manage" #define ARGUMENT_RULE_KEY_STICKY "sticky" #define ARGUMENT_RULE_KEY_MFF "mouse_follows_focus" @@ -1050,6 +1054,26 @@ static void handle_domain_config(FILE *rsp, struct token domain, char *message) } else { daemon_fail(rsp, "unknown value '%.*s' given to command '%.*s' for domain '%.*s'\n", value.length, value.text, command.length, command.text, domain.length, domain.text); } + } else if (token_equals(command, COMMAND_CONFIG_BLUR)) { + struct token value = get_token(&message); + if (!token_is_valid(value)) { + fprintf(rsp, "%s\n", bool_str[g_window_manager.enable_window_blur]); + } else if (token_equals(value, ARGUMENT_COMMON_VAL_OFF)) { + window_manager_set_window_blur_enabled(&g_window_manager, false); + } else if (token_equals(value, ARGUMENT_COMMON_VAL_ON)) { + window_manager_set_window_blur_enabled(&g_window_manager, true); + } else { + daemon_fail(rsp, "unknown value '%.*s' given to command '%.*s' for domain '%.*s'\n", value.length, value.text, command.length, command.text, domain.length, domain.text); + } + } else if (token_equals(command, COMMAND_CONFIG_BLUR_RADIUS)) { + struct token_value value = token_to_value(get_token(&message), false); + if (value.type == TOKEN_TYPE_INVALID) { + fprintf(rsp, "%d\n", g_window_manager.window_blur_radius); + } else if (value.type == TOKEN_TYPE_INT && value.int_value) { + g_window_manager.window_blur_radius = value.int_value; + } else { + daemon_fail(rsp, "unknown value '%.*s' given to command '%.*s' for domain '%.*s'\n", value.token.length, value.token.text, command.length, command.text, domain.length, domain.text); + } } else if (token_equals(command, COMMAND_CONFIG_OPACITY_DURATION)) { struct token_value value = token_to_value(get_token(&message), false); if (value.type == TOKEN_TYPE_INVALID) { @@ -1904,6 +1928,17 @@ static void handle_domain_window(FILE *rsp, struct token domain, char *message) } else { daemon_fail(rsp, "unknown value '%.*s' given to command '%.*s' for domain '%.*s'\n", value.token.length, value.token.text, command.length, command.text, domain.length, domain.text); } + } else if (token_equals(command, COMMAND_WINDOW_BLUR)) { + struct token_value value = token_to_value(get_token(&message), false); + if (value.type == TOKEN_TYPE_U32 && value.u32_value) { + if (window_manager_set_blur_radius(&g_window_manager, acting_window, value.u32_value)) { + acting_window->blur_radius = value.u32_value; + } else { + daemon_fail(rsp, "could not change blur radius of window with id '%d' due to an error with the scripting-addition.\n", acting_window->id); + } + } else { + daemon_fail(rsp, "unknown value '%.*s' given to command '%.*s' for domain '%.*s'\n", value.token.length, value.token.text, command.length, command.text, domain.length, domain.text); + } } else if (token_equals(command, COMMAND_WINDOW_TOGGLE)) { struct token value = get_token(&message); if (token_equals(value, ARGUMENT_WINDOW_TOGGLE_FLOAT)) { diff --git a/src/osax/payload.m b/src/osax/payload.m index 3dcd3436..91bc8849 100644 --- a/src/osax/payload.m +++ b/src/osax/payload.m @@ -59,6 +59,11 @@ extern void CGSShowSpaces(int cid, CFArrayRef spaces); extern void CGSHideSpaces(int cid, CFArrayRef spaces); +// extern CGError SLSSetSurfaceBackgroundBlur(int cid, uint32_t wid); +extern CGError SLSSetWindowBackgroundBlurRadius(int cid, uint32_t wid, uint32_t radius); +// extern CGError SLSSetWindowBackgroundBlurRadiusStyle(int cid, uint32_t wid, uint32_t radius); +// extern CGError SLSSetWindowBackgroundBlurRadiusWithOpacityHint(int cid, uint32_t wid, uint32_t radius); + static int _connection; static id dock_spaces; static id dp_desktop_picture_manager; @@ -332,10 +337,10 @@ static void init_instances() unsigned int length; } Token; -static bool token_equals(Token token, const char *match) +static bool token_sub_equals(Token token, const char *match, unsigned int length) { const char *at = match; - for (int i = 0; i < token.length; ++i, ++at) { + for (int i = 0; i < length; ++i, ++at) { if ((*at == 0) || (token.text[i] != *at)) { return false; } @@ -343,6 +348,11 @@ static bool token_equals(Token token, const char *match) return *at == 0; } +static bool token_equals(Token token, const char *match) +{ + return token_sub_equals(token, match, token.length); +} + static uint64_t token_to_uint64t(Token token) { uint64_t result = 0; @@ -583,12 +593,8 @@ static void do_space_change(const char *message) } } -static void do_window_scale(const char *message) +static void do_window_scale(uint32_t wid, const char *message) { - Token wid_token = get_token(&message); - uint32_t wid = token_to_uint32t(wid_token); - if (!wid) return; - CGRect frame = {}; CGSGetWindowBounds(_connection, wid, &frame); CGAffineTransform original_transform = CGAffineTransformMakeTranslation(-frame.origin.x, -frame.origin.y); @@ -623,12 +629,8 @@ static void do_window_scale(const char *message) } } -static void do_window_move(const char *message) +static void do_window_move(uint32_t wid, const char *message) { - Token wid_token = get_token(&message); - uint32_t wid = token_to_uint32t(wid_token); - if (!wid) return; - Token x_token = get_token(&message); int x = token_to_int(x_token); @@ -643,23 +645,22 @@ static void do_window_move(const char *message) [window_list release]; } -static void do_window_alpha(const char *message) +static void do_window_alpha(uint32_t wid, const char *message) { - Token wid_token = get_token(&message); - uint32_t wid = token_to_uint32t(wid_token); - if (!wid) return; - Token alpha_token = get_token(&message); float alpha = token_to_float(alpha_token); CGSSetWindowAlpha(_connection, wid, alpha); } -static void do_window_alpha_fade(const char *message) +static void do_window_blur(uint32_t wid, const char *message) { - Token wid_token = get_token(&message); - uint32_t wid = token_to_uint32t(wid_token); - if (!wid) return; + Token radius_token = get_token(&message); + uint32_t radius = token_to_uint32t(radius_token); + SLSSetWindowBackgroundBlurRadius(_connection, wid, radius); +} +static void do_window_alpha_fade(uint32_t wid, const char *message) +{ Token alpha_token = get_token(&message); float alpha = token_to_float(alpha_token); Token duration_token = get_token(&message); @@ -667,23 +668,15 @@ static void do_window_alpha_fade(const char *message) CGSSetWindowListAlpha(_connection, &wid, 1, alpha, duration); } -static void do_window_level(const char *message) +static void do_window_level(uint32_t wid, const char *message) { - Token wid_token = get_token(&message); - uint32_t wid = token_to_uint32t(wid_token); - if (!wid) return; - Token key_token = get_token(&message); int key = token_to_int(key_token); CGSSetWindowLevel(_connection, wid, CGWindowLevelForKey(key)); } -static void do_window_sticky(const char *message) +static void do_window_sticky(uint32_t wid, const char *message) { - Token wid_token = get_token(&message); - uint32_t wid = token_to_uint32t(wid_token); - if (!wid) return; - Token value_token = get_token(&message); int value = token_to_int(value_token); int tags[2] = { kCGSOnAllWorkspacesTagBit, 0 }; @@ -695,28 +688,21 @@ static void do_window_sticky(const char *message) } typedef void (*focus_window_call)(ProcessSerialNumber psn, uint32_t wid); -static void do_window_focus(const char *message) +static void do_window_focus(uint32_t wid, const char *message) { if (set_front_window_fp == 0) return; int window_connection; ProcessSerialNumber window_psn; - Token wid_token = get_token(&message); - uint32_t window_id = token_to_uint32t(wid_token); - - CGSGetWindowOwner(_connection, window_id, &window_connection); + CGSGetWindowOwner(_connection, wid, &window_connection); CGSGetConnectionPSN(window_connection, &window_psn); - ((focus_window_call) set_front_window_fp)(window_psn, window_id); + ((focus_window_call) set_front_window_fp)(window_psn, wid); } -static void do_window_shadow(const char *message) +static void do_window_shadow(uint32_t wid, const char *message) { - Token wid_token = get_token(&message); - uint32_t wid = token_to_uint32t(wid_token); - if (!wid) return; - Token value_token = get_token(&message); int value = token_to_int(value_token); int tags[2] = { kCGSNoShadowTagBit, 0}; @@ -727,7 +713,7 @@ static void do_window_shadow(const char *message) } } -static void do_window_group_add(const char *message) +static void do_window_group_add(uint32_t wid, const char *message) { Token parent_token = get_token(&message); uint32_t parent = token_to_uint32t(parent_token); @@ -741,7 +727,7 @@ static void do_window_group_add(const char *message) CGSAddWindowToWindowOrderingGroup(_connection, parent, child, 1); } -static void do_window_group_remove(const char *message) +static void do_window_group_remove(uint32_t wid, const char *message) { Token parent_token = get_token(&message); uint32_t parent = token_to_uint32t(parent_token); @@ -792,26 +778,35 @@ static void handle_message(int sockfd, const char *message) do_space_destroy(message); } else if (token_equals(token, "space_move")) { do_space_move(message); - } else if (token_equals(token, "window_scale")) { - do_window_scale(message); - } else if (token_equals(token, "window_move")) { - do_window_move(message); - } else if (token_equals(token, "window_alpha")) { - do_window_alpha(message); - } else if (token_equals(token, "window_alpha_fade")) { - do_window_alpha_fade(message); - } else if (token_equals(token, "window_level")) { - do_window_level(message); - } else if (token_equals(token, "window_sticky")) { - do_window_sticky(message); - } else if (token_equals(token, "window_focus")) { - do_window_focus(message); - } else if (token_equals(token, "window_shadow")) { - do_window_shadow(message); - } else if (token_equals(token, "window_group_add")) { - do_window_group_add(message); - } else if (token_equals(token, "window_group_remove")) { - do_window_group_remove(message); + } else if (token_sub_equals(token, "window_", 7)) { + Token wid_token = get_token(&message); + uint32_t wid = token_to_uint32t(wid_token); + if (!wid) return; + + Token window_command = get_token(&message); + if (token_equals(window_command, "scale")) { + do_window_scale(wid, message); + } else if (token_equals(window_command, "move")) { + do_window_move(wid, message); + } else if (token_equals(window_command, "alpha")) { + do_window_alpha(wid, message); + } else if (token_equals(window_command, "alpha_fade")) { + do_window_alpha_fade(wid, message); + } else if (token_equals(window_command, "blur")) { + do_window_blur(wid, message); + } else if (token_equals(window_command, "level")) { + do_window_level(wid, message); + } else if (token_equals(window_command, "sticky")) { + do_window_sticky(wid, message); + } else if (token_equals(window_command, "focus")) { + do_window_focus(wid, message); + } else if (token_equals(window_command, "shadow")) { + do_window_shadow(wid, message); + } else if (token_equals(window_command, "group_add")) { + do_window_group_add(wid, message); + } else if (token_equals(window_command, "group_remove")) { + do_window_group_remove(wid, message); + } } } diff --git a/src/sa.h b/src/sa.h index faeaccb7..ac7a0480 100644 --- a/src/sa.h +++ b/src/sa.h @@ -20,6 +20,7 @@ bool scripting_addition_add_to_window_group(uint32_t child_wid, uint32_t parent_ bool scripting_addition_remove_from_window_group(uint32_t child_wid, uint32_t parent_wid); bool scripting_addition_move_window(uint32_t wid, int x, int y); bool scripting_addition_set_opacity(uint32_t wid, float opacity, float duration); +bool scripting_addition_set_blur(uint32_t wid, uint32_t radius); bool scripting_addition_set_layer(uint32_t wid, int layer); bool scripting_addition_set_sticky(uint32_t wid, bool sticky); bool scripting_addition_set_shadow(uint32_t wid, bool shadow); diff --git a/src/sa.m b/src/sa.m index 3bb0afe6..cb588958 100644 --- a/src/sa.m +++ b/src/sa.m @@ -610,6 +610,13 @@ bool scripting_addition_set_opacity(uint32_t wid, float opacity, float duration) return scripting_addition_run_command(message); } +bool scripting_addition_set_blur(uint32_t wid, uint32_t radius) +{ + char message[MAXLEN]; + snprintf(message, sizeof(message), "window_blur %d %d", wid, radius); + return scripting_addition_run_command(message); +} + bool scripting_addition_set_layer(uint32_t wid, int layer) { char message[MAXLEN]; diff --git a/src/window.c b/src/window.c index e905dbc4..98298218 100644 --- a/src/window.c +++ b/src/window.c @@ -107,6 +107,7 @@ void window_serialize(FILE *rsp, struct window *window) bool visible = !is_minimized && !window->application->is_hidden && (window->is_sticky || space_is_visible(sid)); bool border = window->border.id ? 1 : 0; float opacity = window_opacity(window); + uint32_t blur_radius = window->blur_radius; bool grabbed = window == g_mouse_state.window; CFStringRef cfrole = window_role(window); @@ -143,6 +144,7 @@ void window_serialize(FILE *rsp, struct window *window) "\t\"space\":%d,\n" "\t\"level\":%d,\n" "\t\"opacity\":%.4f,\n" + "\t\"blur-radius\":%d,\n" "\t\"split-type\":\"%s\",\n" "\t\"stack-index\":%d,\n" "\t\"can-move\":%s,\n" @@ -172,6 +174,7 @@ void window_serialize(FILE *rsp, struct window *window) space, window_level(window), opacity, + blur_radius, split, stack_index, json_bool(window_can_move(window)), diff --git a/src/window.h b/src/window.h index 818f76b8..9f47fb23 100644 --- a/src/window.h +++ b/src/window.h @@ -43,6 +43,7 @@ struct window bool is_floating; bool is_sticky; float opacity; + uint32_t blur_radius; bool rule_manage; bool rule_fullscreen; bool rule_mff; diff --git a/src/window_manager.c b/src/window_manager.c index 3c71e7d3..c69c065f 100644 --- a/src/window_manager.c +++ b/src/window_manager.c @@ -256,6 +256,22 @@ void window_manager_set_window_opacity_enabled(struct window_manager *wm, bool e } } +void window_manager_set_window_blur_enabled(struct window_manager *wm, bool enabled) +{ + wm->enable_window_blur = enabled; + for (int window_index = 0; window_index < wm->window.capacity; ++window_index) { + struct bucket *bucket = wm->window.buckets[window_index]; + while (bucket) { + if (bucket->value) { + struct window *window = bucket->value; + window_manager_set_blur_radius(wm, window, enabled ? window->blur_radius : 0); + } + + bucket = bucket->next; + } + } +} + void window_manager_center_mouse(struct window_manager *wm, struct window *window) { if (window->rule_mff) { @@ -470,6 +486,13 @@ bool window_manager_set_opacity(struct window_manager *wm, struct window *window return scripting_addition_set_opacity(window->id, opacity, wm->window_opacity_duration); } +bool window_manager_set_blur_radius(struct window_manager *wm, struct window *window, uint32_t radius) +{ + if ((!window->rule_manage) && (!window_is_standard(window)) && (!window_is_dialog(window))) return false; + if (window->blur_radius == radius) return true; + return scripting_addition_set_blur(window->id, radius); +} + void window_manager_set_window_opacity(struct window_manager *wm, struct window *window, float opacity) { if (!wm->enable_window_opacity) return; @@ -1628,9 +1651,11 @@ void window_manager_init(struct window_manager *wm) wm->enable_mff = false; wm->enable_window_border = false; wm->enable_window_opacity = false; + wm->enable_window_blur = false; wm->enable_window_topmost = false; wm->active_window_opacity = 1.0f; wm->normal_window_opacity = 1.0f; + wm->window_blur_radius = 0; wm->window_opacity_duration = 0.0f; wm->insert_feedback_windows = NULL; wm->insert_feedback_color = rgba_color_from_hex(0xffd75f5f); diff --git a/src/window_manager.h b/src/window_manager.h index 653743a5..30cd23f4 100644 --- a/src/window_manager.h +++ b/src/window_manager.h @@ -82,11 +82,15 @@ struct window_manager enum purify_mode purify_mode; enum window_origin_mode window_origin_mode; bool enable_window_border; + bool enable_window_blur; bool enable_window_opacity; bool enable_window_topmost; float active_window_opacity; float normal_window_opacity; float window_opacity_duration; + uint32_t window_blur_radius; + // uint32_t active_window_blur_radius; + // uint32_t normal_window_blur_radius; uint32_t *insert_feedback_windows; int border_width; struct rgba_color insert_feedback_color; @@ -153,6 +157,11 @@ void window_manager_set_normal_window_opacity(struct window_manager *wm, float o void window_manager_set_window_opacity_enabled(struct window_manager *wm, bool enabled); bool window_manager_set_opacity(struct window_manager *wm, struct window *window, float opacity); void window_manager_set_window_opacity(struct window_manager *wm, struct window *window, float opacity); +// void window_manager_set_active_window_blur(struct window_manager *wm, float blur); +// void window_manager_set_normal_window_blur(struct window_manager *wm, float blur); +bool window_manager_set_blur_radius(struct window_manager *wm, struct window *window, uint32_t radius); +void window_manager_set_window_blur_enabled(struct window_manager *wm, bool enabled); +// bool window_manager_set_blur(struct window_manager *wm, struct window *window, float blur); void window_manager_set_window_border_enabled(struct window_manager *wm, bool enabled); void window_manager_set_window_border_width(struct window_manager *wm, int width); void window_manager_set_active_window_border_color(struct window_manager *wm, uint32_t color);