From 55f82231a6457131d28bb796a9ae35c8a72a602e Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 09:29:12 +0800 Subject: [PATCH 01/30] feat: scenefx blur shadow corner radius and opacity --- meson.build | 3 + src/client/client.h | 4 +- src/config/parse_config.h | 117 +++++++ src/config/preset_config.h | 32 ++ src/maomao.c | 662 ++++++++++++++++++++++++------------- 5 files changed, 588 insertions(+), 230 deletions(-) diff --git a/meson.build b/meson.build index 8e88c9f..e2d181b 100644 --- a/meson.build +++ b/meson.build @@ -38,6 +38,8 @@ xkbcommon_dep = dependency('xkbcommon') libinput_dep = dependency('libinput') libwayland_client_dep = dependency('wayland-client') pcre2_dep = dependency('libpcre2-8') +libscenefx_dep = dependency('scenefx-0.3') + # 获取 Git Commit Hash 和最新的 tag git = find_program('git', required : false) @@ -75,6 +77,7 @@ executable('maomao', libm, xcb, xlibs, + libscenefx_dep, wayland_server_dep, wlroots_dep, xkbcommon_dep, diff --git a/src/client/client.h b/src/client/client.h index 0c9a059..5b184ba 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -308,9 +308,7 @@ static inline void client_send_close(Client *c) { static inline void client_set_border_color(Client *c, const float color[static 4]) { - int i; - for (i = 0; i < 4; i++) - wlr_scene_rect_set_color(c->border[i], color); + wlr_scene_rect_set_color(c->border, color); } static inline void client_set_fullscreen(Client *c, int fullscreen) { diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 5860fe9..97644ab 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -60,6 +60,8 @@ typedef struct { int noswallow; int scratchpad_width; int scratchpad_height; + float focused_opacity; + float unfocused_opacity; uint32_t passmod; xkb_keysym_t keysym; KeyBinding globalkeybinding; @@ -151,6 +153,8 @@ typedef struct { int enable_floating_snap; int drag_tile_to_tile; unsigned int swipe_min_threshold; + float focused_opacity; + float unfocused_opacity; float *scroller_proportion_preset; int scroller_proportion_preset_count; @@ -192,6 +196,16 @@ typedef struct { unsigned int accel_profile; double accel_speed; + int blur; + int border_radius; + struct blur_data blur_params; + int shadows; + unsigned int shadows_size; + float shadows_blur; + int shadows_position_x; + int shadows_position_y; + float shadowscolor[4]; + int smartgaps; unsigned int gappih; unsigned int gappiv; @@ -866,6 +880,34 @@ void parse_config_line(Config *config, const char *line) { config->focus_cross_monitor = atoi(value); } else if (strcmp(key, "focus_cross_tag") == 0) { config->focus_cross_tag = atoi(value); + } else if (strcmp(key, "focus_cross_tag") == 0) { + config->focus_cross_tag = atoi(value); + } else if (strcmp(key, "blur") == 0) { + config->blur = atoi(value); + } else if (strcmp(key, "border_radius") == 0) { + config->border_radius = atoi(value); + } else if (strcmp(key, "blur_params_num_passes") == 0) { + config->blur_params.num_passes = atoi(value); + } else if (strcmp(key, "blur_params_radius") == 0) { + config->blur_params.radius = atoi(value); + } else if (strcmp(key, "blur_params_noise") == 0) { + config->blur_params.noise = atof(value); + } else if (strcmp(key, "blur_params_brightness") == 0) { + config->blur_params.brightness = atof(value); + } else if (strcmp(key, "blur_params_contrast") == 0) { + config->blur_params.contrast = atof(value); + } else if (strcmp(key, "blur_params_saturation") == 0) { + config->blur_params.saturation = atof(value); + } else if (strcmp(key, "shadows") == 0) { + config->shadows = atoi(value); + } else if (strcmp(key, "shadows_size") == 0) { + config->shadows_size = atoi(value); + } else if (strcmp(key, "shadows_blur") == 0) { + config->shadows_blur = atof(value); + } else if (strcmp(key, "shadows_position_x") == 0) { + config->shadows_position_x = atoi(value); + } else if (strcmp(key, "shadows_position_y") == 0) { + config->shadows_position_y = atoi(value); } else if (strcmp(key, "single_scratchpad") == 0) { config->single_scratchpad = atoi(value); } else if (strcmp(key, "xwayland_persistence") == 0) { @@ -880,6 +922,10 @@ void parse_config_line(Config *config, const char *line) { config->drag_tile_to_tile = atoi(value); } else if (strcmp(key, "swipe_min_threshold") == 0) { config->swipe_min_threshold = atoi(value); + } else if (strcmp(key, "focused_opacity") == 0) { + config->focused_opacity = atof(value); + } else if (strcmp(key, "unfocused_opacity") == 0) { + config->unfocused_opacity = atof(value); } else if (strcmp(key, "xkb_rules_rules") == 0) { strncpy(xkb_rules_rules, value, sizeof(xkb_rules_rules) - 1); xkb_rules_rules[sizeof(xkb_rules_rules) - 1] = @@ -1100,6 +1146,14 @@ void parse_config_line(Config *config, const char *line) { } else { convert_hex_to_rgba(config->rootcolor, color); } + + } else if (strcmp(key, "shadowscolor") == 0) { + long int color = parse_color(value); + if (color == -1) { + fprintf(stderr, "Error: Invalid shadowscolor format: %s\n", value); + } else { + convert_hex_to_rgba(config->shadowscolor, color); + } } else if (strcmp(key, "bordercolor") == 0) { long int color = parse_color(value); if (color == -1) { @@ -1229,6 +1283,8 @@ void parse_config_line(Config *config, const char *line) { rule->no_force_center = -1; rule->scratchpad_width = 0; rule->scratchpad_height = 0; + rule->focused_opacity = 0; + rule->unfocused_opacity = 0; rule->width = 0; rule->height = 0; rule->animation_type_open = NULL; @@ -2010,6 +2066,23 @@ void override_config(void) { borderpx = CLAMP_INT(config.borderpx, 0, 200); smartgaps = CLAMP_INT(config.smartgaps, 0, 1); + blur = CLAMP_INT(config.blur, 0, 1); + border_radius = CLAMP_INT(config.border_radius, 0, 100); + blur_params.num_passes = CLAMP_INT(config.blur_params.num_passes, 0, 10); + blur_params.radius = CLAMP_INT(config.blur_params.radius, 0, 100); + blur_params.noise = CLAMP_FLOAT(config.blur_params.noise, 0, 1); + blur_params.brightness = CLAMP_FLOAT(config.blur_params.brightness, 0, 1); + blur_params.contrast = CLAMP_FLOAT(config.blur_params.contrast, 0, 1); + blur_params.saturation = CLAMP_FLOAT(config.blur_params.saturation, 0, 1); + shadows = CLAMP_INT(config.shadows, 0, 1); + shadows_size = CLAMP_INT(config.shadows_size, 0, 100); + shadows_blur = CLAMP_INT(config.shadows_blur, 0, 100); + shadows_position_x = CLAMP_INT(config.shadows_position_x, 0, 100); + shadows_position_y = CLAMP_INT(config.shadows_position_y, 0, 100); + focused_opacity = CLAMP_FLOAT(config.focused_opacity, 0.0f, 1.0f); + unfocused_opacity = CLAMP_FLOAT(config.unfocused_opacity, 0.0f, 1.0f); + memcpy(shadowscolor, config.shadowscolor, sizeof(shadowscolor)); + // 复制颜色数组 memcpy(rootcolor, config.rootcolor, sizeof(rootcolor)); memcpy(bordercolor, config.bordercolor, sizeof(bordercolor)); @@ -2120,6 +2193,23 @@ void set_value_default() { config.accel_profile = accel_profile; config.accel_speed = accel_speed; + config.blur = blur; + config.border_radius = border_radius; + config.blur_params.num_passes = blur_params_num_passes; + config.blur_params.radius = blur_params_radius; + config.blur_params.noise = blur_params_noise; + config.blur_params.brightness = blur_params_brightness; + config.blur_params.contrast = blur_params_contrast; + config.blur_params.saturation = blur_params_saturation; + config.shadows = shadows; + config.shadows_size = shadows_size; + config.shadows_blur = shadows_blur; + config.shadows_position_x = shadows_position_x; + config.shadows_position_y = shadows_position_y; + config.focused_opacity = focused_opacity; + config.unfocused_opacity = unfocused_opacity; + memcpy(config.shadowscolor, shadowscolor, sizeof(shadowscolor)); + memcpy(config.animation_curve_move, animation_curve_move, sizeof(animation_curve_move)); memcpy(config.animation_curve_open, animation_curve_open, @@ -2230,6 +2320,30 @@ void parse_config(void) { override_config(); } +void reset_blur_params(void) { + if (blur) { + Monitor *m; + wl_list_for_each(m, &mons, link) { + if (m->blur != NULL) { + wlr_scene_node_destroy(&m->blur->node); + } + m->blur = wlr_scene_optimized_blur_create(&scene->tree, 0, 0); + wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]); + wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); + wlr_scene_set_blur_data(scene, blur_params); + } + } else { + Monitor *m; + wl_list_for_each(m, &mons, link) { + + if (m->blur) { + wlr_scene_node_destroy(&m->blur->node); + m->blur = NULL; + } + } + } +} + void reload_config(const Arg *arg) { Client *c; Monitor *m; @@ -2239,6 +2353,7 @@ void reload_config(const Arg *arg) { init_baked_points(); handlecursoractivity(); reset_keyboard_layout(); + reset_blur_params(); run_exec(); // reset border width when config change @@ -2246,6 +2361,8 @@ void reload_config(const Arg *arg) { if (c && !c->iskilling) { if (c->bw) { c->bw = borderpx; + c->focused_opacity = focused_opacity; + c->unfocused_opacity = unfocused_opacity; } } } diff --git a/src/config/preset_config.h b/src/config/preset_config.h index dab4400..8b0d48e 100644 --- a/src/config/preset_config.h +++ b/src/config/preset_config.h @@ -179,3 +179,35 @@ enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", }; + +float focused_opacity = 1.0; +float unfocused_opacity = 0.8; + +int border_radius = 0; +int border_radius_location_default = CORNER_LOCATION_ALL; +int blur = 0; + +struct blur_data { + int num_passes; + int radius; + float noise; + float brightness; + float contrast; + float saturation; +}; +struct blur_data blur_params; + +int blur_params_num_passes = 1; +int blur_params_radius = 5; +float blur_params_noise = 0.02; +float blur_params_brightness = 0.9; +float blur_params_contrast = 0.9; +float blur_params_saturation = 1.2; + +int shadows = 0; +unsigned int shadows_size = 10; +double shadows_blur = 15; +int shadows_position_x = 0; +int shadows_position_y = 0; +float shadowscolor[] = COLOR(0x000000ff); +; \ No newline at end of file diff --git a/src/maomao.c b/src/maomao.c index 5328260..8223a1d 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -6,6 +6,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include @@ -54,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -121,6 +125,7 @@ enum { XDGShell, LayerShell, X11 }; /* client types */ enum { AxisUp, AxisDown, AxisLeft, AxisRight }; // 滚轮滚动的方向 enum { LyrBg, + LyrBlur, LyrBottom, LyrTile, LyrFloat, @@ -202,6 +207,9 @@ typedef struct { float height_scale; int width; int height; + double percent; + float opacity; + enum corner_location corner_location; bool should_scale; } animationScale; @@ -213,7 +221,8 @@ struct Client { overview_backup_geom, current; /* layout-relative, includes border */ Monitor *mon; struct wlr_scene_tree *scene; - struct wlr_scene_rect *border[4]; /* top, bottom, left, right */ + struct wlr_scene_rect *border; /* top, bottom, left, right */ + struct wlr_scene_shadow *shadow; struct wlr_scene_tree *scene_surface; struct wl_list link; struct wl_list flink; @@ -286,6 +295,8 @@ struct Client { int nofadeout; int no_force_center; int isunglobal; + float focused_opacity; + float unfocused_opacity; }; typedef struct { @@ -384,6 +395,7 @@ struct Monitor { int gamma_lut_changed; int asleep; unsigned int visible_clients; + struct wlr_scene_optimized_blur *blur; }; typedef struct { @@ -632,7 +644,8 @@ static unsigned int get_tags_first_tag(unsigned int tags); static void client_commit(Client *c); static void apply_border(Client *c, struct wlr_box clip_box, int offsetx, - int offsety); + int offsety, + enum corner_location current_corner_location); static void client_set_opacity(Client *c, double opacity); static void init_baked_points(void); static void scene_buffer_apply_opacity(struct wlr_scene_buffer *buffer, int sx, @@ -1030,19 +1043,9 @@ void client_animation_next_tick(Client *c) { .height = height, }; - if (!c->iskilling && (c->is_open_animation || c->animation.begin_fade_in) && - animation_fade_in && !c->nofadein) { - c->animation.begin_fade_in = true; - client_set_opacity(c, - MIN(animation_passed + fadein_begin_opacity, 1.0)); - } - c->is_open_animation = false; if (animation_passed == 1.0) { - if (c->animation.begin_fade_in) { - c->animation.begin_fade_in = false; - } // clear the open action state // To prevent him from being mistaken that @@ -1105,222 +1108,298 @@ bool check_hit_no_border(Client *c) { return hit_no_border; } +void +client_draw_shadow(Client *c) { + + if (c->iskilling || !client_surface(c)->mapped) + return; + + if(!shadows || !c->isfloating) { + wlr_scene_shadow_set_size(c->shadow, 0, 0); + return; + } + + uint32_t width, height; + client_actual_size(c, &width, &height); + + uint32_t delta = shadows_size + c->bw; + + /* we calculate where to clip the shadow */ + struct wlr_box client_box = { + .x = 0, + .y = 0, + .width = width, + .height = height, + }; + + struct wlr_box shadow_box = { + .x = shadows_position_x, + .y = shadows_position_y, + .width = width + 2 * delta, + .height = height + 2 * delta, + }; + + struct wlr_box intersection_box; + wlr_box_intersection(&intersection_box, &client_box, &shadow_box); + /* clipped region takes shadow relative coords, so we translate everything by its position */ + intersection_box.x -= shadows_position_x; + intersection_box.y -= shadows_position_y; + + struct clipped_region clipped_region = { + .area = intersection_box, + .corner_radius = border_radius, + .corners = border_radius_location_default, + }; + + wlr_scene_node_set_position(&c->shadow->node, shadow_box.x, shadow_box.y); + + wlr_scene_shadow_set_size(c->shadow, shadow_box.width, shadow_box.height); + wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region); +} + void apply_border(Client *c, struct wlr_box clip_box, int offsetx, - int offsety) { - bool hit_no_border = false; + int offsety, enum corner_location border_radius_location) { + bool hit_no_border = false; - if (c->iskilling || !client_surface(c)->mapped) - return; + if (c->iskilling || !client_surface(c)->mapped) + return; - if (clip_box.width > c->animation.current.width) { - clip_box.width = c->animation.current.width; + if (clip_box.width > c->animation.current.width) { + clip_box.width = c->animation.current.width; + } + + if (clip_box.height > c->animation.current.height) { + clip_box.height = c->animation.current.height; + } + +hit_no_border = check_hit_no_border(c); + + if (hit_no_border && smartgaps) { + c->bw = 0; + c->fake_no_border = true; + } else if (hit_no_border && !smartgaps) { + wlr_scene_rect_set_size(c->border, 0, 0); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + c->fake_no_border = true; + return; + } else if (!c->isfullscreen && VISIBLEON(c, c->mon)) { + c->bw = c->isnoborder ? 0 : borderpx; + c->fake_no_border = false; + } + + int clip_box_width = clip_box.width - 2 * c->bw; + int clip_box_height = clip_box.height - 2 * c->bw; + + if(clip_box_width < 0) { + clip_box_width = 0; + } + + if(clip_box_height < 0) { + clip_box_height = 0; + } + + int clip_x = c->bw - offsetx; + int clip_y = c->bw - offsety; + + clip_x = clip_x < 0 ? 0 : clip_x; + clip_y = clip_y < 0 ? 0 : clip_y; + + struct clipped_region clipped_region = { + .area = { clip_x, clip_y, clip_box_width, clip_box_height }, + .corner_radius = border_radius, + .corners = border_radius_location, + }; + + int right_offset = GEZERO(c->animation.current.x + c->animation.current.width - c->mon->m.x - c->mon->m.width); + int bottom_offset = GEZERO(c->animation.current.y + c->animation.current.height - c->mon->m.y - c->mon->m.height); + int rect_width = clip_box.width; + int rect_height = clip_box.height; + + + if(right_offset > 0) { + clipped_region.area.width = MIN(clip_box.width,clipped_region.area.width + right_offset); + } + + if(bottom_offset > 0) { + clipped_region.area.height = MIN(clip_box.height,clipped_region.area.height + bottom_offset); + } + + if(rect_width < 0) { + rect_width = 0; + } + + if(rect_height < 0) { + rect_height = 0; + } + + int node_x = offsetx; + int node_y = offsety; + + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border, rect_width, rect_height); + wlr_scene_node_set_position(&c->border->node, node_x, node_y); + wlr_scene_rect_set_corner_radius(c->border, border_radius, border_radius_location); + wlr_scene_rect_set_clipped_region(c->border, clipped_region); +} + +enum corner_location set_client_corner_location(Client *c) { + enum corner_location current_corner_location = CORNER_LOCATION_ALL; + struct wlr_box target_geom = animations ? c->animation.current : c->geom; + if (target_geom.x + border_radius <= c->mon->m.x) { + current_corner_location &= ~CORNER_LOCATION_LEFT; // 清除左标志位 } - - if (clip_box.height > c->animation.current.height) { - clip_box.height = c->animation.current.height; + if (target_geom.x + target_geom.width - border_radius >= + c->mon->m.x + c->mon->m.width) { + current_corner_location &= ~CORNER_LOCATION_RIGHT; // 清除右标志位 } - - hit_no_border = check_hit_no_border(c); - - if (hit_no_border && smartgaps) { - c->bw = 0; - c->fake_no_border = true; - } else if (hit_no_border && !smartgaps) { - set_rect_size(c->border[0], 0, 0); - set_rect_size(c->border[1], 0, 0); - set_rect_size(c->border[2], 0, 0); - set_rect_size(c->border[3], 0, 0); - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); - c->fake_no_border = true; - return; - } else if (!c->isfullscreen && VISIBLEON(c, c->mon)) { - c->bw = c->isnoborder ? 0 : borderpx; - c->fake_no_border = false; + if (target_geom.y + border_radius <= c->mon->m.y) { + current_corner_location &= ~CORNER_LOCATION_TOP; // 清除上标志位 } - - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); - set_rect_size(c->border[0], clip_box.width, c->bw); - set_rect_size(c->border[1], clip_box.width, c->bw); - set_rect_size(c->border[2], c->bw, clip_box.height - 2 * c->bw); - set_rect_size(c->border[3], c->bw, clip_box.height - 2 * c->bw); - wlr_scene_node_set_position(&c->border[0]->node, 0, 0); - wlr_scene_node_set_position(&c->border[2]->node, 0, c->bw); - wlr_scene_node_set_position(&c->border[1]->node, 0, - clip_box.height - c->bw); - wlr_scene_node_set_position(&c->border[3]->node, clip_box.width - c->bw, - c->bw); - - if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || - c->animation.tagouting) { - if (c->animation.current.x < c->mon->m.x) { - set_rect_size(c->border[2], GEZERO(c->bw - offsetx), - clip_box.height - 2 * c->bw); - } else if (c->animation.current.x + c->animation.current.width > - c->mon->m.x + c->mon->m.width) { - set_rect_size(c->border[3], - GEZERO(c->bw - GEZERO(c->animation.current.x + - c->animation.current.width - - c->mon->m.x - c->mon->m.width)), - clip_box.height - 2 * c->bw); - set_rect_size(c->border[0], clip_box.width + c->bw, - GEZERO(c->bw - offsety)); - set_rect_size( - c->border[1], clip_box.width + c->bw, - GEZERO(c->bw - GEZERO(c->animation.current.y + - c->animation.current.height - - c->mon->m.y - c->mon->m.height))); - } else if (c->animation.current.y < c->mon->m.y) { - set_rect_size(c->border[0], clip_box.width, - GEZERO(c->bw - offsety)); - } else if (c->animation.current.y + c->animation.current.height > - c->mon->m.y + c->mon->m.height) { - set_rect_size( - c->border[1], clip_box.width, - GEZERO(c->bw - GEZERO(c->animation.current.y + - c->animation.current.height - - c->mon->m.y - c->mon->m.height))); - set_rect_size(c->border[2], GEZERO(c->bw - offsetx), - clip_box.height - c->bw); - set_rect_size(c->border[3], - GEZERO(c->bw - GEZERO(c->animation.current.x + - c->animation.current.width - - c->mon->m.x - c->mon->m.width)), - clip_box.height - c->bw); - } + if (target_geom.y + target_geom.height - border_radius >= + c->mon->m.y + c->mon->m.height) { + current_corner_location &= ~CORNER_LOCATION_BOTTOM; // 清除下标志位 } - - wlr_scene_node_set_position(&c->border[0]->node, offsetx, offsety); - wlr_scene_node_set_position(&c->border[2]->node, offsetx, c->bw + offsety); - wlr_scene_node_set_position(&c->border[1]->node, offsetx, - clip_box.height - c->bw + offsety); - wlr_scene_node_set_position( - &c->border[3]->node, clip_box.width - c->bw + offsetx, c->bw + offsety); + return current_corner_location; } struct uvec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { - int offsetx = 0; - int offsety = 0; - struct uvec2 offset; - offset.x = 0; - offset.y = 0; + int offsetx = 0; + int offsety = 0; + struct uvec2 offset; + offset.x = 0; + offset.y = 0; - if (!ISTILED(c) && !c->animation.tagining && !c->animation.tagouted && - !c->animation.tagouting) - return offset; + if (!ISTILED(c) && !c->animation.tagining && !c->animation.tagouted && + !c->animation.tagouting) + return offset; - // // make tagout tagin animations not visible in other monitors - if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || - c->animation.tagouting) { - if (c->animation.current.x < c->mon->m.x) { - offsetx = c->mon->m.x - c->bw - c->animation.current.x; - offsetx = offsetx < 0 ? 0 : offsetx; - clip_box->x = clip_box->x + offsetx; - clip_box->width = clip_box->width - offsetx; - } else if (c->animation.current.x + c->animation.current.width > - c->mon->m.x + c->mon->m.width) { - clip_box->width = - clip_box->width - - (c->animation.current.x + c->animation.current.width - - c->mon->m.x - c->mon->m.width) + - c->bw; - } + // // make tagout tagin animations not visible in other monitors + if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || + c->animation.tagouting) { + if (c->animation.current.x < c->mon->m.x) { + offsetx = c->mon->m.x - c->bw - c->animation.current.x; + offsetx = offsetx < 0 ? 0 : offsetx; + clip_box->x = clip_box->x + offsetx; + clip_box->width = clip_box->width - offsetx; + } else if (c->animation.current.x + c->animation.current.width > + c->mon->m.x + c->mon->m.width) { + clip_box->width = clip_box->width - + (c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width) + + c->bw; + } - if (c->animation.current.y < c->mon->m.y) { - offsety = c->mon->m.y - c->bw - c->animation.current.y; - offsety = offsety < 0 ? 0 : offsety; - clip_box->y = clip_box->y + offsety; - clip_box->height = clip_box->height - offsety; - } else if (c->animation.current.y + c->animation.current.height > - c->mon->m.y + c->mon->m.height) { - clip_box->height = - clip_box->height - - (c->animation.current.y + c->animation.current.height - - c->mon->m.y - c->mon->m.height) + - c->bw; - } - } + if (c->animation.current.y < c->mon->m.y) { + offsety = c->mon->m.y - c->bw - c->animation.current.y; + offsety = offsety < 0 ? 0 : offsety; + clip_box->y = clip_box->y + offsety; + clip_box->height = clip_box->height - offsety; + } else if (c->animation.current.y + c->animation.current.height > + c->mon->m.y + c->mon->m.height) { + clip_box->height = clip_box->height - + (c->animation.current.y + c->animation.current.height - + c->mon->m.y - c->mon->m.height) + + c->bw; + } + } - offset.x = offsetx; - offset.y = offsety; + offset.x = offsetx; + offset.y = offsety; - if ((clip_box->width < 0 || clip_box->height < 0) && - (ISTILED(c) || c->animation.tagouting || c->animation.tagining)) { - c->is_clip_to_hide = true; - wlr_scene_node_set_enabled(&c->scene->node, false); - } else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) { - c->is_clip_to_hide = false; - wlr_scene_node_set_enabled(&c->scene->node, true); - } + if ((clip_box->width < 0 || clip_box->height < 0) && + (ISTILED(c) || c->animation.tagouting || c->animation.tagining)) { + c->is_clip_to_hide = true; + wlr_scene_node_set_enabled(&c->scene->node, false); + } else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) { + c->is_clip_to_hide = false; + wlr_scene_node_set_enabled(&c->scene->node, true); + } - if (clip_box->width > c->animation.current.width) { - clip_box->width = c->animation.current.width; - } + if (clip_box->width > c->animation.current.width) { + clip_box->width = c->animation.current.width; + } - if (clip_box->height > c->animation.current.height) { - clip_box->height = c->animation.current.height; - } + if (clip_box->height > c->animation.current.height) { + clip_box->height = c->animation.current.height; + } - return offset; + return offset; } void client_apply_clip(Client *c) { - if (c->iskilling || !client_surface(c)->mapped) - return; - struct wlr_box clip_box; - struct uvec2 offset; - animationScale scale_data; + if (c->iskilling || !client_surface(c)->mapped) + return; + struct wlr_box clip_box; + struct uvec2 offset; + animationScale scale_data; + struct wlr_box surface_clip; + enum corner_location current_corner_location = set_client_corner_location(c); - if (!animations) { - c->animation.running = false; - c->need_output_flush = false; - c->animainit_geom = c->current = c->pending = c->animation.current = - c->geom; - client_get_clip(c, &clip_box); - offset = clip_to_hide(c, &clip_box); - apply_border(c, clip_box, offset.x, offset.y); + if (!animations) { + c->animation.running = false; + c->need_output_flush = false; + c->animainit_geom = c->current = c->pending = c->animation.current = + c->geom; + client_get_clip(c, &clip_box); - if (clip_box.width <= 0 || clip_box.height <= 0) - return; + offset = clip_to_hide(c, &clip_box); - wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box); - buffer_set_effect(c, (animationScale){0, 0, 0, 0, false}); - return; - } + apply_border(c, clip_box, offset.x, offset.y, current_corner_location); + client_draw_shadow(c); - uint32_t width, height; - client_actual_size(c, &width, &height); + surface_clip = clip_box; + surface_clip.width = surface_clip.width - 2 * c->bw; + surface_clip.height = surface_clip.height - 2 * c->bw; - struct wlr_box geometry; - client_get_geometry(c, &geometry); - clip_box = (struct wlr_box){ - .x = geometry.x, - .y = geometry.y, - .width = width, - .height = height, - }; + if(surface_clip.width <= 0 || surface_clip.height <= 0) { + return; + } - if (client_is_x11(c)) { - clip_box.x = 0; - clip_box.y = 0; - } + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); + buffer_set_effect(c, (animationScale){0, 0, 0, 0, current_corner_location,false}); + return; + } - offset = clip_to_hide(c, &clip_box); - apply_border(c, clip_box, offset.x, offset.y); + uint32_t width, height; + client_actual_size(c, &width, &height); - if (clip_box.width <= 0 || clip_box.height <= 0) - return; + struct wlr_box geometry; + client_get_geometry(c, &geometry); + clip_box = (struct wlr_box){ + .x = geometry.x, + .y = geometry.y, + .width = width, + .height = height, + }; - wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box); + if (client_is_x11(c)) { + clip_box.x = 0; + clip_box.y = 0; + } - scale_data.should_scale = true; - scale_data.width = clip_box.width - 2 * c->bw; - scale_data.height = clip_box.height - 2 * c->bw; - scale_data.width_scale = - (float)scale_data.width / (geometry.width - offset.x); - scale_data.height_scale = - (float)scale_data.height / (geometry.height - offset.y); - buffer_set_effect(c, scale_data); + offset = clip_to_hide(c, &clip_box); + apply_border(c, clip_box, offset.x, offset.y, current_corner_location); + client_draw_shadow(c); + + surface_clip = clip_box; + surface_clip.width = surface_clip.width - 2 * c->bw; + surface_clip.height = surface_clip.height - 2 * c->bw; + + if(surface_clip.width <= 0 || surface_clip.height <= 0) { + return; + } + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); + + scale_data.should_scale = true; + scale_data.width = clip_box.width - 2 * c->bw; + scale_data.height = clip_box.height - 2 * c->bw; + scale_data.width_scale = (float)scale_data.width / (geometry.width - offset.x); + scale_data.height_scale = (float)scale_data.height / (geometry.height - offset.y); + scale_data.corner_location = current_corner_location; + scale_data.percent = c->is_open_animation && animation_fade_in ? (double)c->animation.passed_frames / c->animation.total_frames : 1.0; + scale_data.opacity = c->isfullscreen ? 1 : c == selmon->sel ? c->focused_opacity : c->unfocused_opacity; + buffer_set_effect(c, scale_data); } bool client_draw_frame(Client *c) { @@ -1328,6 +1407,14 @@ bool client_draw_frame(Client *c) { if (!c || !client_surface(c)->mapped) return false; + if (c->isfullscreen) + client_set_opacity(c, 1); + else if (c == selmon->sel && !c->animation.running) { + client_set_opacity(c, c->focused_opacity); + } else if (!c->animation.running) { + client_set_opacity(c, c->unfocused_opacity); + } + if (!c->need_output_flush) return false; @@ -1335,8 +1422,9 @@ bool client_draw_frame(Client *c) { client_animation_next_tick(c); client_apply_clip(c); } else { - wlr_scene_node_set_position(&c->scene->node, c->pending.x, - c->pending.y); + if (!c->is_clip_to_hide) + wlr_scene_node_set_position(&c->scene->node, c->pending.x, + c->pending.y); c->animainit_geom = c->animation.initial = c->pending = c->current = c->geom; client_apply_clip(c); @@ -1712,7 +1800,7 @@ void gpureset(struct wl_listener *listener, void *data) { wlr_log(WLR_DEBUG, "gpu reset"); - if (!(drw = wlr_renderer_autocreate(backend))) + if (!(drw = fx_renderer_create(backend))) die("couldn't recreate renderer"); if (!(alloc = wlr_allocator_autocreate(backend, drw))) @@ -1914,6 +2002,11 @@ applyrules(Client *c) { c->isglobal = r->isglobal >= 0 ? r->isglobal : c->isglobal; c->isoverlay = r->isoverlay >= 0 ? r->isoverlay : c->isoverlay; c->isunglobal = r->isunglobal >= 0 ? r->isunglobal : c->isunglobal; + c->focused_opacity = r->focused_opacity > 0 ? r->focused_opacity + : c->focused_opacity; + c->unfocused_opacity = r->unfocused_opacity > 0 + ? r->unfocused_opacity + : c->unfocused_opacity; newtags = r->tags > 0 ? r->tags | newtags : newtags; i = 0; @@ -2958,6 +3051,10 @@ void cleanupmon(struct wl_listener *listener, void *data) { wlr_scene_output_destroy(m->scene_output); closemon(m); + if (m->blur) { + wlr_scene_node_destroy(&m->blur->node); + m->blur = NULL; + } // wlr_scene_node_destroy(&m->fullscreen_bg->node); free(m); } @@ -3043,6 +3140,19 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) { } arrangelayers(l->mon); + + if (blur) { + // Rerender the optimized blur on change + struct wlr_layer_surface_v1 *wlr_layer_surface = l->layer_surface; + if (wlr_layer_surface->current.layer == + ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || + wlr_layer_surface->current.layer == + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) { + if (l->mon) { + wlr_scene_optimized_blur_mark_dirty(l->mon->blur); + } + } + } } void client_set_pending_state(Client *c) { @@ -3459,6 +3569,14 @@ void createmon(struct wl_listener *listener, void *data) { wlr_output_layout_add_auto(output_layout, wlr_output); else wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y); + + if (blur) { + m->blur = wlr_scene_optimized_blur_create(&scene->tree, 0, 0); + // wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); + wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]); + wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); + // wlr_scene_node_set_enabled(&m->blur->node, 1); + } } void // fix for 0.5 @@ -4170,7 +4288,12 @@ void incovgaps(const Arg *arg) { void requestmonstate(struct wl_listener *listener, void *data) { struct wlr_output_event_request_state *event = data; + Monitor *m = wl_container_of(listener, m, frame); + wlr_output_commit_state(event->output, event->state); + if (blur) { + wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); + } updatemons(NULL, NULL); } @@ -4417,15 +4540,16 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, struct wlr_scene_node *snapshot_node = NULL; switch (node->type) { - case WLR_SCENE_NODE_TREE:; + case WLR_SCENE_NODE_TREE: { struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node); + struct wlr_scene_node *child; wl_list_for_each(child, &scene_tree->children, link) { scene_node_snapshot(child, lx, ly, snapshot_tree); } break; - case WLR_SCENE_NODE_RECT:; - + } + case WLR_SCENE_NODE_RECT: { struct wlr_scene_rect *scene_rect = wlr_scene_rect_from_node(node); struct wlr_scene_rect *snapshot_rect = @@ -4435,10 +4559,20 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, if (snapshot_rect == NULL) { return false; } + + wlr_scene_rect_set_clipped_region(scene_rect, + snapshot_rect->clipped_region); + wlr_scene_rect_set_backdrop_blur(scene_rect, false); + // wlr_scene_rect_set_backdrop_blur_optimized( + // scene_rect, snapshot_rect->backdrop_blur_optimized); + wlr_scene_rect_set_corner_radius( + scene_rect, snapshot_rect->corner_radius, snapshot_rect->corners); + wlr_scene_rect_set_color(scene_rect, snapshot_rect->color); + snapshot_node = &snapshot_rect->node; break; - case WLR_SCENE_NODE_BUFFER:; - + } + case WLR_SCENE_NODE_BUFFER: { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); @@ -4463,6 +4597,15 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, // Effects wlr_scene_buffer_set_opacity(snapshot_buffer, scene_buffer->opacity); + wlr_scene_buffer_set_corner_radius(snapshot_buffer, + scene_buffer->corner_radius, + scene_buffer->corners); + + // wlr_scene_buffer_set_backdrop_blur_optimized( + // snapshot_buffer, scene_buffer->backdrop_blur_optimized); + // wlr_scene_buffer_set_backdrop_blur_ignore_transparent( + // snapshot_buffer, scene_buffer->backdrop_blur_ignore_transparent); + wlr_scene_buffer_set_backdrop_blur(snapshot_buffer, false); snapshot_buffer->node.data = scene_buffer->node.data; @@ -4476,6 +4619,31 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, } break; } + case WLR_SCENE_NODE_SHADOW: { + struct wlr_scene_shadow *scene_shadow = + wlr_scene_shadow_from_node(node); + + struct wlr_scene_shadow *snapshot_shadow = wlr_scene_shadow_create( + snapshot_tree, scene_shadow->width, scene_shadow->height, + scene_shadow->corner_radius, scene_shadow->blur_sigma, + scene_shadow->color); + if (snapshot_shadow == NULL) { + return false; + } + snapshot_node = &snapshot_shadow->node; + + wlr_scene_shadow_set_clipped_region(snapshot_shadow, + scene_shadow->clipped_region); + + snapshot_shadow->node.data = scene_shadow->node.data; + + wlr_scene_node_set_enabled(&snapshot_shadow->node, false); + + break; + } + case WLR_SCENE_NODE_OPTIMIZED_BLUR: + return true; + } if (snapshot_node != NULL) { wlr_scene_node_set_position(snapshot_node, lx, ly); @@ -4541,12 +4709,33 @@ void locksession(struct wl_listener *listener, void *data) { wlr_session_lock_v1_send_locked(session_lock); } +static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, + int sy, void *user_data) { + Client *c = user_data; + + struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); + if (!scene_surface) { + return; + } + + struct wlr_surface *surface = scene_surface->surface; + /* we dont blur subsurfaces */ + if(wlr_subsurface_try_from_wlr_surface(surface) != NULL) return; + + if (blur && c) { + wlr_scene_buffer_set_backdrop_blur(buffer, true); + wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true); + wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true); + } else { + wlr_scene_buffer_set_backdrop_blur(buffer, false); + } +} + void // old fix to 0.5 mapnotify(struct wl_listener *listener, void *data) { /* Called when the surface is mapped, or ready to display on-screen. */ Client *p = NULL; Client *c = wl_container_of(listener, c, map); - int i; /* Create scene tree for this client and its border */ c->scene = client_surface(c)->data = wlr_scene_tree_create(layers[LyrTile]); wlr_scene_node_set_enabled(&c->scene->node, c->type != XDGShell); @@ -4583,11 +4772,22 @@ mapnotify(struct wl_listener *listener, void *data) { return; } - for (i = 0; i < 4; i++) { - c->border[i] = wlr_scene_rect_create( - c->scene, 0, 0, c->isurgent ? urgentcolor : bordercolor); - c->border[i]->node.data = c; - } + c->border = wlr_scene_rect_create(c->scene, 0, 0, + c->isurgent ? urgentcolor : bordercolor); + wlr_scene_node_lower_to_bottom(&c->border->node); + wlr_scene_node_set_position(&c->border->node, 0, 0); + wlr_scene_rect_set_corner_radius(c->border, border_radius, + border_radius_location_default); + wlr_scene_node_set_enabled(&c->border->node, true); + + c->shadow = wlr_scene_shadow_create(c->scene, 0, 0, border_radius, + shadows_blur, shadowscolor); + + wlr_scene_node_lower_to_bottom(&c->shadow->node); + wlr_scene_node_set_enabled(&c->shadow->node, true); + + wlr_scene_node_for_each_buffer(&c->scene_surface->node, + iter_xdg_scene_buffers, c); /* Initialize client geometry with room for border */ client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | @@ -4614,6 +4814,8 @@ mapnotify(struct wl_listener *listener, void *data) { c->is_open_animation = true; c->drag_to_tile = false; c->fake_no_border = false; + c->focused_opacity = focused_opacity; + c->unfocused_opacity = unfocused_opacity; c->nofadein = 0; c->nofadeout = 0; c->no_force_center = 0; @@ -5105,6 +5307,18 @@ void scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, int sy, } } // TODO: blur set, opacity set + + if (wlr_xdg_popup_try_from_wlr_surface(surface) != NULL) + return; + + wlr_scene_buffer_set_corner_radius(buffer, border_radius, + scale_data->corner_location); + + float target_opacity = scale_data->percent + fadein_begin_opacity; + if (target_opacity > scale_data->opacity) { + target_opacity = scale_data->opacity; + } + wlr_scene_buffer_set_opacity(buffer, target_opacity); } void snap_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, @@ -5138,18 +5352,6 @@ void client_set_opacity(Client *c, double opacity) { scene_buffer_apply_opacity, &opacity); } -void client_handle_opacity(Client *c) { - if (!c || !c->mon || !client_surface(c)->mapped) - return; - - double opacity = c->isfullscreen || c->ismaxmizescreen ? 1.0 - : c == selmon->sel ? 0.8 - : 0.5; - - wlr_scene_node_for_each_buffer(&c->scene_surface->node, - scene_buffer_apply_opacity, &opacity); -} - void rendermon(struct wl_listener *listener, void *data) { Monitor *m = wl_container_of(listener, m, frame); Client *c, *tmp; @@ -5402,7 +5604,6 @@ void resize(Client *c, struct wlr_box geo, int interact) { if (!c->is_open_animation) { c->animation.begin_fade_in = false; - client_set_opacity(c, 1); } if (c->animation.action == OPEN && !c->animation.tagining && @@ -5447,8 +5648,8 @@ void resize(Client *c, struct wlr_box geo, int interact) { c->need_output_flush = false; c->animainit_geom = c->current = c->pending = c->animation.current = c->geom; - wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); - apply_border(c, c->geom, 0, 0); + apply_border(c, c->geom, 0, 0, CORNER_LOCATION_ALL); + client_draw_shadow(c); client_get_clip(c, &clip); wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); return; @@ -6348,7 +6549,7 @@ void setup(void) { wlr_scene_node_place_below(&drag_icon->node, &layers[LyrBlock]->node); /* Create a renderer with the default implementation */ - if (!(drw = wlr_renderer_autocreate(backend))) + if (!(drw = fx_renderer_create(backend))) die("couldn't create renderer"); wl_signal_add(&drw->events.lost, &gpu_reset); @@ -6539,6 +6740,9 @@ void setup(void) { wl_signal_add(&output_mgr->events.apply, &output_mgr_apply); wl_signal_add(&output_mgr->events.test, &output_mgr_test); + // blur + wlr_scene_set_blur_data(scene, blur_params); + /* create text_input-, and input_method-protocol relevant globals */ input_method_manager = wlr_input_method_manager_v2_create(dpy); text_input_manager = wlr_text_input_manager_v3_create(dpy); @@ -7245,6 +7449,10 @@ void updatemons(struct wl_listener *listener, void *data) { // wlr_scene_node_set_position(&m->fullscreen_bg->node, m->m.x, m->m.y); // wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); + if (blur && m->blur) { + wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); + } + if (m->lock_surface) { struct wlr_scene_tree *scene_tree = m->lock_surface->surface->data; wlr_scene_node_set_position(&scene_tree->node, m->m.x, m->m.y); From d5c8a7bd911fd5f771cfcf61b5c5b3ae58fe0a95 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 09:39:47 +0800 Subject: [PATCH 02/30] fix: fade in not apply --- src/maomao.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/maomao.c b/src/maomao.c index 8223a1d..c7737a9 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1397,7 +1397,7 @@ void client_apply_clip(Client *c) { scale_data.width_scale = (float)scale_data.width / (geometry.width - offset.x); scale_data.height_scale = (float)scale_data.height / (geometry.height - offset.y); scale_data.corner_location = current_corner_location; - scale_data.percent = c->is_open_animation && animation_fade_in ? (double)c->animation.passed_frames / c->animation.total_frames : 1.0; + scale_data.percent = c->animation.action == OPEN && animation_fade_in && !c->nofadein ? (double)c->animation.passed_frames / c->animation.total_frames : 1.0; scale_data.opacity = c->isfullscreen ? 1 : c == selmon->sel ? c->focused_opacity : c->unfocused_opacity; buffer_set_effect(c, scale_data); } From 33947c30f26d7af6c7335ee6075de294ad3a34be Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 10:21:30 +0800 Subject: [PATCH 03/30] fix: Avoid animation ghosting --- src/maomao.c | 477 +++++++++++++++++++++++++++------------------------ 1 file changed, 254 insertions(+), 223 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index c7737a9..82bb0b0 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1108,138 +1108,144 @@ bool check_hit_no_border(Client *c) { return hit_no_border; } -void -client_draw_shadow(Client *c) { +void client_draw_shadow(Client *c) { - if (c->iskilling || !client_surface(c)->mapped) - return; + if (c->iskilling || !client_surface(c)->mapped) + return; - if(!shadows || !c->isfloating) { - wlr_scene_shadow_set_size(c->shadow, 0, 0); - return; - } + if (!shadows || !c->isfloating) { + wlr_scene_shadow_set_size(c->shadow, 0, 0); + return; + } - uint32_t width, height; - client_actual_size(c, &width, &height); + uint32_t width, height; + client_actual_size(c, &width, &height); - uint32_t delta = shadows_size + c->bw; + uint32_t delta = shadows_size + c->bw; - /* we calculate where to clip the shadow */ - struct wlr_box client_box = { - .x = 0, - .y = 0, - .width = width, - .height = height, - }; + /* we calculate where to clip the shadow */ + struct wlr_box client_box = { + .x = 0, + .y = 0, + .width = width, + .height = height, + }; - struct wlr_box shadow_box = { - .x = shadows_position_x, - .y = shadows_position_y, - .width = width + 2 * delta, - .height = height + 2 * delta, - }; + struct wlr_box shadow_box = { + .x = shadows_position_x, + .y = shadows_position_y, + .width = width + 2 * delta, + .height = height + 2 * delta, + }; - struct wlr_box intersection_box; - wlr_box_intersection(&intersection_box, &client_box, &shadow_box); - /* clipped region takes shadow relative coords, so we translate everything by its position */ - intersection_box.x -= shadows_position_x; - intersection_box.y -= shadows_position_y; + struct wlr_box intersection_box; + wlr_box_intersection(&intersection_box, &client_box, &shadow_box); + /* clipped region takes shadow relative coords, so we translate everything + * by its position */ + intersection_box.x -= shadows_position_x; + intersection_box.y -= shadows_position_y; - struct clipped_region clipped_region = { - .area = intersection_box, - .corner_radius = border_radius, - .corners = border_radius_location_default, - }; + struct clipped_region clipped_region = { + .area = intersection_box, + .corner_radius = border_radius, + .corners = border_radius_location_default, + }; - wlr_scene_node_set_position(&c->shadow->node, shadow_box.x, shadow_box.y); + wlr_scene_node_set_position(&c->shadow->node, shadow_box.x, shadow_box.y); - wlr_scene_shadow_set_size(c->shadow, shadow_box.width, shadow_box.height); - wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region); + wlr_scene_shadow_set_size(c->shadow, shadow_box.width, shadow_box.height); + wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region); } -void apply_border(Client *c, struct wlr_box clip_box, int offsetx, - int offsety, enum corner_location border_radius_location) { - bool hit_no_border = false; +void apply_border(Client *c, struct wlr_box clip_box, int offsetx, int offsety, + enum corner_location border_radius_location) { + bool hit_no_border = false; - if (c->iskilling || !client_surface(c)->mapped) - return; + if (c->iskilling || !client_surface(c)->mapped) + return; - if (clip_box.width > c->animation.current.width) { - clip_box.width = c->animation.current.width; - } + if (clip_box.width > c->animation.current.width) { + clip_box.width = c->animation.current.width; + } - if (clip_box.height > c->animation.current.height) { - clip_box.height = c->animation.current.height; - } + if (clip_box.height > c->animation.current.height) { + clip_box.height = c->animation.current.height; + } -hit_no_border = check_hit_no_border(c); + hit_no_border = check_hit_no_border(c); - if (hit_no_border && smartgaps) { - c->bw = 0; - c->fake_no_border = true; - } else if (hit_no_border && !smartgaps) { - wlr_scene_rect_set_size(c->border, 0, 0); - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); - c->fake_no_border = true; - return; - } else if (!c->isfullscreen && VISIBLEON(c, c->mon)) { - c->bw = c->isnoborder ? 0 : borderpx; - c->fake_no_border = false; - } + if (hit_no_border && smartgaps) { + c->bw = 0; + c->fake_no_border = true; + } else if (hit_no_border && !smartgaps) { + wlr_scene_rect_set_size(c->border, 0, 0); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + c->fake_no_border = true; + return; + } else if (!c->isfullscreen && VISIBLEON(c, c->mon)) { + c->bw = c->isnoborder ? 0 : borderpx; + c->fake_no_border = false; + } - int clip_box_width = clip_box.width - 2 * c->bw; - int clip_box_height = clip_box.height - 2 * c->bw; + int clip_box_width = clip_box.width - 2 * c->bw; + int clip_box_height = clip_box.height - 2 * c->bw; - if(clip_box_width < 0) { - clip_box_width = 0; - } + if (clip_box_width < 0) { + clip_box_width = 0; + } - if(clip_box_height < 0) { - clip_box_height = 0; - } + if (clip_box_height < 0) { + clip_box_height = 0; + } - int clip_x = c->bw - offsetx; - int clip_y = c->bw - offsety; + int clip_x = c->bw - offsetx; + int clip_y = c->bw - offsety; - clip_x = clip_x < 0 ? 0 : clip_x; - clip_y = clip_y < 0 ? 0 : clip_y; + clip_x = clip_x < 0 ? 0 : clip_x; + clip_y = clip_y < 0 ? 0 : clip_y; - struct clipped_region clipped_region = { - .area = { clip_x, clip_y, clip_box_width, clip_box_height }, - .corner_radius = border_radius, - .corners = border_radius_location, - }; + struct clipped_region clipped_region = { + .area = {clip_x, clip_y, clip_box_width, clip_box_height}, + .corner_radius = border_radius, + .corners = border_radius_location, + }; - int right_offset = GEZERO(c->animation.current.x + c->animation.current.width - c->mon->m.x - c->mon->m.width); - int bottom_offset = GEZERO(c->animation.current.y + c->animation.current.height - c->mon->m.y - c->mon->m.height); - int rect_width = clip_box.width; - int rect_height = clip_box.height; - + int right_offset = + GEZERO(c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width); + int bottom_offset = + GEZERO(c->animation.current.y + c->animation.current.height - + c->mon->m.y - c->mon->m.height); + int rect_width = clip_box.width; + int rect_height = clip_box.height; - if(right_offset > 0) { - clipped_region.area.width = MIN(clip_box.width,clipped_region.area.width + right_offset); - } + if (right_offset > 0) { + clipped_region.area.width = + MIN(clip_box.width, clipped_region.area.width + right_offset); + } - if(bottom_offset > 0) { - clipped_region.area.height = MIN(clip_box.height,clipped_region.area.height + bottom_offset); - } + if (bottom_offset > 0) { + clipped_region.area.height = + MIN(clip_box.height, clipped_region.area.height + bottom_offset); + } - if(rect_width < 0) { - rect_width = 0; - } + if (rect_width < 0) { + rect_width = 0; + } - if(rect_height < 0) { - rect_height = 0; - } + if (rect_height < 0) { + rect_height = 0; + } - int node_x = offsetx; - int node_y = offsety; + int node_x = offsetx; + int node_y = offsety; - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); - wlr_scene_rect_set_size(c->border, rect_width, rect_height); - wlr_scene_node_set_position(&c->border->node, node_x, node_y); - wlr_scene_rect_set_corner_radius(c->border, border_radius, border_radius_location); - wlr_scene_rect_set_clipped_region(c->border, clipped_region); + wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); + wlr_scene_rect_set_size(c->border, rect_width, rect_height); + wlr_scene_node_set_position(&c->border->node, node_x, node_y); + wlr_scene_rect_set_corner_radius(c->border, border_radius, + border_radius_location); + wlr_scene_rect_set_clipped_region(c->border, clipped_region); } enum corner_location set_client_corner_location(Client *c) { @@ -1263,143 +1269,166 @@ enum corner_location set_client_corner_location(Client *c) { } struct uvec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { - int offsetx = 0; - int offsety = 0; - struct uvec2 offset; - offset.x = 0; - offset.y = 0; + int offsetx = 0; + int offsety = 0; + struct uvec2 offset; + offset.x = 0; + offset.y = 0; - if (!ISTILED(c) && !c->animation.tagining && !c->animation.tagouted && - !c->animation.tagouting) - return offset; + if (!ISTILED(c) && !c->animation.tagining && !c->animation.tagouted && + !c->animation.tagouting) + return offset; - // // make tagout tagin animations not visible in other monitors - if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || - c->animation.tagouting) { - if (c->animation.current.x < c->mon->m.x) { - offsetx = c->mon->m.x - c->bw - c->animation.current.x; - offsetx = offsetx < 0 ? 0 : offsetx; - clip_box->x = clip_box->x + offsetx; - clip_box->width = clip_box->width - offsetx; - } else if (c->animation.current.x + c->animation.current.width > - c->mon->m.x + c->mon->m.width) { - clip_box->width = clip_box->width - - (c->animation.current.x + c->animation.current.width - - c->mon->m.x - c->mon->m.width) + - c->bw; - } + // // make tagout tagin animations not visible in other monitors + if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || + c->animation.tagouting) { + if (c->animation.current.x < c->mon->m.x) { + offsetx = c->mon->m.x - c->bw - c->animation.current.x; + offsetx = offsetx < 0 ? 0 : offsetx; + clip_box->x = clip_box->x + offsetx; + clip_box->width = clip_box->width - offsetx; + } else if (c->animation.current.x + c->animation.current.width > + c->mon->m.x + c->mon->m.width) { + clip_box->width = + clip_box->width - + (c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width) + + c->bw; + } - if (c->animation.current.y < c->mon->m.y) { - offsety = c->mon->m.y - c->bw - c->animation.current.y; - offsety = offsety < 0 ? 0 : offsety; - clip_box->y = clip_box->y + offsety; - clip_box->height = clip_box->height - offsety; - } else if (c->animation.current.y + c->animation.current.height > - c->mon->m.y + c->mon->m.height) { - clip_box->height = clip_box->height - - (c->animation.current.y + c->animation.current.height - - c->mon->m.y - c->mon->m.height) + - c->bw; - } - } + if (c->animation.current.y < c->mon->m.y) { + offsety = c->mon->m.y - c->bw - c->animation.current.y; + offsety = offsety < 0 ? 0 : offsety; + clip_box->y = clip_box->y + offsety; + clip_box->height = clip_box->height - offsety; + } else if (c->animation.current.y + c->animation.current.height > + c->mon->m.y + c->mon->m.height) { + clip_box->height = + clip_box->height - + (c->animation.current.y + c->animation.current.height - + c->mon->m.y - c->mon->m.height) + + c->bw; + } + } - offset.x = offsetx; - offset.y = offsety; + offset.x = offsetx; + offset.y = offsety; - if ((clip_box->width < 0 || clip_box->height < 0) && - (ISTILED(c) || c->animation.tagouting || c->animation.tagining)) { - c->is_clip_to_hide = true; - wlr_scene_node_set_enabled(&c->scene->node, false); - } else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) { - c->is_clip_to_hide = false; - wlr_scene_node_set_enabled(&c->scene->node, true); - } + if ((clip_box->width < 0 || clip_box->height < 0) && + (ISTILED(c) || c->animation.tagouting || c->animation.tagining)) { + c->is_clip_to_hide = true; + wlr_scene_node_set_enabled(&c->scene->node, false); + } else if (c->is_clip_to_hide && VISIBLEON(c, c->mon)) { + c->is_clip_to_hide = false; + wlr_scene_node_set_enabled(&c->scene->node, true); + } - if (clip_box->width > c->animation.current.width) { - clip_box->width = c->animation.current.width; - } + if (clip_box->width > c->animation.current.width) { + clip_box->width = c->animation.current.width; + } - if (clip_box->height > c->animation.current.height) { - clip_box->height = c->animation.current.height; - } + if (clip_box->height > c->animation.current.height) { + clip_box->height = c->animation.current.height; + } - return offset; + return offset; } void client_apply_clip(Client *c) { - if (c->iskilling || !client_surface(c)->mapped) - return; - struct wlr_box clip_box; - struct uvec2 offset; - animationScale scale_data; - struct wlr_box surface_clip; - enum corner_location current_corner_location = set_client_corner_location(c); + if (c->iskilling || !client_surface(c)->mapped) + return; + struct wlr_box clip_box; + struct uvec2 offset; + bool should_render_client_surface = false; + animationScale scale_data; + struct wlr_box surface_clip; + enum corner_location current_corner_location = + set_client_corner_location(c); - if (!animations) { - c->animation.running = false; - c->need_output_flush = false; - c->animainit_geom = c->current = c->pending = c->animation.current = - c->geom; - client_get_clip(c, &clip_box); + if (!animations) { + c->animation.running = false; + c->need_output_flush = false; + c->animainit_geom = c->current = c->pending = c->animation.current = + c->geom; + client_get_clip(c, &clip_box); - offset = clip_to_hide(c, &clip_box); + offset = clip_to_hide(c, &clip_box); - apply_border(c, clip_box, offset.x, offset.y, current_corner_location); - client_draw_shadow(c); + apply_border(c, clip_box, offset.x, offset.y, current_corner_location); + client_draw_shadow(c); - surface_clip = clip_box; - surface_clip.width = surface_clip.width - 2 * c->bw; - surface_clip.height = surface_clip.height - 2 * c->bw; + surface_clip = clip_box; + surface_clip.width = surface_clip.width - 2 * c->bw; + surface_clip.height = surface_clip.height - 2 * c->bw; - if(surface_clip.width <= 0 || surface_clip.height <= 0) { - return; - } + if (surface_clip.width <= 0 || surface_clip.height <= 0) { + return; + } - wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); - buffer_set_effect(c, (animationScale){0, 0, 0, 0, current_corner_location,false}); - return; - } + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, + &surface_clip); + buffer_set_effect( + c, (animationScale){0, 0, 0, 0, current_corner_location, false}); + return; + } - uint32_t width, height; - client_actual_size(c, &width, &height); + uint32_t width, height; + client_actual_size(c, &width, &height); - struct wlr_box geometry; - client_get_geometry(c, &geometry); - clip_box = (struct wlr_box){ - .x = geometry.x, - .y = geometry.y, - .width = width, - .height = height, - }; + struct wlr_box geometry; + client_get_geometry(c, &geometry); + clip_box = (struct wlr_box){ + .x = geometry.x, + .y = geometry.y, + .width = width, + .height = height, + }; - if (client_is_x11(c)) { - clip_box.x = 0; - clip_box.y = 0; - } + if (client_is_x11(c)) { + clip_box.x = 0; + clip_box.y = 0; + } - offset = clip_to_hide(c, &clip_box); - apply_border(c, clip_box, offset.x, offset.y, current_corner_location); - client_draw_shadow(c); + offset = clip_to_hide(c, &clip_box); - surface_clip = clip_box; - surface_clip.width = surface_clip.width - 2 * c->bw; - surface_clip.height = surface_clip.height - 2 * c->bw; + surface_clip = clip_box; + surface_clip.width = surface_clip.width - 2 * c->bw; + surface_clip.height = surface_clip.height - 2 * c->bw; - if(surface_clip.width <= 0 || surface_clip.height <= 0) { - return; - } - wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); + if (surface_clip.width <= 0 || surface_clip.height <= 0) { + should_render_client_surface = false; + wlr_scene_node_set_enabled(&c->scene_surface->node, false); + } else { + should_render_client_surface = true; + wlr_scene_node_set_enabled(&c->scene_surface->node, true); + } - scale_data.should_scale = true; - scale_data.width = clip_box.width - 2 * c->bw; - scale_data.height = clip_box.height - 2 * c->bw; - scale_data.width_scale = (float)scale_data.width / (geometry.width - offset.x); - scale_data.height_scale = (float)scale_data.height / (geometry.height - offset.y); - scale_data.corner_location = current_corner_location; - scale_data.percent = c->animation.action == OPEN && animation_fade_in && !c->nofadein ? (double)c->animation.passed_frames / c->animation.total_frames : 1.0; - scale_data.opacity = c->isfullscreen ? 1 : c == selmon->sel ? c->focused_opacity : c->unfocused_opacity; - buffer_set_effect(c, scale_data); + apply_border(c, clip_box, offset.x, offset.y, current_corner_location); + client_draw_shadow(c); + + if (!should_render_client_surface) { + return; + } + + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); + + scale_data.should_scale = true; + scale_data.width = clip_box.width - 2 * c->bw; + scale_data.height = clip_box.height - 2 * c->bw; + scale_data.width_scale = + (float)scale_data.width / (geometry.width - offset.x); + scale_data.height_scale = + (float)scale_data.height / (geometry.height - offset.y); + scale_data.corner_location = current_corner_location; + scale_data.percent = + c->animation.action == OPEN && animation_fade_in && !c->nofadein + ? (double)c->animation.passed_frames / c->animation.total_frames + : 1.0; + scale_data.opacity = c->isfullscreen ? 1 + : c == selmon->sel ? c->focused_opacity + : c->unfocused_opacity; + buffer_set_effect(c, scale_data); } bool client_draw_frame(Client *c) { @@ -4713,22 +4742,24 @@ static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) { Client *c = user_data; - struct wlr_scene_surface * scene_surface = wlr_scene_surface_try_from_buffer(buffer); + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_try_from_buffer(buffer); if (!scene_surface) { return; } - struct wlr_surface *surface = scene_surface->surface; - /* we dont blur subsurfaces */ - if(wlr_subsurface_try_from_wlr_surface(surface) != NULL) return; + struct wlr_surface *surface = scene_surface->surface; + /* we dont blur subsurfaces */ + if (wlr_subsurface_try_from_wlr_surface(surface) != NULL) + return; if (blur && c) { - wlr_scene_buffer_set_backdrop_blur(buffer, true); - wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true); - wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true); + wlr_scene_buffer_set_backdrop_blur(buffer, true); + wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true); + wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true); } else { - wlr_scene_buffer_set_backdrop_blur(buffer, false); - } + wlr_scene_buffer_set_backdrop_blur(buffer, false); + } } void // old fix to 0.5 From 107c717d9f489502e0e17192e882acf20f113737 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 10:55:14 +0800 Subject: [PATCH 04/30] fix: no animaion can drag and scroller half window not enable --- src/maomao.c | 70 +++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 82bb0b0..99f2263 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1433,33 +1433,31 @@ void client_apply_clip(Client *c) { bool client_draw_frame(Client *c) { - if (!c || !client_surface(c)->mapped) - return false; + if (!c || !client_surface(c)->mapped) + return false; - if (c->isfullscreen) - client_set_opacity(c, 1); - else if (c == selmon->sel && !c->animation.running) { - client_set_opacity(c, c->focused_opacity); - } else if (!c->animation.running) { - client_set_opacity(c, c->unfocused_opacity); - } + if(c->isfullscreen) { + client_set_opacity(c, 1); + } else if(c == selmon->sel && !c->animation.running) { + client_set_opacity(c, c->focused_opacity); + } else if(!c->animation.running) { + client_set_opacity(c, c->unfocused_opacity); + } - if (!c->need_output_flush) - return false; + if (!c->need_output_flush) + return false; - if (animations && c->animation.running) { - client_animation_next_tick(c); - client_apply_clip(c); - } else { - if (!c->is_clip_to_hide) - wlr_scene_node_set_position(&c->scene->node, c->pending.x, - c->pending.y); - c->animainit_geom = c->animation.initial = c->pending = c->current = - c->geom; - client_apply_clip(c); - c->need_output_flush = false; - } - return true; + if (animations && c->animation.running) { + client_animation_next_tick(c); + client_apply_clip(c); + } else { + wlr_scene_node_set_position(&c->scene->node, c->pending.x, c->pending.y); + c->animainit_geom = c->animation.initial = c->pending = c->current = + c->geom; + client_apply_clip(c); + c->need_output_flush = false; + } + return true; } bool client_draw_fadeout_frame(Client *c) { @@ -5674,18 +5672,18 @@ void resize(Client *c, struct wlr_box geo, int interact) { c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); - if (c == grabc) { - c->animation.running = false; - c->need_output_flush = false; - c->animainit_geom = c->current = c->pending = c->animation.current = - c->geom; - apply_border(c, c->geom, 0, 0, CORNER_LOCATION_ALL); - client_draw_shadow(c); - client_get_clip(c, &clip); - wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); - return; - } - + if (c == grabc) { + c->animation.running = false; + c->need_output_flush = false; + c->animainit_geom = c->current = c->pending = c->animation.current = + c->geom; + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + apply_border(c, c->geom, 0, 0, CORNER_LOCATION_ALL); + client_draw_shadow(c); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + return; + } // 如果不是工作区切换时划出去的窗口,就让动画的结束位置,就是上面的真实位置和大小 // c->pending 决定动画的终点,一般在其他调用resize的函数的附近设置了 if (!c->animation.tagouting && !c->iskilling) { From a59b1040e47e99a3f4b55e61174bb5544e33e5a2 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 11:04:17 +0800 Subject: [PATCH 05/30] fix: Sometimes the window flashes when reresizing when there is no animation --- src/maomao.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/maomao.c b/src/maomao.c index 99f2263..950ffe3 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -5672,7 +5672,7 @@ void resize(Client *c, struct wlr_box geo, int interact) { c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); - if (c == grabc) { + if (!animations || c == grabc) { c->animation.running = false; c->need_output_flush = false; c->animainit_geom = c->current = c->pending = c->animation.current = From e0b8608cf0313ef965b90b485c078c33e16aebd5 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 11:20:27 +0800 Subject: [PATCH 06/30] fix: opacity winrule not apply --- src/config/parse_config.h | 4 +++ src/maomao.c | 75 ++++++++++++++++++++------------------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 97644ab..acf6861 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -1348,6 +1348,10 @@ void parse_config_line(Config *config, const char *line) { rule->isunglobal = atoi(val); } else if (strcmp(key, "isglobal") == 0) { rule->isglobal = atoi(val); + } else if (strcmp(key, "unfocused_opacity") == 0) { + rule->unfocused_opacity = atof(val); + } else if (strcmp(key, "focused_opacity") == 0) { + rule->focused_opacity = atof(val); } else if (strcmp(key, "isoverlay") == 0) { rule->isoverlay = atoi(val); } else if (strcmp(key, "isterm") == 0) { diff --git a/src/maomao.c b/src/maomao.c index 950ffe3..5e8eb84 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1433,31 +1433,32 @@ void client_apply_clip(Client *c) { bool client_draw_frame(Client *c) { - if (!c || !client_surface(c)->mapped) - return false; + if (!c || !client_surface(c)->mapped) + return false; - if(c->isfullscreen) { - client_set_opacity(c, 1); - } else if(c == selmon->sel && !c->animation.running) { - client_set_opacity(c, c->focused_opacity); - } else if(!c->animation.running) { - client_set_opacity(c, c->unfocused_opacity); - } + if (c->isfullscreen) { + client_set_opacity(c, 1); + } else if (c == selmon->sel && !c->animation.running) { + client_set_opacity(c, c->focused_opacity); + } else if (!c->animation.running) { + client_set_opacity(c, c->unfocused_opacity); + } - if (!c->need_output_flush) - return false; + if (!c->need_output_flush) + return false; - if (animations && c->animation.running) { - client_animation_next_tick(c); - client_apply_clip(c); - } else { - wlr_scene_node_set_position(&c->scene->node, c->pending.x, c->pending.y); - c->animainit_geom = c->animation.initial = c->pending = c->current = - c->geom; - client_apply_clip(c); - c->need_output_flush = false; - } - return true; + if (animations && c->animation.running) { + client_animation_next_tick(c); + client_apply_clip(c); + } else { + wlr_scene_node_set_position(&c->scene->node, c->pending.x, + c->pending.y); + c->animainit_geom = c->animation.initial = c->pending = c->current = + c->geom; + client_apply_clip(c); + c->need_output_flush = false; + } + return true; } bool client_draw_fadeout_frame(Client *c) { @@ -2029,9 +2030,9 @@ applyrules(Client *c) { c->isglobal = r->isglobal >= 0 ? r->isglobal : c->isglobal; c->isoverlay = r->isoverlay >= 0 ? r->isoverlay : c->isoverlay; c->isunglobal = r->isunglobal >= 0 ? r->isunglobal : c->isunglobal; - c->focused_opacity = r->focused_opacity > 0 ? r->focused_opacity - : c->focused_opacity; - c->unfocused_opacity = r->unfocused_opacity > 0 + c->focused_opacity = r->focused_opacity > 0.0f ? r->focused_opacity + : c->focused_opacity; + c->unfocused_opacity = r->unfocused_opacity > 0.0f ? r->unfocused_opacity : c->unfocused_opacity; @@ -5672,18 +5673,18 @@ void resize(Client *c, struct wlr_box geo, int interact) { c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); - if (!animations || c == grabc) { - c->animation.running = false; - c->need_output_flush = false; - c->animainit_geom = c->current = c->pending = c->animation.current = - c->geom; - wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); - apply_border(c, c->geom, 0, 0, CORNER_LOCATION_ALL); - client_draw_shadow(c); - client_get_clip(c, &clip); - wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); - return; - } + if (!animations || c == grabc) { + c->animation.running = false; + c->need_output_flush = false; + c->animainit_geom = c->current = c->pending = c->animation.current = + c->geom; + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + apply_border(c, c->geom, 0, 0, CORNER_LOCATION_ALL); + client_draw_shadow(c); + client_get_clip(c, &clip); + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + return; + } // 如果不是工作区切换时划出去的窗口,就让动画的结束位置,就是上面的真实位置和大小 // c->pending 决定动画的终点,一般在其他调用resize的函数的附近设置了 if (!c->animation.tagouting && !c->iskilling) { From 5e0787c111182b42e945a9bcbc9918359dc41011 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 11:32:00 +0800 Subject: [PATCH 07/30] opt: remove useless code --- src/maomao.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 5e8eb84..80c1e59 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -906,39 +906,14 @@ double find_animation_curve_at(double t, int type) { void apply_opacity_to_rect_nodes(Client *c, struct wlr_scene_node *node, double animation_passed) { - int offsetx = 0; - int offsety = 0; if (node->type == WLR_SCENE_NODE_RECT) { struct wlr_scene_rect *rect = wlr_scene_rect_from_node(node); // Assuming the rect has a color field and we can modify it - rect->color[0] = (1 - animation_passed) * rect->color[0]; - rect->color[1] = (1 - animation_passed) * rect->color[1]; - rect->color[2] = (1 - animation_passed) * rect->color[2]; - rect->color[3] = (1 - animation_passed) * rect->color[3]; + rect->color[0] = 0; + rect->color[1] = 0; + rect->color[2] = 0; + rect->color[3] = 0; wlr_scene_rect_set_color(rect, rect->color); - - offsetx = c->geom.width - c->animation.current.width; - offsety = c->geom.height - c->animation.current.height; - if (node->y > c->geom.y + c->geom.height / 2) { - wlr_scene_node_set_position(node, c->geom.x, - c->geom.y + c->geom.height - offsety); - wlr_scene_rect_set_size(rect, c->animation.current.width, - c->bw); // down - } else if (node->y < c->geom.y + c->geom.height / 2 && - rect->width > rect->height) { - wlr_scene_node_set_position(node, c->geom.x, c->geom.y); - wlr_scene_rect_set_size(rect, c->animation.current.width, - c->bw); // up - } else if (node->x < c->geom.x + c->geom.width / 2 && - rect->width < rect->height) { - wlr_scene_rect_set_size(rect, c->bw, - c->animation.current.height); // left - } else { - wlr_scene_node_set_position( - node, c->geom.x + c->geom.width - offsetx, c->geom.y); - wlr_scene_rect_set_size(rect, c->bw, - c->animation.current.height); // right - } } // If the node is a tree, recursively traverse its children From fda4cc7a0167a821ed2ac9e350ef8132bf9f88e6 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 11:59:43 +0800 Subject: [PATCH 08/30] opt: x11 app miss last frame scale --- src/maomao.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 80c1e59..fdc6058 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -5340,11 +5340,6 @@ void buffer_set_effect(Client *c, animationScale data) { data.should_scale = false; } - if (client_is_x11(c) && c->current.height >= c->animation.current.height && - c->current.width >= c->animation.current.width) { - data.should_scale = false; - } - if (c == grabc) data.should_scale = false; From 7f5cf991a345c5a2334f9b82f9b1573ecea18784 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 12:10:52 +0800 Subject: [PATCH 09/30] fix: opacitiy reset by default by wrong way --- src/config/parse_config.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index acf6861..ac5d201 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -2365,8 +2365,6 @@ void reload_config(const Arg *arg) { if (c && !c->iskilling) { if (c->bw) { c->bw = borderpx; - c->focused_opacity = focused_opacity; - c->unfocused_opacity = unfocused_opacity; } } } From be7d81d33748b01e1812d206241c46f8666d5236 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 12:12:36 +0800 Subject: [PATCH 10/30] fix: bw will reset by a wrong way --- src/config/parse_config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index ac5d201..2a825c4 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -2363,7 +2363,7 @@ void reload_config(const Arg *arg) { // reset border width when config change wl_list_for_each(c, &clients, link) { if (c && !c->iskilling) { - if (c->bw) { + if (c->bw && !c->isnoborder) { c->bw = borderpx; } } From eabb18b3698eb3945528fc517273d8fcdf704daf Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 14:04:49 +0800 Subject: [PATCH 11/30] feat: blur layer shell surface --- src/maomao.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/maomao.c b/src/maomao.c index fdc6058..61bc149 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1,6 +1,7 @@ /* * See LICENSE file for copyright and license details. */ +#include "wlr-layer-shell-unstable-v1-protocol.h" #include "wlr/util/box.h" #include #include @@ -3102,6 +3103,25 @@ void closemon(Monitor *m) { } } +static void iter_layer_scene_buffers(struct wlr_scene_buffer *buffer, int sx, + int sy, void *user_data) { + LayerSurface *l = user_data; + + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_try_from_buffer(buffer); + if (!scene_surface) { + return; + } + + if (blur && l) { + wlr_scene_buffer_set_backdrop_blur(buffer, true); + wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true); + wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true); + } else { + wlr_scene_buffer_set_backdrop_blur(buffer, false); + } +} + void commitlayersurfacenotify(struct wl_listener *listener, void *data) { LayerSurface *l = wl_container_of(listener, l, surface_commit); struct wlr_layer_surface_v1 *layer_surface = l->layer_surface; @@ -3147,6 +3167,15 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) { if (blur) { // Rerender the optimized blur on change struct wlr_layer_surface_v1 *wlr_layer_surface = l->layer_surface; + + if (wlr_layer_surface->current.layer != + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM && + wlr_layer_surface->current.layer != + ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) { + wlr_scene_node_for_each_buffer(&l->scene->node, + iter_layer_scene_buffers, l); + } + if (wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || wlr_layer_surface->current.layer == From 81b67cdec7d0225b13d832c31ce351cea2aadca1 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 14 Jun 2025 15:59:41 +0800 Subject: [PATCH 12/30] feat: focusmon dispatch support mon name --- src/config/parse_config.h | 3 +++ src/maomao.c | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 2a825c4..cda7823 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -700,6 +700,9 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, } else if (strcmp(func_name, "focusmon") == 0) { func = focusmon; (*arg).i = parse_direction(arg_value); + if((*arg).i == UNDIR) { + (*arg).v = strdup(arg_value); + } } else if (strcmp(func_name, "tagmon") == 0) { func = tagmon; (*arg).i = parse_direction(arg_value); diff --git a/src/maomao.c b/src/maomao.c index 61bc149..2930ff8 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -4211,11 +4211,24 @@ void focusclient(Client *c, int lift) { void focusmon(const Arg *arg) { Client *c; + Monitor *m = NULL; int i = 0, nmons = wl_list_length(&mons); - if (nmons) { + if (nmons && arg->i != UNDIR) { do /* don't switch to disabled mons */ selmon = dirtomon(arg->i); while (!selmon->wlr_output->enabled && i++ < nmons); + } else if(arg->v) { + wl_list_for_each(m, &mons, link) { + if (!m->wlr_output->enabled) { + continue; + } + if(regex_match(arg->v, m->wlr_output->name)) { + selmon = m; + break; + } + } + } else { + return; } warp_cursor_to_selmon(selmon); c = focustop(selmon); From 08166c69bc0a22e788b63d1caf2f96368c5285c1 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Wed, 18 Jun 2025 08:49:46 +0800 Subject: [PATCH 13/30] fix: border draw offset error --- src/maomao.c | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 51ada7e..1fb6286 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1168,6 +1168,18 @@ void apply_border(Client *c) { c->fake_no_border = false; } + struct wlr_box clip_box = c->animation.current; + + int right_offset = + GEZERO(c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width); + int bottom_offset = + GEZERO(c->animation.current.y + c->animation.current.height - + c->mon->m.y - c->mon->m.height); + + int left_offset = GEZERO(c->mon->m.x - c->animation.current.x); + int top_offset = GEZERO(c->mon->m.y - c->animation.current.y); + int clip_box_width = clip_box.width - 2 * c->bw; int clip_box_height = clip_box.height - 2 * c->bw; @@ -1179,8 +1191,8 @@ void apply_border(Client *c) { clip_box_height = 0; } - int clip_x = c->bw - offsetx; - int clip_y = c->bw - offsety; + int clip_x = c->bw - left_offset; + int clip_y = c->bw - top_offset; clip_x = clip_x < 0 ? 0 : clip_x; clip_y = clip_y < 0 ? 0 : clip_y; @@ -1191,14 +1203,19 @@ void apply_border(Client *c) { .corners = CORNER_LOCATION_ALL, }; - int right_offset = - GEZERO(c->animation.current.x + c->animation.current.width - - c->mon->m.x - c->mon->m.width); - int bottom_offset = - GEZERO(c->animation.current.y + c->animation.current.height - - c->mon->m.y - c->mon->m.height); - int rect_width = clip_box.width; - int rect_height = clip_box.height; + int node_x = left_offset; + int node_y = top_offset; + + int rect_width = c->animation.current.width - left_offset - right_offset; + int rect_height = c->animation.current.height - top_offset - bottom_offset; + + if (left_offset > c->bw) + clipped_region.area.width = + clipped_region.area.width - left_offset + c->bw; + + if (top_offset > c->bw) + clipped_region.area.height = + clipped_region.area.height - top_offset + c->bw; if (right_offset > 0) { clipped_region.area.width = @@ -1218,14 +1235,11 @@ void apply_border(Client *c) { rect_height = 0; } - int node_x = offsetx; - int node_y = offsety; - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); wlr_scene_rect_set_size(c->border, rect_width, rect_height); wlr_scene_node_set_position(&c->border->node, node_x, node_y); wlr_scene_rect_set_corner_radius(c->border, border_radius, - border_radius_location); + CORNER_LOCATION_ALL); wlr_scene_rect_set_clipped_region(c->border, clipped_region); } @@ -1374,8 +1388,8 @@ void client_apply_clip(Client *c) { apply_border(c); surface_clip = clip_box; - surface_clip.width = surface_clip.width - 2 * c->bw; - surface_clip.height = surface_clip.height - 2 * c->bw; + surface_clip.width = surface_clip.width - c->bw; + surface_clip.height = surface_clip.height - c->bw; if (surface_clip.width <= 0 || surface_clip.height <= 0) { should_render_client_surface = false; @@ -1385,7 +1399,7 @@ void client_apply_clip(Client *c) { wlr_scene_node_set_enabled(&c->scene_surface->node, true); } - apply_border(c, clip_box, offset.x, offset.y, current_corner_location); + apply_border(c); client_draw_shadow(c); if (!should_render_client_surface) { From f07be79f317d1d30d6e8613ce601ef2abd389e63 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Wed, 18 Jun 2025 10:51:23 +0800 Subject: [PATCH 14/30] feat: add blur_layer option --- src/config/parse_config.h | 5 +++++ src/config/preset_config.h | 1 + src/maomao.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index eb55396..3ea3c67 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -197,6 +197,7 @@ typedef struct { double accel_speed; int blur; + int blur_layer; int border_radius; struct blur_data blur_params; int shadows; @@ -891,6 +892,8 @@ void parse_config_line(Config *config, const char *line) { config->focus_cross_tag = atoi(value); } else if (strcmp(key, "blur") == 0) { config->blur = atoi(value); + } else if (strcmp(key, "blur_layer") == 0) { + config->blur_layer = atoi(value); } else if (strcmp(key, "border_radius") == 0) { config->border_radius = atoi(value); } else if (strcmp(key, "blur_params_num_passes") == 0) { @@ -2081,6 +2084,7 @@ void override_config(void) { smartgaps = CLAMP_INT(config.smartgaps, 0, 1); blur = CLAMP_INT(config.blur, 0, 1); + blur_layer = CLAMP_INT(config.blur_layer, 0, 1); border_radius = CLAMP_INT(config.border_radius, 0, 100); blur_params.num_passes = CLAMP_INT(config.blur_params.num_passes, 0, 10); blur_params.radius = CLAMP_INT(config.blur_params.radius, 0, 100); @@ -2209,6 +2213,7 @@ void set_value_default() { config.accel_speed = accel_speed; config.blur = blur; + config.blur_layer = blur_layer; config.border_radius = border_radius; config.blur_params.num_passes = blur_params_num_passes; config.blur_params.radius = blur_params_radius; diff --git a/src/config/preset_config.h b/src/config/preset_config.h index 1b5a1f0..e898689 100644 --- a/src/config/preset_config.h +++ b/src/config/preset_config.h @@ -187,6 +187,7 @@ float unfocused_opacity = 0.8; int border_radius = 0; int border_radius_location_default = CORNER_LOCATION_ALL; int blur = 0; +int blur_layer = 0; struct blur_data { int num_passes; diff --git a/src/maomao.c b/src/maomao.c index 1fb6286..154273e 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -3129,7 +3129,7 @@ static void iter_layer_scene_buffers(struct wlr_scene_buffer *buffer, int sx, return; } - if (blur && l) { + if (blur && blur_layer && l) { wlr_scene_buffer_set_backdrop_blur(buffer, true); wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true); wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true); From b3c70bed38cfac6cffc3bc02486acf5300a34b54 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Wed, 18 Jun 2025 12:53:56 +0800 Subject: [PATCH 15/30] opt: optimize code struce about border_draw --- src/maomao.c | 76 +++++++++++++++++++++------------------------------- 1 file changed, 30 insertions(+), 46 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 154273e..c1c9eda 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1169,6 +1169,8 @@ void apply_border(Client *c) { } struct wlr_box clip_box = c->animation.current; + // 一但在GEZERO如果使用无符号,那么其他数据也会转换为无符号导致没有负数出错 + int bw = (int)c->bw; int right_offset = GEZERO(c->animation.current.x + c->animation.current.width - @@ -1180,64 +1182,46 @@ void apply_border(Client *c) { int left_offset = GEZERO(c->mon->m.x - c->animation.current.x); int top_offset = GEZERO(c->mon->m.y - c->animation.current.y); - int clip_box_width = clip_box.width - 2 * c->bw; - int clip_box_height = clip_box.height - 2 * c->bw; + int inner_surface_width = GEZERO(clip_box.width - 2 * bw); + int inner_surface_height = GEZERO(clip_box.height - 2 * bw); - if (clip_box_width < 0) { - clip_box_width = 0; + int inner_surface_x = GEZERO(bw - left_offset); + int inner_surface_y = GEZERO(bw - top_offset); + + int rect_x = left_offset; + int rect_y = top_offset; + + int rect_width = + GEZERO(c->animation.current.width - left_offset - right_offset); + int rect_height = + GEZERO(c->animation.current.height - top_offset - bottom_offset); + + if (left_offset > c->bw) + inner_surface_width = inner_surface_width - left_offset + c->bw; + + if (top_offset > c->bw) + inner_surface_height = inner_surface_height - top_offset + c->bw; + + if (right_offset > 0) { + inner_surface_width = + MIN(clip_box.width, inner_surface_width + right_offset); } - if (clip_box_height < 0) { - clip_box_height = 0; + if (bottom_offset > 0) { + inner_surface_height = + MIN(clip_box.height, inner_surface_height + bottom_offset); } - int clip_x = c->bw - left_offset; - int clip_y = c->bw - top_offset; - - clip_x = clip_x < 0 ? 0 : clip_x; - clip_y = clip_y < 0 ? 0 : clip_y; - struct clipped_region clipped_region = { - .area = {clip_x, clip_y, clip_box_width, clip_box_height}, + .area = {inner_surface_x, inner_surface_y, inner_surface_width, + inner_surface_height}, .corner_radius = border_radius, .corners = CORNER_LOCATION_ALL, }; - int node_x = left_offset; - int node_y = top_offset; - - int rect_width = c->animation.current.width - left_offset - right_offset; - int rect_height = c->animation.current.height - top_offset - bottom_offset; - - if (left_offset > c->bw) - clipped_region.area.width = - clipped_region.area.width - left_offset + c->bw; - - if (top_offset > c->bw) - clipped_region.area.height = - clipped_region.area.height - top_offset + c->bw; - - if (right_offset > 0) { - clipped_region.area.width = - MIN(clip_box.width, clipped_region.area.width + right_offset); - } - - if (bottom_offset > 0) { - clipped_region.area.height = - MIN(clip_box.height, clipped_region.area.height + bottom_offset); - } - - if (rect_width < 0) { - rect_width = 0; - } - - if (rect_height < 0) { - rect_height = 0; - } - wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); wlr_scene_rect_set_size(c->border, rect_width, rect_height); - wlr_scene_node_set_position(&c->border->node, node_x, node_y); + wlr_scene_node_set_position(&c->border->node, rect_x, rect_y); wlr_scene_rect_set_corner_radius(c->border, border_radius, CORNER_LOCATION_ALL); wlr_scene_rect_set_clipped_region(c->border, clipped_region); From b981d1b0f15ec871b9d4441788be9d12475c831b Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Wed, 18 Jun 2025 16:08:46 +0800 Subject: [PATCH 16/30] opt: update blur node position --- src/maomao.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/maomao.c b/src/maomao.c index c1c9eda..f2d4683 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -3604,7 +3604,7 @@ void createmon(struct wl_listener *listener, void *data) { if (blur) { m->blur = wlr_scene_optimized_blur_create(&scene->tree, 0, 0); - // wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); + wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]); wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); // wlr_scene_node_set_enabled(&m->blur->node, 1); @@ -4341,6 +4341,7 @@ void requestmonstate(struct wl_listener *listener, void *data) { wlr_output_commit_state(event->output, event->state); if (blur) { + wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); } updatemons(NULL, NULL); @@ -7570,6 +7571,7 @@ void updatemons(struct wl_listener *listener, void *data) { // wlr_scene_rect_set_size(m->fullscreen_bg, m->m.width, m->m.height); if (blur && m->blur) { + wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); } From 8250775e05ea302ba940741e4c0dbc7b6b3f17eb Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Thu, 19 Jun 2025 09:45:21 +0800 Subject: [PATCH 17/30] fix: scroller window out of monitor when no animaiton --- src/maomao.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/maomao.c b/src/maomao.c index f2d4683..7954827 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -5715,7 +5715,7 @@ void resize(Client *c, struct wlr_box geo, int interact) { c->configure_serial = client_set_size(c, c->geom.width - 2 * c->bw, c->geom.height - 2 * c->bw); - if (!animations || c == grabc) { + if (c == grabc) { c->animation.running = false; c->need_output_flush = false; c->animainit_geom = c->current = c->pending = c->animation.current = From 1b97dd533e0dfb085794abd215f2754295a2ba56 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 21 Jun 2025 21:53:24 +0800 Subject: [PATCH 18/30] fix: The coordinates of the shadow position are allowed to be negative --- src/config/parse_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 3ea3c67..c9ff9a4 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -2095,8 +2095,8 @@ void override_config(void) { shadows = CLAMP_INT(config.shadows, 0, 1); shadows_size = CLAMP_INT(config.shadows_size, 0, 100); shadows_blur = CLAMP_INT(config.shadows_blur, 0, 100); - shadows_position_x = CLAMP_INT(config.shadows_position_x, 0, 100); - shadows_position_y = CLAMP_INT(config.shadows_position_y, 0, 100); + shadows_position_x = CLAMP_INT(config.shadows_position_x, -1000, 1000); + shadows_position_y = CLAMP_INT(config.shadows_position_y, -1000, 1000); focused_opacity = CLAMP_FLOAT(config.focused_opacity, 0.0f, 1.0f); unfocused_opacity = CLAMP_FLOAT(config.unfocused_opacity, 0.0f, 1.0f); memcpy(shadowscolor, config.shadowscolor, sizeof(shadowscolor)); From 7ded90021b8d85df5550ca86d57625322d3c2232 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 19:02:47 +0800 Subject: [PATCH 19/30] fix: error surface clip size when no animaitons --- src/maomao.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index b7adad2..74d3b25 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1283,8 +1283,8 @@ void client_apply_clip(Client *c) { client_draw_shadow(c); surface_clip = clip_box; - surface_clip.width = surface_clip.width - 2 * c->bw; - surface_clip.height = surface_clip.height - 2 * c->bw; + surface_clip.width = surface_clip.width - c->bw; + surface_clip.height = surface_clip.height - c->bw; if (surface_clip.width <= 0 || surface_clip.height <= 0) { return; From e1368e1121028390a2db31bbf5c0079a27416a6f Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 19:19:26 +0800 Subject: [PATCH 20/30] fix: error args for effect set when no animaiton --- src/maomao.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 74d3b25..e051768 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1269,6 +1269,14 @@ void client_apply_clip(Client *c) { enum corner_location current_corner_location = set_client_corner_location(c); + float percent = + c->animation.action == OPEN && animation_fade_in && !c->nofadein + ? (double)c->animation.passed_frames / c->animation.total_frames + : 1.0; + float opacity = c->isfullscreen ? 1 + : c == selmon->sel ? c->focused_opacity + : c->unfocused_opacity; + if (!animations) { c->animation.running = false; c->need_output_flush = false; @@ -1285,6 +1293,9 @@ void client_apply_clip(Client *c) { surface_clip = clip_box; surface_clip.width = surface_clip.width - c->bw; surface_clip.height = surface_clip.height - c->bw; + scale_data.opacity = c->isfullscreen ? 1 + : c == selmon->sel ? c->focused_opacity + : c->unfocused_opacity; if (surface_clip.width <= 0 || surface_clip.height <= 0) { return; @@ -1292,8 +1303,8 @@ void client_apply_clip(Client *c) { wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); - buffer_set_effect( - c, (animationScale){0, 0, 0, 0, current_corner_location, false}); + buffer_set_effect(c, (animationScale){0, 0, 0, 0, opacity, opacity, + current_corner_location, false}); return; } @@ -1347,13 +1358,8 @@ void client_apply_clip(Client *c) { scale_data.height_scale = (float)scale_data.height / (geometry.height - offset.y); scale_data.corner_location = current_corner_location; - scale_data.percent = - c->animation.action == OPEN && animation_fade_in && !c->nofadein - ? (double)c->animation.passed_frames / c->animation.total_frames - : 1.0; - scale_data.opacity = c->isfullscreen ? 1 - : c == selmon->sel ? c->focused_opacity - : c->unfocused_opacity; + scale_data.percent = percent; + scale_data.opacity = opacity; buffer_set_effect(c, scale_data); } From 139c3c484b488f6023ef6a97507981d104f9ee23 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 20:10:26 +0800 Subject: [PATCH 21/30] fix: error clip size in animaiton --- src/maomao.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index e051768..1285850 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1329,9 +1329,17 @@ void client_apply_clip(Client *c) { apply_border(c); + int bottom_out_offset = + GEZERO(c->animation.current.y - c->animation.current.height - + c->mon->m.y - c->mon->m.height); + int right_out_offset = + GEZERO(c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width); + int bw = (int)c->bw; + surface_clip = clip_box; - surface_clip.width = surface_clip.width - c->bw; - surface_clip.height = surface_clip.height - c->bw; + surface_clip.width = surface_clip.width - GEZERO(bw - right_out_offset); + surface_clip.height = surface_clip.height - GEZERO(bw - bottom_out_offset); if (surface_clip.width <= 0 || surface_clip.height <= 0) { should_render_client_surface = false; @@ -1351,8 +1359,8 @@ void client_apply_clip(Client *c) { wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); scale_data.should_scale = true; - scale_data.width = clip_box.width - c->bw; - scale_data.height = clip_box.height - c->bw; + scale_data.width = clip_box.width - GEZERO(bw - right_out_offset); + scale_data.height = clip_box.height - GEZERO(bw - bottom_out_offset); scale_data.width_scale = (float)scale_data.width / (geometry.width - offset.x); scale_data.height_scale = From eaba32056b85b26e08743b71d1ae5c264f54675c Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 21:26:37 +0800 Subject: [PATCH 22/30] fix: error surface size clip when no animation --- src/maomao.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 1285850..f3be54a 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1276,23 +1276,40 @@ void client_apply_clip(Client *c) { float opacity = c->isfullscreen ? 1 : c == selmon->sel ? c->focused_opacity : c->unfocused_opacity; + int bottom_out_offset = + GEZERO(c->animation.current.y - c->animation.current.height - + c->mon->m.y - c->mon->m.height); + int right_out_offset = + GEZERO(c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width); + int bw = (int)c->bw; if (!animations) { c->animation.running = false; c->need_output_flush = false; c->animainit_geom = c->current = c->pending = c->animation.current = c->geom; + client_get_clip(c, &clip_box); offset = clip_to_hide(c, &clip_box); + bottom_out_offset = + GEZERO(c->animation.current.y - c->animation.current.height - + c->mon->m.y - c->mon->m.height); + right_out_offset = + GEZERO(c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width); + apply_border(c); client_draw_shadow(c); surface_clip = clip_box; - surface_clip.width = surface_clip.width - c->bw; - surface_clip.height = surface_clip.height - c->bw; + surface_clip.width = surface_clip.width - GEZERO(bw - right_out_offset); + surface_clip.height = + surface_clip.height - GEZERO(bw - bottom_out_offset); + scale_data.opacity = c->isfullscreen ? 1 : c == selmon->sel ? c->focused_opacity : c->unfocused_opacity; @@ -1329,14 +1346,6 @@ void client_apply_clip(Client *c) { apply_border(c); - int bottom_out_offset = - GEZERO(c->animation.current.y - c->animation.current.height - - c->mon->m.y - c->mon->m.height); - int right_out_offset = - GEZERO(c->animation.current.x + c->animation.current.width - - c->mon->m.x - c->mon->m.width); - int bw = (int)c->bw; - surface_clip = clip_box; surface_clip.width = surface_clip.width - GEZERO(bw - right_out_offset); surface_clip.height = surface_clip.height - GEZERO(bw - bottom_out_offset); From 4c496307eb9535245bead186698fa86ccecf2b89 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 21:46:11 +0800 Subject: [PATCH 23/30] feat: add option no_radius_when_single --- src/config/parse_config.h | 5 +++++ src/config/preset.h | 1 + src/maomao.c | 14 +++++++++++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index c9ff9a4..4427648 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -149,6 +149,7 @@ typedef struct { int focus_cross_monitor; int focus_cross_tag; int no_border_when_single; + int no_radius_when_single; int snap_distance; int enable_floating_snap; int drag_tile_to_tile; @@ -926,6 +927,8 @@ void parse_config_line(Config *config, const char *line) { config->syncobj_enable = atoi(value); } else if (strcmp(key, "no_border_when_single") == 0) { config->no_border_when_single = atoi(value); + } else if (strcmp(key, "no_radius_when_single") == 0) { + config->no_radius_when_single = atoi(value); } else if (strcmp(key, "snap_distance") == 0) { config->snap_distance = atoi(value); } else if (strcmp(key, "enable_floating_snap") == 0) { @@ -2049,6 +2052,7 @@ void override_config(void) { snap_distance = CLAMP_INT(config.snap_distance, 0, 99999); cursor_size = CLAMP_INT(config.cursor_size, 4, 512); no_border_when_single = CLAMP_INT(config.no_border_when_single, 0, 1); + no_radius_when_single = CLAMP_INT(config.no_radius_when_single, 0, 1); cursor_hide_timeout = CLAMP_INT(config.cursor_hide_timeout, 0, 36000); // 0-10小时 drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1); @@ -2178,6 +2182,7 @@ void set_value_default() { config.xwayland_persistence = xwayland_persistence; config.syncobj_enable = syncobj_enable; config.no_border_when_single = no_border_when_single; + config.no_radius_when_single = no_radius_when_single; config.snap_distance = snap_distance; config.drag_tile_to_tile = drag_tile_to_tile; config.enable_floating_snap = enable_floating_snap; diff --git a/src/config/preset.h b/src/config/preset.h index e898689..10740ee 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -56,6 +56,7 @@ int scroller_prefer_center = 0; int focus_cross_monitor = 0; int focus_cross_tag = 0; int no_border_when_single = 0; +int no_radius_when_single = 0; int snap_distance = 30; int enable_floating_snap = 0; int drag_tile_to_tile = 0; diff --git a/src/maomao.c b/src/maomao.c index f3be54a..2b99fed 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1096,10 +1096,14 @@ void client_draw_shadow(Client *c) { } void apply_border(Client *c) { - if (c->iskilling || !client_surface(c)->mapped) + if (!c || c->iskilling || !client_surface(c)->mapped) return; bool hit_no_border = check_hit_no_border(c); + enum corner_location current_corner_location = + c->mon->visible_clients == 1 && no_radius_when_single + ? CORNER_LOCATION_NONE + : CORNER_LOCATION_ALL; // Handle no-border cases if (hit_no_border && smartgaps) { @@ -1163,14 +1167,14 @@ void apply_border(Client *c) { .area = {inner_surface_x, inner_surface_y, inner_surface_width, inner_surface_height}, .corner_radius = border_radius, - .corners = CORNER_LOCATION_ALL, + .corners = current_corner_location, }; wlr_scene_node_set_position(&c->scene_surface->node, c->bw, c->bw); wlr_scene_rect_set_size(c->border, rect_width, rect_height); wlr_scene_node_set_position(&c->border->node, rect_x, rect_y); wlr_scene_rect_set_corner_radius(c->border, border_radius, - CORNER_LOCATION_ALL); + current_corner_location); wlr_scene_rect_set_clipped_region(c->border, clipped_region); } @@ -5122,6 +5126,10 @@ void buffer_set_effect(Client *c, animationScale data) { if (c == grabc) data.should_scale = false; + if (c->mon->visible_clients == 1 && no_radius_when_single) { + data.corner_location = CORNER_LOCATION_NONE; + } + wlr_scene_node_for_each_buffer(&c->scene_surface->node, scene_buffer_apply_effect, &data); } From bff64274e4539823ca4df0c93d7fc74857ee5928 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 22:27:05 +0800 Subject: [PATCH 24/30] opt: avoid unnecessary calculations --- src/maomao.c | 55 ++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 2b99fed..73e53ed 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -153,7 +153,7 @@ struct dvec2 { }; struct ivec2 { - int x, y; + int x, y, width, height; }; typedef struct { @@ -1204,11 +1204,20 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { struct ivec2 offset; offset.x = 0; offset.y = 0; + offset.width = 0; + offset.height = 0; if (!ISTILED(c) && !c->animation.tagining && !c->animation.tagouted && !c->animation.tagouting) return offset; + int bottom_out_offset = + GEZERO(c->animation.current.y - c->animation.current.height - + c->mon->m.y - c->mon->m.height); + int right_out_offset = + GEZERO(c->animation.current.x + c->animation.current.width - + c->mon->m.x - c->mon->m.width); + // // make tagout tagin animations not visible in other monitors if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || c->animation.tagouting) { @@ -1217,11 +1226,8 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { offsetx = offsetx < 0 ? 0 : offsetx; clip_box->x = clip_box->x + offsetx; clip_box->width = clip_box->width - offsetx; - } else if (c->animation.current.x + c->animation.current.width > - c->mon->m.x + c->mon->m.width) { - clip_box->width = clip_box->width - (c->animation.current.x + - c->animation.current.width - - c->mon->m.x - c->mon->m.width); + } else if (right_out_offset > 0) { + clip_box->width = clip_box->width - right_out_offset; } if (c->animation.current.y < c->mon->m.y) { @@ -1229,17 +1235,15 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { offsety = offsety < 0 ? 0 : offsety; clip_box->y = clip_box->y + offsety; clip_box->height = clip_box->height - offsety; - } else if (c->animation.current.y + c->animation.current.height > - c->mon->m.y + c->mon->m.height) { - clip_box->height = - clip_box->height - - (c->animation.current.y + c->animation.current.height - - c->mon->m.y - c->mon->m.height); + } else if (bottom_out_offset > 0) { + clip_box->height = clip_box->height - bottom_out_offset; } } offset.x = offsetx; offset.y = offsety; + offset.width = right_out_offset; + offset.height = bottom_out_offset; if ((clip_box->width < 0 || clip_box->height < 0) && (ISTILED(c) || c->animation.tagouting || c->animation.tagining)) { @@ -1280,12 +1284,7 @@ void client_apply_clip(Client *c) { float opacity = c->isfullscreen ? 1 : c == selmon->sel ? c->focused_opacity : c->unfocused_opacity; - int bottom_out_offset = - GEZERO(c->animation.current.y - c->animation.current.height - - c->mon->m.y - c->mon->m.height); - int right_out_offset = - GEZERO(c->animation.current.x + c->animation.current.width - - c->mon->m.x - c->mon->m.width); + int bw = (int)c->bw; if (!animations) { @@ -1298,21 +1297,13 @@ void client_apply_clip(Client *c) { offset = clip_to_hide(c, &clip_box); - bottom_out_offset = - GEZERO(c->animation.current.y - c->animation.current.height - - c->mon->m.y - c->mon->m.height); - right_out_offset = - GEZERO(c->animation.current.x + c->animation.current.width - - c->mon->m.x - c->mon->m.width); - apply_border(c); client_draw_shadow(c); surface_clip = clip_box; - surface_clip.width = surface_clip.width - GEZERO(bw - right_out_offset); - surface_clip.height = - surface_clip.height - GEZERO(bw - bottom_out_offset); + surface_clip.width = surface_clip.width - GEZERO(bw - offset.width); + surface_clip.height = surface_clip.height - GEZERO(bw - offset.height); scale_data.opacity = c->isfullscreen ? 1 : c == selmon->sel ? c->focused_opacity @@ -1351,8 +1342,8 @@ void client_apply_clip(Client *c) { apply_border(c); surface_clip = clip_box; - surface_clip.width = surface_clip.width - GEZERO(bw - right_out_offset); - surface_clip.height = surface_clip.height - GEZERO(bw - bottom_out_offset); + surface_clip.width = surface_clip.width - GEZERO(bw - offset.width); + surface_clip.height = surface_clip.height - GEZERO(bw - offset.height); if (surface_clip.width <= 0 || surface_clip.height <= 0) { should_render_client_surface = false; @@ -1372,8 +1363,8 @@ void client_apply_clip(Client *c) { wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &surface_clip); scale_data.should_scale = true; - scale_data.width = clip_box.width - GEZERO(bw - right_out_offset); - scale_data.height = clip_box.height - GEZERO(bw - bottom_out_offset); + scale_data.width = clip_box.width - GEZERO(bw - offset.width); + scale_data.height = clip_box.height - GEZERO(bw - offset.height); scale_data.width_scale = (float)scale_data.width / (geometry.width - offset.x); scale_data.height_scale = From f3c33899bdb7870268e0ae1d2eb25ab988efcd07 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 22:32:53 +0800 Subject: [PATCH 25/30] fix: fix offset caculate for out clip --- src/maomao.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 73e53ed..92bfc8c 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1212,27 +1212,28 @@ struct ivec2 clip_to_hide(Client *c, struct wlr_box *clip_box) { return offset; int bottom_out_offset = - GEZERO(c->animation.current.y - c->animation.current.height - + GEZERO(c->animation.current.y + c->animation.current.height - c->mon->m.y - c->mon->m.height); int right_out_offset = GEZERO(c->animation.current.x + c->animation.current.width - c->mon->m.x - c->mon->m.width); + int left_out_offset = GEZERO(c->mon->m.x - c->animation.current.x); + int top_out_offset = GEZERO(c->mon->m.y - c->animation.current.y); + int bw = (int)c->bw; // // make tagout tagin animations not visible in other monitors if (ISTILED(c) || c->animation.tagining || c->animation.tagouted || c->animation.tagouting) { - if (c->animation.current.x < c->mon->m.x) { - offsetx = c->mon->m.x - c->bw - c->animation.current.x; - offsetx = offsetx < 0 ? 0 : offsetx; + if (left_out_offset > 0) { + offsetx = GEZERO(left_out_offset - bw); clip_box->x = clip_box->x + offsetx; clip_box->width = clip_box->width - offsetx; } else if (right_out_offset > 0) { clip_box->width = clip_box->width - right_out_offset; } - if (c->animation.current.y < c->mon->m.y) { - offsety = c->mon->m.y - c->bw - c->animation.current.y; - offsety = offsety < 0 ? 0 : offsety; + if (top_out_offset > 0) { + offsety = GEZERO(top_out_offset - bw); clip_box->y = clip_box->y + offsety; clip_box->height = clip_box->height - offsety; } else if (bottom_out_offset > 0) { From 26e326c7dc0a14b4a3d977839721d23209a1361a Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 22 Jun 2025 22:42:56 +0800 Subject: [PATCH 26/30] fix: fullscreen should no corner radius --- src/maomao.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index 92bfc8c..ae924fb 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1101,7 +1101,8 @@ void apply_border(Client *c) { bool hit_no_border = check_hit_no_border(c); enum corner_location current_corner_location = - c->mon->visible_clients == 1 && no_radius_when_single + c->isfullscreen || + (c->mon->visible_clients == 1 && no_radius_when_single) ? CORNER_LOCATION_NONE : CORNER_LOCATION_ALL; @@ -5118,7 +5119,8 @@ void buffer_set_effect(Client *c, animationScale data) { if (c == grabc) data.should_scale = false; - if (c->mon->visible_clients == 1 && no_radius_when_single) { + if (c->isfullscreen || + (c->mon->visible_clients == 1 && no_radius_when_single)) { data.corner_location = CORNER_LOCATION_NONE; } From c8b8e373c631c91d97d4adccb1fd917201078a4a Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 23 Jun 2025 11:31:17 +0800 Subject: [PATCH 27/30] fix: chase scenefx api change --- src/config/parse_config.h | 5 ++++- src/maomao.c | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 4427648..eeee7c2 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -2355,7 +2355,10 @@ void reset_blur_params(void) { m->blur = wlr_scene_optimized_blur_create(&scene->tree, 0, 0); wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]); wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); - wlr_scene_set_blur_data(scene, blur_params); + wlr_scene_set_blur_data( + scene, blur_params.num_passes, blur_params.radius, + blur_params.noise, blur_params.brightness, blur_params.contrast, + blur_params.saturation); } } else { Monitor *m; diff --git a/src/maomao.c b/src/maomao.c index ae924fb..a8d4766 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -6475,7 +6475,9 @@ void setup(void) { wl_signal_add(&output_mgr->events.test, &output_mgr_test); // blur - wlr_scene_set_blur_data(scene, blur_params); + wlr_scene_set_blur_data(scene, blur_params.num_passes, blur_params.radius, + blur_params.noise, blur_params.brightness, + blur_params.contrast, blur_params.saturation); /* create text_input-, and input_method-protocol relevant globals */ input_method_manager = wlr_input_method_manager_v2_create(dpy); From 51f5e52d3d81f167e6d0393ad59c4f5bfbee42c5 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 23 Jun 2025 13:06:05 +0800 Subject: [PATCH 28/30] fix: avoid operating null data --- src/maomao.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/maomao.c b/src/maomao.c index a8d4766..fdefb07 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -1101,8 +1101,8 @@ void apply_border(Client *c) { bool hit_no_border = check_hit_no_border(c); enum corner_location current_corner_location = - c->isfullscreen || - (c->mon->visible_clients == 1 && no_radius_when_single) + c->isfullscreen || (no_radius_when_single && c->mon && + c->mon->visible_clients == 1) ? CORNER_LOCATION_NONE : CORNER_LOCATION_ALL; @@ -5111,7 +5111,10 @@ void snap_scene_buffer_apply_effect(struct wlr_scene_buffer *buffer, int sx, void buffer_set_effect(Client *c, animationScale data) { - if (c->iskilling || c->animation.tagouting || c->animation.tagouted || + if (!c || c->iskilling) + return; + + if (c->animation.tagouting || c->animation.tagouted || c->animation.tagining) { data.should_scale = false; } @@ -5120,7 +5123,7 @@ void buffer_set_effect(Client *c, animationScale data) { data.should_scale = false; if (c->isfullscreen || - (c->mon->visible_clients == 1 && no_radius_when_single)) { + (no_radius_when_single && c->mon && c->mon->visible_clients == 1)) { data.corner_location = CORNER_LOCATION_NONE; } From 91738f25adc4f1444ebd3006f1581b4f728f81e9 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 24 Jun 2025 14:40:31 +0800 Subject: [PATCH 29/30] dep: update scenefx to 0.4 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index ae7f80c..dc15884 100644 --- a/meson.build +++ b/meson.build @@ -38,7 +38,7 @@ xkbcommon_dep = dependency('xkbcommon') libinput_dep = dependency('libinput') libwayland_client_dep = dependency('wayland-client') pcre2_dep = dependency('libpcre2-8') -libscenefx_dep = dependency('scenefx-0.3') +libscenefx_dep = dependency('scenefx-0.4') # 获取 Git Commit Hash 和最新的 tag From 58e1cd945dc495732a0f3edbea8171e5732c1c5e Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 24 Jun 2025 14:55:18 +0800 Subject: [PATCH 30/30] update readme --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 5bc023b..bc50245 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ This project's development is based on [dwl](https://codeberg.org/dwl/dwl/). - Sway-like scratchpad and named scratchpad - Minimize window to scratchpad - Hycov-like overview + - Window effects from scenefx(blur, shadow, corner radius, opacity) Master-Stack Layout @@ -58,6 +59,11 @@ cd wlroots meson build -Dprefix=/usr sudo ninja -C build install +git clone https://github.com/wlrfx/scenefx.git +cd scenefx +meson build -Dprefix=/usr +sudo ninja -C build install + git clone https://github.com/DreamMaoMao/maomaowm.git cd maomaowm meson build -Dprefix=/usr @@ -176,3 +182,5 @@ Here's an example of using the modules in a flake: - https://codeberg.org/dwl/dwl - Basal dwl feature - https://github.com/swaywm/sway - Sample of Wayland protocol + +- https://github.com/wlrfx/scenefx - Make it simple to add window effect. \ No newline at end of file