diff --git a/src/animation/client.h b/src/animation/client.h index bb1d2231..a34a3348 100644 --- a/src/animation/client.h +++ b/src/animation/client.h @@ -645,6 +645,7 @@ void client_set_drop_area(Client *c) { 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) && diff --git a/src/layout/arrange.h b/src/layout/arrange.h index 41598d5e..42d15f86 100644 --- a/src/layout/arrange.h +++ b/src/layout/arrange.h @@ -33,6 +33,7 @@ void restore_size_per(Monitor *m, Client *c) { if (current_layout->id == SCROLLER || current_layout->id == VERTICAL_SCROLLER || current_layout->id == GRID || + current_layout->id == FAIR || current_layout->id == VERTICAL_FAIR || current_layout->id == VERTICAL_GRID || current_layout->id == DECK || current_layout->id == VERTICAL_DECK || current_layout->id == MONOCLE) { return; diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index 37c8793e..3ff8bd44 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -674,4 +674,80 @@ monocle(Monitor *m) { } if ((c = focustop(m))) wlr_scene_node_raise_to_top(&c->scene->node); +} + +void fair(Monitor *m) { + int32_t i, n = 0; + Client *c = NULL; + + n = m->visible_tiling_clients; + if (n == 0) + return; + + // 间隙参数处理 + int32_t cur_gappiv = enablegaps ? m->gappiv : 0; + int32_t cur_gappih = enablegaps ? m->gappih : 0; + int32_t cur_gappov = enablegaps ? m->gappov : 0; + int32_t cur_gappoh = enablegaps ? m->gappoh : 0; + + // 智能间隙 + cur_gappiv = config.smartgaps && n == 1 ? 0 : cur_gappiv; + cur_gappih = config.smartgaps && n == 1 ? 0 : cur_gappih; + cur_gappov = config.smartgaps && n == 1 ? 0 : cur_gappov; + cur_gappoh = config.smartgaps && n == 1 ? 0 : cur_gappoh; + + // 计算最佳列数 cols = ceil(sqrt(n)) + int32_t cols; + for (cols = 0; cols <= n; cols++) { + if (cols * cols >= n) + break; + } + + int32_t base_rows = n / cols; // 每列的基础行数 + int32_t remainder = n % cols; // 多出来的窗口,分配给前 remainder 列 + + // 计算标准列宽 + int32_t col_width = + (m->w.width - 2 * cur_gappoh - (cols - 1) * cur_gappih) / cols; + + i = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || !ISTILED(c)) + continue; + + int32_t col_idx, row_idx, rows_in_this_col; + + // 判断当前窗口属于哪一列、哪一行 + if (i < remainder * (base_rows + 1)) { + col_idx = i / (base_rows + 1); + row_idx = i % (base_rows + 1); + rows_in_this_col = base_rows + 1; + } else { + int32_t offset = i - remainder * (base_rows + 1); + col_idx = remainder + offset / base_rows; + row_idx = offset % base_rows; + rows_in_this_col = base_rows; + } + + // 计算 X 坐标和宽度 (最后一列吃掉剩余像素,防止缝隙) + int32_t cx = m->w.x + cur_gappoh + col_idx * (col_width + cur_gappih); + int32_t cw = (col_idx == cols - 1) + ? (m->w.width - 2 * cur_gappoh - + col_idx * (col_width + cur_gappih)) + : col_width; + + // 计算 Y 坐标和高度 (最后一行吃掉剩余像素) + int32_t base_ch = (m->w.height - 2 * cur_gappov - + (rows_in_this_col - 1) * cur_gappiv) / + rows_in_this_col; + int32_t cy = m->w.y + cur_gappov + row_idx * (base_ch + cur_gappiv); + int32_t ch = (row_idx == rows_in_this_col - 1) + ? (m->w.height - 2 * cur_gappov - + row_idx * (base_ch + cur_gappiv)) + : base_ch; + + resize(c, (struct wlr_box){.x = cx, .y = cy, .width = cw, .height = ch}, + 0); + i++; + } } \ No newline at end of file diff --git a/src/layout/layout.h b/src/layout/layout.h index 16773dc7..1f82eeaa 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -12,6 +12,8 @@ static void vertical_grid(Monitor *m); static void vertical_scroller(Monitor *m); static void vertical_deck(Monitor *mon); static void dwindle(Monitor *m); +static void fair(Monitor *m); +static void vertical_fair(Monitor *m); /* layout(s) */ Layout overviewlayout = {"󰃇", overview, "overview"}; @@ -29,6 +31,8 @@ enum { VERTICAL_DECK, RIGHT_TILE, DWINDLE, + FAIR, + VERTICAL_FAIR, }; Layout layouts[] = { @@ -47,4 +51,6 @@ Layout layouts[] = { {"VG", vertical_grid, "vertical_grid", VERTICAL_GRID}, // 垂直格子布局 {"VK", vertical_deck, "vertical_deck", VERTICAL_DECK}, // 垂直卡片布局 {"DW", dwindle, "dwindle", DWINDLE}, + {"F", fair, "fair", FAIR}, + {"VF", vertical_fair, "vertical_fair", VERTICAL_FAIR}, }; \ No newline at end of file diff --git a/src/layout/vertical.h b/src/layout/vertical.h index 36114dde..484dfd85 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -281,4 +281,80 @@ void vertical_grid(Monitor *m) { i++; } } +} + +void vertical_fair(Monitor *m) { + int32_t i, n = 0; + Client *c = NULL; + + n = m->visible_tiling_clients; + if (n == 0) + return; + + // 间隙参数处理 + int32_t cur_gappiv = enablegaps ? m->gappiv : 0; + int32_t cur_gappih = enablegaps ? m->gappih : 0; + int32_t cur_gappov = enablegaps ? m->gappov : 0; + int32_t cur_gappoh = enablegaps ? m->gappoh : 0; + + // 智能间隙 + cur_gappiv = config.smartgaps && n == 1 ? 0 : cur_gappiv; + cur_gappih = config.smartgaps && n == 1 ? 0 : cur_gappih; + cur_gappov = config.smartgaps && n == 1 ? 0 : cur_gappov; + cur_gappoh = config.smartgaps && n == 1 ? 0 : cur_gappoh; + + // 计算最佳行数 rows = ceil(sqrt(n)) + int32_t rows; + for (rows = 0; rows <= n; rows++) { + if (rows * rows >= n) + break; + } + + int32_t base_cols = n / rows; // 每行的基础列数 + int32_t remainder = n % rows; // 多出来的窗口,分配给前 remainder 行 + + // 计算标准行高 + int32_t row_height = + (m->w.height - 2 * cur_gappov - (rows - 1) * cur_gappiv) / rows; + + i = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || !ISTILED(c)) + continue; + + int32_t row_idx, col_idx, cols_in_this_row; + + // 判断当前窗口属于哪一行、哪一列 + if (i < remainder * (base_cols + 1)) { + row_idx = i / (base_cols + 1); + col_idx = i % (base_cols + 1); + cols_in_this_row = base_cols + 1; + } else { + int32_t offset = i - remainder * (base_cols + 1); + row_idx = remainder + offset / base_cols; + col_idx = offset % base_cols; + cols_in_this_row = base_cols; + } + + // 计算 Y 坐标和高度 (最后一行吃掉剩余像素) + int32_t cy = m->w.y + cur_gappov + row_idx * (row_height + cur_gappiv); + int32_t ch = (row_idx == rows - 1) + ? (m->w.height - 2 * cur_gappov - + row_idx * (row_height + cur_gappiv)) + : row_height; + + // 计算 X 坐标和宽度 (最后一列吃掉剩余像素,防止缝隙) + int32_t base_cw = (m->w.width - 2 * cur_gappoh - + (cols_in_this_row - 1) * cur_gappih) / + cols_in_this_row; + int32_t cx = m->w.x + cur_gappoh + col_idx * (base_cw + cur_gappih); + int32_t cw = (col_idx == cols_in_this_row - 1) + ? (m->w.width - 2 * cur_gappoh - + col_idx * (base_cw + cur_gappih)) + : base_cw; + + resize(c, (struct wlr_box){.x = cx, .y = cy, .width = cw, .height = ch}, + 0); + i++; + } } \ No newline at end of file