From 58790c0e538910f4c77240ef21f2472354f495c0 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Fri, 7 Nov 2025 10:02:51 +0800 Subject: [PATCH 01/18] fix: adjust scenefx blur node feature --- src/animation/client.h | 12 +++++++++++ src/animation/common.h | 8 ++------ src/animation/layer.h | 4 ++++ src/mango.c | 46 +++++++++++++++++++++++++++--------------- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/animation/client.h b/src/animation/client.h index 90b664b5..e9459d55 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -245,6 +245,13 @@ void buffer_set_effect(Client *c, BufferData data) { data.corner_location = CORNER_LOCATION_NONE; } + if (blur && !c->noblur) { + wlr_scene_blur_set_size(c->blur, c->animation.current.width - 2 * c->bw, + c->animation.current.height - 2 * c->bw); + + wlr_scene_blur_set_corner_radius(c->blur, border_radius, + data.corner_location); + } wlr_scene_node_for_each_buffer(&c->scene_surface->node, scene_buffer_apply_effect, &data); } @@ -535,6 +542,7 @@ void client_apply_clip(Client *c, float factor) { } wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip_box); + buffer_set_effect(c, (BufferData){1.0f, 1.0f, clip_box.width, clip_box.height, current_corner_location, true}); @@ -987,6 +995,10 @@ void resize(Client *c, struct wlr_box geo, int interact) { apply_border(c); client_get_clip(c, &clip); wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + if (blur && !c->noblur) + wlr_scene_blur_set_size(c->blur, + c->animation.current.width - 2 * c->bw, + c->animation.current.height - 2 * c->bw); return; } // 如果不是工作区切换时划出去的窗口,就让动画的结束位置,就是上面的真实位置和大小 diff --git a/src/animation/common.h b/src/animation/common.h index 06ffe1ab..7079df86 100644 --- a/src/animation/common.h +++ b/src/animation/common.h @@ -158,12 +158,6 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, 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; struct wlr_scene_surface *scene_surface = @@ -198,6 +192,8 @@ static bool scene_node_snapshot(struct wlr_scene_node *node, int lx, int ly, break; } + case WLR_SCENE_NODE_BLUR: + break; case WLR_SCENE_NODE_OPTIMIZED_BLUR: return true; } diff --git a/src/animation/layer.h b/src/animation/layer.h index 48ceb211..80caec56 100644 --- a/src/animation/layer.h +++ b/src/animation/layer.h @@ -356,6 +356,10 @@ void layer_animation_next_tick(LayerSurface *l) { .height = height, }; + if (blur && blur_layer && !l->noblur && l->blur) + wlr_scene_blur_set_size(l->blur, l->animation.current.width, + l->animation.current.height); + if (animation_passed >= 1.0) { l->animation.running = false; l->need_output_flush = false; diff --git a/src/mango.c b/src/mango.c index 36cbbbfa..69208d63 100644 --- a/src/mango.c +++ b/src/mango.c @@ -276,6 +276,7 @@ struct Client { struct wlr_scene_tree *scene; struct wlr_scene_rect *border; /* top, bottom, left, right */ struct wlr_scene_shadow *shadow; + struct wlr_scene_blur *blur; struct wlr_scene_tree *scene_surface; struct wl_list link; struct wl_list flink; @@ -405,6 +406,7 @@ typedef struct { struct wlr_scene_tree *scene; struct wlr_scene_tree *popups; struct wlr_scene_shadow *shadow; + struct wlr_scene_blur *blur; struct wlr_scene_layer_surface_v1 *scene_layer; struct wl_list link; struct wl_list fadeout_link; @@ -2081,12 +2083,16 @@ static void iter_layer_scene_buffers(struct wlr_scene_buffer *buffer, int sx, return; } - wlr_scene_buffer_set_backdrop_blur(buffer, true); - wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, true); + LayerSurface *l = (LayerSurface *)user_data; + + wlr_scene_node_set_enabled(&l->blur->node, true); + wlr_scene_blur_set_transparency_mask_source(l->blur, buffer); + wlr_scene_blur_set_size(l->blur, l->geom.width, l->geom.height); + if (blur_optimized) { - wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true); + wlr_scene_blur_set_should_only_blur_bottom_layer(l->blur, true); } else { - wlr_scene_buffer_set_backdrop_blur_optimized(buffer, false); + wlr_scene_blur_set_should_only_blur_bottom_layer(l->blur, false); } } @@ -2131,13 +2137,17 @@ void maplayersurfacenotify(struct wl_listener *listener, void *data) { } // 初始化阴影 - if (layer_surface->current.exclusive_zone == 0 && - layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM && + if (layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM && layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) { - l->shadow = wlr_scene_shadow_create(l->scene, 0, 0, border_radius, - shadows_blur, shadowscolor); - wlr_scene_node_lower_to_bottom(&l->shadow->node); - wlr_scene_node_set_enabled(&l->shadow->node, true); + if (layer_surface->current.exclusive_zone == 0) { + l->shadow = wlr_scene_shadow_create(l->scene, 0, 0, border_radius, + shadows_blur, shadowscolor); + wlr_scene_node_lower_to_bottom(&l->shadow->node); + wlr_scene_node_set_enabled(&l->shadow->node, true); + } + + l->blur = wlr_scene_blur_create(l->scene, 0, 0); + wlr_scene_node_lower_to_bottom(&l->blur->node); } // 初始化动画 @@ -2194,7 +2204,8 @@ void commitlayersurfacenotify(struct wl_listener *listener, void *data) { if (!l->noblur && layer_surface->current.layer != ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM && layer_surface->current.layer != - ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND) { + ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND && + l->blur) { wlr_scene_node_for_each_buffer(&l->scene->node, iter_layer_scene_buffers, l); @@ -3521,15 +3532,15 @@ static void iter_xdg_scene_buffers(struct wlr_scene_buffer *buffer, int sx, return; if (blur && c && !c->noblur) { - wlr_scene_buffer_set_backdrop_blur(buffer, true); - wlr_scene_buffer_set_backdrop_blur_ignore_transparent(buffer, false); + wlr_scene_node_set_enabled(&c->blur->node, true); + // wlr_scene_blur_set_transparency_mask_source(c->blur, buffer); if (blur_optimized) { - wlr_scene_buffer_set_backdrop_blur_optimized(buffer, true); + wlr_scene_blur_set_should_only_blur_bottom_layer(c->blur, true); } else { - wlr_scene_buffer_set_backdrop_blur_optimized(buffer, false); + wlr_scene_blur_set_should_only_blur_bottom_layer(c->blur, false); } } else { - wlr_scene_buffer_set_backdrop_blur(buffer, false); + wlr_scene_node_set_enabled(&c->blur->node, false); } } @@ -3642,6 +3653,9 @@ mapnotify(struct wl_listener *listener, void *data) { c->shadow = wlr_scene_shadow_create(c->scene, 0, 0, border_radius, shadows_blur, shadowscolor); + c->blur = wlr_scene_blur_create(c->scene_surface, 0, 0); + wlr_scene_node_lower_to_bottom(&c->blur->node); + wlr_scene_node_lower_to_bottom(&c->shadow->node); wlr_scene_node_set_enabled(&c->shadow->node, true); From 9b97d11c836857d6db691a7341a36998a989acd6 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Fri, 7 Nov 2025 21:56:25 +0800 Subject: [PATCH 02/18] fix: crash when click waybar overview button --- src/ext-protocol/ext-workspace.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ext-protocol/ext-workspace.h b/src/ext-protocol/ext-workspace.h index 61e36da3..930e6c98 100644 --- a/src/ext-protocol/ext-workspace.h +++ b/src/ext-protocol/ext-workspace.h @@ -47,6 +47,11 @@ static void handle_ext_workspace_activate(struct wl_listener *listener, void *data) { struct workspace *workspace = wl_container_of(listener, workspace, activate); + + if (workspace->m->isoverview) { + return; + } + goto_workspace(workspace); wlr_log(WLR_INFO, "ext activating workspace %d", workspace->tag); } @@ -55,6 +60,11 @@ static void handle_ext_workspace_deactivate(struct wl_listener *listener, void *data) { struct workspace *workspace = wl_container_of(listener, workspace, deactivate); + + if (workspace->m->isoverview) { + return; + } + toggle_workspace(workspace); wlr_log(WLR_INFO, "ext deactivating workspace %d", workspace->tag); } From 16dc4fa9cdb5327514d4f2777631a5957323313c Mon Sep 17 00:00:00 2001 From: eater <=@eater.me> Date: Fri, 7 Nov 2025 15:44:47 +0100 Subject: [PATCH 03/18] check is drm_release_manager is set before cleaning up to avoid segfault --- src/mango.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mango.c b/src/mango.c index 69208d63..54ca7116 100644 --- a/src/mango.c +++ b/src/mango.c @@ -1966,7 +1966,9 @@ void cleanuplisteners(void) { wl_list_remove(&request_start_drag.link); wl_list_remove(&start_drag.link); wl_list_remove(&new_session_lock.link); - wl_list_remove(&drm_lease_request.link); + if (drm_lease_manager) { + wl_list_remove(&drm_lease_request.link); + } wl_list_remove(&tearing_new_object.link); #ifdef XWAYLAND wl_list_remove(&new_xwayland_surface.link); From a42939f0c2b64e365494d67c41fd4dc95238ae7b Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 10:35:16 +0800 Subject: [PATCH 04/18] feat: add global option scroller_ignore_proportion_single --- src/config/parse_config.h | 7 +++++++ src/config/preset.h | 1 + src/layout/horizontal.h | 6 +++++- src/layout/vertical.h | 9 ++++++++- 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 19e64b70..30e118e8 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -193,6 +193,7 @@ typedef struct { int scroller_structs; float scroller_default_proportion; float scroller_default_proportion_single; + int scroller_ignore_proportion_single; int scroller_focus_center; int scroller_prefer_center; int edge_scroller_pointer_focus; @@ -1210,6 +1211,8 @@ void parse_option(Config *config, char *key, char *value) { config->scroller_default_proportion = atof(value); } else if (strcmp(key, "scroller_default_proportion_single") == 0) { config->scroller_default_proportion_single = atof(value); + } else if (strcmp(key, "scroller_ignore_proportion_single") == 0) { + config->scroller_ignore_proportion_single = atoi(value); } else if (strcmp(key, "scroller_focus_center") == 0) { config->scroller_focus_center = atoi(value); } else if (strcmp(key, "scroller_prefer_center") == 0) { @@ -2665,6 +2668,8 @@ void override_config(void) { CLAMP_FLOAT(config.scroller_default_proportion, 0.1f, 1.0f); scroller_default_proportion_single = CLAMP_FLOAT(config.scroller_default_proportion_single, 0.1f, 1.0f); + scroller_ignore_proportion_single = + CLAMP_INT(config.scroller_ignore_proportion_single, 0, 1); scroller_focus_center = CLAMP_INT(config.scroller_focus_center, 0, 1); scroller_prefer_center = CLAMP_INT(config.scroller_prefer_center, 0, 1); edge_scroller_pointer_focus = @@ -2852,6 +2857,8 @@ void set_value_default() { config.scroller_default_proportion = scroller_default_proportion; config.scroller_default_proportion_single = scroller_default_proportion_single; + config.scroller_ignore_proportion_single = + scroller_ignore_proportion_single; config.scroller_focus_center = scroller_focus_center; config.scroller_prefer_center = scroller_prefer_center; config.edge_scroller_pointer_focus = edge_scroller_pointer_focus; diff --git a/src/config/preset.h b/src/config/preset.h index 2f994ec1..be1c1b0a 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -60,6 +60,7 @@ float scratchpad_height_ratio = 0.9; int scroller_structs = 20; float scroller_default_proportion = 0.9; float scroller_default_proportion_single = 1.0; +int scroller_ignore_proportion_single = 0; int scroller_focus_center = 0; int scroller_prefer_center = 0; int focus_cross_monitor = 0; diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index b2d76bb3..178ae9e0 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -231,7 +231,7 @@ void scroller(Monitor *m) { } } - if (n == 1) { + if (n == 1 && !scroller_ignore_proportion_single) { c = tempClients[0]; target_geom.height = m->w.height - 2 * cur_gappov; target_geom.width = @@ -274,6 +274,10 @@ void scroller(Monitor *m) { } } + if (n == 1 && scroller_ignore_proportion_single) { + need_scroller = true; + } + if (start_drag_window) need_scroller = false; diff --git a/src/layout/vertical.h b/src/layout/vertical.h index 3c744639..6ae21a6c 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -192,7 +192,7 @@ void vertical_scroller(Monitor *m) { } } - if (n == 1) { + if (n == 1 && !scroller_ignore_proportion_single) { c = tempClients[0]; target_geom.width = m->w.width - 2 * cur_gappoh; target_geom.height = @@ -235,6 +235,13 @@ void vertical_scroller(Monitor *m) { } } + if (n == 1 && scroller_ignore_proportion_single) { + need_scroller = true; + } + + if (start_drag_window) + need_scroller = false; + target_geom.width = m->w.width - 2 * cur_gappoh; target_geom.height = max_client_height * c->scroller_proportion; target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; From c51cf7d6cce3fe5767d2681a03f9002e5db3d2cc Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 12:39:41 +0800 Subject: [PATCH 05/18] opt:optimize code struct --- src/mango.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mango.c b/src/mango.c index 54ca7116..e1e7703e 100644 --- a/src/mango.c +++ b/src/mango.c @@ -1966,10 +1966,10 @@ void cleanuplisteners(void) { wl_list_remove(&request_start_drag.link); wl_list_remove(&start_drag.link); wl_list_remove(&new_session_lock.link); + wl_list_remove(&tearing_new_object.link); if (drm_lease_manager) { wl_list_remove(&drm_lease_request.link); } - wl_list_remove(&tearing_new_object.link); #ifdef XWAYLAND wl_list_remove(&new_xwayland_surface.link); wl_list_remove(&xwayland_ready.link); From 9fecdb6c3ab0954190d57f34a035c2069a4bf99f Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 19:59:05 +0800 Subject: [PATCH 06/18] fix: blur node size and position are wrong --- src/animation/client.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/animation/client.h b/src/animation/client.h index e9459d55..3792358d 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -246,9 +246,6 @@ void buffer_set_effect(Client *c, BufferData data) { } if (blur && !c->noblur) { - wlr_scene_blur_set_size(c->blur, c->animation.current.width - 2 * c->bw, - c->animation.current.height - 2 * c->bw); - wlr_scene_blur_set_corner_radius(c->blur, border_radius, data.corner_location); } @@ -352,6 +349,14 @@ void client_draw_shadow(Client *c) { wlr_scene_shadow_set_clipped_region(c->shadow, clipped_region); } +void client_draw_blur(Client *c, struct wlr_box clip_box, struct ivec2 offset) { + if (blur && !c->noblur) { + wlr_scene_node_set_position(&c->blur->node, offset.x, offset.y); + wlr_scene_blur_set_size(c->blur, clip_box.width - c->bw, + clip_box.height - c->bw); + } +} + void apply_border(Client *c) { if (!c || c->iskilling || !client_surface(c)->mapped) return; @@ -536,6 +541,7 @@ void client_apply_clip(Client *c, float factor) { apply_border(c); client_draw_shadow(c); + client_draw_blur(c, clip_box, offset); if (clip_box.width <= 0 || clip_box.height <= 0) { return; @@ -574,6 +580,7 @@ void client_apply_clip(Client *c, float factor) { // 应用窗口装饰 apply_border(c); client_draw_shadow(c); + client_draw_blur(c, clip_box, offset); // 如果窗口剪切区域已经剪切到0,则不渲染窗口表面 if (clip_box.width <= 0 || clip_box.height <= 0) { From e59b9c10b5c3d7a09c3c01270442bb9107edc0b9 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 20:10:11 +0800 Subject: [PATCH 07/18] opt: optimize shadow node and blur node enable --- src/animation/client.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/animation/client.h b/src/animation/client.h index 3792358d..70da39e9 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -259,8 +259,12 @@ void client_draw_shadow(Client *c) { return; if (!shadows || (!c->isfloating && shadow_only_floating)) { - wlr_scene_shadow_set_size(c->shadow, 0, 0); + if (c->shadow->node.enabled) + wlr_scene_node_set_enabled(&c->shadow->node, false); return; + } else { + if (c->scene_surface->node.enabled && !c->shadow->node.enabled) + wlr_scene_node_set_enabled(&c->shadow->node, true); } bool hit_no_border = check_hit_no_border(c); @@ -351,9 +355,14 @@ void client_draw_shadow(Client *c) { void client_draw_blur(Client *c, struct wlr_box clip_box, struct ivec2 offset) { if (blur && !c->noblur) { + if (c->scene_surface->node.enabled && !c->blur->node.enabled) + wlr_scene_node_set_enabled(&c->blur->node, true); wlr_scene_node_set_position(&c->blur->node, offset.x, offset.y); wlr_scene_blur_set_size(c->blur, clip_box.width - c->bw, clip_box.height - c->bw); + } else { + if (c->blur->node.enabled) + wlr_scene_node_set_enabled(&c->blur->node, false); } } From 8ac331aa64e07867258a3bfdb7724e9a6127f812 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 20:17:16 +0800 Subject: [PATCH 08/18] opt: disable resize scroller window when it force to default single size --- src/layout/arrange.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/layout/arrange.h b/src/layout/arrange.h index 4df97865..b53592f3 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -374,6 +374,10 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int offsetx, int offsety, float delta_x, delta_y; float new_scroller_proportion; + if (grabc && grabc->mon->visible_tiling_clients == 1 && + !scroller_ignore_proportion_single) + return; + if (!start_drag_window && isdrag) { drag_begin_cursorx = cursor->x; drag_begin_cursory = cursor->y; From ee789613ff06f39f2f46b4d4eec5a8a3c45c390e Mon Sep 17 00:00:00 2001 From: Yappaholic Date: Sat, 8 Nov 2025 16:43:20 +0300 Subject: [PATCH 09/18] nix: bump scenefx flake and fix build --- flake.lock | 46 ++++++++++++++++++++++++++++++++++++++++++---- flake.nix | 5 +++-- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 2917a6fd..6ed92805 100644 --- a/flake.lock +++ b/flake.lock @@ -18,6 +18,27 @@ "type": "github" } }, + "flake-utils": { + "inputs": { + "systems": [ + "scenefx", + "systems" + ] + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1750386251, @@ -58,16 +79,18 @@ }, "scenefx": { "inputs": { + "flake-utils": "flake-utils", "nixpkgs": [ "nixpkgs" - ] + ], + "systems": "systems" }, "locked": { - "lastModified": 1750785057, - "narHash": "sha256-tGX6j4W91rcb+glXJo43sjPI9zQvPotonknG1BdihR4=", + "lastModified": 1762447505, + "narHash": "sha256-VEBQ8KXkSS4c+kdAhmvq06lEd9WNeCXdRK1U+qSilFw=", "owner": "wlrfx", "repo": "scenefx", - "rev": "3a6cfb12e4ba97b43326357d14f7b3e40897adfc", + "rev": "7f9e7409f6169fa637f1265895c121a8f8b70272", "type": "github" }, "original": { @@ -75,6 +98,21 @@ "repo": "scenefx", "type": "github" } + }, + "systems": { + "locked": { + "lastModified": 1689347949, + "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", + "owner": "nix-systems", + "repo": "default-linux", + "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default-linux", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index b7158bbd..0207cd49 100644 --- a/flake.nix +++ b/flake.nix @@ -25,12 +25,13 @@ perSystem = { config, + system, pkgs, ... }: let - inherit (pkgs) callPackage ; + inherit (pkgs) callPackage; mango = callPackage ./nix { - inherit (inputs.scenefx.packages.${pkgs.stdenv.hostPlatform.system}) scenefx; + scenefx = inputs.scenefx.packages.${system}.default; }; shellOverride = old: { nativeBuildInputs = old.nativeBuildInputs ++ []; From 276560840b43fc4ad790eebdbfadefb3288e6375 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 22:47:18 +0800 Subject: [PATCH 10/18] opt: remove increase_proportion dispatch should use resizewin to replace it --- src/config/parse_config.h | 3 --- src/dispatch/bind_declare.h | 1 - src/dispatch/bind_define.h | 12 ------------ 3 files changed, 16 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 30e118e8..321de209 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -887,9 +887,6 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, } else if (strcmp(func_name, "set_proportion") == 0) { func = set_proportion; (*arg).f = atof(arg_value); - } else if (strcmp(func_name, "increase_proportion") == 0) { - func = increase_proportion; - (*arg).f = atof(arg_value); } else if (strcmp(func_name, "switch_proportion_preset") == 0) { func = switch_proportion_preset; } else if (strcmp(func_name, "viewtoleft") == 0) { diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index b38e2da5..5bc215a2 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -4,7 +4,6 @@ int toggle_scratchpad(const Arg *arg); int focusdir(const Arg *arg); int toggleoverview(const Arg *arg); int set_proportion(const Arg *arg); -int increase_proportion(const Arg *arg); int switch_proportion_preset(const Arg *arg); int zoom(const Arg *arg); int tagsilent(const Arg *arg); diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 57288b4c..464e2a6c 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -281,18 +281,6 @@ int incovgaps(const Arg *arg) { return 0; } -int increase_proportion(const Arg *arg) { - if (selmon->sel) { - unsigned int max_client_width = - selmon->w.width - 2 * scroller_structs - gappih; - selmon->sel->scroller_proportion = - MIN(MAX(arg->f + selmon->sel->scroller_proportion, 0.1), 1.0); - selmon->sel->geom.width = max_client_width * arg->f; - arrange(selmon, false); - } - return 0; -} - int setmfact(const Arg *arg) { float f; Client *c = NULL; From 3cfcaa21c0645b11ac94a83bfb95516d0f837bcd Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 22:48:53 +0800 Subject: [PATCH 11/18] opt: not resizewin in overview --- src/layout/arrange.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/layout/arrange.h b/src/layout/arrange.h index b53592f3..aafb79e0 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -479,6 +479,9 @@ void resize_tile_client(Client *grabc, bool isdrag, int offsetx, int offsety, if (!grabc || grabc->isfullscreen || grabc->ismaximizescreen) return; + if (grabc->mon->isoverview) + return; + const Layout *current_layout = grabc->mon->pertag->ltidxs[grabc->mon->pertag->curtag]; if (current_layout->id == TILE || current_layout->id == DECK || From 11dfab478a2b1d1e149751ac6a76a30c6eb5ed43 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 8 Nov 2025 23:26:52 +0800 Subject: [PATCH 12/18] opt: disable switch proportion action in some case --- src/dispatch/bind_define.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 464e2a6c..65c2b03e 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -518,6 +518,14 @@ int setkeymode(const Arg *arg) { } int set_proportion(const Arg *arg) { + + if (selmon->isoverview || !is_scroller_layout(selmon)) + return 0; + + if (selmon->visible_tiling_clients == 1 && + !scroller_ignore_proportion_single) + return 0; + if (selmon->sel) { unsigned int max_client_width = selmon->w.width - 2 * scroller_structs - gappih; @@ -919,6 +927,13 @@ int switch_proportion_preset(const Arg *arg) { return 0; } + if (selmon->isoverview || !is_scroller_layout(selmon)) + return 0; + + if (selmon->visible_tiling_clients == 1 && + !scroller_ignore_proportion_single) + return 0; + if (selmon->sel) { for (int i = 0; i < config.scroller_proportion_preset_count; i++) { From c20669325797b3141e4883bcf65caca6a680f1ef Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 9 Nov 2025 15:40:51 +0800 Subject: [PATCH 13/18] feat: support nofucs rule for some special window --- src/config/parse_config.h | 4 ++++ src/mango.c | 42 +++++++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 321de209..0e9e15c5 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -77,6 +77,7 @@ typedef struct { int offsety; int width; int height; + int nofocus; int nofadein; int nofadeout; int no_force_center; @@ -1716,6 +1717,7 @@ void parse_option(Config *config, char *key, char *value) { rule->force_tearing = -1; rule->noswallow = -1; rule->noblur = -1; + rule->nofocus = -1; rule->nofadein = -1; rule->nofadeout = -1; rule->no_force_center = -1; @@ -1770,6 +1772,8 @@ void parse_option(Config *config, char *key, char *value) { rule->offsetx = atoi(val); } else if (strcmp(key, "offsety") == 0) { rule->offsety = atoi(val); + } else if (strcmp(key, "nofocus") == 0) { + rule->nofocus = atoi(val); } else if (strcmp(key, "nofadein") == 0) { rule->nofadein = atoi(val); } else if (strcmp(key, "nofadeout") == 0) { diff --git a/src/mango.c b/src/mango.c index e1e7703e..74345bd5 100644 --- a/src/mango.c +++ b/src/mango.c @@ -353,6 +353,7 @@ struct Client { bool drag_to_tile; bool scratchpad_switching_mon; bool fake_no_border; + int nofocus; int nofadein; int nofadeout; int no_force_center; @@ -1132,6 +1133,7 @@ static void apply_rule_properties(Client *c, const ConfigWinRule *r) { APPLY_INT_PROP(c, r, force_maximize); APPLY_INT_PROP(c, r, force_tearing); APPLY_INT_PROP(c, r, noswallow); + APPLY_INT_PROP(c, r, nofocus); APPLY_INT_PROP(c, r, nofadein); APPLY_INT_PROP(c, r, nofadeout); APPLY_INT_PROP(c, r, no_force_center); @@ -1245,11 +1247,16 @@ void applyrules(Client *c) { const char *appid, *title; unsigned int i, newtags = 0; const ConfigWinRule *r; - Monitor *mon = selmon, *m = NULL; + Monitor *m = NULL; Client *fc = NULL; bool hit_rule_pos = false; + Client *parent = NULL; - c->isfloating = client_is_float_type(c); + parent = client_get_parent(c); + + Monitor *mon = parent && parent->mon ? parent->mon : selmon; + + c->isfloating = client_is_float_type(c) || parent; if (!(appid = client_get_appid(c))) appid = broken; if (!(title = client_get_title(c))) @@ -1266,8 +1273,14 @@ void applyrules(Client *c) { // set general properties apply_rule_properties(c, r); - // set tags - newtags |= (r->tags > 0) ? r->tags : 0; + // // set tags + if (r->tags > 0) { + newtags |= r->tags; + } else if (parent) { + newtags = parent->tags; + } else { + newtags |= 0; + } // set monitor of client wl_list_for_each(m, &mons, link) { @@ -1336,8 +1349,9 @@ void applyrules(Client *c) { int fullscreen_state_backup = c->isfullscreen || client_wants_fullscreen(c); setmon(c, mon, newtags, - !c->isopensilent && (!c->istagsilent || !newtags || - newtags & mon->tagset[mon->seltags])); + !c->isopensilent && !client_should_ignore_focus(c) && + (!c->istagsilent || !newtags || + newtags & mon->tagset[mon->seltags])); if (c->mon && !(c->mon == selmon && c->tags & c->mon->tagset[c->mon->seltags]) && @@ -3095,6 +3109,9 @@ void focusclient(Client *c, int lift) { if (c && client_should_ignore_focus(c) && client_is_x11_popup(c)) return; + if (c && c->nofocus) + return; + /* Raise client in stacking order if requested */ if (c && lift) wlr_scene_node_raise_to_top(&c->scene->node); // 将视图提升到顶层 @@ -3571,6 +3588,7 @@ void init_client_properties(Client *c) { c->fake_no_border = false; c->focused_opacity = focused_opacity; c->unfocused_opacity = unfocused_opacity; + c->nofocus = 0; c->nofadein = 0; c->nofadeout = 0; c->no_force_center = 0; @@ -3591,7 +3609,6 @@ void init_client_properties(Client *c) { 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 *at_client = NULL; Client *c = wl_container_of(listener, c, map); /* Create scene tree for this client and its border */ @@ -3686,16 +3703,7 @@ mapnotify(struct wl_listener *listener, void *data) { wl_list_insert(clients.prev, &c->link); // 尾部入栈 wl_list_insert(&fstack, &c->flink); - /* Set initial monitor, tags, floating status, and focus: - * we always consider floating, clients that have parent and thus - * we set the same tags and monitor than its parent, if not - * try to apply rules for them */ - if ((p = client_get_parent(c))) { - c->isfloating = 1; - setmon(c, p->mon, p->tags, true); - } else { - applyrules(c); - } + applyrules(c); client_set_tiled(c, WLR_EDGE_TOP | WLR_EDGE_BOTTOM | WLR_EDGE_LEFT | WLR_EDGE_RIGHT); From d0a51f47856b62ed1d135eaa2a1824377efc85a4 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 9 Nov 2025 23:19:49 +0800 Subject: [PATCH 14/18] opt: remove useless code --- src/mango.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mango.c b/src/mango.c index 74345bd5..960b5cb5 100644 --- a/src/mango.c +++ b/src/mango.c @@ -1278,8 +1278,6 @@ void applyrules(Client *c) { newtags |= r->tags; } else if (parent) { newtags = parent->tags; - } else { - newtags |= 0; } // set monitor of client From 64d8764f58d6469ae641bde9079938702022f309 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 10 Nov 2025 14:30:20 +0800 Subject: [PATCH 15/18] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c90cee1f..8e982b60 100644 --- a/README.md +++ b/README.md @@ -101,7 +101,7 @@ emerge --ask --verbose gui-wm/mangowc ## Other ```bash -git clone -b 0.19.1 https://gitlab.freedesktop.org/wlroots/wlroots.git +git clone -b 0.19.2 https://gitlab.freedesktop.org/wlroots/wlroots.git cd wlroots meson build -Dprefix=/usr sudo ninja -C build install @@ -119,7 +119,7 @@ sudo ninja -C build install ## Suggested Tools -### integrated component +### Hybrid component - [dms-shell](https://github.com/AvengeMedia/DankMaterialShell) ### Independent component From e1dc0c5b616ac7b4ec5c5201016982f64b9e2d31 Mon Sep 17 00:00:00 2001 From: salivala Date: Tue, 11 Nov 2025 12:34:09 -0500 Subject: [PATCH 16/18] impl comboview_spawn_on_empty --- src/config/parse_config.h | 4 ++++ src/dispatch/bind_declare.h | 3 ++- src/dispatch/bind_define.h | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 0e9e15c5..345fbc60 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -1014,6 +1014,10 @@ FuncType parse_func_name(char *func_name, Arg *arg, char *arg_value, func = spawn_on_empty; (*arg).v = strdup(arg_value); // 注意:之后需要释放这个内存 (*arg).ui = 1 << (atoi(arg_value2) - 1); + } else if (strcmp(func_name, "comboview_spawn_on_empty") == 0) { + func = comboview_spawn_on_empty; + (*arg).v = strdup(arg_value); // 注意:之后需要释放这个内存 + (*arg).ui = 1 << (atoi(arg_value2) - 1); } else if (strcmp(func_name, "quit") == 0) { func = quit; } else if (strcmp(func_name, "create_virtual_output") == 0) { diff --git a/src/dispatch/bind_declare.h b/src/dispatch/bind_declare.h index 5bc215a2..111db1e6 100644 --- a/src/dispatch/bind_declare.h +++ b/src/dispatch/bind_declare.h @@ -23,6 +23,7 @@ int tagmon(const Arg *arg); int spawn(const Arg *arg); int spawn_shell(const Arg *arg); int spawn_on_empty(const Arg *arg); +int comboview_spawn_on_empty(const Arg *arg); int setkeymode(const Arg *arg); int switch_keyboard_layout(const Arg *arg); int setlayout(const Arg *arg); @@ -68,4 +69,4 @@ int toggle_trackpad_enable(const Arg *arg); int setoption(const Arg *arg); int disable_monitor(const Arg *arg); int enable_monitor(const Arg *arg); -int toggle_monitor(const Arg *arg); \ No newline at end of file +int toggle_monitor(const Arg *arg); diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 65c2b03e..50889130 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -810,6 +810,37 @@ int spawn_on_empty(const Arg *arg) { return 0; } +comboview_spawn_on_empty(const Arg *arg) { + unsigned int newtags = arg->ui & TAGMASK; + bool is_empty = true; + Client *c = NULL; + + if (!newtags || !selmon) + return 0; + + wl_list_for_each(c, &clients, link) { + if (arg->ui & c->tags && c->mon == selmon) { + is_empty = false; + break; + } + } + + if (tag_combo) { + selmon->tagset[selmon->seltags] |= newtags; + focusclient(focustop(selmon), 1); + arrange(selmon, false); + } else { + tag_combo = true; + view(&(Arg){.ui = newtags}, false); + } + if (is_empty) { + spawn(arg); + } + + printstatus(); + return 0; +} + int switch_keyboard_layout(const Arg *arg) { if (!kb_group || !kb_group->wlr_group || !seat) { wlr_log(WLR_ERROR, "Invalid keyboard group or seat"); @@ -1548,4 +1579,4 @@ int toggle_monitor(const Arg *arg) { } } return 0; -} \ No newline at end of file +} From ea4118fa451c95ed9dba52d3eb5275c66dfd410b Mon Sep 17 00:00:00 2001 From: salivala Date: Tue, 11 Nov 2025 12:46:51 -0500 Subject: [PATCH 17/18] updated func sig --- src/dispatch/bind_define.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 50889130..1f4af19f 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -810,7 +810,7 @@ int spawn_on_empty(const Arg *arg) { return 0; } -comboview_spawn_on_empty(const Arg *arg) { +int comboview_spawn_on_empty(const Arg *arg) { unsigned int newtags = arg->ui & TAGMASK; bool is_empty = true; Client *c = NULL; From 9fe6d0904841f2ef3d7b9ded6b5776d625682bcf Mon Sep 17 00:00:00 2001 From: salivala Date: Tue, 11 Nov 2025 13:08:42 -0500 Subject: [PATCH 18/18] isolating spawn to only current pressed tag in comboview --- src/dispatch/bind_define.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 1f4af19f..b1b234bc 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -834,7 +834,10 @@ int comboview_spawn_on_empty(const Arg *arg) { view(&(Arg){.ui = newtags}, false); } if (is_empty) { + unsigned int old = selmon->tagset[selmon->seltags]; + selmon->tagset[selmon->seltags] = newtags; spawn(arg); + selmon->tagset[selmon->seltags] = old; } printstatus();