diff --git a/src/layout/arrange.h b/src/layout/arrange.h index 56fda657..41598d5e 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -122,14 +122,13 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, bool begin_find_nextnext = false; bool begin_find_prevprev = false; - // 从当前节点的下一个开始遍历 + /* 寻找 next / nextnext */ for (node = grabc->link.next; node != &clients; node = node->next) { tc = wl_container_of(node, tc, link); if (begin_find_nextnext && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { nextnext = tc; break; } - if (!begin_find_nextnext && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { next = tc; begin_find_nextnext = true; @@ -137,15 +136,13 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, } } - // 从当前节点的上一个开始遍历 + /* 寻找 prev / prevprev */ for (node = grabc->link.prev; node != &clients; node = node->prev) { tc = wl_container_of(node, tc, link); - if (begin_find_prevprev && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { prevprev = tc; break; } - if (!begin_find_prevprev && VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { prev = tc; begin_find_prevprev = true; @@ -157,7 +154,6 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, drag_begin_cursorx = cursor->x; drag_begin_cursory = cursor->y; start_drag_window = true; - // 记录初始状态 grabc->old_master_mfact_per = grabc->master_mfact_per; grabc->old_master_inner_per = grabc->master_inner_per; grabc->old_stack_inner_per = grabc->stack_inner_per; @@ -165,12 +161,9 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, cursor->y < grabc->geom.y + grabc->geom.height / 2; grabc->cursor_in_left_half = cursor->x < grabc->geom.x + grabc->geom.width / 2; - // 记录初始几何信息 grabc->drag_begin_geom = grabc->geom; } else { - // 计算相对于屏幕尺寸的比例变化 if (isdrag) { - offsetx = cursor->x - drag_begin_cursorx; offsety = cursor->y - drag_begin_cursory; } else { @@ -193,97 +186,122 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, delta_y = (float)(offsety) * (grabc->old_stack_inner_per) / grabc->drag_begin_geom.height; } - bool moving_up; - bool moving_down; + bool moving_up, moving_down; if (!isdrag) { - moving_up = offsety < 0 ? true : false; - moving_down = offsety > 0 ? true : false; + moving_up = offsety < 0; + moving_down = offsety > 0; } else { moving_up = cursor->y < drag_begin_cursory; moving_down = cursor->y > drag_begin_cursory; } if (grabc->ismaster && !prev) { - if (moving_up) { + if (moving_up) delta_y = -fabsf(delta_y); - } else { + else delta_y = fabsf(delta_y); - } } else if (grabc->ismaster && next && !next->ismaster) { - if (moving_up) { + if (moving_up) delta_y = fabsf(delta_y); - } else { + else delta_y = -fabsf(delta_y); - } } else if (!grabc->ismaster && prev && prev->ismaster) { - if (moving_up) { + if (moving_up) delta_y = -fabsf(delta_y); - } else { + else delta_y = fabsf(delta_y); - } } else if (!grabc->ismaster && !next) { - if (moving_up) { + if (moving_up) delta_y = fabsf(delta_y); - } else { + else delta_y = -fabsf(delta_y); - } } else if (type == CENTER_TILE && !grabc->ismaster && !nextnext) { - if (moving_up) { + if (moving_up) delta_y = fabsf(delta_y); - } else { + else delta_y = -fabsf(delta_y); - } } else if (type == CENTER_TILE && !grabc->ismaster && prevprev && prevprev->ismaster) { - if (moving_up) { + if (moving_up) delta_y = -fabsf(delta_y); - } else { + else delta_y = fabsf(delta_y); - } } else if ((grabc->cursor_in_upper_half && moving_up) || (!grabc->cursor_in_upper_half && moving_down)) { - // 光标在窗口上方且向上移动,或在窗口下方且向下移动 → 增加高度 - delta_y = fabsf(delta_y); - delta_y = delta_y * 2; + delta_y = fabsf(delta_y) * 2; } else { - // 其他情况 → 减小高度 - delta_y = -fabsf(delta_y); - delta_y = delta_y * 2; + delta_y = -fabsf(delta_y) * 2; } - if (!grabc->ismaster && grabc->isleftstack && type == CENTER_TILE) { + if (!grabc->ismaster && grabc->isleftstack && type == CENTER_TILE) delta_x = delta_x * -1.0f; - } - if (grabc->ismaster && type == CENTER_TILE && - grabc->cursor_in_left_half) { + grabc->cursor_in_left_half) delta_x = delta_x * -1.0f; - } - - if (grabc->ismaster && type == CENTER_TILE) { + if (grabc->ismaster && type == CENTER_TILE) delta_x = delta_x * 2; - } - - if (type == RIGHT_TILE) { + if (type == RIGHT_TILE) delta_x = delta_x * -1.0f; - } - // 直接设置新的比例,基于初始值 + 变化量 float new_master_mfact_per = grabc->old_master_mfact_per + delta_x; float new_master_inner_per = grabc->old_master_inner_per + delta_y; float new_stack_inner_per = grabc->old_stack_inner_per + delta_y; - // 应用限制,确保比例在合理范围内 new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per)); new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per)); new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per)); - // 应用到所有平铺窗口 - wl_list_for_each(tc, &clients, link) { - if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { - - if (!isdrag && tc != grabc) { + // 实时缩放同组其他窗口的比例,保持组内总和为 1, + // 不然增加的比例并不是排布后的比例 + if (isdrag) { + if (grabc->ismaster) { + /* 主窗口组:调整所有主窗口的 master_inner_per */ + float cur_other_sum = 1.0f - grabc->master_inner_per; + float new_other_sum = 1.0f - new_master_inner_per; + if (cur_other_sum > 0.001f) { + float scale = new_other_sum / cur_other_sum; + wl_list_for_each(tc, &clients, link) { + if (VISIBLEON(tc, grabc->mon) && ISTILED(tc) && + tc->ismaster && tc != grabc) + tc->master_inner_per *= scale; + } + } + } else { + /* 栈窗口组:根据布局类型分开处理 */ + if (type == CENTER_TILE) { + /* 仅缩放同侧栈窗口的 stack_inner_per */ + float cur_other_sum = 1.0f - grabc->stack_inner_per; + float new_other_sum = 1.0f - new_stack_inner_per; + if (cur_other_sum > 0.001f) { + float scale = new_other_sum / cur_other_sum; + wl_list_for_each(tc, &clients, link) { + if (VISIBLEON(tc, grabc->mon) && ISTILED(tc) && + !tc->ismaster && tc != grabc && + tc->isleftstack == grabc->isleftstack) + tc->stack_inner_per *= scale; + } + } + } else { + /* TILE / RIGHT_TILE / DECK:所有栈窗口共用一个比例组 */ + float cur_other_sum = 1.0f - grabc->stack_inner_per; + float new_other_sum = 1.0f - new_stack_inner_per; + if (cur_other_sum > 0.001f) { + float scale = new_other_sum / cur_other_sum; + wl_list_for_each(tc, &clients, link) { + if (VISIBLEON(tc, grabc->mon) && ISTILED(tc) && + !tc->ismaster && tc != grabc) + tc->stack_inner_per *= scale; + } + } + } + } + } else { + /* 键盘步进 */ + wl_list_for_each(tc, &clients, link) { + if (!VISIBLEON(tc, grabc->mon) || !ISTILED(tc)) + continue; + if (tc != grabc) { if (!tc->ismaster && new_stack_inner_per != 1.0f && grabc->old_stack_inner_per != 1.0f && (type != CENTER_TILE || @@ -298,14 +316,19 @@ void resize_tile_master_horizontal(Client *grabc, bool isdrag, int32_t offsetx, (1.0f - grabc->old_master_inner_per) * tc->master_inner_per; } - - tc->master_mfact_per = new_master_mfact_per; } } + /* 将新比例应用到抓取窗口本身 */ grabc->master_inner_per = new_master_inner_per; grabc->stack_inner_per = new_stack_inner_per; + /* 广播 master_mfact_per 到所有平铺窗口 */ + wl_list_for_each(tc, &clients, link) { + if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) + tc->master_mfact_per = new_master_mfact_per; + } + if (!isdrag) { arrange(grabc->mon, false, false); return; @@ -327,20 +350,18 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx, Client *prev = NULL; struct wl_list *node; - // 从当前节点的下一个开始遍历 + /* 寻找 next */ for (node = grabc->link.next; node != &clients; node = node->next) { tc = wl_container_of(node, tc, link); - if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { next = tc; break; } } - // 从当前节点的上一个开始遍历 + /* 寻找 prev */ for (node = grabc->link.prev; node != &clients; node = node->prev) { tc = wl_container_of(node, tc, link); - if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { prev = tc; break; @@ -351,8 +372,6 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx, drag_begin_cursorx = cursor->x; drag_begin_cursory = cursor->y; start_drag_window = true; - - // 记录初始状态 grabc->old_master_mfact_per = grabc->master_mfact_per; grabc->old_master_inner_per = grabc->master_inner_per; grabc->old_stack_inner_per = grabc->stack_inner_per; @@ -360,13 +379,9 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx, cursor->y < grabc->geom.y + grabc->geom.height / 2; grabc->cursor_in_left_half = cursor->x < grabc->geom.x + grabc->geom.width / 2; - // 记录初始几何信息 grabc->drag_begin_geom = grabc->geom; } else { - // 计算相对于屏幕尺寸的比例变化 - // 计算相对于屏幕尺寸的比例变化 if (isdrag) { - offsetx = cursor->x - drag_begin_cursorx; offsety = cursor->y - drag_begin_cursory; } else { @@ -379,7 +394,6 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx, } if (grabc->ismaster) { - // 垂直版本:左右移动调整高度比例,上下移动调整宽度比例 delta_x = (float)(offsetx) * (grabc->old_master_inner_per) / grabc->drag_begin_geom.width; delta_y = (float)(offsety) * (grabc->old_master_mfact_per) / @@ -391,70 +405,84 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx, grabc->drag_begin_geom.height; } - bool moving_left; - bool moving_right; - + bool moving_left, moving_right; if (!isdrag) { - moving_left = offsetx < 0 ? true : false; - moving_right = offsetx > 0 ? true : false; + moving_left = offsetx < 0; + moving_right = offsetx > 0; } else { moving_left = cursor->x < drag_begin_cursorx; moving_right = cursor->x > drag_begin_cursorx; } - // 调整主区域和栈区域的高度比例(垂直分割) if (grabc->ismaster && !prev) { - if (moving_left) { - delta_x = -fabsf(delta_x); // 向上移动减少主区域高度 - } else { - delta_x = fabsf(delta_x); // 向下移动增加主区域高度 - } + if (moving_left) + delta_x = -fabsf(delta_x); + else + delta_x = fabsf(delta_x); } else if (grabc->ismaster && next && !next->ismaster) { - if (moving_left) { - delta_x = fabsf(delta_x); // 向上移动增加主区域高度 - } else { - delta_x = -fabsf(delta_x); // 向下移动减少主区域高度 - } + if (moving_left) + delta_x = fabsf(delta_x); + else + delta_x = -fabsf(delta_x); } else if (!grabc->ismaster && prev && prev->ismaster) { - if (moving_left) { - delta_x = -fabsf(delta_x); // 向上移动减少栈区域高度 - } else { - delta_x = fabsf(delta_x); // 向下移动增加栈区域高度 - } + if (moving_left) + delta_x = -fabsf(delta_x); + else + delta_x = fabsf(delta_x); } else if (!grabc->ismaster && !next) { - if (moving_left) { - delta_x = fabsf(delta_x); // 向上移动增加栈区域高度 - } else { - delta_x = -fabsf(delta_x); // 向下移动减少栈区域高度 - } + if (moving_left) + delta_x = fabsf(delta_x); + else + delta_x = -fabsf(delta_x); } else if ((grabc->cursor_in_left_half && moving_left) || (!grabc->cursor_in_left_half && moving_right)) { - // 光标在窗口左侧且向左移动,或在窗口右侧且向右移动 → 增加宽度 - delta_x = fabsf(delta_x); - delta_x = delta_x * 2; + delta_x = fabsf(delta_x) * 2; } else { - // 其他情况 → 减小宽度 - delta_x = -fabsf(delta_x); - delta_x = delta_x * 2; + delta_x = -fabsf(delta_x) * 2; } - // 直接设置新的比例,基于初始值 + 变化量 - float new_master_mfact_per = grabc->old_master_mfact_per + - delta_y; // 垂直:delta_y调整主区域高度 - float new_master_inner_per = grabc->old_master_inner_per + - delta_x; // 垂直:delta_x调整主区域内部宽度 - float new_stack_inner_per = grabc->old_stack_inner_per + - delta_x; // 垂直:delta_x调整栈区域内部宽度 + float new_master_mfact_per = grabc->old_master_mfact_per + delta_y; + float new_master_inner_per = grabc->old_master_inner_per + delta_x; + float new_stack_inner_per = grabc->old_stack_inner_per + delta_x; - // 应用限制,确保比例在合理范围内 new_master_mfact_per = fmaxf(0.1f, fminf(0.9f, new_master_mfact_per)); new_master_inner_per = fmaxf(0.1f, fminf(0.9f, new_master_inner_per)); new_stack_inner_per = fmaxf(0.1f, fminf(0.9f, new_stack_inner_per)); - // 应用到所有平铺窗口 - wl_list_for_each(tc, &clients, link) { - if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) { - if (!isdrag && tc != grabc && type != CENTER_TILE) { + // 实时缩放同组其他窗口的比例,保持组内总和为 1, + // 不然增加的比例并不是排布后的比例 + + if (isdrag) { + if (grabc->ismaster) { + float cur_other_sum = 1.0f - grabc->master_inner_per; + float new_other_sum = 1.0f - new_master_inner_per; + if (cur_other_sum > 0.001f) { + float scale = new_other_sum / cur_other_sum; + wl_list_for_each(tc, &clients, link) { + if (VISIBLEON(tc, grabc->mon) && ISTILED(tc) && + tc->ismaster && tc != grabc) + tc->master_inner_per *= scale; + } + } + } else { + /* 所有栈窗口(垂直布局没有左侧/右侧区分) */ + float cur_other_sum = 1.0f - grabc->stack_inner_per; + float new_other_sum = 1.0f - new_stack_inner_per; + if (cur_other_sum > 0.001f) { + float scale = new_other_sum / cur_other_sum; + wl_list_for_each(tc, &clients, link) { + if (VISIBLEON(tc, grabc->mon) && ISTILED(tc) && + !tc->ismaster && tc != grabc) + tc->stack_inner_per *= scale; + } + } + } + } else { + /* 键盘步进 */ + wl_list_for_each(tc, &clients, link) { + if (!VISIBLEON(tc, grabc->mon) || !ISTILED(tc)) + continue; + if (tc != grabc) { if (!tc->ismaster && new_stack_inner_per != 1.0f && grabc->old_stack_inner_per != 1.0f) tc->stack_inner_per = (1 - new_stack_inner_per) / @@ -467,14 +495,18 @@ void resize_tile_master_vertical(Client *grabc, bool isdrag, int32_t offsetx, (1.0f - grabc->old_master_inner_per) * tc->master_inner_per; } - - tc->master_mfact_per = new_master_mfact_per; } } grabc->master_inner_per = new_master_inner_per; grabc->stack_inner_per = new_stack_inner_per; + /* 广播 master_mfact_per */ + wl_list_for_each(tc, &clients, link) { + if (VISIBLEON(tc, grabc->mon) && ISTILED(tc)) + tc->master_mfact_per = new_master_mfact_per; + } + if (!isdrag) { arrange(grabc->mon, false, false); return; @@ -665,24 +697,38 @@ void resize_tile_scroller(Client *grabc, bool isdrag, int32_t offsetx, fmaxf(0.1f, fminf(1.0f, new_scroller_proportion)); new_stack_proportion = fmaxf(0.1f, fminf(0.9f, new_stack_proportion)); - curnode->stack_proportion = new_stack_proportion; - headnode->scroller_proportion = new_scroller_proportion; - - /* 调整同一堆叠内其他节点的 stack_proportion */ - /* 调整整个堆叠内除当前窗口外的所有节点 */ - if (!isdrag && grabc->old_stack_proportion != 1.0f) { - for (struct ScrollerStackNode *tc = headnode; tc; - tc = tc->next_in_stack) { - if (tc != curnode) { - tc->stack_proportion = - (1.0f - new_stack_proportion) / - (1.0f - grabc->old_stack_proportion) * - tc->stack_proportion; + // 保持总和为 1,避免后续 arrange 归一化吞掉位移 + if (isdrag) { + float current_other_sum = 1.0f - curnode->stack_proportion; + float new_other_sum = 1.0f - new_stack_proportion; + if (current_other_sum > 0.001f) { + float scale = new_other_sum / current_other_sum; + for (struct ScrollerStackNode *tc = headnode; tc; + tc = tc->next_in_stack) { + if (tc != curnode) { + tc->stack_proportion *= scale; + } + } + } + } else { + // 键盘步进 + if (grabc->old_stack_proportion != 1.0f) { + for (struct ScrollerStackNode *tc = headnode; tc; + tc = tc->next_in_stack) { + if (tc != curnode) { + tc->stack_proportion = + (1.0f - new_stack_proportion) / + (1.0f - grabc->old_stack_proportion) * + tc->stack_proportion; + } } } } - /* 同步回全局字段*/ + curnode->stack_proportion = new_stack_proportion; + headnode->scroller_proportion = new_scroller_proportion; + + /* 同步回全局字段 */ sync_scroller_state_to_clients(m, tag); if (!isdrag) {