opt: optimzie fair layout caculate

This commit is contained in:
DreamMaoMao 2026-05-18 11:41:30 +08:00
parent d7ee60e79a
commit d9b40795ac
2 changed files with 219 additions and 113 deletions

View file

@ -874,16 +874,17 @@ void fair(Monitor *m) {
if (n == 0) if (n == 0)
return; return;
// 获取间距配置
int32_t cur_gappiv = enablegaps ? m->gappiv : 0; int32_t cur_gappiv = enablegaps ? m->gappiv : 0;
int32_t cur_gappih = enablegaps ? m->gappih : 0; int32_t cur_gappih = enablegaps ? m->gappih : 0;
int32_t cur_gappov = enablegaps ? m->gappov : 0; int32_t cur_gappov = enablegaps ? m->gappov : 0;
int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
cur_gappiv = config.smartgaps && n == 1 ? 0 : cur_gappiv; if (config.smartgaps && n == 1) {
cur_gappih = config.smartgaps && n == 1 ? 0 : cur_gappih; cur_gappiv = cur_gappih = cur_gappov = cur_gappoh = 0;
cur_gappov = config.smartgaps && n == 1 ? 0 : cur_gappov; }
cur_gappoh = config.smartgaps && n == 1 ? 0 : cur_gappoh;
// 计算网格行列数
int32_t cols; int32_t cols;
for (cols = 0; cols <= n; cols++) { for (cols = 0; cols <= n; cols++) {
if (cols * cols >= n) if (cols * cols >= n)
@ -896,56 +897,130 @@ void fair(Monitor *m) {
int32_t first_group_count = first_group_cols * base_rows; int32_t first_group_count = first_group_cols * base_rows;
int32_t max_rows = base_rows + (remainder > 0 ? 1 : 0); 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 col_pers[cols];
float row_pers[max_rows]; float row_pers[max_rows];
for (i = 0; i < cols; i++) for (i = 0; i < cols; i++)
col_pers[i] = 1.0f; col_pers[i] = 0.0f;
for (i = 0; i < max_rows; i++) 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) { for (i = 0; i < n; i++) {
if (!VISIBLEON(c, m) || !ISTILED(c)) c = arr[i];
continue; int32_t col_idx =
int32_t col_idx, row_idx; (i < first_group_count)
if (i < first_group_count) { ? (i / base_rows)
col_idx = i / base_rows; : (first_group_cols + (i - first_group_count) / max_rows);
row_idx = i % base_rows; int32_t row_idx = (i < first_group_count)
} else { ? (i % base_rows)
int32_t offset = i - first_group_count; : ((i - first_group_count) % max_rows);
col_idx = first_group_cols + (offset / (base_rows + 1));
row_idx = offset % (base_rows + 1);
}
if (row_idx == 0) if (c->grid_col_idx == col_idx && c->grid_col_per > 0.0f)
col_pers[col_idx] = col_pers[col_idx] = c->grid_col_per;
(c->grid_col_per > 0.0f) ? c->grid_col_per : 1.0f; if (c->grid_row_idx == row_idx && c->grid_row_per > 0.0f)
if (col_idx == 0) row_pers[row_idx] = c->grid_row_per;
row_pers[row_idx] = }
(c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f; for (i = 0; i < n; i++) {
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; 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]; 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 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) { float row_y_base[base_rows], row_h_base[base_rows];
if (!VISIBLEON(c, m) || !ISTILED(c)) float sum_row_base = 0.0f;
continue; 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) { if (i < first_group_count) {
col_idx = i / base_rows; col_idx = i / base_rows;
row_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 { } else {
int32_t offset = i - first_group_count; int32_t offset = i - first_group_count;
col_idx = first_group_cols + (offset / (base_rows + 1)); col_idx = first_group_cols + (offset / max_rows);
row_idx = offset % (base_rows + 1); row_idx = offset % max_rows;
rows_in_this_col = base_rows + 1; fl_cy = row_y_max[row_idx];
fl_ch = row_h_max[row_idx];
} }
c->grid_col_per = col_pers[col_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_col_idx = col_idx;
c->grid_row_idx = row_idx; c->grid_row_idx = row_idx;
float fl_cx = m->w.x + cur_gappoh; fl_cx = col_x[col_idx];
for (int j = 0; j < col_idx; j++) fl_cw = col_w[col_idx];
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);
resize(c, resize(c,
(struct wlr_box){.x = (int32_t)fl_cx, (struct wlr_box){.x = (int32_t)fl_cx,
@ -979,6 +1037,5 @@ void fair(Monitor *m) {
.width = (int32_t)fl_cw, .width = (int32_t)fl_cw,
.height = (int32_t)fl_ch}, .height = (int32_t)fl_ch},
0); 0);
i++;
} }
} }

View file

@ -367,10 +367,9 @@ void vertical_fair(Monitor *m) {
int32_t cur_gappov = enablegaps ? m->gappov : 0; int32_t cur_gappov = enablegaps ? m->gappov : 0;
int32_t cur_gappoh = enablegaps ? m->gappoh : 0; int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
cur_gappiv = config.smartgaps && n == 1 ? 0 : cur_gappiv; if (config.smartgaps && n == 1) {
cur_gappih = config.smartgaps && n == 1 ? 0 : cur_gappih; cur_gappiv = cur_gappih = cur_gappov = cur_gappoh = 0;
cur_gappov = config.smartgaps && n == 1 ? 0 : cur_gappov; }
cur_gappoh = config.smartgaps && n == 1 ? 0 : cur_gappoh;
int32_t rows; int32_t rows;
for (rows = 0; rows <= n; 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 first_group_count = first_group_rows * base_cols;
int32_t max_cols = base_cols + (remainder > 0 ? 1 : 0); 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 row_pers[rows];
float col_pers[max_cols]; float col_pers[max_cols];
for (i = 0; i < rows; i++) for (i = 0; i < rows; i++)
row_pers[i] = 1.0f; row_pers[i] = 0.0f;
for (i = 0; i < max_cols; i++) for (i = 0; i < max_cols; i++)
col_pers[i] = 1.0f; col_pers[i] = 0.0f;
i = 0; for (i = 0; i < n; i++) {
wl_list_for_each(c, &clients, link) { c = arr[i];
if (!VISIBLEON(c, m) || !ISTILED(c)) int32_t row_idx =
continue; (i < first_group_count)
int32_t row_idx, col_idx; ? (i / base_cols)
if (i < first_group_count) { : (first_group_rows + (i - first_group_count) / max_cols);
row_idx = i / base_cols; int32_t col_idx = (i < first_group_count)
col_idx = i % base_cols; ? (i % base_cols)
} else { : ((i - first_group_count) % max_cols);
int32_t offset = i - first_group_count;
row_idx = first_group_rows + (offset / (base_cols + 1));
col_idx = offset % (base_cols + 1);
}
if (col_idx == 0) if (c->grid_row_idx == row_idx && c->grid_row_per > 0.0f)
row_pers[row_idx] = row_pers[row_idx] = c->grid_row_per;
(c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f; if (c->grid_col_idx == col_idx && c->grid_col_per > 0.0f)
if (row_idx == 0) col_pers[col_idx] = c->grid_col_per;
col_pers[col_idx] = }
(c->grid_col_per > 0.0f) ? c->grid_col_per : 1.0f; for (i = 0; i < n; i++) {
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; 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]; 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 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; float col_x_base[base_cols], col_w_base[base_cols];
wl_list_for_each(c, &clients, link) { float sum_col_base = 0.0f;
if (!VISIBLEON(c, m) || !ISTILED(c)) for (i = 0; i < base_cols; i++)
continue; 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) { if (i < first_group_count) {
row_idx = i / base_cols; row_idx = i / base_cols;
col_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 { } else {
int32_t offset = i - first_group_count; int32_t offset = i - first_group_count;
row_idx = first_group_rows + (offset / (base_cols + 1)); row_idx = first_group_rows + (offset / max_cols);
col_idx = offset % (base_cols + 1); col_idx = offset % max_cols;
cols_in_this_row = base_cols + 1; fl_cx = col_x_max[col_idx];
fl_cw = col_w_max[col_idx];
} }
c->grid_row_per = row_pers[row_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_row_idx = row_idx;
c->grid_col_idx = col_idx; c->grid_col_idx = col_idx;
float fl_cy = m->w.y + cur_gappov; fl_cy = row_y[row_idx];
for (int j = 0; j < row_idx; j++) fl_ch = row_h[row_idx];
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);
resize(c, resize(c,
(struct wlr_box){.x = (int32_t)fl_cx, (struct wlr_box){.x = (int32_t)fl_cx,
@ -467,6 +517,5 @@ void vertical_fair(Monitor *m) {
.width = (int32_t)fl_cw, .width = (int32_t)fl_cw,
.height = (int32_t)fl_ch}, .height = (int32_t)fl_ch},
0); 0);
i++;
} }
} }