From d9b40795acc39c611b6110243e8b71c4e4e9b9d9 Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Mon, 18 May 2026 11:41:30 +0800 Subject: [PATCH] opt: optimzie fair layout caculate --- src/layout/horizontal.h | 171 ++++++++++++++++++++++++++-------------- src/layout/vertical.h | 161 ++++++++++++++++++++++++------------- 2 files changed, 219 insertions(+), 113 deletions(-) diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h index ee37b168..00bea0e0 100644 --- a/src/layout/horizontal.h +++ b/src/layout/horizontal.h @@ -874,16 +874,17 @@ void fair(Monitor *m) { 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; + if (config.smartgaps && n == 1) { + cur_gappiv = cur_gappih = cur_gappov = cur_gappoh = 0; + } + // 计算网格行列数 int32_t cols; for (cols = 0; cols <= n; cols++) { if (cols * cols >= n) @@ -896,56 +897,130 @@ void fair(Monitor *m) { int32_t first_group_count = first_group_cols * base_rows; int32_t max_rows = base_rows + (remainder > 0 ? 1 : 0); + // 将有效客户端存入数组 + Client *arr[n]; + int32_t arr_idx = 0; + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && ISTILED(c)) { + arr[arr_idx++] = c; + if (arr_idx >= n) + break; // 安全边界 + } + } + + // 初始化比例数组 float col_pers[cols]; float row_pers[max_rows]; for (i = 0; i < cols; i++) - col_pers[i] = 1.0f; + col_pers[i] = 0.0f; for (i = 0; i < max_rows; i++) - row_pers[i] = 1.0f; + row_pers[i] = 0.0f; - i = 0; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || !ISTILED(c)) - continue; - int32_t col_idx, row_idx; - if (i < first_group_count) { - col_idx = i / base_rows; - row_idx = i % base_rows; - } else { - int32_t offset = i - first_group_count; - col_idx = first_group_cols + (offset / (base_rows + 1)); - row_idx = offset % (base_rows + 1); - } + // 直接基于数组进行两遍比例锁定 + for (i = 0; i < n; i++) { + c = arr[i]; + int32_t col_idx = + (i < first_group_count) + ? (i / base_rows) + : (first_group_cols + (i - first_group_count) / max_rows); + int32_t row_idx = (i < first_group_count) + ? (i % base_rows) + : ((i - first_group_count) % max_rows); - if (row_idx == 0) - col_pers[col_idx] = - (c->grid_col_per > 0.0f) ? c->grid_col_per : 1.0f; - if (col_idx == 0) - row_pers[row_idx] = - (c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f; - i++; + if (c->grid_col_idx == col_idx && c->grid_col_per > 0.0f) + col_pers[col_idx] = c->grid_col_per; + if (c->grid_row_idx == row_idx && c->grid_row_per > 0.0f) + row_pers[row_idx] = c->grid_row_per; + } + for (i = 0; i < n; i++) { + c = arr[i]; + int32_t col_idx = + (i < first_group_count) + ? (i / base_rows) + : (first_group_cols + (i - first_group_count) / max_rows); + int32_t row_idx = (i < first_group_count) + ? (i % base_rows) + : ((i - first_group_count) % max_rows); + + if (col_pers[col_idx] == 0.0f && c->grid_col_per > 0.0f) + col_pers[col_idx] = c->grid_col_per; + if (row_pers[row_idx] == 0.0f && c->grid_row_per > 0.0f) + row_pers[row_idx] = c->grid_row_per; } + // 兜底策略与总权重计算 float sum_col = 0.0f; - for (i = 0; i < cols; i++) + for (i = 0; i < cols; i++) { + if (col_pers[i] == 0.0f) + col_pers[i] = 1.0f; sum_col += col_pers[i]; + } + for (i = 0; i < max_rows; i++) { + if (row_pers[i] == 0.0f) + row_pers[i] = 1.0f; + } + + // 预计算所有列的 X 坐标和宽度 + float col_x[cols], col_w[cols]; float avail_w = m->w.width - 2 * cur_gappoh - (cols - 1) * cur_gappih; + float next_x = m->w.x + cur_gappoh; + for (i = 0; i < cols; i++) { + col_x[i] = next_x; + col_w[i] = (i == cols - 1) ? (m->w.x + m->w.width - cur_gappoh - next_x) + : (avail_w * (col_pers[i] / sum_col)); + next_x += col_w[i] + cur_gappih; + } - i = 0; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || !ISTILED(c)) - continue; + // 预计算两组不同的行几何参数(解决不同列行数不一致的问题) + float row_y_base[base_rows], row_h_base[base_rows]; + float sum_row_base = 0.0f; + for (i = 0; i < base_rows; i++) + sum_row_base += row_pers[i]; + float avail_h_base = + m->w.height - 2 * cur_gappov - (base_rows - 1) * cur_gappiv; + float next_y = m->w.y + cur_gappov; + for (i = 0; i < base_rows; i++) { + row_y_base[i] = next_y; + row_h_base[i] = (i == base_rows - 1) + ? (m->w.y + m->w.height - cur_gappov - next_y) + : (avail_h_base * (row_pers[i] / sum_row_base)); + next_y += row_h_base[i] + cur_gappiv; + } + + float row_y_max[max_rows], row_h_max[max_rows]; + if (remainder > 0) { + float sum_row_max = 0.0f; + for (i = 0; i < max_rows; i++) + sum_row_max += row_pers[i]; + float avail_h_max = + m->w.height - 2 * cur_gappov - (max_rows - 1) * cur_gappiv; + next_y = m->w.y + cur_gappov; + for (i = 0; i < max_rows; i++) { + row_y_max[i] = next_y; + row_h_max[i] = (i == max_rows - 1) + ? (m->w.y + m->w.height - cur_gappov - next_y) + : (avail_h_max * (row_pers[i] / sum_row_max)); + next_y += row_h_max[i] + cur_gappiv; + } + } + + // 最终渲染布局 + for (i = 0; i < n; i++) { + c = arr[i]; + int32_t col_idx, row_idx; + float fl_cx, fl_cy, fl_cw, fl_ch; - int32_t col_idx, row_idx, rows_in_this_col; if (i < first_group_count) { col_idx = i / base_rows; row_idx = i % base_rows; - rows_in_this_col = base_rows; + fl_cy = row_y_base[row_idx]; + fl_ch = row_h_base[row_idx]; } else { int32_t offset = i - first_group_count; - col_idx = first_group_cols + (offset / (base_rows + 1)); - row_idx = offset % (base_rows + 1); - rows_in_this_col = base_rows + 1; + col_idx = first_group_cols + (offset / max_rows); + row_idx = offset % max_rows; + fl_cy = row_y_max[row_idx]; + fl_ch = row_h_max[row_idx]; } c->grid_col_per = col_pers[col_idx]; @@ -953,25 +1028,8 @@ void fair(Monitor *m) { c->grid_col_idx = col_idx; c->grid_row_idx = row_idx; - float fl_cx = m->w.x + cur_gappoh; - for (int j = 0; j < col_idx; j++) - fl_cx += avail_w * (col_pers[j] / sum_col) + cur_gappih; - float fl_cw = (col_idx == cols - 1) - ? (m->w.x + m->w.width - cur_gappoh - fl_cx) - : avail_w * (col_pers[col_idx] / sum_col); - - float sum_row_this_col = 0.0f; - for (int j = 0; j < rows_in_this_col; j++) - sum_row_this_col += row_pers[j]; - - float avail_h = - m->w.height - 2 * cur_gappov - (rows_in_this_col - 1) * cur_gappiv; - float fl_cy = m->w.y + cur_gappov; - for (int j = 0; j < row_idx; j++) - fl_cy += avail_h * (row_pers[j] / sum_row_this_col) + cur_gappiv; - float fl_ch = (row_idx == rows_in_this_col - 1) - ? (m->w.y + m->w.height - cur_gappov - fl_cy) - : avail_h * (row_pers[row_idx] / sum_row_this_col); + fl_cx = col_x[col_idx]; + fl_cw = col_w[col_idx]; resize(c, (struct wlr_box){.x = (int32_t)fl_cx, @@ -979,6 +1037,5 @@ void fair(Monitor *m) { .width = (int32_t)fl_cw, .height = (int32_t)fl_ch}, 0); - i++; } -} +} \ No newline at end of file diff --git a/src/layout/vertical.h b/src/layout/vertical.h index f9c19690..733ee364 100644 --- a/src/layout/vertical.h +++ b/src/layout/vertical.h @@ -367,10 +367,9 @@ void vertical_fair(Monitor *m) { 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; + if (config.smartgaps && n == 1) { + cur_gappiv = cur_gappih = cur_gappov = cur_gappoh = 0; + } int32_t rows; for (rows = 0; rows <= n; rows++) { @@ -384,56 +383,124 @@ void vertical_fair(Monitor *m) { int32_t first_group_count = first_group_rows * base_cols; int32_t max_cols = base_cols + (remainder > 0 ? 1 : 0); + Client *arr[n]; + int32_t arr_idx = 0; + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && ISTILED(c)) { + arr[arr_idx++] = c; + if (arr_idx >= n) + break; + } + } + float row_pers[rows]; float col_pers[max_cols]; for (i = 0; i < rows; i++) - row_pers[i] = 1.0f; + row_pers[i] = 0.0f; for (i = 0; i < max_cols; i++) - col_pers[i] = 1.0f; + col_pers[i] = 0.0f; - i = 0; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || !ISTILED(c)) - continue; - int32_t row_idx, col_idx; - if (i < first_group_count) { - row_idx = i / base_cols; - col_idx = i % base_cols; - } else { - int32_t offset = i - first_group_count; - row_idx = first_group_rows + (offset / (base_cols + 1)); - col_idx = offset % (base_cols + 1); - } + for (i = 0; i < n; i++) { + c = arr[i]; + int32_t row_idx = + (i < first_group_count) + ? (i / base_cols) + : (first_group_rows + (i - first_group_count) / max_cols); + int32_t col_idx = (i < first_group_count) + ? (i % base_cols) + : ((i - first_group_count) % max_cols); - if (col_idx == 0) - row_pers[row_idx] = - (c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f; - if (row_idx == 0) - col_pers[col_idx] = - (c->grid_col_per > 0.0f) ? c->grid_col_per : 1.0f; - i++; + if (c->grid_row_idx == row_idx && c->grid_row_per > 0.0f) + row_pers[row_idx] = c->grid_row_per; + if (c->grid_col_idx == col_idx && c->grid_col_per > 0.0f) + col_pers[col_idx] = c->grid_col_per; + } + for (i = 0; i < n; i++) { + c = arr[i]; + int32_t row_idx = + (i < first_group_count) + ? (i / base_cols) + : (first_group_rows + (i - first_group_count) / max_cols); + int32_t col_idx = (i < first_group_count) + ? (i % base_cols) + : ((i - first_group_count) % max_cols); + + if (row_pers[row_idx] == 0.0f && c->grid_row_per > 0.0f) + row_pers[row_idx] = c->grid_row_per; + if (col_pers[col_idx] == 0.0f && c->grid_col_per > 0.0f) + col_pers[col_idx] = c->grid_col_per; } float sum_row = 0.0f; - for (i = 0; i < rows; i++) + for (i = 0; i < rows; i++) { + if (row_pers[i] == 0.0f) + row_pers[i] = 1.0f; sum_row += row_pers[i]; + } + for (i = 0; i < max_cols; i++) { + if (col_pers[i] == 0.0f) + col_pers[i] = 1.0f; + } + + float row_y[rows], row_h[rows]; float avail_h = m->w.height - 2 * cur_gappov - (rows - 1) * cur_gappiv; + float next_y = m->w.y + cur_gappov; + for (i = 0; i < rows; i++) { + row_y[i] = next_y; + row_h[i] = (i == rows - 1) + ? (m->w.y + m->w.height - cur_gappov - next_y) + : (avail_h * (row_pers[i] / sum_row)); + next_y += row_h[i] + cur_gappiv; + } - i = 0; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || !ISTILED(c)) - continue; + float col_x_base[base_cols], col_w_base[base_cols]; + float sum_col_base = 0.0f; + for (i = 0; i < base_cols; i++) + sum_col_base += col_pers[i]; + float avail_w_base = + m->w.width - 2 * cur_gappoh - (base_cols - 1) * cur_gappih; + float next_x = m->w.x + cur_gappoh; + for (i = 0; i < base_cols; i++) { + col_x_base[i] = next_x; + col_w_base[i] = (i == base_cols - 1) + ? (m->w.x + m->w.width - cur_gappoh - next_x) + : (avail_w_base * (col_pers[i] / sum_col_base)); + next_x += col_w_base[i] + cur_gappih; + } + + float col_x_max[max_cols], col_w_max[max_cols]; + if (remainder > 0) { + float sum_col_max = 0.0f; + for (i = 0; i < max_cols; i++) + sum_col_max += col_pers[i]; + float avail_w_max = + m->w.width - 2 * cur_gappoh - (max_cols - 1) * cur_gappih; + next_x = m->w.x + cur_gappoh; + for (i = 0; i < max_cols; i++) { + col_x_max[i] = next_x; + col_w_max[i] = (i == max_cols - 1) + ? (m->w.x + m->w.width - cur_gappoh - next_x) + : (avail_w_max * (col_pers[i] / sum_col_max)); + next_x += col_w_max[i] + cur_gappih; + } + } + + for (i = 0; i < n; i++) { + c = arr[i]; + int32_t row_idx, col_idx; + float fl_cx, fl_cy, fl_cw, fl_ch; - int32_t row_idx, col_idx, cols_in_this_row; if (i < first_group_count) { row_idx = i / base_cols; col_idx = i % base_cols; - cols_in_this_row = base_cols; + fl_cx = col_x_base[col_idx]; + fl_cw = col_w_base[col_idx]; } else { int32_t offset = i - first_group_count; - row_idx = first_group_rows + (offset / (base_cols + 1)); - col_idx = offset % (base_cols + 1); - cols_in_this_row = base_cols + 1; + row_idx = first_group_rows + (offset / max_cols); + col_idx = offset % max_cols; + fl_cx = col_x_max[col_idx]; + fl_cw = col_w_max[col_idx]; } c->grid_row_per = row_pers[row_idx]; @@ -441,25 +508,8 @@ void vertical_fair(Monitor *m) { c->grid_row_idx = row_idx; c->grid_col_idx = col_idx; - float fl_cy = m->w.y + cur_gappov; - for (int j = 0; j < row_idx; j++) - fl_cy += avail_h * (row_pers[j] / sum_row) + cur_gappiv; - float fl_ch = (row_idx == rows - 1) - ? (m->w.y + m->w.height - cur_gappov - fl_cy) - : avail_h * (row_pers[row_idx] / sum_row); - - float sum_col_this_row = 0.0f; - for (int j = 0; j < cols_in_this_row; j++) - sum_col_this_row += col_pers[j]; - - float avail_w = - m->w.width - 2 * cur_gappoh - (cols_in_this_row - 1) * cur_gappih; - float fl_cx = m->w.x + cur_gappoh; - for (int j = 0; j < col_idx; j++) - fl_cx += avail_w * (col_pers[j] / sum_col_this_row) + cur_gappih; - float fl_cw = (col_idx == cols_in_this_row - 1) - ? (m->w.x + m->w.width - cur_gappoh - fl_cx) - : avail_w * (col_pers[col_idx] / sum_col_this_row); + fl_cy = row_y[row_idx]; + fl_ch = row_h[row_idx]; resize(c, (struct wlr_box){.x = (int32_t)fl_cx, @@ -467,6 +517,5 @@ void vertical_fair(Monitor *m) { .width = (int32_t)fl_cw, .height = (int32_t)fl_ch}, 0); - i++; } } \ No newline at end of file