2025-06-28 12:35:58 +08:00
|
|
|
|
void deck(Monitor *m) {
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t mw, my;
|
2026-01-03 09:37:34 +08:00
|
|
|
|
int32_t i, n = 0;
|
2025-10-06 14:11:36 +08:00
|
|
|
|
Client *c = NULL;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
Client *fc = NULL;
|
|
|
|
|
|
float mfact;
|
2026-01-27 14:45:28 +08:00
|
|
|
|
uint32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
2025-10-09 13:09:40 +08:00
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t cur_gappih = enablegaps ? m->gappih : 0;
|
|
|
|
|
|
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
|
|
|
|
|
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
|
2026-03-12 06:49:58 -07:00
|
|
|
|
cur_gappih =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
|
|
|
|
|
cur_gappoh =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
|
|
|
|
|
cur_gappov =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
|
2025-09-09 16:32:15 +08:00
|
|
|
|
n = m->visible_tiling_clients;
|
|
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
if (n == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2025-10-09 13:09:40 +08:00
|
|
|
|
wl_list_for_each(fc, &clients, link) {
|
|
|
|
|
|
|
|
|
|
|
|
if (VISIBLEON(fc, m) && ISTILED(fc))
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
// Calculate master width using mfact from pertag
|
2025-10-09 13:09:40 +08:00
|
|
|
|
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
|
|
|
|
|
|
: m->pertag->mfacts[m->pertag->curtag];
|
2025-06-28 12:35:58 +08:00
|
|
|
|
|
|
|
|
|
|
// Calculate master width including outer gaps
|
2026-01-27 14:45:28 +08:00
|
|
|
|
if (n > nmasters)
|
|
|
|
|
|
mw = nmasters ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
else
|
|
|
|
|
|
mw = m->w.width - 2 * cur_gappoh;
|
|
|
|
|
|
|
|
|
|
|
|
i = my = 0;
|
|
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (!VISIBLEON(c, m) || !ISTILED(c))
|
|
|
|
|
|
continue;
|
2026-01-27 14:45:28 +08:00
|
|
|
|
if (i < nmasters) {
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
// Master area clients
|
2025-07-09 23:31:16 +08:00
|
|
|
|
resize(
|
|
|
|
|
|
c,
|
|
|
|
|
|
(struct wlr_box){.x = m->w.x + cur_gappoh,
|
|
|
|
|
|
.y = m->w.y + cur_gappov + my,
|
|
|
|
|
|
.width = mw,
|
|
|
|
|
|
.height = (m->w.height - 2 * cur_gappov - my) /
|
2026-01-27 14:45:28 +08:00
|
|
|
|
(MIN(n, nmasters) - i)},
|
2025-07-09 23:31:16 +08:00
|
|
|
|
0);
|
|
|
|
|
|
my += c->geom.height;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// Stack area clients
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = m->w.x + mw + cur_gappoh + cur_gappih,
|
|
|
|
|
|
.y = m->w.y + cur_gappov,
|
|
|
|
|
|
.width = m->w.width - mw - 2 * cur_gappoh -
|
|
|
|
|
|
cur_gappih,
|
|
|
|
|
|
.height = m->w.height - 2 * cur_gappov},
|
|
|
|
|
|
0);
|
|
|
|
|
|
if (c == focustop(m))
|
|
|
|
|
|
wlr_scene_node_raise_to_top(&c->scene->node);
|
|
|
|
|
|
}
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 21:30:45 +08:00
|
|
|
|
void center_tile(Monitor *m) {
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t i, n = 0, h, r, ie = enablegaps, mw, mx, my, oty, ety, tw;
|
2025-10-06 14:11:36 +08:00
|
|
|
|
Client *c = NULL;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
Client *fc = NULL;
|
|
|
|
|
|
double mfact = 0;
|
2026-01-03 09:37:34 +08:00
|
|
|
|
int32_t master_num = 0;
|
|
|
|
|
|
int32_t stack_num = 0;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
|
|
|
|
|
n = m->visible_tiling_clients;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
master_num = m->pertag->nmasters[m->pertag->curtag];
|
2025-12-07 21:12:45 +08:00
|
|
|
|
master_num = n > master_num ? master_num : n;
|
|
|
|
|
|
|
2025-10-09 13:09:40 +08:00
|
|
|
|
stack_num = n - master_num;
|
|
|
|
|
|
|
2025-09-26 21:30:45 +08:00
|
|
|
|
if (n == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2025-10-09 13:09:40 +08:00
|
|
|
|
// 获取第一个可见的平铺客户端用于主区域宽度百分比
|
|
|
|
|
|
wl_list_for_each(fc, &clients, link) {
|
|
|
|
|
|
if (VISIBLEON(fc, m) && ISTILED(fc))
|
|
|
|
|
|
break;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-09 13:09:40 +08:00
|
|
|
|
// 间隙参数处理
|
2026-01-03 10:38:42 +08:00
|
|
|
|
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; // 外部水平间隙
|
2025-10-09 13:09:40 +08:00
|
|
|
|
|
|
|
|
|
|
// 智能间隙处理
|
2026-03-12 06:49:58 -07:00
|
|
|
|
cur_gappiv =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
|
|
|
|
|
cur_gappih =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
|
|
|
|
|
cur_gappov =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
|
|
|
|
cur_gappoh =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t nmasters = m->pertag->nmasters[m->pertag->curtag];
|
2025-10-09 13:09:40 +08:00
|
|
|
|
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
|
|
|
|
|
|
: m->pertag->mfacts[m->pertag->curtag];
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
|
|
|
|
|
// 初始化区域
|
|
|
|
|
|
mw = m->w.width;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
mx = cur_gappoh;
|
|
|
|
|
|
my = cur_gappov;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
tw = mw;
|
|
|
|
|
|
|
2025-09-27 09:17:13 +08:00
|
|
|
|
// 判断是否需要主区域铺满
|
2026-03-12 06:49:58 -07:00
|
|
|
|
int32_t should_overspread =
|
|
|
|
|
|
config.center_master_overspread && (n <= nmasters);
|
2025-09-27 09:17:13 +08:00
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t master_surplus_height =
|
2025-12-10 18:32:06 +08:00
|
|
|
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
2025-12-09 20:35:21 +08:00
|
|
|
|
float master_surplus_ratio = 1.0;
|
|
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t slave_left_surplus_height =
|
2025-12-10 18:32:06 +08:00
|
|
|
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num / 2 - 1));
|
2025-12-09 20:35:21 +08:00
|
|
|
|
float slave_left_surplus_ratio = 1.0;
|
|
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t slave_right_surplus_height =
|
2025-12-10 18:32:06 +08:00
|
|
|
|
(m->w.height - 2 * cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * ((stack_num + 1) / 2 - 1));
|
2025-12-09 20:35:21 +08:00
|
|
|
|
float slave_right_surplus_ratio = 1.0;
|
|
|
|
|
|
|
2025-09-27 09:17:13 +08:00
|
|
|
|
if (n > nmasters || !should_overspread) {
|
|
|
|
|
|
// 计算主区域宽度(居中模式)
|
2025-10-09 13:09:40 +08:00
|
|
|
|
mw = nmasters ? (m->w.width - 2 * cur_gappoh - cur_gappih * ie) * mfact
|
|
|
|
|
|
: 0;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
|
|
|
|
|
if (n - nmasters > 1) {
|
|
|
|
|
|
// 多个堆叠窗口:主区域居中,左右两侧各有一个堆叠区域
|
2025-10-09 13:09:40 +08:00
|
|
|
|
tw = (m->w.width - mw) / 2 - cur_gappoh - cur_gappih * ie;
|
|
|
|
|
|
mx = cur_gappoh + tw + cur_gappih * ie;
|
2025-09-27 09:17:13 +08:00
|
|
|
|
} else if (n - nmasters == 1) {
|
2025-09-27 16:18:01 +08:00
|
|
|
|
// 单个堆叠窗口的处理
|
2026-03-12 06:49:58 -07:00
|
|
|
|
if (config.center_when_single_stack) {
|
2025-10-09 13:09:40 +08:00
|
|
|
|
// stack在右边,master居中,左边空着
|
|
|
|
|
|
tw = (m->w.width - mw) / 2 - cur_gappoh - cur_gappih * ie;
|
|
|
|
|
|
mx = cur_gappoh + tw + cur_gappih * ie; // master居中
|
2025-09-27 16:18:01 +08:00
|
|
|
|
} else {
|
2025-10-09 13:09:40 +08:00
|
|
|
|
// stack在右边,master在左边
|
|
|
|
|
|
tw = m->w.width - mw - 2 * cur_gappoh - cur_gappih * ie;
|
|
|
|
|
|
mx = cur_gappoh; // master在左边
|
2025-09-27 16:18:01 +08:00
|
|
|
|
}
|
2025-09-27 09:17:13 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 只有主区域窗口:居中显示
|
2025-10-09 13:09:40 +08:00
|
|
|
|
tw = (m->w.width - mw) / 2 - cur_gappoh - cur_gappih * ie;
|
|
|
|
|
|
mx = cur_gappoh + tw + cur_gappih * ie;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-09-27 09:17:13 +08:00
|
|
|
|
// 主区域铺满模式(只有主区域窗口时)
|
2025-10-09 13:09:40 +08:00
|
|
|
|
mw = m->w.width - 2 * cur_gappoh;
|
|
|
|
|
|
mx = cur_gappoh;
|
2025-09-27 09:17:13 +08:00
|
|
|
|
tw = 0; // 堆叠区域宽度为0
|
2025-09-26 21:30:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-09 13:09:40 +08:00
|
|
|
|
oty = cur_gappov;
|
|
|
|
|
|
ety = cur_gappov;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (!VISIBLEON(c, m) || !ISTILED(c))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
if (i < nmasters) {
|
|
|
|
|
|
// 主区域窗口
|
2025-10-09 13:09:40 +08:00
|
|
|
|
r = MIN(n, nmasters) - i;
|
|
|
|
|
|
if (c->master_inner_per > 0.0f) {
|
2025-12-10 18:32:06 +08:00
|
|
|
|
h = master_surplus_height * c->master_inner_per /
|
|
|
|
|
|
master_surplus_ratio;
|
2025-12-09 20:35:21 +08:00
|
|
|
|
master_surplus_height = master_surplus_height - h;
|
2025-12-10 18:32:06 +08:00
|
|
|
|
master_surplus_ratio =
|
|
|
|
|
|
master_surplus_ratio - c->master_inner_per;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - my - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
|
|
|
|
|
c->master_inner_per = h / (m->w.height - my - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
|
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
|
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = m->w.x + mx,
|
|
|
|
|
|
.y = m->w.y + my,
|
2025-10-15 15:45:04 +08:00
|
|
|
|
.width = mw,
|
2025-09-26 21:30:45 +08:00
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
2025-10-09 13:09:40 +08:00
|
|
|
|
my += c->geom.height + cur_gappiv * ie;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 堆叠区域窗口
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t stack_index = i - nmasters;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
|
|
|
|
|
if (n - nmasters == 1) {
|
2025-09-27 16:18:01 +08:00
|
|
|
|
// 单个堆叠窗口
|
2025-10-09 13:09:40 +08:00
|
|
|
|
r = n - i;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
if (c->stack_inner_per > 0.0f) {
|
2025-10-09 13:09:40 +08:00
|
|
|
|
h = (m->w.height - 2 * cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (stack_num - 1)) *
|
2025-12-11 15:44:08 +08:00
|
|
|
|
c->stack_inner_per;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - ety - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
c->stack_inner_per = h / (m->w.height - ety - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
2026-01-03 09:37:34 +08:00
|
|
|
|
int32_t stack_x;
|
2026-03-12 06:49:58 -07:00
|
|
|
|
if (config.center_when_single_stack) {
|
2025-10-09 13:09:40 +08:00
|
|
|
|
// 放在右侧(master居中时,stack在右边)
|
|
|
|
|
|
stack_x = m->w.x + mx + mw + cur_gappih * ie;
|
2025-09-27 18:03:19 +08:00
|
|
|
|
} else {
|
2025-10-09 13:09:40 +08:00
|
|
|
|
// 放在右侧(master在左边时,stack在右边)
|
|
|
|
|
|
stack_x = m->w.x + mx + mw + cur_gappih * ie;
|
2025-09-27 16:18:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-26 21:30:45 +08:00
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = stack_x,
|
|
|
|
|
|
.y = m->w.y + ety,
|
2025-10-15 15:45:04 +08:00
|
|
|
|
.width = tw,
|
2025-09-26 21:30:45 +08:00
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
2025-10-09 13:09:40 +08:00
|
|
|
|
ety += c->geom.height + cur_gappiv * ie;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 多个堆叠窗口:交替放在左右两侧
|
2025-10-09 13:09:40 +08:00
|
|
|
|
r = (n - i + 1) / 2;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
|
2025-09-27 16:18:01 +08:00
|
|
|
|
if ((stack_index % 2) ^ (n % 2 == 0)) {
|
2025-09-26 21:30:45 +08:00
|
|
|
|
// 右侧堆叠窗口
|
2025-12-11 15:44:08 +08:00
|
|
|
|
if (c->stack_inner_per > 0.0f) {
|
|
|
|
|
|
h = slave_right_surplus_height * c->stack_inner_per /
|
2025-12-10 18:32:06 +08:00
|
|
|
|
slave_right_surplus_ratio;
|
|
|
|
|
|
slave_right_surplus_height =
|
|
|
|
|
|
slave_right_surplus_height - h;
|
|
|
|
|
|
slave_right_surplus_ratio =
|
2025-12-11 15:44:08 +08:00
|
|
|
|
slave_right_surplus_ratio - c->stack_inner_per;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - ety - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
c->stack_inner_per =
|
2025-10-09 13:09:40 +08:00
|
|
|
|
h / (m->w.height - ety - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
|
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-03 09:37:34 +08:00
|
|
|
|
int32_t stack_x = m->w.x + mx + mw + cur_gappih * ie;
|
2025-10-15 15:45:04 +08:00
|
|
|
|
|
2025-09-26 21:30:45 +08:00
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = stack_x,
|
|
|
|
|
|
.y = m->w.y + ety,
|
2025-10-15 15:45:04 +08:00
|
|
|
|
.width = tw,
|
2025-09-26 21:30:45 +08:00
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
2025-10-09 13:09:40 +08:00
|
|
|
|
ety += c->geom.height + cur_gappiv * ie;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
// 左侧堆叠窗口
|
2025-12-11 15:44:08 +08:00
|
|
|
|
if (c->stack_inner_per > 0.0f) {
|
|
|
|
|
|
h = slave_left_surplus_height * c->stack_inner_per /
|
2025-12-10 18:32:06 +08:00
|
|
|
|
slave_left_surplus_ratio;
|
|
|
|
|
|
slave_left_surplus_height =
|
|
|
|
|
|
slave_left_surplus_height - h;
|
|
|
|
|
|
slave_left_surplus_ratio =
|
2025-12-11 15:44:08 +08:00
|
|
|
|
slave_left_surplus_ratio - c->stack_inner_per;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - oty - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
c->stack_inner_per =
|
2025-10-09 13:09:40 +08:00
|
|
|
|
h / (m->w.height - oty - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
|
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-03 09:37:34 +08:00
|
|
|
|
int32_t stack_x = m->w.x + cur_gappoh;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = stack_x,
|
|
|
|
|
|
.y = m->w.y + oty,
|
2025-10-15 15:45:04 +08:00
|
|
|
|
.width = tw,
|
2025-09-26 21:30:45 +08:00
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
2025-10-09 13:09:40 +08:00
|
|
|
|
oty += c->geom.height + cur_gappiv * ie;
|
2025-09-26 21:30:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
void tile(Monitor *m) {
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty;
|
2025-10-06 14:11:36 +08:00
|
|
|
|
Client *c = NULL;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
Client *fc = NULL;
|
|
|
|
|
|
double mfact = 0;
|
2026-01-03 09:37:34 +08:00
|
|
|
|
int32_t master_num = 0;
|
|
|
|
|
|
int32_t stack_num = 0;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
|
2025-09-09 16:32:15 +08:00
|
|
|
|
n = m->visible_tiling_clients;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
master_num = m->pertag->nmasters[m->pertag->curtag];
|
2025-12-07 21:12:45 +08:00
|
|
|
|
master_num = n > master_num ? master_num : n;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
stack_num = n - master_num;
|
2025-09-09 16:32:15 +08:00
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
if (n == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
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;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
|
2026-03-12 06:49:58 -07:00
|
|
|
|
cur_gappiv =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
|
|
|
|
|
cur_gappih =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
|
|
|
|
|
cur_gappov =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
|
|
|
|
cur_gappoh =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
|
2025-10-09 13:09:40 +08:00
|
|
|
|
wl_list_for_each(fc, &clients, link) {
|
|
|
|
|
|
|
|
|
|
|
|
if (VISIBLEON(fc, m) && ISTILED(fc))
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
|
|
|
|
|
|
: m->pertag->mfacts[m->pertag->curtag];
|
|
|
|
|
|
|
2025-09-19 20:38:05 +08:00
|
|
|
|
if (n > m->pertag->nmasters[m->pertag->curtag])
|
|
|
|
|
|
mw = m->pertag->nmasters[m->pertag->curtag]
|
2025-10-09 13:09:40 +08:00
|
|
|
|
? (m->w.width + cur_gappih * ie) * mfact
|
2025-06-28 12:35:58 +08:00
|
|
|
|
: 0;
|
|
|
|
|
|
else
|
2025-07-09 23:31:16 +08:00
|
|
|
|
mw = m->w.width - 2 * cur_gappoh + cur_gappih * ie;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
i = 0;
|
2025-07-09 23:31:16 +08:00
|
|
|
|
my = ty = cur_gappov;
|
2025-12-09 20:35:21 +08:00
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t master_surplus_height =
|
2025-12-09 20:35:21 +08:00
|
|
|
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
|
|
|
|
|
float master_surplus_ratio = 1.0;
|
|
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t slave_surplus_height =
|
2025-12-09 20:35:21 +08:00
|
|
|
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1));
|
|
|
|
|
|
float slave_surplus_ratio = 1.0;
|
|
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (!VISIBLEON(c, m) || !ISTILED(c))
|
|
|
|
|
|
continue;
|
2025-09-19 20:38:05 +08:00
|
|
|
|
if (i < m->pertag->nmasters[m->pertag->curtag]) {
|
|
|
|
|
|
r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
if (c->master_inner_per > 0.0f) {
|
2025-12-09 20:35:21 +08:00
|
|
|
|
h = master_surplus_height * c->master_inner_per /
|
|
|
|
|
|
master_surplus_ratio;
|
|
|
|
|
|
master_surplus_height = master_surplus_height - h;
|
|
|
|
|
|
master_surplus_ratio =
|
|
|
|
|
|
master_surplus_ratio - c->master_inner_per;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - my - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
|
|
|
|
|
c->master_inner_per = h / (m->w.height - my - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
|
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
2025-06-28 12:35:58 +08:00
|
|
|
|
resize(c,
|
2025-07-09 23:31:16 +08:00
|
|
|
|
(struct wlr_box){.x = m->w.x + cur_gappoh,
|
2025-06-28 12:35:58 +08:00
|
|
|
|
.y = m->w.y + my,
|
2025-07-09 23:31:16 +08:00
|
|
|
|
.width = mw - cur_gappih * ie,
|
2025-06-28 12:35:58 +08:00
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
2025-07-09 23:31:16 +08:00
|
|
|
|
my += c->geom.height + cur_gappiv * ie;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
r = n - i;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
if (c->stack_inner_per > 0.0f) {
|
|
|
|
|
|
h = slave_surplus_height * c->stack_inner_per /
|
2025-12-09 20:35:21 +08:00
|
|
|
|
slave_surplus_ratio;
|
|
|
|
|
|
slave_surplus_height = slave_surplus_height - h;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per;
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - ty - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
c->stack_inner_per = h / (m->w.height - ty - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
2025-10-09 13:09:40 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-11 15:44:08 +08:00
|
|
|
|
// wlr_log(WLR_ERROR, "stack_inner_per: %f", c->stack_inner_per);
|
2025-10-09 13:09:40 +08:00
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
resize(c,
|
2025-07-09 23:31:16 +08:00
|
|
|
|
(struct wlr_box){.x = m->w.x + mw + cur_gappoh,
|
2025-06-28 12:35:58 +08:00
|
|
|
|
.y = m->w.y + ty,
|
2025-07-09 23:31:16 +08:00
|
|
|
|
.width = m->w.width - mw - 2 * cur_gappoh,
|
2025-06-28 12:35:58 +08:00
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
2025-07-09 23:31:16 +08:00
|
|
|
|
ty += c->geom.height + cur_gappiv * ie;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-10-15 13:22:41 +08:00
|
|
|
|
void right_tile(Monitor *m) {
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t i, n = 0, h, r, ie = enablegaps, mw, my, ty;
|
2025-10-15 13:22:41 +08:00
|
|
|
|
Client *c = NULL;
|
|
|
|
|
|
Client *fc = NULL;
|
|
|
|
|
|
double mfact = 0;
|
2026-01-03 09:37:34 +08:00
|
|
|
|
int32_t master_num = 0;
|
|
|
|
|
|
int32_t stack_num = 0;
|
2025-10-15 13:22:41 +08:00
|
|
|
|
|
|
|
|
|
|
n = m->visible_tiling_clients;
|
|
|
|
|
|
master_num = m->pertag->nmasters[m->pertag->curtag];
|
2025-12-07 21:12:45 +08:00
|
|
|
|
master_num = n > master_num ? master_num : n;
|
2025-10-15 13:22:41 +08:00
|
|
|
|
stack_num = n - master_num;
|
|
|
|
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
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;
|
2025-10-15 13:22:41 +08:00
|
|
|
|
|
2026-03-12 06:49:58 -07:00
|
|
|
|
cur_gappiv =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappiv;
|
|
|
|
|
|
cur_gappih =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappih;
|
|
|
|
|
|
cur_gappov =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
|
|
|
|
|
cur_gappoh =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
2025-10-15 13:22:41 +08:00
|
|
|
|
|
|
|
|
|
|
wl_list_for_each(fc, &clients, link) {
|
|
|
|
|
|
|
|
|
|
|
|
if (VISIBLEON(fc, m) && ISTILED(fc))
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mfact = fc->master_mfact_per > 0.0f ? fc->master_mfact_per
|
|
|
|
|
|
: m->pertag->mfacts[m->pertag->curtag];
|
|
|
|
|
|
|
|
|
|
|
|
if (n > m->pertag->nmasters[m->pertag->curtag])
|
|
|
|
|
|
mw = m->pertag->nmasters[m->pertag->curtag]
|
|
|
|
|
|
? (m->w.width + cur_gappih * ie) * mfact
|
|
|
|
|
|
: 0;
|
|
|
|
|
|
else
|
|
|
|
|
|
mw = m->w.width - 2 * cur_gappoh + cur_gappih * ie;
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
my = ty = cur_gappov;
|
2025-12-09 20:35:21 +08:00
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t master_surplus_height =
|
2025-12-09 20:35:21 +08:00
|
|
|
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (master_num - 1));
|
|
|
|
|
|
float master_surplus_ratio = 1.0;
|
|
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t slave_surplus_height =
|
2025-12-09 20:35:21 +08:00
|
|
|
|
(m->w.height - 2 * cur_gappov - cur_gappiv * ie * (stack_num - 1));
|
|
|
|
|
|
float slave_surplus_ratio = 1.0;
|
|
|
|
|
|
|
2025-10-15 13:22:41 +08:00
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (!VISIBLEON(c, m) || !ISTILED(c))
|
|
|
|
|
|
continue;
|
|
|
|
|
|
if (i < m->pertag->nmasters[m->pertag->curtag]) {
|
|
|
|
|
|
r = MIN(n, m->pertag->nmasters[m->pertag->curtag]) - i;
|
|
|
|
|
|
if (c->master_inner_per > 0.0f) {
|
2025-12-09 20:35:21 +08:00
|
|
|
|
h = master_surplus_height * c->master_inner_per /
|
|
|
|
|
|
master_surplus_ratio;
|
|
|
|
|
|
master_surplus_height = master_surplus_height - h;
|
|
|
|
|
|
master_surplus_ratio =
|
|
|
|
|
|
master_surplus_ratio - c->master_inner_per;
|
2025-10-15 13:22:41 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - my - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
|
|
|
|
|
c->master_inner_per = h / (m->w.height - my - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
|
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
|
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = m->w.x + m->w.width - mw - cur_gappoh +
|
|
|
|
|
|
cur_gappih * ie,
|
|
|
|
|
|
.y = m->w.y + my,
|
|
|
|
|
|
.width = mw - cur_gappih * ie,
|
|
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
|
|
|
|
|
my += c->geom.height + cur_gappiv * ie;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
r = n - i;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
if (c->stack_inner_per > 0.0f) {
|
|
|
|
|
|
h = slave_surplus_height * c->stack_inner_per /
|
2025-12-09 20:35:21 +08:00
|
|
|
|
slave_surplus_ratio;
|
|
|
|
|
|
slave_surplus_height = slave_surplus_height - h;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
slave_surplus_ratio = slave_surplus_ratio - c->stack_inner_per;
|
2025-10-15 13:22:41 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
h = (m->w.height - ty - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1)) /
|
|
|
|
|
|
r;
|
2025-12-11 15:44:08 +08:00
|
|
|
|
c->stack_inner_per = h / (m->w.height - ty - cur_gappov -
|
|
|
|
|
|
cur_gappiv * ie * (r - 1));
|
2025-10-15 13:22:41 +08:00
|
|
|
|
c->master_mfact_per = mfact;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-11 15:44:08 +08:00
|
|
|
|
// wlr_log(WLR_ERROR, "stack_inner_per: %f", c->stack_inner_per);
|
2025-10-15 13:22:41 +08:00
|
|
|
|
|
|
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = m->w.x + cur_gappoh,
|
|
|
|
|
|
.y = m->w.y + ty,
|
|
|
|
|
|
.width = m->w.width - mw - 2 * cur_gappoh,
|
|
|
|
|
|
.height = h},
|
|
|
|
|
|
0);
|
|
|
|
|
|
ty += c->geom.height + cur_gappiv * ie;
|
|
|
|
|
|
}
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
void // 17
|
|
|
|
|
|
monocle(Monitor *m) {
|
2025-10-06 14:11:36 +08:00
|
|
|
|
Client *c = NULL;
|
2025-09-29 12:24:22 +08:00
|
|
|
|
struct wlr_box geom;
|
2025-06-28 12:35:58 +08:00
|
|
|
|
|
2026-01-03 10:38:42 +08:00
|
|
|
|
int32_t cur_gappov = enablegaps ? m->gappov : 0;
|
|
|
|
|
|
int32_t cur_gappoh = enablegaps ? m->gappoh : 0;
|
2025-10-15 12:53:33 +08:00
|
|
|
|
|
2026-03-12 06:49:58 -07:00
|
|
|
|
cur_gappoh =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappoh;
|
|
|
|
|
|
cur_gappov =
|
|
|
|
|
|
config.smartgaps && m->visible_tiling_clients == 1 ? 0 : cur_gappov;
|
2025-10-15 12:53:33 +08:00
|
|
|
|
|
2025-06-28 12:35:58 +08:00
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (!VISIBLEON(c, m) || !ISTILED(c))
|
|
|
|
|
|
continue;
|
2025-10-15 12:53:33 +08:00
|
|
|
|
geom.x = m->w.x + cur_gappoh;
|
|
|
|
|
|
geom.y = m->w.y + cur_gappov;
|
|
|
|
|
|
geom.width = m->w.width - 2 * cur_gappoh;
|
|
|
|
|
|
geom.height = m->w.height - 2 * cur_gappov;
|
2025-09-29 12:24:22 +08:00
|
|
|
|
resize(c, geom, 0);
|
2025-06-28 12:35:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
if ((c = focustop(m)))
|
|
|
|
|
|
wlr_scene_node_raise_to_top(&c->scene->node);
|
2026-05-16 08:23:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-16 17:32:39 +08:00
|
|
|
|
// 网格布局窗口大小和位置计算
|
|
|
|
|
|
void grid(Monitor *m) {
|
|
|
|
|
|
int32_t i, n;
|
|
|
|
|
|
int32_t cw, ch;
|
|
|
|
|
|
int32_t cols, rows, overcols;
|
|
|
|
|
|
Client *c = NULL;
|
|
|
|
|
|
n = 0;
|
|
|
|
|
|
int32_t target_gappo =
|
|
|
|
|
|
enablegaps ? m->isoverview ? config.overviewgappo : config.gappoh : 0;
|
|
|
|
|
|
int32_t target_gappi =
|
|
|
|
|
|
enablegaps ? m->isoverview ? config.overviewgappi : config.gappih : 0;
|
|
|
|
|
|
float single_width_ratio = m->isoverview ? 0.7 : 0.9;
|
|
|
|
|
|
float single_height_ratio = m->isoverview ? 0.8 : 0.9;
|
|
|
|
|
|
|
|
|
|
|
|
n = m->isoverview ? m->visible_clients : m->visible_tiling_clients;
|
|
|
|
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (c->mon != m)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
if (VISIBLEON(c, m) && !c->isunglobal &&
|
|
|
|
|
|
((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) {
|
|
|
|
|
|
cw = (m->w.width - 2 * target_gappo) * single_width_ratio;
|
|
|
|
|
|
ch = (m->w.height - 2 * target_gappo) * single_height_ratio;
|
|
|
|
|
|
c->geom.x = m->w.x + (m->w.width - cw) / 2;
|
|
|
|
|
|
c->geom.y = m->w.y + (m->w.height - ch) / 2;
|
|
|
|
|
|
c->geom.width = cw;
|
|
|
|
|
|
c->geom.height = ch;
|
|
|
|
|
|
resize(c, c->geom, 0);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (n == 2) {
|
|
|
|
|
|
float col_pers[2] = {1.0f, 1.0f};
|
|
|
|
|
|
// 先提取这两个窗口现有的列比例
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (c->mon != m)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
if (VISIBLEON(c, m) && !c->isunglobal &&
|
|
|
|
|
|
((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) {
|
|
|
|
|
|
if (i < 2)
|
|
|
|
|
|
col_pers[i] =
|
|
|
|
|
|
(c->grid_col_per > 0.0f) ? c->grid_col_per : 1.0f;
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float sum_col = col_pers[0] + col_pers[1];
|
|
|
|
|
|
float avail_w = m->w.width - 2 * target_gappo - target_gappi;
|
|
|
|
|
|
ch =
|
|
|
|
|
|
(m->w.height - 2 * target_gappo) * 0.65; // 依然保持 0.65 的美观高度
|
|
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (c->mon != m)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
if (VISIBLEON(c, m) && !c->isunglobal &&
|
|
|
|
|
|
((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) {
|
|
|
|
|
|
c->grid_col_idx = i;
|
|
|
|
|
|
c->grid_row_idx = 0;
|
|
|
|
|
|
c->grid_col_per = col_pers[i];
|
|
|
|
|
|
c->grid_row_per = 1.0f;
|
|
|
|
|
|
|
|
|
|
|
|
// 根据分配的权重动态计算当前窗口的宽度
|
|
|
|
|
|
cw = avail_w * (col_pers[i] / sum_col);
|
|
|
|
|
|
|
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
|
c->geom.x = m->w.x + target_gappo;
|
|
|
|
|
|
} else if (i == 1) {
|
|
|
|
|
|
// 第二个窗口的 X 坐标紧跟第一个窗口后面
|
|
|
|
|
|
float cw0 = avail_w * (col_pers[0] / sum_col);
|
|
|
|
|
|
c->geom.x = m->w.x + target_gappo + cw0 + target_gappi;
|
|
|
|
|
|
}
|
|
|
|
|
|
c->geom.y = m->w.y + (m->w.height - ch) / 2 + target_gappo;
|
|
|
|
|
|
c->geom.width = cw;
|
|
|
|
|
|
c->geom.height = ch;
|
|
|
|
|
|
resize(c, c->geom, 0);
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算列数和行数
|
|
|
|
|
|
for (cols = 0; cols <= n / 2; cols++) {
|
|
|
|
|
|
if (cols * cols >= n)
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
rows = (cols && (cols - 1) * cols >= n) ? cols - 1 : cols;
|
|
|
|
|
|
overcols = n % cols;
|
|
|
|
|
|
|
|
|
|
|
|
float col_pers[cols];
|
|
|
|
|
|
float row_pers[rows];
|
|
|
|
|
|
for (i = 0; i < cols; i++)
|
|
|
|
|
|
col_pers[i] = 1.0f;
|
|
|
|
|
|
for (i = 0; i < rows; i++)
|
|
|
|
|
|
row_pers[i] = 1.0f;
|
|
|
|
|
|
|
|
|
|
|
|
// 提取首个窗口比例
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (c->mon != m)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
if (VISIBLEON(c, m) && !c->isunglobal &&
|
|
|
|
|
|
((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) {
|
|
|
|
|
|
int32_t c_idx = i % cols;
|
|
|
|
|
|
int32_t r_idx = i / cols;
|
|
|
|
|
|
if (r_idx == 0)
|
|
|
|
|
|
col_pers[c_idx] =
|
|
|
|
|
|
(c->grid_col_per > 0.0f) ? c->grid_col_per : 1.0f;
|
|
|
|
|
|
if (c_idx == 0)
|
|
|
|
|
|
row_pers[r_idx] =
|
|
|
|
|
|
(c->grid_row_per > 0.0f) ? c->grid_row_per : 1.0f;
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float sum_col = 0.0f, sum_row = 0.0f;
|
|
|
|
|
|
for (i = 0; i < cols; i++)
|
|
|
|
|
|
sum_col += col_pers[i];
|
|
|
|
|
|
for (i = 0; i < rows; i++)
|
|
|
|
|
|
sum_row += row_pers[i];
|
|
|
|
|
|
|
|
|
|
|
|
float avail_w = m->w.width - 2 * target_gappo - (cols - 1) * target_gappi;
|
|
|
|
|
|
float avail_h = m->w.height - 2 * target_gappo - (rows - 1) * target_gappi;
|
|
|
|
|
|
|
|
|
|
|
|
// 分配位置与尺寸
|
|
|
|
|
|
i = 0;
|
|
|
|
|
|
wl_list_for_each(c, &clients, link) {
|
|
|
|
|
|
if (c->mon != m)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
if (VISIBLEON(c, m) && !c->isunglobal &&
|
|
|
|
|
|
((m->isoverview && !client_is_x11_popup(c)) || ISTILED(c))) {
|
|
|
|
|
|
int32_t c_idx = i % cols;
|
|
|
|
|
|
int32_t r_idx = i / cols;
|
|
|
|
|
|
|
|
|
|
|
|
// 矫正属性及标记索引
|
|
|
|
|
|
c->grid_col_per = col_pers[c_idx];
|
|
|
|
|
|
c->grid_row_per = row_pers[r_idx];
|
|
|
|
|
|
c->grid_col_idx = c_idx;
|
|
|
|
|
|
c->grid_row_idx = r_idx;
|
|
|
|
|
|
|
|
|
|
|
|
// X 坐标及宽度计算
|
|
|
|
|
|
float fl_cx = m->w.x + target_gappo;
|
|
|
|
|
|
float fl_cw = 0.0f;
|
|
|
|
|
|
|
|
|
|
|
|
if (overcols && i >= n - overcols) {
|
|
|
|
|
|
float over_w = 0.0f;
|
|
|
|
|
|
for (int j = 0; j < overcols; j++)
|
|
|
|
|
|
over_w += avail_w * (col_pers[j] / sum_col);
|
|
|
|
|
|
over_w += (overcols - 1) * target_gappi;
|
|
|
|
|
|
float dx = (m->w.width - over_w) / 2.0f - target_gappo;
|
|
|
|
|
|
|
|
|
|
|
|
fl_cx += dx;
|
|
|
|
|
|
for (int j = 0; j < c_idx; j++)
|
|
|
|
|
|
fl_cx += avail_w * (col_pers[j] / sum_col) + target_gappi;
|
|
|
|
|
|
fl_cw = avail_w * (col_pers[c_idx] / sum_col);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
for (int j = 0; j < c_idx; j++)
|
|
|
|
|
|
fl_cx += avail_w * (col_pers[j] / sum_col) + target_gappi;
|
|
|
|
|
|
fl_cw = (c_idx == cols - 1)
|
|
|
|
|
|
? (m->w.x + m->w.width - target_gappo - fl_cx)
|
|
|
|
|
|
: avail_w * (col_pers[c_idx] / sum_col);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Y 坐标及高度计算
|
|
|
|
|
|
float fl_cy = m->w.y + target_gappo;
|
|
|
|
|
|
for (int j = 0; j < r_idx; j++)
|
|
|
|
|
|
fl_cy += avail_h * (row_pers[j] / sum_row) + target_gappi;
|
|
|
|
|
|
float fl_ch = (r_idx == rows - 1)
|
|
|
|
|
|
? (m->w.y + m->w.height - target_gappo - fl_cy)
|
|
|
|
|
|
: avail_h * (row_pers[r_idx] / sum_row);
|
|
|
|
|
|
|
|
|
|
|
|
c->geom.x = (int32_t)fl_cx;
|
|
|
|
|
|
c->geom.y = (int32_t)fl_cy;
|
|
|
|
|
|
c->geom.width = (int32_t)fl_cw;
|
|
|
|
|
|
c->geom.height = (int32_t)fl_ch;
|
|
|
|
|
|
resize(c, c->geom, 0);
|
|
|
|
|
|
i++;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-16 08:23:48 +08:00
|
|
|
|
void fair(Monitor *m) {
|
|
|
|
|
|
int32_t i, n = 0;
|
|
|
|
|
|
Client *c = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
n = m->visible_tiling_clients;
|
|
|
|
|
|
if (n == 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
// 获取间距配置
|
2026-05-16 08:23:48 +08:00
|
|
|
|
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;
|
|
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
if (config.smartgaps && n == 1) {
|
|
|
|
|
|
cur_gappiv = cur_gappih = cur_gappov = cur_gappoh = 0;
|
|
|
|
|
|
}
|
2026-05-16 08:23:48 +08:00
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
// 计算网格行列数
|
2026-05-16 08:23:48 +08:00
|
|
|
|
int32_t cols;
|
|
|
|
|
|
for (cols = 0; cols <= n; cols++) {
|
|
|
|
|
|
if (cols * cols >= n)
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-16 17:32:39 +08:00
|
|
|
|
int32_t base_rows = n / cols;
|
|
|
|
|
|
int32_t remainder = n % cols;
|
2026-05-16 16:31:16 +08:00
|
|
|
|
int32_t first_group_cols = cols - remainder;
|
|
|
|
|
|
int32_t first_group_count = first_group_cols * base_rows;
|
2026-05-16 17:32:39 +08:00
|
|
|
|
int32_t max_rows = base_rows + (remainder > 0 ? 1 : 0);
|
2026-05-16 08:23:48 +08:00
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
// 将有效客户端存入数组
|
|
|
|
|
|
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; // 安全边界
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化比例数组
|
2026-05-16 17:32:39 +08:00
|
|
|
|
float col_pers[cols];
|
|
|
|
|
|
float row_pers[max_rows];
|
|
|
|
|
|
for (i = 0; i < cols; i++)
|
2026-05-18 11:41:30 +08:00
|
|
|
|
col_pers[i] = 0.0f;
|
2026-05-16 17:32:39 +08:00
|
|
|
|
for (i = 0; i < max_rows; i++)
|
2026-05-18 11:41:30 +08:00
|
|
|
|
row_pers[i] = 0.0f;
|
2026-05-16 17:32:39 +08:00
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
// 直接基于数组进行两遍比例锁定
|
|
|
|
|
|
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);
|
2026-05-16 17:32:39 +08:00
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
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;
|
2026-05-16 17:32:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
// 兜底策略与总权重计算
|
2026-05-16 17:32:39 +08:00
|
|
|
|
float sum_col = 0.0f;
|
2026-05-18 11:41:30 +08:00
|
|
|
|
for (i = 0; i < cols; i++) {
|
|
|
|
|
|
if (col_pers[i] == 0.0f)
|
|
|
|
|
|
col_pers[i] = 1.0f;
|
2026-05-16 17:32:39 +08:00
|
|
|
|
sum_col += col_pers[i];
|
2026-05-18 11:41:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
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];
|
2026-05-16 17:32:39 +08:00
|
|
|
|
float avail_w = m->w.width - 2 * cur_gappoh - (cols - 1) * cur_gappih;
|
2026-05-18 11:41:30 +08:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
2026-05-16 08:23:48 +08:00
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
// 预计算两组不同的行几何参数(解决不同列行数不一致的问题)
|
|
|
|
|
|
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;
|
2026-05-16 08:23:48 +08:00
|
|
|
|
|
2026-05-16 16:31:16 +08:00
|
|
|
|
if (i < first_group_count) {
|
|
|
|
|
|
col_idx = i / base_rows;
|
|
|
|
|
|
row_idx = i % base_rows;
|
2026-05-18 11:41:30 +08:00
|
|
|
|
fl_cy = row_y_base[row_idx];
|
|
|
|
|
|
fl_ch = row_h_base[row_idx];
|
2026-05-16 16:31:16 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
int32_t offset = i - first_group_count;
|
2026-05-18 11:41:30 +08:00
|
|
|
|
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];
|
2026-05-16 08:23:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-16 17:32:39 +08:00
|
|
|
|
c->grid_col_per = col_pers[col_idx];
|
|
|
|
|
|
c->grid_row_per = row_pers[row_idx];
|
|
|
|
|
|
c->grid_col_idx = col_idx;
|
|
|
|
|
|
c->grid_row_idx = row_idx;
|
2026-05-16 08:23:48 +08:00
|
|
|
|
|
2026-05-18 11:41:30 +08:00
|
|
|
|
fl_cx = col_x[col_idx];
|
|
|
|
|
|
fl_cw = col_w[col_idx];
|
2026-05-16 17:32:39 +08:00
|
|
|
|
|
|
|
|
|
|
resize(c,
|
|
|
|
|
|
(struct wlr_box){.x = (int32_t)fl_cx,
|
|
|
|
|
|
.y = (int32_t)fl_cy,
|
|
|
|
|
|
.width = (int32_t)fl_cw,
|
|
|
|
|
|
.height = (int32_t)fl_ch},
|
2026-05-16 08:23:48 +08:00
|
|
|
|
0);
|
|
|
|
|
|
}
|
2026-05-18 11:41:30 +08:00
|
|
|
|
}
|