From 3ab2780b84a19a6c861b53fb3eb24616208db81e Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 6 Jun 2026 18:16:08 +0800 Subject: [PATCH 01/26] fix: excrescent gap in fullscreen --- src/animation/client.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/animation/client.h b/src/animation/client.h index 8aa39050..f988651e 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -495,6 +495,7 @@ void apply_border(Client *c) { if (c->isfullscreen) { if (c->border->node.enabled) { + wlr_scene_node_set_position(&c->scene_surface->node, 0, 0); wlr_scene_node_set_enabled(&c->border->node, false); } return; From db8d22ae8e39fb53d766c33c974c0c6a5fe43359 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 6 Jun 2026 21:21:34 +0800 Subject: [PATCH 02/26] bump version to 0.14.2 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 553ba0e1..23b59d61 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mango', ['c'], - version : '0.14.1', + version : '0.14.2', ) subdir('protocols') From ccb58a4f1ab95fb22a3b93395c306df854a4d475 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 7 Jun 2026 18:08:55 +0800 Subject: [PATCH 03/26] docs: fix some error im sample --- docs/window-management/rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/window-management/rules.md b/docs/window-management/rules.md index 41b4cc53..7e221bf1 100644 --- a/docs/window-management/rules.md +++ b/docs/window-management/rules.md @@ -115,7 +115,7 @@ windowrule=width:1000,height:900,appid:yesplaymusic,title:Demons # Global keybindings for OBS Studio windowrule=globalkeybinding:ctrl+alt-o,appid:com.obsproject.Studio -windowrule=globalkeybinding:ctrl+alt+n,appid:com.obsproject.Studio +windowrule=globalkeybinding:ctrl+alt-n,appid:com.obsproject.Studio windowrule=isopensilent:1,appid:com.obsproject.Studio # Force tearing for games From 27f4f64173b143baf85d8c000239d96f5e91881f Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 8 Jun 2026 11:40:21 +0800 Subject: [PATCH 04/26] opt: not need send output enter when layer map scene scene-graph API will auto do this --- src/mango.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mango.c b/src/mango.c index 74d4c196..8c96dba2 100644 --- a/src/mango.c +++ b/src/mango.c @@ -3140,7 +3140,6 @@ void createlayersurface(struct wl_listener *listener, void *data) { LISTEN(&l->scene->node.events.destroy, &l->destroy, destroylayernodenotify); wl_list_insert(&l->mon->layers[layer_surface->pending.layer], &l->link); - wlr_surface_send_enter(surface, layer_surface->output); } void createlocksurface(struct wl_listener *listener, void *data) { From 009e2d21119e36e4f1921d4b2878ddc50f674ab9 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 8 Jun 2026 13:05:04 +0800 Subject: [PATCH 05/26] opt: optimzie xwayland position set --- src/fetch/client.h | 4 ++-- src/mango.c | 58 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/fetch/client.h b/src/fetch/client.h index 85b296a3..77b2d865 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -91,9 +91,9 @@ setclient_coordinate_center(Client *c, Monitor *tm, struct wlr_box geom, if (!m) return geom; - uint32_t cbw = check_hit_no_border(c) ? c->bw : 0; + uint32_t cbw = c && check_hit_no_border(c) ? c->bw : 0; - if (!c->no_force_center && m) { + if ((!c || !c->no_force_center) && m) { tempbox.x = m->w.x + (m->w.width - geom.width) / 2; tempbox.y = m->w.y + (m->w.height - geom.height) / 2; } else { diff --git a/src/mango.c b/src/mango.c index 8c96dba2..268ab33f 100644 --- a/src/mango.c +++ b/src/mango.c @@ -1073,7 +1073,7 @@ static struct wl_listener last_cursor_surface_destroy_listener = { .notify = last_cursor_surface_destroy}; #ifdef XWAYLAND -static void fix_xwayland_unmanaged_coordinate(Client *c); +static void fix_xwayland_coordinate(struct wlr_box *geom); static int32_t synckeymap(void *data); static void activatex11(struct wl_listener *listener, void *data); static void configurex11(struct wl_listener *listener, void *data); @@ -1615,7 +1615,7 @@ void applyrules(Client *c) { #ifdef XWAYLAND if (c->isfloating && client_is_x11(c)) { - fix_xwayland_unmanaged_coordinate(c); + fix_xwayland_coordinate(&c->geom); c->float_geom = c->geom; } #endif @@ -4472,7 +4472,11 @@ mapnotify(struct wl_listener *listener, void *data) { /* Unmanaged clients always are floating */ #ifdef XWAYLAND if (client_is_x11(c)) { - fix_xwayland_unmanaged_coordinate(c); + fix_xwayland_coordinate(&c->geom); + wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x, + c->geom.y, c->geom.width, + c->geom.height); LISTEN(&c->surface.xwayland->events.set_geometry, &c->set_geometry, setgeometrynotify); } @@ -6824,16 +6828,17 @@ void virtualpointer(struct wl_listener *listener, void *data) { } #ifdef XWAYLAND -void fix_xwayland_unmanaged_coordinate(Client *c) { +void fix_xwayland_coordinate(struct wlr_box *geom) { if (!selmon) return; // 1. 如果窗口已经在当前活动显示器内,直接返回 - if (c->geom.x >= selmon->m.x && c->geom.x < selmon->m.x + selmon->m.width && - c->geom.y >= selmon->m.y && c->geom.y < selmon->m.y + selmon->m.height) + if (geom->x >= selmon->m.x && geom->x <= selmon->m.x + selmon->m.width && + geom->y >= selmon->m.y && geom->y <= selmon->m.y + selmon->m.height) return; - c->geom = setclient_coordinate_center(c, selmon, c->geom, 0, 0); + geom->x = selmon->m.x + (selmon->m.width - geom->width) / 2; + geom->y = selmon->m.y + (selmon->m.height - geom->height) / 2; } int32_t synckeymap(void *data) { @@ -6888,24 +6893,41 @@ void activatex11(struct wl_listener *listener, void *data) { void configurex11(struct wl_listener *listener, void *data) { Client *c = wl_container_of(listener, c, configure); struct wlr_xwayland_surface_configure_event *event = data; + struct wlr_box new_geo; + new_geo.x = event->x; + new_geo.y = event->y; + new_geo.width = event->width; + new_geo.height = event->height; + fix_xwayland_coordinate(&new_geo); + if (!client_surface(c) || !client_surface(c)->mapped) { - wlr_xwayland_surface_configure(c->surface.xwayland, event->x, event->y, - event->width, event->height); + + wlr_xwayland_surface_configure(c->surface.xwayland, new_geo.x, + new_geo.y, new_geo.width, + new_geo.height); return; } + if (client_is_unmanaged(c)) { - wlr_scene_node_set_position(&c->scene->node, event->x, event->y); - wlr_xwayland_surface_configure(c->surface.xwayland, event->x, event->y, - event->width, event->height); + wlr_scene_node_set_position(&c->scene->node, new_geo.x, new_geo.y); + wlr_xwayland_surface_configure(c->surface.xwayland, new_geo.x, + new_geo.y, new_geo.width, + new_geo.height); return; } - if ((c->isfloating && c != grabc) || - !c->mon->pertag->ltidxs[c->mon->pertag->curtag]->arrange) { + + if (c->isfloating && c != grabc) { + new_geo.x = new_geo.x - c->bw; + new_geo.y = new_geo.y - c->bw; + new_geo.width = new_geo.width + c->bw * 2; + new_geo.height = new_geo.height + c->bw * 2; + fix_xwayland_coordinate(&new_geo); + resize(c, - (struct wlr_box){.x = event->x - c->bw, - .y = event->y - c->bw, - .width = event->width + c->bw * 2, - .height = event->height + c->bw * 2}, + (struct wlr_box){.x = new_geo.x, + .y = new_geo.y, + .width = new_geo.width, + .height = new_geo.height}, 0); } else { arrange(c->mon, false, false); From a429420b73ac35b6c40aa726fcb5502545e059e6 Mon Sep 17 00:00:00 2001 From: Osama Ragab Date: Sun, 7 Jun 2026 16:30:22 +0300 Subject: [PATCH 06/26] feat: add hide cursor on keypress option (#871) --- docs/configuration/miscellaneous.md | 3 ++- src/config/parse_config.h | 6 ++++++ src/mango.c | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/configuration/miscellaneous.md b/docs/configuration/miscellaneous.md index 1001c4c1..cd8d167d 100644 --- a/docs/configuration/miscellaneous.md +++ b/docs/configuration/miscellaneous.md @@ -21,6 +21,7 @@ description: Advanced settings for XWayland, focus behavior, and system integrat | `sloppyfocus` | `1` | Focus follows the mouse cursor. | | `warpcursor` | `1` | Warp the cursor to the center of the window when focus changes via keyboard. | | `cursor_hide_timeout` | `0` | Hide the cursor after `N` seconds of inactivity (`0` to disable). | +| `cursor_hide_on_keypress` | `0` | Hide the cursor on keypress. | | `drag_tile_to_tile` | `0` | Allow dragging a tiled window onto another to swap their positions. | | `drag_tile_small` | `1` | Allow dragging a tiled window temporarily to small size.| | `drag_corner` | `3` | Corner for drag-to-tile detection (0: none, 1–3: corners, 4: auto-detect). | @@ -48,4 +49,4 @@ description: Advanced settings for XWayland, focus behavior, and system integrat | `idleinhibit_ignore_visible` | `0` | Allow invisible clients (e.g., background audio players) to inhibit idle. | | `tag_carousel` | `0` | Enable tag carousel (cycling through tags). | | `drag_tile_refresh_interval` | `8.0` | Interval (1.0–16.0) to refresh tiled window resize during drag. Too small may cause application lag. | -| `drag_floating_refresh_interval` | `8.0` | Interval (1.0–16.0) to refresh floating window resize during drag. Too small may cause application lag. | \ No newline at end of file +| `drag_floating_refresh_interval` | `8.0` | Interval (1.0–16.0) to refresh floating window resize during drag. Too small may cause application lag. | diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 5379ddca..72196c5f 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -261,6 +261,7 @@ typedef struct { int32_t overviewgappi; int32_t overviewgappo; uint32_t cursor_hide_timeout; + uint32_t cursor_hide_on_keypress; uint32_t axis_bind_apply_timeout; uint32_t focus_on_activate; @@ -1714,6 +1715,8 @@ bool parse_option(Config *config, char *key, char *value) { config->overviewgappo = atoi(value); } else if (strcmp(key, "cursor_hide_timeout") == 0) { config->cursor_hide_timeout = atoi(value); + } else if (strcmp(key, "cursor_hide_on_keypress") == 0) { + config->cursor_hide_on_keypress = atoi(value); } else if (strcmp(key, "axis_bind_apply_timeout") == 0) { config->axis_bind_apply_timeout = atoi(value); } else if (strcmp(key, "focus_on_activate") == 0) { @@ -3346,6 +3349,8 @@ void override_config(void) { CLAMP_INT(config.no_radius_when_single, 0, 1); config.cursor_hide_timeout = CLAMP_INT(config.cursor_hide_timeout, 0, 36000); + config.cursor_hide_on_keypress = + CLAMP_INT(config.cursor_hide_on_keypress, 0, 1); config.single_scratchpad = CLAMP_INT(config.single_scratchpad, 0, 1); config.repeat_rate = CLAMP_INT(config.repeat_rate, 1, 1000); config.repeat_delay = CLAMP_INT(config.repeat_delay, 1, 20000); @@ -3507,6 +3512,7 @@ void set_value_default() { config.overviewgappi = 5; config.overviewgappo = 30; config.cursor_hide_timeout = 0; + config.cursor_hide_on_keypress = 0; config.warpcursor = 1; config.drag_corner = 3; diff --git a/src/mango.c b/src/mango.c index 74d4c196..b0b93023 100644 --- a/src/mango.c +++ b/src/mango.c @@ -4206,6 +4206,11 @@ void keypress(struct wl_listener *listener, void *data) { } } + if (config.cursor_hide_on_keypress && !cursor_hidden && + event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { + hidecursor(NULL); + } + /* On _press_ if there is no active screen locker, * attempt to process a compositor keybinding. */ for (i = 0; i < nsyms; i++) From 36398a1af2bc06f57154a68934a4f89045c86a77 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 8 Jun 2026 19:28:28 +0800 Subject: [PATCH 07/26] opt: optimize unmanaged client init --- src/mango.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/mango.c b/src/mango.c index ee64a551..c18c4b1c 100644 --- a/src/mango.c +++ b/src/mango.c @@ -4473,28 +4473,24 @@ mapnotify(struct wl_listener *listener, void *data) { /* Handle unmanaged clients first so we can return prior create borders */ +#ifdef XWAYLAND if (client_is_unmanaged(c)) { /* Unmanaged clients always are floating */ -#ifdef XWAYLAND - if (client_is_x11(c)) { - fix_xwayland_coordinate(&c->geom); - wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); - wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x, - c->geom.y, c->geom.width, - c->geom.height); - LISTEN(&c->surface.xwayland->events.set_geometry, &c->set_geometry, - setgeometrynotify); - } -#endif - wlr_scene_node_reparent(&c->scene->node, layers[LyrOverlay]); + fix_xwayland_coordinate(&c->geom); wlr_scene_node_set_position(&c->scene->node, c->geom.x, c->geom.y); + wlr_xwayland_surface_configure(c->surface.xwayland, c->geom.x, + c->geom.y, c->geom.width, + c->geom.height); + LISTEN(&c->surface.xwayland->events.set_geometry, &c->set_geometry, + setgeometrynotify); + wlr_scene_node_reparent(&c->scene->node, layers[LyrOverlay]); if (client_wants_focus(c)) { focusclient(c, 1); exclusive_focus = c; } return; } - +#endif // extra node for (i = 0; i < 2; i++) { From 47f30454e6e7cd920026b836f6152b03c88a962b Mon Sep 17 00:00:00 2001 From: xtheeq Date: Mon, 8 Jun 2026 20:33:21 +0530 Subject: [PATCH 08/26] docs: fix wayfreeze link page --- docs/screenshot.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/screenshot.md b/docs/screenshot.md index 7f85224a..8c512313 100644 --- a/docs/screenshot.md +++ b/docs/screenshot.md @@ -14,7 +14,7 @@ Instead, compose your own workflow from small Wayland utilities and bind them to | [`slurp`](https://github.com/emersion/slurp) | Interactively select a region for `grim` | | [`wl-copy`](https://github.com/bugaevc/wl-clipboard) | Copy screenshots directly to the clipboard | | [`satty`](https://github.com/gabm/Satty) | Annotate screenshots before saving | -| [`wayfreeze`](https://github.com/nicbk/wayfreeze) | Freeze the screen before capture | +| [`wayfreeze`](https://github.com/Jappie3/wayfreeze) | Freeze the screen before capture | Install the required with your package manager or from source. From 52732c928b8e24127fb76cefad8e17db47003569 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 9 Jun 2026 21:50:16 +0800 Subject: [PATCH 09/26] fix: grid layout cant fullscreen --- src/layout/horizontal.h | 33 +++++++++++------------ src/layout/vertical.h | 58 +++++++++++++++++++---------------------- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index 92980731..24eed392 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -588,6 +588,7 @@ void grid(Monitor *m) { int32_t target_gappi = enablegaps ? config.gappih : 0; float single_width_ratio = 0.9; float single_height_ratio = 0.9; + struct wlr_box target_geom; n = m->visible_fake_tiling_clients; @@ -603,11 +604,11 @@ void grid(Monitor *m) { ISFAKETILED(c))) { cw = (m->w.width - 2 * target_gappo) * single_width_ratio; ch = (m->w.height - 2 * target_gappo) * single_height_ratio; - c->geom.x = m->w.x + (m->w.width - cw) / 2; - c->geom.y = m->w.y + (m->w.height - ch) / 2; - c->geom.width = cw; - c->geom.height = ch; - client_tile_resize(c, c->geom, 0); + target_geom.x = m->w.x + (m->w.width - cw) / 2; + target_geom.y = m->w.y + (m->w.height - ch) / 2; + target_geom.width = cw; + target_geom.height = ch; + client_tile_resize(c, target_geom, 0); return; } } @@ -651,16 +652,16 @@ void grid(Monitor *m) { cw = avail_w * (col_pers[i] / sum_col); if (i == 0) { - c->geom.x = m->w.x + target_gappo; + target_geom.x = m->w.x + target_gappo; } else if (i == 1) { // 第二个窗口的 X 坐标紧跟第一个窗口后面 float cw0 = avail_w * (col_pers[0] / sum_col); - c->geom.x = m->w.x + target_gappo + cw0 + target_gappi; + target_geom.x = m->w.x + target_gappo + cw0 + target_gappi; } - c->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo; - c->geom.width = cw; - c->geom.height = ch; - client_tile_resize(c, c->geom, 0); + target_geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo; + target_geom.width = cw; + target_geom.height = ch; + client_tile_resize(c, target_geom, 0); i++; } } @@ -757,11 +758,11 @@ void grid(Monitor *m) { ? (m->w.y + m->w.height - target_gappo - fl_cy) : avail_h * (row_pers[r_idx] / sum_row); - c->geom.x = (int32_t)fl_cx; - c->geom.y = (int32_t)fl_cy; - c->geom.width = (int32_t)fl_cw; - c->geom.height = (int32_t)fl_ch; - client_tile_resize(c, c->geom, 0); + target_geom.x = (int32_t)fl_cx; + target_geom.y = (int32_t)fl_cy; + target_geom.width = (int32_t)fl_cw; + target_geom.height = (int32_t)fl_ch; + client_tile_resize(c, target_geom, 0); i++; } } diff --git a/src/layout/vertical.h b/src/layout/vertical.h index 523467f9..6e058dea 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -186,14 +186,13 @@ void vertical_grid(Monitor *m) { int32_t cw, ch; int32_t rows, cols, overrows; Client *c = NULL; - int32_t target_gappo = - enablegaps ? m->isoverview ? config.overviewgappo : config.gappov : 0; - int32_t target_gappi = - enablegaps ? m->isoverview ? config.overviewgappi : config.gappiv : 0; - float single_width_ratio = m->isoverview ? 0.7 : 0.9; - float single_height_ratio = m->isoverview ? 0.8 : 0.9; + int32_t target_gappo = enablegaps ? config.gappov : 0; + int32_t target_gappi = enablegaps ? config.gappiv : 0; + float single_width_ratio = 0.9; + float single_height_ratio = 0.9; + struct wlr_box target_geom; - n = m->isoverview ? m->visible_clients : m->visible_fake_tiling_clients; + n = m->visible_fake_tiling_clients; if (n == 0) return; @@ -202,15 +201,14 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_is_x11_popup(c)) || - ISFAKETILED(c))) { + (!client_is_x11_popup(c) || ISFAKETILED(c))) { ch = (m->w.height - 2 * target_gappo) * single_height_ratio; cw = (m->w.width - 2 * target_gappo) * single_width_ratio; - c->geom.x = m->w.x + (m->w.width - cw) / 2; - c->geom.y = m->w.y + (m->w.height - ch) / 2; - c->geom.width = cw; - c->geom.height = ch; - client_tile_resize(c, c->geom, 0); + target_geom.x = m->w.x + (m->w.width - cw) / 2; + target_geom.y = m->w.y + (m->w.height - ch) / 2; + target_geom.width = cw; + target_geom.height = ch; + client_tile_resize(c, target_geom, 0); return; } } @@ -224,8 +222,7 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_is_x11_popup(c)) || - ISFAKETILED(c))) { + (!client_is_x11_popup(c) || ISFAKETILED(c))) { if (i < 2) row_pers[i] = (c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f; @@ -242,8 +239,7 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_is_x11_popup(c)) || - ISFAKETILED(c))) { + (!client_is_x11_popup(c) || ISFAKETILED(c))) { c->grid_col_idx = 0; c->grid_row_idx = i; c->grid_col_per = 1.0f; @@ -252,17 +248,17 @@ void vertical_grid(Monitor *m) { // 根据分配的权重动态计算当前窗口的高度 ch = avail_h * (row_pers[i] / sum_row); - c->geom.x = m->w.x + (m->w.width - cw) / 2 + target_gappo; + target_geom.x = m->w.x + (m->w.width - cw) / 2 + target_gappo; if (i == 0) { - c->geom.y = m->w.y + target_gappo; + target_geom.y = m->w.y + target_gappo; } else if (i == 1) { // 第二个窗口的 Y 坐标紧跟第一个窗口下面 float ch0 = avail_h * (row_pers[0] / sum_row); - c->geom.y = m->w.y + target_gappo + ch0 + target_gappi; + target_geom.y = m->w.y + target_gappo + ch0 + target_gappi; } - c->geom.width = cw; - c->geom.height = ch; - client_tile_resize(c, c->geom, 0); + target_geom.width = cw; + target_geom.height = ch; + client_tile_resize(c, target_geom, 0); i++; } } @@ -287,7 +283,7 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_is_x11_popup(c)) || ISFAKETILED(c))) { + (!client_is_x11_popup(c) || ISFAKETILED(c))) { int32_t c_idx = i / rows; int32_t r_idx = i % rows; if (r_idx == 0) @@ -314,7 +310,7 @@ void vertical_grid(Monitor *m) { if (c->mon != m) continue; if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_is_x11_popup(c)) || ISFAKETILED(c))) { + (!client_is_x11_popup(c) || ISFAKETILED(c))) { int32_t c_idx = i / rows; int32_t r_idx = i % rows; @@ -352,11 +348,11 @@ void vertical_grid(Monitor *m) { ? (m->w.x + m->w.width - target_gappo - fl_cx) : avail_w * (col_pers[c_idx] / sum_col); - c->geom.x = (int32_t)fl_cx; - c->geom.y = (int32_t)fl_cy; - c->geom.width = (int32_t)fl_cw; - c->geom.height = (int32_t)fl_ch; - client_tile_resize(c, c->geom, 0); + target_geom.x = (int32_t)fl_cx; + target_geom.y = (int32_t)fl_cy; + target_geom.width = (int32_t)fl_cw; + target_geom.height = (int32_t)fl_ch; + client_tile_resize(c, target_geom, 0); i++; } } From ef59224cdb110731c361a68959f4596665e6d2a2 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 9 Jun 2026 21:56:48 +0800 Subject: [PATCH 10/26] fix: deck layout caculate error when multi master --- src/layout/horizontal.h | 22 +++++++++------------- src/layout/vertical.h | 22 +++++++++++----------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index 24eed392..419e218a 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -500,16 +500,13 @@ void deck(Monitor *m) { return; wl_list_for_each(fc, &clients, link) { - if (VISIBLEON(fc, m) && ISFAKETILED(fc)) break; } - // Calculate master width using mfact from pertag mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per : m->pertag->mfacts[m->pertag->curtag]; - // Calculate master width including outer gaps if (n > nmasters) mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0; else @@ -521,16 +518,15 @@ void deck(Monitor *m) { continue; if (i < nmasters) { c->master_mfact_per = mfact; - // Master area clients - client_tile_resize( - c, - (struct wlr_box){.x = m->w.x + cur_gappoh, - .y = m->w.y + cur_gappov + my, - .width = mw, - .height = (m->w.height - 2 * cur_gappov - my) / - (MIN(n, nmasters) - i)}, - 0); - my += c->geom.height; + int32_t h = + (m->w.height - 2 * cur_gappov - my) / (MIN(n, nmasters) - i); + client_tile_resize(c, + (struct wlr_box){.x = m->w.x + cur_gappoh, + .y = m->w.y + cur_gappov + my, + .width = mw, + .height = h}, + 0); + my += h; } else { // Stack area clients c->master_mfact_per = mfact; diff --git a/src/layout/vertical.h b/src/layout/vertical.h index 6e058dea..b1de212e 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -137,12 +137,10 @@ void vertical_deck(Monitor *m) { return; wl_list_for_each(fc, &clients, link) { - if (VISIBLEON(fc, m) && ISFAKETILED(fc)) break; } - // Calculate master width using mfact from pertag mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per : m->pertag->mfacts[m->pertag->curtag]; @@ -156,16 +154,18 @@ void vertical_deck(Monitor *m) { if (!VISIBLEON(c, m) || !ISFAKETILED(c)) continue; if (i < nmasters) { - client_tile_resize( - c, - (struct wlr_box){.x = m->w.x + cur_gappoh + mx, - .y = m->w.y + cur_gappov, - .width = (m->w.width - 2 * cur_gappoh - mx) / - (MIN(n, nmasters) - i), - .height = mh}, - 0); - mx += c->geom.width; + c->master_mfact_per = mfact; + int32_t w = + (m->w.width - 2 * cur_gappoh - mx) / (MIN(n, nmasters) - i); + client_tile_resize(c, + (struct wlr_box){.x = m->w.x + cur_gappoh + mx, + .y = m->w.y + cur_gappov, + .width = w, + .height = mh}, + 0); + mx += w; } else { + c->master_mfact_per = mfact; client_tile_resize( c, (struct wlr_box){.x = m->w.x + cur_gappoh, From 94db68ef88b8a922a3812746465e7374f3465567 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Thu, 11 Jun 2026 11:08:44 +0800 Subject: [PATCH 11/26] fix: floating window can't get pointer focus when cross monitor --- src/mango.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mango.c b/src/mango.c index c18c4b1c..35815e38 100644 --- a/src/mango.c +++ b/src/mango.c @@ -4824,13 +4824,13 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, } if (!scroller_focus_lock || !(c && c->mon && !INSIDEMON(c))) { - if (c && c->mon && is_scroller_layout(c->mon) && !INSIDEMON(c)) { + if (c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) && !INSIDEMON(c)) { should_lock = true; } if (!((!config.edge_scroller_pointer_focus || speed < config.edge_scroller_focus_allow_speed) && - c && c->mon && is_scroller_layout(c->mon) && !INSIDEMON(c))) { + c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) && !INSIDEMON(c))) { pointerfocus(c, surface, sx, sy, time); } From 33cda5afea459aed69ac517a8b50d9082e57a396 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Thu, 11 Jun 2026 12:37:48 +0800 Subject: [PATCH 12/26] opt:optimize edge focus judge --- src/mango.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mango.c b/src/mango.c index 35815e38..281d1720 100644 --- a/src/mango.c +++ b/src/mango.c @@ -4812,7 +4812,7 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, if (!surface && !seat->drag && !cursor_hidden) wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); - if (c && c->mon && !c->animation.running && (INSIDEMON(c) || !ISTILED(c))) { + if (c && c->mon && !c->animation.running && (INSIDEMON(c) || !ISSCROLLTILED(c))) { scroller_focus_lock = 0; } From 03e68ba069f51833466c23509a41b78f0a3faf32 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Thu, 11 Jun 2026 12:39:17 +0800 Subject: [PATCH 13/26] opt: optimize marco use in client tile resize --- src/action/client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/action/client.h b/src/action/client.h index f374ca14..1b3c9335 100644 --- a/src/action/client.h +++ b/src/action/client.h @@ -51,7 +51,7 @@ static void finish_exchange_arrange_and_focus(Client *c1, Client *c2, } void client_tile_resize(Client *c, struct wlr_box geo, int32_t interact) { - if (!ISSCROLLTILED(c)) + if (!ISFAKETILED(c)) return; if (!c->isfullscreen && !c->ismaximizescreen) { From 792bfac475cab87bd470ed70bb9f540d72959263 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Thu, 11 Jun 2026 23:14:50 +0800 Subject: [PATCH 14/26] fix: can't resize tile scroller window when only two tiled client --- src/layout/arrange.h | 3 ++- src/mango.c | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/layout/arrange.h b/src/layout/arrange.h index 7223b430..eab3ac00 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -751,6 +751,7 @@ void resize_tile_grid_fair(Client *grabc, bool isdrag, int32_t offsetx, void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, int32_t offsety, uint32_t time, bool isvertical) { + if (!grabc || grabc->isfullscreen || grabc->ismaximizescreen) return; if (grabc->mon->isoverview) @@ -772,7 +773,7 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, Client *stack_head_client = headnode->client; - if (m->visible_tiling_clients == 1 && + if (m->visible_scroll_tiling_clients == 1 && !config.scroller_ignore_proportion_single) return; diff --git a/src/mango.c b/src/mango.c index 281d1720..731c0ac3 100644 --- a/src/mango.c +++ b/src/mango.c @@ -4812,7 +4812,8 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, if (!surface && !seat->drag && !cursor_hidden) wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); - if (c && c->mon && !c->animation.running && (INSIDEMON(c) || !ISSCROLLTILED(c))) { + if (c && c->mon && !c->animation.running && + (INSIDEMON(c) || !ISSCROLLTILED(c))) { scroller_focus_lock = 0; } @@ -4824,13 +4825,15 @@ void motionnotify(uint32_t time, struct wlr_input_device *device, double dx, } if (!scroller_focus_lock || !(c && c->mon && !INSIDEMON(c))) { - if (c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) && !INSIDEMON(c)) { + if (c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) && + !INSIDEMON(c)) { should_lock = true; } if (!((!config.edge_scroller_pointer_focus || speed < config.edge_scroller_focus_allow_speed) && - c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) && !INSIDEMON(c))) { + c && c->mon && ISSCROLLTILED(c) && is_scroller_layout(c->mon) && + !INSIDEMON(c))) { pointerfocus(c, surface, sx, sy, time); } From 7e178369ffda32aa5905856c45b42b81a8859530 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 14 Jun 2026 07:53:57 +0800 Subject: [PATCH 15/26] opt: optimize drop tile client when cross monitor --- src/animation/client.h | 112 +++++++++++++++++++++++++++-------------- src/mango.c | 7 ++- 2 files changed, 78 insertions(+), 41 deletions(-) diff --git a/src/animation/client.h b/src/animation/client.h index f988651e..35d2a30f 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -699,17 +699,6 @@ void client_set_drop_area(Client *c) { bool dwindle_familiar = cur_layout->id == DWINDLE && config.dwindle_drop_simple_split; - uint32_t nmaster = c->mon->pertag->nmasters[c->mon->pertag->curtag]; - - bool should_swap = - (cur_layout->id == DECK || cur_layout->id == VERTICAL_DECK || - cur_layout->id == MONOCLE || cur_layout->id == GRID || - cur_layout->id == FAIR || cur_layout->id == VERTICAL_FAIR || - cur_layout->id == VERTICAL_GRID) || - ((cur_layout->id == TILE || cur_layout->id == VERTICAL_TILE || - cur_layout->id == CENTER_TILE || cur_layout->id == RIGHT_TILE) && - nmaster == 1 && c->ismaster); - if (dwindle_familiar) { bool split_h = c->geom.width >= c->geom.height; float ratio = config.dwindle_split_ratio; @@ -743,42 +732,87 @@ void client_set_drop_area(Client *c) { client_height - (int32_t)(client_height * ratio); } } - } else if (should_swap) { - drop_box.x = bw; - drop_box.y = bw; - drop_box.width = client_width; - drop_box.height = client_height; - drop_direction = UNDIR; } else if (cur_layout->id == TILE || cur_layout->id == DECK || cur_layout->id == CENTER_TILE || cur_layout->id == RIGHT_TILE) { - if (rel_y < client_height * 0.5) { - drop_direction = UP; - drop_box.x = bw; - drop_box.y = bw; - drop_box.width = client_width; - drop_box.height = client_height / 2; + + if (c->ismaster) { + if (c->mon->visible_tiling_clients == 1) { + if (rel_x < client_width * 0.5) { + drop_direction = LEFT; + drop_box.x = bw; + drop_box.y = bw; + drop_box.width = client_width / 2; + drop_box.height = client_height; + } else { + drop_direction = RIGHT; + drop_box.x = bw + client_width / 2; + drop_box.y = bw; + drop_box.width = client_width / 2; + drop_box.height = client_height; + } + } else { + drop_box.x = bw; + drop_box.y = bw; + drop_box.width = client_width; + drop_box.height = client_height; + drop_direction = UNDIR; + } } else { - drop_direction = DOWN; - drop_box.x = bw; - drop_box.y = bw + client_height / 2; - drop_box.width = client_width; - drop_box.height = client_height / 2; + if (rel_y < client_height * 0.5) { + drop_direction = UP; + drop_box.x = bw; + drop_box.y = bw; + drop_box.width = client_width; + drop_box.height = client_height / 2; + } else { + drop_direction = DOWN; + drop_box.x = bw; + drop_box.y = bw + client_height / 2; + drop_box.width = client_width; + drop_box.height = client_height / 2; + } } } else if (cur_layout->id == VERTICAL_TILE || cur_layout->id == VERTICAL_DECK) { - if (rel_x < client_width * 0.5) { - drop_direction = LEFT; - drop_box.x = bw; - drop_box.y = bw; - drop_box.width = client_width / 2; - drop_box.height = client_height; + if (c->ismaster) { + if (c->mon->visible_tiling_clients == 1) { + if (rel_y < client_height * 0.5) { + drop_direction = UP; + drop_box.x = bw; + drop_box.y = bw; + drop_box.width = client_width; + drop_box.height = client_height / 2; + } else { + drop_direction = DOWN; + drop_box.x = bw; + drop_box.y = bw + client_height / 2; + drop_box.width = client_width; + drop_box.height = client_height / 2; + } + } else { + drop_box.x = bw; + drop_box.y = bw; + drop_box.width = client_width; + drop_box.height = client_height; + drop_direction = UNDIR; + } + } else { - drop_direction = RIGHT; - drop_box.x = bw + client_width / 2; - drop_box.y = bw; - drop_box.width = client_width / 2; - drop_box.height = client_height; + if (rel_x < client_width * 0.5) { + drop_direction = LEFT; + drop_box.x = bw; + drop_box.y = bw; + drop_box.width = client_width / 2; + drop_box.height = client_height; + } else { + drop_direction = RIGHT; + drop_box.x = bw + client_width / 2; + drop_box.y = bw; + drop_box.width = client_width / 2; + drop_box.height = client_height; + } } + } else { double dist_left = rel_x; double dist_right = client_width - rel_x; diff --git a/src/mango.c b/src/mango.c index 731c0ac3..1e39ddb5 100644 --- a/src/mango.c +++ b/src/mango.c @@ -2202,9 +2202,10 @@ void hold_end(struct wl_listener *listener, void *data) { Client *find_closest_tiled_client(Client *c) { Client *tc, *closest = NULL; long min_dist = LONG_MAX; + Monitor *cursor_mon = xytomon(cursor->x, cursor->y); wl_list_for_each(tc, &clients, link) { - if (tc == c || !ISTILED(tc) || !VISIBLEON(tc, c->mon)) + if (tc == c || !ISTILED(tc) || !VISIBLEON(tc, cursor_mon)) continue; if (cursor->x >= tc->geom.x && @@ -2236,7 +2237,9 @@ void place_drag_tile_client(Client *c) { if (closest->drop_direction == UNDIR) { setfloating(c, 0); - exchange_two_client(c, closest); + wl_list_remove(&c->link); + wl_list_insert(closest->link.prev, &c->link); + arrange(closest->mon, false, false); return; } From 15fb37f1c63597a54223ad745d779082e088498f Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 14 Jun 2026 13:14:38 +0800 Subject: [PATCH 16/26] update docs --- docs/configuration/monitors.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/configuration/monitors.md b/docs/configuration/monitors.md index 084db60c..a8001ae0 100644 --- a/docs/configuration/monitors.md +++ b/docs/configuration/monitors.md @@ -163,6 +163,8 @@ Some GPUs have compatibility issues with `syncobj_enable=1` — it may crash app ## Power Management You can control monitor power using the `mmsg` IPC tool. +> Notice: This command does not remove the monitor, it only turns it off. +> if you want completely remove monitor, just use `wlr-randr` ```bash # Turn off @@ -178,13 +180,13 @@ mmsg dispatch toggle_monitor,eDP-1 You can also use `wlr-randr` for monitor management: ```bash -# Turn off monitor +# remove a monitor wlr-randr --output eDP-1 --off -# Turn on monitor +# add a monitor wlr-randr --output eDP-1 --on -# Show all monitors +# Show all monitors spec wlr-randr ``` From 83adb33ad2c8532c291a1a8fc75a2004b7e4690c Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 00:00:03 +0800 Subject: [PATCH 17/26] fix: overview cursor jump miss apply when no mousebind --- src/mango.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/mango.c b/src/mango.c index 1e39ddb5..1fad3011 100644 --- a/src/mango.c +++ b/src/mango.c @@ -2338,6 +2338,17 @@ bool handle_buttonpress(struct wlr_pointer_button_event *event) { } } + // overview模式下鼠标左键跳转,右键关闭窗口 + if (selmon && selmon->isoverview && event->button == BTN_LEFT && c) { + toggleoverview(&(Arg){.i = 1}); + return true; + } + + if (selmon && selmon->isoverview && event->button == BTN_RIGHT && c) { + pending_kill_client(c); + return true; + } + // 当鼠标焦点在layer上的时候,不检测虚拟键盘的mod状态, // 避免layer虚拟键盘锁死mod按键状态 hard_keyboard = &kb_group->wlr_group->keyboard; @@ -2354,16 +2365,6 @@ bool handle_buttonpress(struct wlr_pointer_button_event *event) { break; m = &config.mouse_bindings[ji]; - if (selmon->isoverview && event->button == BTN_LEFT && c) { - toggleoverview(&(Arg){.i = 1}); - return true; - } - - if (selmon->isoverview && event->button == BTN_RIGHT && c) { - pending_kill_client(c); - return true; - } - if (CLEANMASK(mods) == CLEANMASK(m->mod) && event->button == m->button && m->func && (CLEANMASK(m->mod) != 0 || From 4daab9e4d54dd4f2ef4347d0b440cc27b9feb263 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sun, 14 Jun 2026 21:40:17 +0800 Subject: [PATCH 18/26] opt: optimzie client layer judge in overveiw --- src/fetch/common.h | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/fetch/common.h b/src/fetch/common.h index f58bd33a..acb5d0e8 100644 --- a/src/fetch/common.h +++ b/src/fetch/common.h @@ -160,11 +160,26 @@ void xytonode(double x, double y, struct wlr_surface **psurface, Client **pc, if (pl) *pl = l; - if (selmon && selmon->isoverview && (!l || layer_ignores_focus(l))) { + if (selmon && selmon->isoverview && config.ov_no_resize) { ovc = xytoclient(x, y); - if (pc) - *pc = ovc; - if (psurface && ovc) - *psurface = client_surface(ovc); + + bool is_below = false; + if (l && l->layer_surface) { + is_below = (l->layer_surface->current.layer == + ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || + l->layer_surface->current.layer == + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM); + } + + if (ovc && (!l || layer_ignores_focus(l) || is_below)) { + if (pc) + *pc = ovc; + + if (psurface) + *psurface = ovc ? client_surface(ovc) : NULL; + + if (pl && ovc) + *pl = NULL; + } } } \ No newline at end of file From 2a9c38df1f12f4df8eca4f1e0b23624757c4dbc9 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 09:53:34 +0800 Subject: [PATCH 19/26] fix: cursor not auto hide in overview --- src/dispatch/bind_define.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index cf0f770a..cf15b261 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -1760,7 +1760,12 @@ int32_t toggleoverview(const Arg *arg) { if (selmon->isoverview) { wlr_seat_pointer_clear_focus(seat); - wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + + if (cursor_hidden) { + handlecursoractivity(); + } else { + wlr_cursor_set_xcursor(cursor, cursor_mgr, "default"); + } wl_list_for_each(c, &clients, link) { if (c && c->mon == selmon && !client_is_unmanaged(c) && From 8a3d065cc1356df36df35be689dd8ef000e75290 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 10:43:54 +0800 Subject: [PATCH 20/26] opt: add ov workspace before remove all tag workspace --- src/ext-protocol/ext-workspace.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ext-protocol/ext-workspace.h b/src/ext-protocol/ext-workspace.h index 480dd5cf..eea0f455 100644 --- a/src/ext-protocol/ext-workspace.h +++ b/src/ext-protocol/ext-workspace.h @@ -188,10 +188,10 @@ void refresh_monitors_workspaces_status(Monitor *m) { int32_t i; if (m->isoverview) { + add_workspace_by_tag(0, m); for (i = 1; i <= LENGTH(tags); i++) { remove_workspace_by_tag(i, m); } - add_workspace_by_tag(0, m); } else { remove_workspace_by_tag(0, m); for (i = 1; i <= LENGTH(tags); i++) { From 8ca013e6c34fac2520272b9c2b887283c8a76569 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 13:33:46 +0800 Subject: [PATCH 21/26] opt: avoid arrange when restore from overview --- src/dispatch/bind_define.h | 8 +++--- src/ext-protocol/foreign-toplevel.h | 8 +++--- src/layout/scroll.h | 8 +++--- src/mango.c | 43 ++++++++++++++++------------- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index cf15b261..a8cf0cd4 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -1355,9 +1355,9 @@ int32_t togglefullscreen(const Arg *arg) { sel->isnamedscratchpad = 0; if (sel->isfullscreen) - setfullscreen(sel, 0); + setfullscreen(sel, 0, true); else - setfullscreen(sel, 1); + setfullscreen(sel, 1, true); return 0; } @@ -1401,9 +1401,9 @@ int32_t togglemaximizescreen(const Arg *arg) { sel->isnamedscratchpad = 0; if (sel->ismaximizescreen) - setmaximizescreen(sel, 0); + setmaximizescreen(sel, 0, true); else - setmaximizescreen(sel, 1); + setmaximizescreen(sel, 1, true); setborder_color(sel); return 0; diff --git a/src/ext-protocol/foreign-toplevel.h b/src/ext-protocol/foreign-toplevel.h index 4fdbbe98..a8c49c77 100644 --- a/src/ext-protocol/foreign-toplevel.h +++ b/src/ext-protocol/foreign-toplevel.h @@ -16,12 +16,12 @@ void handle_foreign_maximize_request(struct wl_listener *listener, void *data) { return; if (c->ismaximizescreen && !event->maximized) { - setmaximizescreen(c, 0); + setmaximizescreen(c, 0, true); return; } if (!c->ismaximizescreen && event->maximized) { - setmaximizescreen(c, 1); + setmaximizescreen(c, 1, true); return; } } @@ -59,12 +59,12 @@ void handle_foreign_fullscreen_request(struct wl_listener *listener, return; if (c->isfullscreen && !event->fullscreen) { - setfullscreen(c, 0); + setfullscreen(c, 0, true); return; } if (!c->isfullscreen && event->fullscreen) { - setfullscreen(c, 1); + setfullscreen(c, 1, true); return; } } diff --git a/src/layout/scroll.h b/src/layout/scroll.h index f6852daa..ce6defd5 100644 --- a/src/layout/scroll.h +++ b/src/layout/scroll.h @@ -743,9 +743,9 @@ void scroller_insert_stack(Client *c, Client *target_client, return; if (c->isfullscreen) - setfullscreen(c, 0); + setfullscreen(c, 0, true); if (c->ismaximizescreen) - setmaximizescreen(c, 0); + setmaximizescreen(c, 0, true); Monitor *m = c->mon; uint32_t tag = m->pertag->curtag; @@ -785,9 +785,9 @@ void scroller_insert_stack(Client *c, Client *target_client, head = head->prev_in_stack; Client *stack_head = head->client; if (stack_head->ismaximizescreen) - setmaximizescreen(stack_head, 0); + setmaximizescreen(stack_head, 0, true); if (stack_head->isfullscreen) - setfullscreen(stack_head, 0); + setfullscreen(stack_head, 0, true); /* 同步到 Client 字段 */ sync_scroller_state_to_clients(m, tag); diff --git a/src/mango.c b/src/mango.c index 1fad3011..eb184e6d 100644 --- a/src/mango.c +++ b/src/mango.c @@ -735,8 +735,9 @@ static void run(char *startup_cmd); static void setcursor(struct wl_listener *listener, void *data); static void setfloating(Client *c, int32_t floating); static void setfakefullscreen(Client *c, int32_t fakefullscreen); -static void setfullscreen(Client *c, int32_t fullscreen); -static void setmaximizescreen(Client *c, int32_t maximizescreen); +static void setfullscreen(Client *c, int32_t fullscreen, bool rearrange); +static void setmaximizescreen(Client *c, int32_t maximizescreen, + bool rearrange); static void reset_maximizescreen_size(Client *c); static void setgaps(int32_t oh, int32_t ov, int32_t ih, int32_t iv); @@ -1150,11 +1151,11 @@ void clear_fullscreen_flag(Client *c) { } if (c->isfullscreen) { - setfullscreen(c, false); + setfullscreen(c, false, true); } if (c->ismaximizescreen) { - setmaximizescreen(c, 0); + setmaximizescreen(c, 0, true); } } @@ -1748,7 +1749,7 @@ void applyrules(Client *c) { view_in_mon(&(Arg){.ui = c->tags}, true, c->mon, true); } - setfullscreen(c, fullscreen_state_backup); + setfullscreen(c, fullscreen_state_backup, true); if (c->isfakefullscreen) { setfakefullscreen(c, 1); @@ -3943,7 +3944,7 @@ fullscreennotify(struct wl_listener *listener, void *data) { if (!c || c->iskilling) return; - setfullscreen(c, client_wants_fullscreen(c)); + setfullscreen(c, client_wants_fullscreen(c), true); } void requestmonstate(struct wl_listener *listener, void *data) { @@ -4586,9 +4587,9 @@ void maximizenotify(struct wl_listener *listener, void *data) { } if (client_request_maximize(c, data)) { - setmaximizescreen(c, 1); + setmaximizescreen(c, 1, true); } else { - setmaximizescreen(c, 0); + setmaximizescreen(c, 0, true); } } @@ -5453,7 +5454,7 @@ void exit_scroller_stack(Client *c) { } } -void setmaximizescreen(Client *c, int32_t maximizescreen) { +void setmaximizescreen(Client *c, int32_t maximizescreen, bool rearrange) { struct wlr_box maximizescreen_box; if (!c || !c->mon || !client_surface(c)->mapped || c->iskilling) return; @@ -5494,7 +5495,8 @@ void setmaximizescreen(Client *c, int32_t maximizescreen) { client_set_maximized(c, true); } - arrange(c->mon, false, false); + if (rearrange) + arrange(c->mon, false, false); } void setfakefullscreen(Client *c, int32_t fakefullscreen) { @@ -5503,12 +5505,13 @@ void setfakefullscreen(Client *c, int32_t fakefullscreen) { return; if (c->isfullscreen) - setfullscreen(c, 0); + setfullscreen(c, 0, true); client_set_fullscreen(c, fakefullscreen); } -void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自带全屏 +void setfullscreen(Client *c, int32_t fullscreen, + bool rearrange) // 用自定义全屏代理自带全屏 { if (!c || !c->mon || !client_surface(c)->mapped || c->iskilling) @@ -5554,7 +5557,8 @@ void setfullscreen(Client *c, int32_t fullscreen) // 用自定义全屏代理自 layers[fullscreen || c->isfloating ? LyrTop : LyrTile]); } - arrange(c->mon, false, false); + if (rearrange) + arrange(c->mon, false, false); } void setgaps(int32_t oh, int32_t ov, int32_t ih, int32_t iv) { @@ -5683,7 +5687,8 @@ void setmon(Client *c, Monitor *m, uint32_t newtags, bool focus) { client_reset_mon_tags(c, m, newtags); check_match_tag_floating_rule(c, m); setfloating(c, c->isfloating); - setfullscreen(c, c->isfullscreen); /* This will call arrange(c->mon) */ + setfullscreen(c, c->isfullscreen, + true); /* This will call arrange(c->mon) */ } if (focus && !client_is_x11_popup(c)) { @@ -6275,13 +6280,13 @@ void overview_restore(Client *c, const Arg *arg) { resize(c, c->overview_backup_geom, 0); } else if (c->isfullscreen || c->ismaximizescreen) { if (want_restore_fullscreen(c) && c->ismaximizescreen) { - setmaximizescreen(c, 1); + setmaximizescreen(c, 1, false); } else if (want_restore_fullscreen(c) && c->isfullscreen) { - setfullscreen(c, 1); + setfullscreen(c, 1, false); } else { client_pending_fullscreen_state(c, 0); client_pending_maximized_state(c, 0); - setfullscreen(c, false); + setfullscreen(c, false, false); } } else { if (c->is_restoring_from_ov) { @@ -6477,8 +6482,8 @@ void unmapnotify(struct wl_listener *listener, void *data) { } if (c->swallowedby) { - setmaximizescreen(c->swallowedby, c->ismaximizescreen); - setfullscreen(c->swallowedby, c->isfullscreen); + setmaximizescreen(c->swallowedby, c->ismaximizescreen, true); + setfullscreen(c->swallowedby, c->isfullscreen, true); c->swallowedby->swallowing = NULL; c->swallowedby = NULL; } From fa24c606a015a327c17943f23c09c30aebfd7209 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 13:43:56 +0800 Subject: [PATCH 22/26] opt: optimize tag animaiton when tagout from overview --- src/animation/tag.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/animation/tag.h b/src/animation/tag.h index c46b9fd0..893d4b0b 100644 --- a/src/animation/tag.h +++ b/src/animation/tag.h @@ -117,6 +117,9 @@ void set_arrange_hidden(Monitor *m, Client *c, bool want_animation) { c->animation.tagining = false; set_tagout_animation(m, c); } else { + c->animation.running = false; wlr_scene_node_set_enabled(&c->scene->node, false); + c->animainit_geom = c->current = c->pending = c->animation.current = + c->geom; } } From b0fb99b95e498a381f174fd29733661e98b14fa5 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 16:49:42 +0800 Subject: [PATCH 23/26] feat: add scroller property to tagrule --- src/config/parse_config.h | 32 ++++++++++++++++++++++++++++++++ src/layout/arrange.h | 3 +++ src/layout/scroll.h | 30 ++++++++++++++++++------------ src/mango.c | 3 +++ 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/config/parse_config.h b/src/config/parse_config.h index 72196c5f..849da3c1 100644 --- a/src/config/parse_config.h +++ b/src/config/parse_config.h @@ -167,6 +167,9 @@ typedef struct { char *monitor_serial; float mfact; int32_t nmaster; + float scroller_default_proportion; + float scroller_default_proportion_single; + int32_t scroller_ignore_proportion_single; int32_t no_render_border; int32_t open_as_floating; int32_t no_hide; @@ -2041,6 +2044,9 @@ bool parse_option(Config *config, char *key, char *value) { rule->no_render_border = 0; rule->open_as_floating = 0; rule->no_hide = 0; + rule->scroller_default_proportion = 0.0f; + rule->scroller_default_proportion_single = 0.0f; + rule->scroller_ignore_proportion_single = -1; bool parse_error = false; char *token = strtok(value, ","); @@ -2076,6 +2082,17 @@ bool parse_option(Config *config, char *key, char *value) { rule->nmaster = CLAMP_INT(atoi(val), 1, 99); } else if (strcmp(key, "mfact") == 0) { rule->mfact = CLAMP_FLOAT(atof(val), 0.1f, 0.9f); + } else if (strcmp(key, "scroller_default_proportion") == 0) { + rule->scroller_default_proportion = + CLAMP_FLOAT(atof(val), 0.0f, 1.0f); + } else if (strcmp(key, "scroller_default_proportion_single") == + 0) { + rule->scroller_default_proportion_single = + CLAMP_FLOAT(atof(val), 0.0f, 1.0f); + } else if (strcmp(key, "scroller_ignore_proportion_single") == + 0) { + rule->scroller_ignore_proportion_single = + CLAMP_INT(atoi(val), 0, 1); } else { fprintf(stderr, "\033[1m\033[31m[ERROR]:\033[33m Unknown " @@ -3934,6 +3951,12 @@ void parse_tagrule(Monitor *m) { for (i = 0; i <= LENGTH(tags); i++) { m->pertag->nmasters[i] = config.default_nmaster; m->pertag->mfacts[i] = config.default_mfact; + m->pertag->scroller_default_proportion[i] = + config.scroller_default_proportion; + m->pertag->scroller_default_proportion_single[i] = + config.scroller_default_proportion_single; + m->pertag->scroller_ignore_proportion_single[i] = + config.scroller_ignore_proportion_single; } for (i = 0; i < config.tag_rules_count; i++) { @@ -3988,6 +4011,15 @@ void parse_tagrule(Monitor *m) { m->pertag->no_render_border[tr.id] = tr.no_render_border; if (tr.open_as_floating >= 0) m->pertag->open_as_floating[tr.id] = tr.open_as_floating; + if (tr.scroller_default_proportion > 0.0f) + m->pertag->scroller_default_proportion[tr.id] = + tr.scroller_default_proportion; + if (tr.scroller_default_proportion_single > 0.0f) + m->pertag->scroller_default_proportion_single[tr.id] = + tr.scroller_default_proportion_single; + if (tr.scroller_ignore_proportion_single >= 0) + m->pertag->scroller_ignore_proportion_single[tr.id] = + tr.scroller_ignore_proportion_single; } } diff --git a/src/layout/arrange.h b/src/layout/arrange.h index eab3ac00..0a39b248 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -25,6 +25,9 @@ void set_size_per(Monitor *m, Client *c) { c->master_inner_per = 1.0f; c->stack_inner_per = 1.0f; } + + c->scroller_proportion = + m->pertag->scroller_default_proportion[m->pertag->curtag]; } void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, diff --git a/src/layout/scroll.h b/src/layout/scroll.h index ce6defd5..b800c5cf 100644 --- a/src/layout/scroll.h +++ b/src/layout/scroll.h @@ -284,6 +284,10 @@ void scroller(Monitor *m) { uint32_t tag = m->pertag->curtag; struct TagScrollerState *st = ensure_scroller_state(m, tag); Client *c = NULL; + float scroller_default_proportion_single = + m->pertag->scroller_default_proportion_single[tag]; + int32_t scroller_ignore_proportion_single = + m->pertag->scroller_ignore_proportion_single[tag]; /* 按全局客户端链表顺序收集所有堆叠头,确保视觉顺序正确 */ struct ScrollerStackNode *heads[64]; @@ -323,14 +327,13 @@ void scroller(Monitor *m) { m->w.width - 2 * config.scroller_structs - cur_gappih; /* 单客户端特例 */ - if (n_heads == 1 && !config.scroller_ignore_proportion_single && + if (n_heads == 1 && !scroller_ignore_proportion_single && !heads[0]->client->isfullscreen && !heads[0]->client->ismaximizescreen) { struct ScrollerStackNode *head = heads[0]; - float single_proportion = - head->scroller_proportion_single > 0.0f - ? head->scroller_proportion_single - : config.scroller_default_proportion_single; + float single_proportion = head->scroller_proportion_single > 0.0f + ? head->scroller_proportion_single + : scroller_default_proportion_single; struct wlr_box target_geom; target_geom.height = m->w.height - 2 * cur_gappov; target_geom.width = (m->w.width - 2 * cur_gappoh) * single_proportion; @@ -420,7 +423,7 @@ void scroller(Monitor *m) { max_client_width) > m->w.width - 2 * config.scroller_structs - cur_gappih))); - if (n_heads == 1 && config.scroller_ignore_proportion_single) { + if (n_heads == 1 && scroller_ignore_proportion_single) { need_scroller = true; } if (start_drag_window) @@ -507,6 +510,10 @@ void vertical_scroller(Monitor *m) { uint32_t tag = m->pertag->curtag; struct TagScrollerState *st = ensure_scroller_state(m, tag); Client *c = NULL; + float scroller_default_proportion_single = + m->pertag->scroller_default_proportion_single[tag]; + int32_t scroller_ignore_proportion_single = + m->pertag->scroller_ignore_proportion_single[tag]; /* 按全局顺序收集堆叠头 */ struct ScrollerStackNode *heads[64]; @@ -542,14 +549,13 @@ void vertical_scroller(Monitor *m) { int32_t max_client_height = m->w.height - 2 * config.scroller_structs - cur_gappiv; - if (n_heads == 1 && !config.scroller_ignore_proportion_single && + if (n_heads == 1 && !scroller_ignore_proportion_single && !heads[0]->client->isfullscreen && !heads[0]->client->ismaximizescreen) { struct ScrollerStackNode *head = heads[0]; - float single_proportion = - head->scroller_proportion_single > 0.0f - ? head->scroller_proportion_single - : config.scroller_default_proportion_single; + float single_proportion = head->scroller_proportion_single > 0.0f + ? head->scroller_proportion_single + : scroller_default_proportion_single; struct wlr_box target_geom; target_geom.width = m->w.width - 2 * cur_gappoh; target_geom.height = (m->w.height - 2 * cur_gappov) * single_proportion; @@ -638,7 +644,7 @@ void vertical_scroller(Monitor *m) { max_client_height) > m->w.height - 2 * config.scroller_structs - cur_gappiv))); - if (n_heads == 1 && config.scroller_ignore_proportion_single) { + if (n_heads == 1 && scroller_ignore_proportion_single) { need_scroller = true; } if (start_drag_window) diff --git a/src/mango.c b/src/mango.c index eb184e6d..fe32761a 100644 --- a/src/mango.c +++ b/src/mango.c @@ -1027,6 +1027,9 @@ struct Pertag { int32_t no_hide[LENGTH(tags) + 1]; int32_t no_render_border[LENGTH(tags) + 1]; int32_t open_as_floating[LENGTH(tags) + 1]; + float scroller_default_proportion[LENGTH(tags) + 1]; + float scroller_default_proportion_single[LENGTH(tags) + 1]; + int32_t scroller_ignore_proportion_single[LENGTH(tags) + 1]; struct DwindleNode *dwindle_root[LENGTH(tags) + 1]; const Layout *ltidxs[LENGTH(tags) + 1]; struct TagScrollerState *scroller_state[LENGTH(tags) + 1]; From ba014d50592775c88e90002842f5253f6589afd2 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 16:56:03 +0800 Subject: [PATCH 24/26] update docs --- docs/window-management/rules.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/window-management/rules.md b/docs/window-management/rules.md index 7e221bf1..b5ae81b1 100644 --- a/docs/window-management/rules.md +++ b/docs/window-management/rules.md @@ -183,6 +183,9 @@ tagrule=id:Values,monitor_make:xxx,monitor_model:xxx,Parameter:Values | `no_hide` | integer | `0` / `1` | Not hide even if the tag is empty | | `nmaster` | integer | 0, 99 | Number of master windows | | `mfact` | float | 0.1–0.9 | Master area factor | +| `scroller_default_proportion` | float | 0.1-1.0 | Set scroller default proportion. | +| `scroller_default_proportion_single` | float | 0.1-1.0 | Set scroller auto adjust proportion when it is single window(only apply when set `scroller_ignore_proportion_single` to `0`) | +| `scroller_ignore_proportion_single` | integer | `0` / `1` | Ignore scroller single proportion setting. | ### Examples @@ -204,6 +207,10 @@ tagrule=id:4,monitor_name:eDP-1,no_hide:1,layout_name:scroller # Advanced tag configuration with master layout settings tagrule=id:5,layout_name:tile,nmaster:2,mfact:0.6 tagrule=id:6,monitor_name:HDMI-A-1,layout_name:monocle,no_render_border:1 + +# set scroller proportion for specific tag +tagrule=id:1,layout_name:scroller,scroller_default_proportion_single:0.5,scroller_ignore_proportion_single:0,scroller_default_proportion:0.9,monitor_name:HDMI-A-1 + ``` > **Tip:** For Waybar configuration with persistent tags, see [Status Bar](/docs/visuals/status-bar) documentation. From 55d366daf263d8be43fe1c5fbebf09a3099089e2 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 20:44:31 +0800 Subject: [PATCH 25/26] bump version to 0.14.3 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 23b59d61..94861590 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('mango', ['c'], - version : '0.14.2', + version : '0.14.3', ) subdir('protocols') From d81ca73ea1c49e927ee46ec9f25a0e6e9911e0da Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 16 Jun 2026 00:06:49 +0800 Subject: [PATCH 26/26] opt: optimzie dir find logic --- src/dispatch/bind_define.h | 2 +- src/fetch/client.h | 334 ++++++++++--------------------------- src/mango.c | 2 +- 3 files changed, 94 insertions(+), 244 deletions(-) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index a8cf0cd4..01604ebb 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -1918,7 +1918,7 @@ int32_t scroller_stack(const Arg *arg) { if (!c || !c->mon || c->isfloating || !is_scroller_layout(selmon)) return 0; - Client *target_client = find_client_by_direction(c, arg, false, true); + Client *target_client = find_client_by_direction(c, arg, false); return scroller_apply_stack(c, target_client, arg->i); } diff --git a/src/fetch/client.h b/src/fetch/client.h index 77b2d865..4d031255 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -163,10 +163,11 @@ Client *center_tiled_select(Monitor *m) { } return target_c; } -Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, - bool ignore_align) { + +Client *find_client_by_direction(Client *tc, const Arg *arg, + bool findfloating) { Client *c = NULL; - Client **tempClients = NULL; // 初始化为 NULL + Client **tempClients = NULL; int32_t last = -1; // 第一次遍历,计算客户端数量 @@ -179,13 +180,12 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } if (last < 0) { - return NULL; // 没有符合条件的客户端 + return NULL; } // 动态分配内存 tempClients = malloc((last + 1) * sizeof(Client *)); if (!tempClients) { - // 处理内存分配失败的情况 return NULL; } @@ -200,249 +200,102 @@ Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating, } } - int32_t sel_x = tc->geom.x; - int32_t sel_y = tc->geom.y; + // 获取当前窗口的四个边界及中心点 + int32_t tc_l = tc->geom.x; + int32_t tc_r = tc->geom.x + tc->geom.width; + int32_t tc_t = tc->geom.y; + int32_t tc_b = tc->geom.y + tc->geom.height; + int32_t tc_cx = tc_l + tc->geom.width / 2; + int32_t tc_cy = tc_t + tc->geom.height / 2; + int64_t distance = LLONG_MAX; int64_t same_monitor_distance = LLONG_MAX; Client *tempFocusClients = NULL; Client *tempSameMonitorFocusClients = NULL; - switch (arg->i) { - case UP: - if (!ignore_align) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y < sel_y && - tempClients[_i]->geom.x == sel_x && - tempClients[_i]->mon == tc->mon) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } + for (int32_t step = 0; step < 2; step++) { + if (step == 1 && tempFocusClients) + break; + + for (int32_t _i = 0; _i <= last; _i++) { + c = tempClients[_i]; + if (c == tc) + continue; + + if (step == 0 && + (!client_is_in_same_stack(tc, c, NULL) || c->mon != tc->mon)) { + continue; + } + + // 获取目标窗口的四个边界及中心点 + int32_t c_l = c->geom.x; + int32_t c_r = c->geom.x + c->geom.width; + int32_t c_t = c->geom.y; + int32_t c_b = c->geom.y + c->geom.height; + int32_t c_cx = c_l + c->geom.width / 2; + int32_t c_cy = c_t + c->geom.height / 2; + + int64_t main_dist = 0; + int64_t orth_dist = 0; + bool match_dir = false; + + switch (arg->i) { + case LEFT: + match_dir = (c_cx < tc_cx && c_l < tc_l); + if (match_dir) { + main_dist = tc_l - c_r; + orth_dist = (c_b < tc_t) + ? (tc_t - c_b) + : ((c_t > tc_b) ? (c_t - tc_b) : 0); + } + break; + case RIGHT: + match_dir = (c_cx > tc_cx && c_r > tc_r); + if (match_dir) { + main_dist = c_l - tc_r; + orth_dist = (c_b < tc_t) + ? (tc_t - c_b) + : ((c_t > tc_b) ? (c_t - tc_b) : 0); + } + break; + case UP: + match_dir = (c_cy < tc_cy && c_t < tc_t); + if (match_dir) { + main_dist = tc_t - c_b; + orth_dist = (c_r < tc_l) + ? (tc_l - c_r) + : ((c_l > tc_r) ? (c_l - tc_r) : 0); + } + break; + case DOWN: + match_dir = (c_cy > tc_cy && c_b > tc_b); + if (match_dir) { + main_dist = c_t - tc_b; + orth_dist = (c_r < tc_l) + ? (tc_l - c_r) + : ((c_l > tc_r) ? (c_l - tc_r) : 0); + } + break; + } + + if (match_dir) { + int64_t tmp_distance = + main_dist * main_dist + 2 * orth_dist * orth_dist; + + if (tmp_distance < distance) { + distance = tmp_distance; + tempFocusClients = c; + } + if (c->mon == tc->mon && tmp_distance < same_monitor_distance) { + same_monitor_distance = tmp_distance; + tempSameMonitorFocusClients = c; } } } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y < sel_y && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y < sel_y) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - break; - case DOWN: - if (!ignore_align) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y > sel_y && - tempClients[_i]->geom.x == sel_x && - tempClients[_i]->mon == tc->mon) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - } - } - } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y > sel_y && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.y > sel_y) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - break; - case LEFT: - if (!ignore_align) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x < sel_x && - tempClients[_i]->geom.y == sel_y && - tempClients[_i]->mon == tc->mon) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - } - } - } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x < sel_x && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x < sel_x) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - break; - case RIGHT: - if (!ignore_align) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x > sel_x && - tempClients[_i]->geom.y == sel_y && - tempClients[_i]->mon == tc->mon) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - } - } - } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x > sel_x && - tempClients[_i]->mon == tc->mon && - client_is_in_same_stack(tc, tempClients[_i], NULL)) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - if (!tempFocusClients) { - for (int32_t _i = 0; _i <= last; _i++) { - if (tempClients[_i]->geom.x > sel_x) { - int32_t dis_x = tempClients[_i]->geom.x - sel_x; - int32_t dis_y = tempClients[_i]->geom.y - sel_y; - int64_t tmp_distance = - dis_x * dis_x + dis_y * dis_y; // 计算距离 - if (tmp_distance < distance) { - distance = tmp_distance; - tempFocusClients = tempClients[_i]; - } - if (tempClients[_i]->mon == tc->mon && - tmp_distance < same_monitor_distance) { - same_monitor_distance = tmp_distance; - tempSameMonitorFocusClients = tempClients[_i]; - } - } - } - } - break; } - free(tempClients); // 释放内存 + free(tempClients); + if (tempSameMonitorFocusClients) { return tempSameMonitorFocusClients; } else { @@ -462,10 +315,7 @@ Client *direction_select(const Arg *arg) { return NULL; } - return find_client_by_direction( - tc, arg, true, - (is_scroller_layout(selmon) || is_centertile_layout(selmon)) && - !selmon->isoverview); + return find_client_by_direction(tc, arg, true); } /* We probably should change the name of this, it sounds like diff --git a/src/mango.c b/src/mango.c index fe32761a..565a7419 100644 --- a/src/mango.c +++ b/src/mango.c @@ -856,7 +856,7 @@ static float *get_border_color(Client *c); static void clear_fullscreen_and_maximized_state(Monitor *m); static void request_fresh_all_monitors(void); static Client *find_client_by_direction(Client *tc, const Arg *arg, - bool findfloating, bool ignore_align); + bool findfloating); static void exit_scroller_stack(Client *c); static Client *scroll_get_stack_head_client(Client *c); static bool client_only_in_one_tag(Client *c);