From 548d58db64a6a1b466c6e984f5b8ecec7ed2aa6d Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 15 Jun 2026 20:44:31 +0800 Subject: [PATCH 1/6] 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 37886975..9da040f0 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 17fd82a08bff111075a65d19ad23f81575fad72d Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 16 Jun 2026 00:06:49 +0800 Subject: [PATCH 2/6] 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 1e39386c..6dcb6b87 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -1919,7 +1919,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 449cd2ae..ddc0feb1 100644 --- a/src/mango.c +++ b/src/mango.c @@ -866,7 +866,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); From 4e25a6c64b25541257c09f1c96617dcca2f06a8b Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 16 Jun 2026 08:08:30 +0800 Subject: [PATCH 3/6] opt: better direction algorithm for client find --- src/dispatch/bind_define.h | 7 +- src/fetch/client.h | 222 ++++++++++++++++--------------------- 2 files changed, 104 insertions(+), 125 deletions(-) diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 6dcb6b87..3c1ca1f1 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -131,9 +131,14 @@ int32_t exchange_stack_client(const Arg *arg) { } int32_t focusdir(const Arg *arg) { + + if(!selmon) + return 0; + Client *c = NULL; c = direction_select(arg); - c = get_focused_stack_client(c, arg->tc); + if(!selmon->isoverview) + c = get_focused_stack_client(c, arg->tc); if (c) { focusclient(c, 1); if (config.warpcursor) diff --git a/src/fetch/client.h b/src/fetch/client.h index 4d031255..25fd2a01 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -164,143 +164,117 @@ Client *center_tiled_select(Monitor *m) { return target_c; } -Client *find_client_by_direction(Client *tc, const Arg *arg, - bool findfloating) { - Client *c = NULL; - Client **tempClients = NULL; - int32_t last = -1; +Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating) { + Client *c = NULL; + Client *tempFocusClients = NULL; + Client *tempSameMonitorFocusClients = NULL; + int64_t distance = LLONG_MAX; + int64_t same_monitor_distance = LLONG_MAX; - // 第一次遍历,计算客户端数量 - wl_list_for_each(c, &clients, link) { - if (c && (findfloating || !c->isfloating) && !c->isunglobal && - (config.focus_cross_monitor || c->mon == tc->mon) && - (c->tags & c->mon->tagset[c->mon->seltags])) { - last++; - } - } + 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; - if (last < 0) { - return NULL; - } + for (int32_t step = 0; step < 2; step++) { + if (step == 1 && tempFocusClients) + break; - // 动态分配内存 - tempClients = malloc((last + 1) * sizeof(Client *)); - if (!tempClients) { - return NULL; - } + wl_list_for_each(c, &clients, link) { + if (!c || c == tc) + continue; + if (!findfloating && c->isfloating) + continue; + if (c->isunglobal) + continue; + if (!config.focus_cross_monitor && c->mon != tc->mon) + continue; + if (!(c->tags & c->mon->tagset[c->mon->seltags])) + continue; - // 第二次遍历,填充 tempClients - last = -1; - wl_list_for_each(c, &clients, link) { - if (c && (findfloating || !c->isfloating) && !c->isunglobal && - (config.focus_cross_monitor || c->mon == tc->mon) && - (c->tags & c->mon->tagset[c->mon->seltags])) { - last++; - tempClients[last] = c; - } - } + if (step == 0 && ((!tc->mon->isoverview && !client_is_in_same_stack(tc, c, NULL)) || c->mon != tc->mon)) + continue; - // 获取当前窗口的四个边界及中心点 - 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; + 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 distance = LLONG_MAX; - int64_t same_monitor_distance = LLONG_MAX; - Client *tempFocusClients = NULL; - Client *tempSameMonitorFocusClients = NULL; + int64_t main_dist = 0; + int64_t orth_dist = 0; + bool match_dir = false; - for (int32_t step = 0; step < 2; step++) { - if (step == 1 && tempFocusClients) - break; + switch (arg->i) { + case LEFT: + if (c_cx < tc_cx || (c_cx == tc_cx && c_l < tc_l)) { + match_dir = true; + 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: + if (c_cx > tc_cx || (c_cx == tc_cx && c_l > tc_l)) { + match_dir = true; + 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: + if (c_cy < tc_cy || (c_cy == tc_cy && c_t < tc_t)) { + match_dir = true; + 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: + if (c_cy > tc_cy || (c_cy == tc_cy && c_t > tc_t)) { + match_dir = true; + 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; + default: + continue; + } - for (int32_t _i = 0; _i <= last; _i++) { - c = tempClients[_i]; - if (c == tc) - continue; + if (!match_dir) + continue; - if (step == 0 && - (!client_is_in_same_stack(tc, c, NULL) || c->mon != tc->mon)) { - continue; - } + int64_t penalty = 0; + if (main_dist < 0) { + penalty = 10000000000LL; // 主方向重叠(反方向)的极大惩罚 + main_dist = -main_dist; + } - // 获取目标窗口的四个边界及中心点 - 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 no_overlap_penalty = 0; + if (orth_dist > 0) { + // LEFT/RIGHT 时 orth_dist 是垂直间距,>0 表示垂直无重叠 + // UP/DOWN 时 orth_dist 是水平间距,>0 表示水平无重叠 + no_overlap_penalty = 10000000LL; + } - int64_t main_dist = 0; - int64_t orth_dist = 0; - bool match_dir = false; + int64_t tmp_distance = penalty + no_overlap_penalty + + (main_dist * main_dist) + (orth_dist * orth_dist); - 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 (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 (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; - } - } - } - } - - free(tempClients); - - if (tempSameMonitorFocusClients) { - return tempSameMonitorFocusClients; - } else { - return tempFocusClients; - } + if (tempSameMonitorFocusClients) + return tempSameMonitorFocusClients; + return tempFocusClients; } Client *direction_select(const Arg *arg) { From d0cd2beeb63953a34cbe349a934c19e27fe760c5 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 16 Jun 2026 08:07:54 +0800 Subject: [PATCH 4/6] fix: scroller proportion option miss apply in windowrule --- src/layout/arrange.h | 11 +++++++++-- src/mango.c | 12 ++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/layout/arrange.h b/src/layout/arrange.h index 0a39b248..23b9d080 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -26,8 +26,15 @@ void set_size_per(Monitor *m, Client *c) { c->stack_inner_per = 1.0f; } - c->scroller_proportion = - m->pertag->scroller_default_proportion[m->pertag->curtag]; + if (!c->iscustom_scroller_proportion) { + c->scroller_proportion = + m->pertag->scroller_default_proportion[m->pertag->curtag]; + } + + if (!c->iscustom_scroller_proportion_single) { + c->scroller_proportion_single = + m->pertag->scroller_default_proportion_single[m->pertag->curtag]; + } } void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, diff --git a/src/mango.c b/src/mango.c index ddc0feb1..b5e0b3ea 100644 --- a/src/mango.c +++ b/src/mango.c @@ -383,6 +383,8 @@ struct Client { int32_t is_in_scratchpad; int32_t iscustomsize; int32_t iscustompos; + int32_t iscustom_scroller_proportion; + int32_t iscustom_scroller_proportion_single; int32_t is_scratchpad_show; int32_t isglobal; int32_t isnoborder; @@ -1677,6 +1679,14 @@ void applyrules(Client *c) { c->isfloating = 1; } + if (r->scroller_proportion > 0.0f) { + c->iscustom_scroller_proportion = 1; + } + + if (r->scroller_proportion_single > 0.0f) { + c->iscustom_scroller_proportion_single = 1; + } + // set geometry of floating client if (r->width > 1) @@ -4333,6 +4343,8 @@ void init_client_properties(Client *c) { c->ignore_minimize = 1; c->iscustomsize = 0; c->iscustompos = 0; + c->iscustom_scroller_proportion = 0; + c->iscustom_scroller_proportion_single = 0; c->master_mfact_per = 0.0f; c->master_inner_per = 0.0f; c->stack_inner_per = 0.0f; From d9ac7ae95b7c34d253e4d9cae3d81aebdefb7938 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 16 Jun 2026 08:12:53 +0800 Subject: [PATCH 5/6] opt: warp cursor to focusing client when exchange --- src/action/client.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/action/client.h b/src/action/client.h index 1b3c9335..6984a394 100644 --- a/src/action/client.h +++ b/src/action/client.h @@ -48,6 +48,9 @@ static void finish_exchange_arrange_and_focus(Client *c1, Client *c2, } wl_list_remove(&c2->flink); wl_list_insert(&c1->flink, &c2->flink); + + if (config.warpcursor) + warp_cursor(c1); } void client_tile_resize(Client *c, struct wlr_box geo, int32_t interact) { From 512d09cda8f7a8edfa1a4e8c2603d94203f36182 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Tue, 16 Jun 2026 08:20:43 +0800 Subject: [PATCH 6/6] opt: format code --- src/action/client.h | 2 +- src/dispatch/bind_define.h | 4 +- src/fetch/client.h | 208 ++++++++++++++++++++----------------- 3 files changed, 113 insertions(+), 101 deletions(-) diff --git a/src/action/client.h b/src/action/client.h index 6984a394..11602e70 100644 --- a/src/action/client.h +++ b/src/action/client.h @@ -49,7 +49,7 @@ static void finish_exchange_arrange_and_focus(Client *c1, Client *c2, wl_list_remove(&c2->flink); wl_list_insert(&c1->flink, &c2->flink); - if (config.warpcursor) + if (config.warpcursor) warp_cursor(c1); } diff --git a/src/dispatch/bind_define.h b/src/dispatch/bind_define.h index 3c1ca1f1..de51c0a0 100644 --- a/src/dispatch/bind_define.h +++ b/src/dispatch/bind_define.h @@ -132,12 +132,12 @@ int32_t exchange_stack_client(const Arg *arg) { int32_t focusdir(const Arg *arg) { - if(!selmon) + if (!selmon) return 0; Client *c = NULL; c = direction_select(arg); - if(!selmon->isoverview) + if (!selmon->isoverview) c = get_focused_stack_client(c, arg->tc); if (c) { focusclient(c, 1); diff --git a/src/fetch/client.h b/src/fetch/client.h index 25fd2a01..fb50c798 100644 --- a/src/fetch/client.h +++ b/src/fetch/client.h @@ -164,117 +164,129 @@ Client *center_tiled_select(Monitor *m) { return target_c; } -Client *find_client_by_direction(Client *tc, const Arg *arg, bool findfloating) { - Client *c = NULL; - Client *tempFocusClients = NULL; - Client *tempSameMonitorFocusClients = NULL; - int64_t distance = LLONG_MAX; - int64_t same_monitor_distance = LLONG_MAX; +Client *find_client_by_direction(Client *tc, const Arg *arg, + bool findfloating) { + Client *c = NULL; + Client *tempFocusClients = NULL; + Client *tempSameMonitorFocusClients = NULL; + int64_t distance = LLONG_MAX; + int64_t same_monitor_distance = LLONG_MAX; - 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; + 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; - for (int32_t step = 0; step < 2; step++) { - if (step == 1 && tempFocusClients) - break; + for (int32_t step = 0; step < 2; step++) { + if (step == 1 && tempFocusClients) + break; - wl_list_for_each(c, &clients, link) { - if (!c || c == tc) - continue; - if (!findfloating && c->isfloating) - continue; - if (c->isunglobal) - continue; - if (!config.focus_cross_monitor && c->mon != tc->mon) - continue; - if (!(c->tags & c->mon->tagset[c->mon->seltags])) - continue; + wl_list_for_each(c, &clients, link) { + if (!c || c == tc) + continue; + if (!findfloating && c->isfloating) + continue; + if (c->isunglobal) + continue; + if (!config.focus_cross_monitor && c->mon != tc->mon) + continue; + if (!(c->tags & c->mon->tagset[c->mon->seltags])) + continue; - if (step == 0 && ((!tc->mon->isoverview && !client_is_in_same_stack(tc, c, NULL)) || c->mon != tc->mon)) - continue; + if (step == 0 && ((!tc->mon->isoverview && + !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; + 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; + int64_t main_dist = 0; + int64_t orth_dist = 0; + bool match_dir = false; - switch (arg->i) { - case LEFT: - if (c_cx < tc_cx || (c_cx == tc_cx && c_l < tc_l)) { - match_dir = true; - 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: - if (c_cx > tc_cx || (c_cx == tc_cx && c_l > tc_l)) { - match_dir = true; - 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: - if (c_cy < tc_cy || (c_cy == tc_cy && c_t < tc_t)) { - match_dir = true; - 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: - if (c_cy > tc_cy || (c_cy == tc_cy && c_t > tc_t)) { - match_dir = true; - 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; - default: - continue; - } + switch (arg->i) { + case LEFT: + if (c_cx < tc_cx || (c_cx == tc_cx && c_l < tc_l)) { + match_dir = true; + 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: + if (c_cx > tc_cx || (c_cx == tc_cx && c_l > tc_l)) { + match_dir = true; + 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: + if (c_cy < tc_cy || (c_cy == tc_cy && c_t < tc_t)) { + match_dir = true; + 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: + if (c_cy > tc_cy || (c_cy == tc_cy && c_t > tc_t)) { + match_dir = true; + 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; + default: + continue; + } - if (!match_dir) - continue; + if (!match_dir) + continue; - int64_t penalty = 0; - if (main_dist < 0) { - penalty = 10000000000LL; // 主方向重叠(反方向)的极大惩罚 - main_dist = -main_dist; - } + int64_t penalty = 0; + if (main_dist < 0) { + penalty = 10000000000LL; // 主方向重叠(反方向)的极大惩罚 + main_dist = -main_dist; + } - // 正交方向无重叠惩罚,优先选择在同一行/列的窗口 - int64_t no_overlap_penalty = 0; - if (orth_dist > 0) { - // LEFT/RIGHT 时 orth_dist 是垂直间距,>0 表示垂直无重叠 - // UP/DOWN 时 orth_dist 是水平间距,>0 表示水平无重叠 - no_overlap_penalty = 10000000LL; - } + // 正交方向无重叠惩罚,优先选择在同一行/列的窗口 + int64_t no_overlap_penalty = 0; + if (orth_dist > 0) { + // LEFT/RIGHT 时 orth_dist 是垂直间距,>0 表示垂直无重叠 + // UP/DOWN 时 orth_dist 是水平间距,>0 表示水平无重叠 + no_overlap_penalty = 10000000LL; + } - int64_t tmp_distance = penalty + no_overlap_penalty - + (main_dist * main_dist) + (orth_dist * orth_dist); + int64_t tmp_distance = penalty + no_overlap_penalty + + (main_dist * main_dist) + + (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 (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 (tempSameMonitorFocusClients) - return tempSameMonitorFocusClients; - return tempFocusClients; + if (tempSameMonitorFocusClients) + return tempSameMonitorFocusClients; + return tempFocusClients; } Client *direction_select(const Arg *arg) {