From 055157406b4608109505199028254f64ecf46f9a Mon Sep 17 00:00:00 2001 From: DreamMaoMao <2523610504@qq.com> Date: Sat, 28 Jun 2025 12:35:58 +0800 Subject: [PATCH] feat: Add vertical version support for each layout --- src/config/preset.h | 14 +- src/layout/horizontal.h | 503 ++++++++++++++++++++++++++++++++++++++ src/layout/layout.h | 519 ++-------------------------------------- src/layout/vertical.h | 488 +++++++++++++++++++++++++++++++++++++ src/maomao.c | 49 ++-- 5 files changed, 1038 insertions(+), 535 deletions(-) create mode 100644 src/layout/horizontal.h create mode 100644 src/layout/vertical.h diff --git a/src/config/preset.h b/src/config/preset.h index 49bad8b..e1f37ab 100644 --- a/src/config/preset.h +++ b/src/config/preset.h @@ -98,9 +98,19 @@ Layout layouts[] = { /* symbol arrange function name */ {"S", scroller, "scroller"}, // 滚动布局 {"T", tile, "tile"}, // 堆栈布局 - {"G", grid, "grid"}, {"M", monocle, "monocle"}, - {"D", dwindle, "dwindle"}, {"P", spiral, "spiral"}, + {"G", grid, "grid"}, + {"M", monocle, "monocle"}, + {"D", dwindle, "dwindle"}, + {"P", spiral, "spiral"}, {"K", deck, "deck"}, + {"VS", vertical_scroller, "vertical_scroller"}, + {"VT", vertical_tile, "vertical_tile"}, + {"VM", vertical_monocle, "vertical_monocle"}, + {"VD", vertical_dwindle, "vertical_dwindle"}, + {"VP", vertical_spiral, "vertical_spiral"}, + {"VG", vertical_grid, "vertical_grid"}, + {"VK", vertical_deck, "vertical_deck"}, + }; /* keyboard */ diff --git a/src/layout/horizontal.h b/src/layout/horizontal.h new file mode 100644 index 0000000..02a70e5 --- /dev/null +++ b/src/layout/horizontal.h @@ -0,0 +1,503 @@ +void fibonacci(Monitor *mon, int s) { + unsigned int i = 0, n = 0, nx, ny, nw, nh; + Client *c; + unsigned int cur_gappih = enablegaps ? mon->gappih : 0; + unsigned int cur_gappiv = enablegaps ? mon->gappiv : 0; + unsigned int cur_gappoh = enablegaps ? mon->gappoh : 0; + unsigned int cur_gappov = enablegaps ? mon->gappov : 0; + + cur_gappih = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappih; + cur_gappiv = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappiv; + cur_gappoh = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappoh; + cur_gappov = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappov; + // Count visible clients + wl_list_for_each(c, &clients, link) if (VISIBLEON(c, mon) && ISTILED(c)) + n++; + + if (n == 0) + return; + + // Initial dimensions including outer gaps + nx = mon->w.x + cur_gappoh; + ny = mon->w.y + cur_gappov; + nw = mon->w.width - 2 * cur_gappoh; + nh = mon->w.height - 2 * cur_gappov; + + // First pass: calculate client geometries + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, mon) || !ISTILED(c)) + continue; + + c->bw = mon->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if ((i % 2 && nh / 2 > 2 * c->bw) || (!(i % 2) && nw / 2 > 2 * c->bw)) { + if (i < n - 1) { + if (i % 2) { + if (i == 1) { + nh = nh * mon->pertag->smfacts[mon->pertag->curtag]; + } else { + nh = (nh - cur_gappiv) / 2; + } + } else { + nw = (nw - cur_gappih) / 2; + } + + if ((i % 4) == 2 && !s) + nx += nw + cur_gappih; + else if ((i % 4) == 3 && !s) + ny += nh + cur_gappiv; + } + + if ((i % 4) == 0) { + if (s) + ny += nh + cur_gappiv; + else + ny -= nh + cur_gappiv; + } else if ((i % 4) == 1) + nx += nw + cur_gappih; + else if ((i % 4) == 2) + ny += nh + cur_gappiv; + else if ((i % 4) == 3) { + if (s) + nx += nw + cur_gappih; + else + nx -= nw + cur_gappih; + } + + if (i == 0) { + if (n != 1) + nw = (mon->w.width - 2 * cur_gappoh) * + mon->pertag->mfacts[mon->pertag->curtag]; + ny = mon->w.y + cur_gappov; + } else if (i == 1) { + nw = mon->w.width - 2 * cur_gappoh - nw - cur_gappih; + } else if (i == 2) { + nh = mon->w.height - 2 * cur_gappov - nh - cur_gappiv; + } + i++; + } + + c->geom = (struct wlr_box){.x = nx, .y = ny, .width = nw, .height = nh}; + } + + // Second pass: apply gaps between clients + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, mon) || !ISTILED(c)) + continue; + + unsigned int right_gap = 0; + unsigned int bottom_gap = 0; + Client *nc; + + wl_list_for_each(nc, &clients, link) { + if (!VISIBLEON(nc, mon) || !ISTILED(nc)) + continue; + + if (c == nc) + continue; + + // Check for right neighbor + if (c->geom.y == nc->geom.y && + c->geom.x + c->geom.width == nc->geom.x) { + right_gap = cur_gappih; + } + + // Check for bottom neighbor + if (c->geom.x == nc->geom.x && + c->geom.y + c->geom.height == nc->geom.y) { + bottom_gap = cur_gappiv; + } + } + + resize(c, + (struct wlr_box){.x = c->geom.x, + .y = c->geom.y, + .width = c->geom.width - right_gap, + .height = c->geom.height - bottom_gap}, + 0); + } +} + +void dwindle(Monitor *mon) { fibonacci(mon, 1); } + +void spiral(Monitor *mon) { fibonacci(mon, 0); } + +// 网格布局窗口大小和位置计算 +void grid(Monitor *m) { + unsigned int i, n; + unsigned int cx, cy, cw, ch; + unsigned int dx; + unsigned int cols, rows, overcols; + Client *c; + n = 0; + + // 第一次遍历,计算 n 的值 + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || ISTILED(c))) { + n++; + } + } + + if (n == 0) { + return; // 没有需要处理的客户端,直接返回 + } + + if (n == 1) { + wl_list_for_each(c, &clients, link) { + c->bw = + m->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || + ISTILED(c))) { + cw = (m->w.width - 2 * overviewgappo) * 0.7; + ch = (m->w.height - 2 * overviewgappo) * 0.8; + 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 - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + resize(c, c->geom, 0); + return; + } + } + } + + if (n == 2) { + cw = (m->w.width - 2 * overviewgappo - overviewgappi) / 2; + ch = (m->w.height - 2 * overviewgappo) * 0.65; + i = 0; + wl_list_for_each(c, &clients, link) { + c->bw = + m->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || + ISTILED(c))) { + if (i == 0) { + c->geom.x = m->w.x + overviewgappo; + c->geom.y = m->w.y + (m->w.height - ch) / 2 + overviewgappo; + c->geom.width = cw - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + resize(c, c->geom, 0); + } else if (i == 1) { + c->geom.x = m->w.x + cw + overviewgappo + overviewgappi; + c->geom.y = m->w.y + (m->w.height - ch) / 2 + overviewgappo; + c->geom.width = cw - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + 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; + + // 计算每个客户端的高度和宽度 + ch = (m->w.height - 2 * overviewgappo - (rows - 1) * overviewgappi) / rows; + cw = (m->w.width - 2 * overviewgappo - (cols - 1) * overviewgappi) / cols; + + // 处理多余的列 + overcols = n % cols; + if (overcols) { + dx = (m->w.width - overcols * cw - (overcols - 1) * overviewgappi) / 2 - + overviewgappo; + } + + // 调整每个客户端的位置和大小 + i = 0; + wl_list_for_each(c, &clients, link) { + c->bw = m->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || ISTILED(c))) { + cx = m->w.x + (i % cols) * (cw + overviewgappi); + cy = m->w.y + (i / cols) * (ch + overviewgappi); + if (overcols && i >= n - overcols) { + cx += dx; + } + c->geom.x = cx + overviewgappo; + c->geom.y = cy + overviewgappo; + c->geom.width = cw - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + resize(c, c->geom, 0); + i++; + } + } +} + +void deck(Monitor *m) { + unsigned int mw, my; + int i, n = 0; + Client *c; + unsigned int cur_gappih = enablegaps ? m->gappih : 0; + unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; + unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + unsigned int cur_gappov = enablegaps ? m->gappov : 0; + + cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; + cur_gappiv = smartgaps && m->visible_clients == 1 ? 0 : cur_gappiv; + cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; + cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; + + wl_list_for_each(c, &clients, link) if (VISIBLEON(c, m) && ISTILED(c)) n++; + if (n == 0) + return; + + // Calculate master width using mfact from pertag + float mfact = m->pertag ? m->pertag->mfacts[m->pertag->curtag] : m->mfact; + + // Calculate master width including outer gaps + if (n > m->nmaster) + mw = m->nmaster ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0; + 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; + if (i < m->nmaster) { + // Master area clients + resize(c, + (struct wlr_box){ + .x = m->w.x + cur_gappoh, + .y = m->w.y + cur_gappov + my, + .width = mw, + .height = (m->w.height - cur_gappov - my - cur_gappiv) / + (MIN(n, m->nmaster) - i)}, + 0); + my += c->geom.height + cur_gappiv; + } else { + // Stack area clients + 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++; + } +} + +// 滚动布局 +void scroller(Monitor *m) { + unsigned int i, n; + + Client *c, *root_client = NULL; + Client **tempClients = NULL; // 初始化为 NULL + n = 0; + struct wlr_box target_geom; + int focus_client_index = 0; + bool need_scroller = false; + unsigned int cur_gappih = enablegaps ? m->gappih : 0; + unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + unsigned int cur_gappov = enablegaps ? m->gappov : 0; + + cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; + cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; + cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; + + unsigned int max_client_width = + m->w.width - 2 * scroller_structs - cur_gappih; + + // 第一次遍历,计算 n 的值 + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && ISTILED(c)) { + n++; + } + } + + if (n == 0) { + return; // 没有需要处理的客户端,直接返回 + } + + // 动态分配内存 + tempClients = malloc(n * sizeof(Client *)); + if (!tempClients) { + // 处理内存分配失败的情况 + return; + } + + // 第二次遍历,填充 tempClients + n = 0; + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && ISTILED(c)) { + tempClients[n] = c; + n++; + } + } + + if (n == 1) { + c = tempClients[0]; + target_geom.height = m->w.height - 2 * cur_gappov; + target_geom.width = + (m->w.width - 2 * cur_gappoh) * scroller_default_proportion_single; + target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; + target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; + resize(c, target_geom, 0); + free(tempClients); // 释放内存 + return; + } + + if (m->sel && !client_is_unmanaged(m->sel) && !m->sel->isfloating && + !m->sel->ismaxmizescreen && !m->sel->isfullscreen) { + root_client = m->sel; + } else if (m->prevsel && !client_is_unmanaged(m->prevsel) && + !m->prevsel->isfloating && !m->prevsel->ismaxmizescreen && + !m->prevsel->isfullscreen) { + root_client = m->prevsel; + } else { + root_client = center_select(m); + } + + if (!root_client) { + free(tempClients); // 释放内存 + return; + } + + for (i = 0; i < n; i++) { + c = tempClients[i]; + if (root_client == c) { + if (!c->is_open_animation && + c->geom.x >= m->w.x + scroller_structs && + c->geom.x + c->geom.width <= + m->w.x + m->w.width - scroller_structs) { + need_scroller = false; + } else { + need_scroller = true; + } + focus_client_index = i; + break; + } + } + + target_geom.height = m->w.height - 2 * cur_gappov; + target_geom.width = max_client_width * c->scroller_proportion; + target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; + + if (need_scroller) { + if (scroller_focus_center || + ((!m->prevsel || + (m->prevsel->scroller_proportion * max_client_width) + + (root_client->scroller_proportion * max_client_width) > + m->w.width - 2 * scroller_structs - cur_gappih) && + scroller_prefer_center)) { + target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; + } else { + target_geom.x = root_client->geom.x > m->w.x + (m->w.width) / 2 + ? m->w.x + (m->w.width - + root_client->scroller_proportion * + max_client_width - + scroller_structs) + : m->w.x + scroller_structs; + } + resize(tempClients[focus_client_index], target_geom, 0); + } else { + target_geom.x = c->geom.x; + resize(tempClients[focus_client_index], target_geom, 0); + } + + for (i = 1; i <= focus_client_index; i++) { + c = tempClients[focus_client_index - i]; + target_geom.width = max_client_width * c->scroller_proportion; + target_geom.x = tempClients[focus_client_index - i + 1]->geom.x - + cur_gappih - target_geom.width; + resize(c, target_geom, 0); + } + + for (i = 1; i < n - focus_client_index; i++) { + c = tempClients[focus_client_index + i]; + target_geom.width = max_client_width * c->scroller_proportion; + target_geom.x = tempClients[focus_client_index + i - 1]->geom.x + + cur_gappih + + tempClients[focus_client_index + i - 1]->geom.width; + resize(c, target_geom, 0); + } + + free(tempClients); // 最后释放内存 +} + +void tile(Monitor *m) { + unsigned int i, n = 0, h, r, ie = enablegaps, mw, my, ty; + Client *c; + + wl_list_for_each(c, &clients, link) if (VISIBLEON(c, m) && ISTILED(c)) n++; + if (n == 0) + return; + + unsigned int cur_gappih = enablegaps ? m->gappih : 0; + unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; + unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + unsigned int cur_gappov = enablegaps ? m->gappov : 0; + + cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; + cur_gappiv = smartgaps && m->visible_clients == 1 ? 0 : cur_gappiv; + cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; + cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; + + if (n > selmon->pertag->nmasters[selmon->pertag->curtag]) + mw = selmon->pertag->nmasters[selmon->pertag->curtag] + ? (m->w.width + cur_gappiv * ie) * + selmon->pertag->mfacts[selmon->pertag->curtag] + : 0; + else + mw = m->w.width - 2 * cur_gappov + cur_gappiv * ie; + i = 0; + my = ty = cur_gappoh; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || !ISTILED(c)) + continue; + if (i < selmon->pertag->nmasters[selmon->pertag->curtag]) { + r = MIN(n, selmon->pertag->nmasters[selmon->pertag->curtag]) - i; + h = (m->w.height - my - cur_gappoh - cur_gappih * ie * (r - 1)) / r; + resize(c, + (struct wlr_box){.x = m->w.x + cur_gappov, + .y = m->w.y + my, + .width = mw - cur_gappiv * ie, + .height = h}, + 0); + my += c->geom.height + cur_gappih * ie; + } else { + r = n - i; + h = (m->w.height - ty - cur_gappoh - cur_gappih * ie * (r - 1)) / r; + resize(c, + (struct wlr_box){.x = m->w.x + mw + cur_gappov, + .y = m->w.y + ty, + .width = m->w.width - mw - 2 * cur_gappov, + .height = h}, + 0); + ty += c->geom.height + cur_gappih * ie; + } + i++; + } +} + +void // 17 +monocle(Monitor *m) { + Client *c; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || !ISTILED(c)) + continue; + resize(c, m->w, 0); + } + if ((c = focustop(m))) + wlr_scene_node_raise_to_top(&c->scene->node); +} \ No newline at end of file diff --git a/src/layout/layout.h b/src/layout/layout.h index 02a70e5..2d55309 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -1,503 +1,16 @@ -void fibonacci(Monitor *mon, int s) { - unsigned int i = 0, n = 0, nx, ny, nw, nh; - Client *c; - unsigned int cur_gappih = enablegaps ? mon->gappih : 0; - unsigned int cur_gappiv = enablegaps ? mon->gappiv : 0; - unsigned int cur_gappoh = enablegaps ? mon->gappoh : 0; - unsigned int cur_gappov = enablegaps ? mon->gappov : 0; - - cur_gappih = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappih; - cur_gappiv = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappiv; - cur_gappoh = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappoh; - cur_gappov = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappov; - // Count visible clients - wl_list_for_each(c, &clients, link) if (VISIBLEON(c, mon) && ISTILED(c)) - n++; - - if (n == 0) - return; - - // Initial dimensions including outer gaps - nx = mon->w.x + cur_gappoh; - ny = mon->w.y + cur_gappov; - nw = mon->w.width - 2 * cur_gappoh; - nh = mon->w.height - 2 * cur_gappov; - - // First pass: calculate client geometries - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, mon) || !ISTILED(c)) - continue; - - c->bw = mon->visible_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; - if ((i % 2 && nh / 2 > 2 * c->bw) || (!(i % 2) && nw / 2 > 2 * c->bw)) { - if (i < n - 1) { - if (i % 2) { - if (i == 1) { - nh = nh * mon->pertag->smfacts[mon->pertag->curtag]; - } else { - nh = (nh - cur_gappiv) / 2; - } - } else { - nw = (nw - cur_gappih) / 2; - } - - if ((i % 4) == 2 && !s) - nx += nw + cur_gappih; - else if ((i % 4) == 3 && !s) - ny += nh + cur_gappiv; - } - - if ((i % 4) == 0) { - if (s) - ny += nh + cur_gappiv; - else - ny -= nh + cur_gappiv; - } else if ((i % 4) == 1) - nx += nw + cur_gappih; - else if ((i % 4) == 2) - ny += nh + cur_gappiv; - else if ((i % 4) == 3) { - if (s) - nx += nw + cur_gappih; - else - nx -= nw + cur_gappih; - } - - if (i == 0) { - if (n != 1) - nw = (mon->w.width - 2 * cur_gappoh) * - mon->pertag->mfacts[mon->pertag->curtag]; - ny = mon->w.y + cur_gappov; - } else if (i == 1) { - nw = mon->w.width - 2 * cur_gappoh - nw - cur_gappih; - } else if (i == 2) { - nh = mon->w.height - 2 * cur_gappov - nh - cur_gappiv; - } - i++; - } - - c->geom = (struct wlr_box){.x = nx, .y = ny, .width = nw, .height = nh}; - } - - // Second pass: apply gaps between clients - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, mon) || !ISTILED(c)) - continue; - - unsigned int right_gap = 0; - unsigned int bottom_gap = 0; - Client *nc; - - wl_list_for_each(nc, &clients, link) { - if (!VISIBLEON(nc, mon) || !ISTILED(nc)) - continue; - - if (c == nc) - continue; - - // Check for right neighbor - if (c->geom.y == nc->geom.y && - c->geom.x + c->geom.width == nc->geom.x) { - right_gap = cur_gappih; - } - - // Check for bottom neighbor - if (c->geom.x == nc->geom.x && - c->geom.y + c->geom.height == nc->geom.y) { - bottom_gap = cur_gappiv; - } - } - - resize(c, - (struct wlr_box){.x = c->geom.x, - .y = c->geom.y, - .width = c->geom.width - right_gap, - .height = c->geom.height - bottom_gap}, - 0); - } -} - -void dwindle(Monitor *mon) { fibonacci(mon, 1); } - -void spiral(Monitor *mon) { fibonacci(mon, 0); } - -// 网格布局窗口大小和位置计算 -void grid(Monitor *m) { - unsigned int i, n; - unsigned int cx, cy, cw, ch; - unsigned int dx; - unsigned int cols, rows, overcols; - Client *c; - n = 0; - - // 第一次遍历,计算 n 的值 - wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_should_ignore_focus(c)) || ISTILED(c))) { - n++; - } - } - - if (n == 0) { - return; // 没有需要处理的客户端,直接返回 - } - - if (n == 1) { - wl_list_for_each(c, &clients, link) { - c->bw = - m->visible_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; - if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_should_ignore_focus(c)) || - ISTILED(c))) { - cw = (m->w.width - 2 * overviewgappo) * 0.7; - ch = (m->w.height - 2 * overviewgappo) * 0.8; - 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 - 2 * c->bw; - c->geom.height = ch - 2 * c->bw; - resize(c, c->geom, 0); - return; - } - } - } - - if (n == 2) { - cw = (m->w.width - 2 * overviewgappo - overviewgappi) / 2; - ch = (m->w.height - 2 * overviewgappo) * 0.65; - i = 0; - wl_list_for_each(c, &clients, link) { - c->bw = - m->visible_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; - if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_should_ignore_focus(c)) || - ISTILED(c))) { - if (i == 0) { - c->geom.x = m->w.x + overviewgappo; - c->geom.y = m->w.y + (m->w.height - ch) / 2 + overviewgappo; - c->geom.width = cw - 2 * c->bw; - c->geom.height = ch - 2 * c->bw; - resize(c, c->geom, 0); - } else if (i == 1) { - c->geom.x = m->w.x + cw + overviewgappo + overviewgappi; - c->geom.y = m->w.y + (m->w.height - ch) / 2 + overviewgappo; - c->geom.width = cw - 2 * c->bw; - c->geom.height = ch - 2 * c->bw; - 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; - - // 计算每个客户端的高度和宽度 - ch = (m->w.height - 2 * overviewgappo - (rows - 1) * overviewgappi) / rows; - cw = (m->w.width - 2 * overviewgappo - (cols - 1) * overviewgappi) / cols; - - // 处理多余的列 - overcols = n % cols; - if (overcols) { - dx = (m->w.width - overcols * cw - (overcols - 1) * overviewgappi) / 2 - - overviewgappo; - } - - // 调整每个客户端的位置和大小 - i = 0; - wl_list_for_each(c, &clients, link) { - c->bw = m->visible_clients == 1 && no_border_when_single && smartgaps - ? 0 - : borderpx; - if (VISIBLEON(c, m) && !c->isunglobal && - ((m->isoverview && !client_should_ignore_focus(c)) || ISTILED(c))) { - cx = m->w.x + (i % cols) * (cw + overviewgappi); - cy = m->w.y + (i / cols) * (ch + overviewgappi); - if (overcols && i >= n - overcols) { - cx += dx; - } - c->geom.x = cx + overviewgappo; - c->geom.y = cy + overviewgappo; - c->geom.width = cw - 2 * c->bw; - c->geom.height = ch - 2 * c->bw; - resize(c, c->geom, 0); - i++; - } - } -} - -void deck(Monitor *m) { - unsigned int mw, my; - int i, n = 0; - Client *c; - unsigned int cur_gappih = enablegaps ? m->gappih : 0; - unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; - - cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; - cur_gappiv = smartgaps && m->visible_clients == 1 ? 0 : cur_gappiv; - cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; - cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; - - wl_list_for_each(c, &clients, link) if (VISIBLEON(c, m) && ISTILED(c)) n++; - if (n == 0) - return; - - // Calculate master width using mfact from pertag - float mfact = m->pertag ? m->pertag->mfacts[m->pertag->curtag] : m->mfact; - - // Calculate master width including outer gaps - if (n > m->nmaster) - mw = m->nmaster ? round((m->w.width - 2 * cur_gappoh) * mfact) : 0; - 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; - if (i < m->nmaster) { - // Master area clients - resize(c, - (struct wlr_box){ - .x = m->w.x + cur_gappoh, - .y = m->w.y + cur_gappov + my, - .width = mw, - .height = (m->w.height - cur_gappov - my - cur_gappiv) / - (MIN(n, m->nmaster) - i)}, - 0); - my += c->geom.height + cur_gappiv; - } else { - // Stack area clients - 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++; - } -} - -// 滚动布局 -void scroller(Monitor *m) { - unsigned int i, n; - - Client *c, *root_client = NULL; - Client **tempClients = NULL; // 初始化为 NULL - n = 0; - struct wlr_box target_geom; - int focus_client_index = 0; - bool need_scroller = false; - unsigned int cur_gappih = enablegaps ? m->gappih : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; - - cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; - cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; - cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; - - unsigned int max_client_width = - m->w.width - 2 * scroller_structs - cur_gappih; - - // 第一次遍历,计算 n 的值 - wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && ISTILED(c)) { - n++; - } - } - - if (n == 0) { - return; // 没有需要处理的客户端,直接返回 - } - - // 动态分配内存 - tempClients = malloc(n * sizeof(Client *)); - if (!tempClients) { - // 处理内存分配失败的情况 - return; - } - - // 第二次遍历,填充 tempClients - n = 0; - wl_list_for_each(c, &clients, link) { - if (VISIBLEON(c, m) && ISTILED(c)) { - tempClients[n] = c; - n++; - } - } - - if (n == 1) { - c = tempClients[0]; - target_geom.height = m->w.height - 2 * cur_gappov; - target_geom.width = - (m->w.width - 2 * cur_gappoh) * scroller_default_proportion_single; - target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; - target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; - resize(c, target_geom, 0); - free(tempClients); // 释放内存 - return; - } - - if (m->sel && !client_is_unmanaged(m->sel) && !m->sel->isfloating && - !m->sel->ismaxmizescreen && !m->sel->isfullscreen) { - root_client = m->sel; - } else if (m->prevsel && !client_is_unmanaged(m->prevsel) && - !m->prevsel->isfloating && !m->prevsel->ismaxmizescreen && - !m->prevsel->isfullscreen) { - root_client = m->prevsel; - } else { - root_client = center_select(m); - } - - if (!root_client) { - free(tempClients); // 释放内存 - return; - } - - for (i = 0; i < n; i++) { - c = tempClients[i]; - if (root_client == c) { - if (!c->is_open_animation && - c->geom.x >= m->w.x + scroller_structs && - c->geom.x + c->geom.width <= - m->w.x + m->w.width - scroller_structs) { - need_scroller = false; - } else { - need_scroller = true; - } - focus_client_index = i; - break; - } - } - - target_geom.height = m->w.height - 2 * cur_gappov; - target_geom.width = max_client_width * c->scroller_proportion; - target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; - - if (need_scroller) { - if (scroller_focus_center || - ((!m->prevsel || - (m->prevsel->scroller_proportion * max_client_width) + - (root_client->scroller_proportion * max_client_width) > - m->w.width - 2 * scroller_structs - cur_gappih) && - scroller_prefer_center)) { - target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; - } else { - target_geom.x = root_client->geom.x > m->w.x + (m->w.width) / 2 - ? m->w.x + (m->w.width - - root_client->scroller_proportion * - max_client_width - - scroller_structs) - : m->w.x + scroller_structs; - } - resize(tempClients[focus_client_index], target_geom, 0); - } else { - target_geom.x = c->geom.x; - resize(tempClients[focus_client_index], target_geom, 0); - } - - for (i = 1; i <= focus_client_index; i++) { - c = tempClients[focus_client_index - i]; - target_geom.width = max_client_width * c->scroller_proportion; - target_geom.x = tempClients[focus_client_index - i + 1]->geom.x - - cur_gappih - target_geom.width; - resize(c, target_geom, 0); - } - - for (i = 1; i < n - focus_client_index; i++) { - c = tempClients[focus_client_index + i]; - target_geom.width = max_client_width * c->scroller_proportion; - target_geom.x = tempClients[focus_client_index + i - 1]->geom.x + - cur_gappih + - tempClients[focus_client_index + i - 1]->geom.width; - resize(c, target_geom, 0); - } - - free(tempClients); // 最后释放内存 -} - -void tile(Monitor *m) { - unsigned int i, n = 0, h, r, ie = enablegaps, mw, my, ty; - Client *c; - - wl_list_for_each(c, &clients, link) if (VISIBLEON(c, m) && ISTILED(c)) n++; - if (n == 0) - return; - - unsigned int cur_gappih = enablegaps ? m->gappih : 0; - unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; - unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; - unsigned int cur_gappov = enablegaps ? m->gappov : 0; - - cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; - cur_gappiv = smartgaps && m->visible_clients == 1 ? 0 : cur_gappiv; - cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; - cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; - - if (n > selmon->pertag->nmasters[selmon->pertag->curtag]) - mw = selmon->pertag->nmasters[selmon->pertag->curtag] - ? (m->w.width + cur_gappiv * ie) * - selmon->pertag->mfacts[selmon->pertag->curtag] - : 0; - else - mw = m->w.width - 2 * cur_gappov + cur_gappiv * ie; - i = 0; - my = ty = cur_gappoh; - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || !ISTILED(c)) - continue; - if (i < selmon->pertag->nmasters[selmon->pertag->curtag]) { - r = MIN(n, selmon->pertag->nmasters[selmon->pertag->curtag]) - i; - h = (m->w.height - my - cur_gappoh - cur_gappih * ie * (r - 1)) / r; - resize(c, - (struct wlr_box){.x = m->w.x + cur_gappov, - .y = m->w.y + my, - .width = mw - cur_gappiv * ie, - .height = h}, - 0); - my += c->geom.height + cur_gappih * ie; - } else { - r = n - i; - h = (m->w.height - ty - cur_gappoh - cur_gappih * ie * (r - 1)) / r; - resize(c, - (struct wlr_box){.x = m->w.x + mw + cur_gappov, - .y = m->w.y + ty, - .width = m->w.width - mw - 2 * cur_gappov, - .height = h}, - 0); - ty += c->geom.height + cur_gappih * ie; - } - i++; - } -} - -void // 17 -monocle(Monitor *m) { - Client *c; - - wl_list_for_each(c, &clients, link) { - if (!VISIBLEON(c, m) || !ISTILED(c)) - continue; - resize(c, m->w, 0); - } - if ((c = focustop(m))) - wlr_scene_node_raise_to_top(&c->scene->node); -} \ No newline at end of file +static void tile(Monitor *m); +static void overview(Monitor *m); +static void grid(Monitor *m); +static void scroller(Monitor *m); +static void deck(Monitor *mon); +static void dwindle(Monitor *mon); +static void spiral(Monitor *mon); +static void monocle(Monitor *m); +static void vertical_tile(Monitor *m); +static void vertical_overview(Monitor *m); +static void vertical_grid(Monitor *m); +static void vertical_scroller(Monitor *m); +static void vertical_deck(Monitor *mon); +static void vertical_dwindle(Monitor *mon); +static void vertical_spiral(Monitor *mon); +static void vertical_monocle(Monitor *m); \ No newline at end of file diff --git a/src/layout/vertical.h b/src/layout/vertical.h new file mode 100644 index 0000000..e9875f1 --- /dev/null +++ b/src/layout/vertical.h @@ -0,0 +1,488 @@ +void vertical_fibonacci(Monitor *mon, int s) { + unsigned int i = 0, n = 0, nx, ny, nw, nh; + Client *c; + unsigned int cur_gappih = enablegaps ? mon->gappih : 0; + unsigned int cur_gappiv = enablegaps ? mon->gappiv : 0; + unsigned int cur_gappoh = enablegaps ? mon->gappoh : 0; + unsigned int cur_gappov = enablegaps ? mon->gappov : 0; + + cur_gappih = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappih; + cur_gappiv = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappiv; + cur_gappoh = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappoh; + cur_gappov = smartgaps && mon->visible_clients == 1 ? 0 : cur_gappov; + // Count visible clients + wl_list_for_each(c, &clients, link) if (VISIBLEON(c, mon) && ISTILED(c)) + n++; + + if (n == 0) + return; + + // Initial dimensions including outer gaps + nx = mon->w.x + cur_gappoh; + ny = mon->w.y + cur_gappov; + nw = mon->w.width - 2 * cur_gappoh; + nh = mon->w.height - 2 * cur_gappov; + + // First pass: calculate client geometries + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, mon) || !ISTILED(c)) + continue; + + c->bw = mon->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if ((i % 2 && nw / 2 > 2 * c->bw) || (!(i % 2) && nh / 2 > 2 * c->bw)) { + if (i < n - 1) { + if (i % 2) { + if (i == 1) { + nw = nw * mon->pertag->smfacts[mon->pertag->curtag]; + } else { + nw = (nw - cur_gappih) / 2; + } + } else { + nh = (nh - cur_gappiv) / 2; + } + + if ((i % 4) == 2 && !s) + ny += nh + cur_gappiv; + else if ((i % 4) == 3 && !s) + nx += nw + cur_gappih; + } + + if ((i % 4) == 0) { + if (s) + nx += nw + cur_gappih; + else + nx -= nw + cur_gappih; + } else if ((i % 4) == 1) + ny += nh + cur_gappiv; + else if ((i % 4) == 2) + nx += nw + cur_gappih; + else if ((i % 4) == 3) { + if (s) + ny += nh + cur_gappiv; + else + ny -= nh + cur_gappiv; + } + + if (i == 0) { + if (n != 1) + nh = (mon->w.height - 2 * cur_gappov) * + mon->pertag->mfacts[mon->pertag->curtag]; + nx = mon->w.x + cur_gappoh; + } else if (i == 1) { + nh = mon->w.height - 2 * cur_gappov - nh - cur_gappiv; + } else if (i == 2) { + nw = mon->w.width - 2 * cur_gappoh - nw - cur_gappih; + } + i++; + } + + c->geom = (struct wlr_box){.x = nx, .y = ny, .width = nw, .height = nh}; + } + + // Second pass: apply gaps between clients + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, mon) || !ISTILED(c)) + continue; + + unsigned int right_gap = 0; + unsigned int bottom_gap = 0; + Client *nc; + + wl_list_for_each(nc, &clients, link) { + if (!VISIBLEON(nc, mon) || !ISTILED(nc)) + continue; + + if (c == nc) + continue; + + // Check for right neighbor + if (c->geom.y == nc->geom.y && + c->geom.x + c->geom.width == nc->geom.x) { + right_gap = cur_gappih; + } + + // Check for bottom neighbor + if (c->geom.x == nc->geom.x && + c->geom.y + c->geom.height == nc->geom.y) { + bottom_gap = cur_gappiv; + } + } + + resize(c, + (struct wlr_box){.x = c->geom.x, + .y = c->geom.y, + .width = c->geom.width - right_gap, + .height = c->geom.height - bottom_gap}, + 0); + } +} + +void vertical_dwindle(Monitor *mon) { vertical_fibonacci(mon, 1); } + +void vertical_spiral(Monitor *mon) { vertical_fibonacci(mon, 0); } + +void vertical_grid(Monitor *m) { + unsigned int i, n; + unsigned int cx, cy, cw, ch; + unsigned int dy; + unsigned int rows, cols, overrows; + Client *c; + n = 0; + + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || ISTILED(c))) { + n++; + } + } + + if (n == 0) { + return; + } + + if (n == 1) { + wl_list_for_each(c, &clients, link) { + c->bw = + m->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || + ISTILED(c))) { + ch = (m->w.height - 2 * overviewgappo) * 0.7; + cw = (m->w.width - 2 * overviewgappo) * 0.8; + 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 - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + resize(c, c->geom, 0); + return; + } + } + } + + if (n == 2) { + ch = (m->w.height - 2 * overviewgappo - overviewgappi) / 2; + cw = (m->w.width - 2 * overviewgappo) * 0.65; + i = 0; + wl_list_for_each(c, &clients, link) { + c->bw = + m->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || + ISTILED(c))) { + if (i == 0) { + c->geom.x = m->w.x + (m->w.width - cw) / 2 + overviewgappo; + c->geom.y = m->w.y + overviewgappo; + c->geom.width = cw - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + resize(c, c->geom, 0); + } else if (i == 1) { + c->geom.x = m->w.x + (m->w.width - cw) / 2 + overviewgappo; + c->geom.y = m->w.y + ch + overviewgappo + overviewgappi; + c->geom.width = cw - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + resize(c, c->geom, 0); + } + i++; + } + } + return; + } + + for (rows = 0; rows <= n / 2; rows++) { + if (rows * rows >= n) { + break; + } + } + cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows; + + cw = (m->w.width - 2 * overviewgappo - (cols - 1) * overviewgappi) / cols; + ch = (m->w.height - 2 * overviewgappo - (rows - 1) * overviewgappi) / rows; + + overrows = n % rows; + if (overrows) { + dy = + (m->w.height - overrows * ch - (overrows - 1) * overviewgappi) / 2 - + overviewgappo; + } + + i = 0; + wl_list_for_each(c, &clients, link) { + c->bw = m->visible_clients == 1 && no_border_when_single && smartgaps + ? 0 + : borderpx; + if (VISIBLEON(c, m) && !c->isunglobal && + ((m->isoverview && !client_should_ignore_focus(c)) || ISTILED(c))) { + cx = m->w.x + (i / rows) * (cw + overviewgappi); + cy = m->w.y + (i % rows) * (ch + overviewgappi); + if (overrows && i >= n - overrows) { + cy += dy; + } + c->geom.x = cx + overviewgappo; + c->geom.y = cy + overviewgappo; + c->geom.width = cw - 2 * c->bw; + c->geom.height = ch - 2 * c->bw; + resize(c, c->geom, 0); + i++; + } + } +} + +void vertical_deck(Monitor *m) { + unsigned int mh, mx; + int i, n = 0; + Client *c; + unsigned int cur_gappih = enablegaps ? m->gappih : 0; + unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; + unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + unsigned int cur_gappov = enablegaps ? m->gappov : 0; + + cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; + cur_gappiv = smartgaps && m->visible_clients == 1 ? 0 : cur_gappiv; + cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; + cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; + + wl_list_for_each(c, &clients, link) if (VISIBLEON(c, m) && ISTILED(c)) n++; + if (n == 0) + return; + + float mfact = m->pertag ? m->pertag->mfacts[m->pertag->curtag] : m->mfact; + + if (n > m->nmaster) + mh = m->nmaster ? round((m->w.height - 2 * cur_gappov) * mfact) : 0; + else + mh = m->w.height - 2 * cur_gappov; + + i = mx = 0; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || !ISTILED(c)) + continue; + if (i < m->nmaster) { + resize(c, + (struct wlr_box){ + .x = m->w.x + cur_gappoh + mx, + .y = m->w.y + cur_gappov, + .width = (m->w.width - cur_gappoh - mx - cur_gappih) / + (MIN(n, m->nmaster) - i), + .height = mh}, + 0); + mx += c->geom.width + cur_gappih; + } else { + resize(c, + (struct wlr_box){.x = m->w.x + cur_gappoh, + .y = m->w.y + mh + cur_gappov + cur_gappiv, + .width = m->w.width - 2 * cur_gappoh, + .height = m->w.height - mh - + 2 * cur_gappov - cur_gappiv}, + 0); + if (c == focustop(m)) + wlr_scene_node_raise_to_top(&c->scene->node); + } + i++; + } +} + +void vertical_scroller(Monitor *m) { + unsigned int i, n; + Client *c, *root_client = NULL; + Client **tempClients = NULL; + n = 0; + struct wlr_box target_geom; + int focus_client_index = 0; + bool need_scroller = false; + unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; + unsigned int cur_gappov = enablegaps ? m->gappov : 0; + unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + + cur_gappiv = smartgaps && m->visible_clients == 1 ? 0 : cur_gappiv; + cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; + cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; + + unsigned int max_client_height = + m->w.height - 2 * scroller_structs - cur_gappiv; + + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && ISTILED(c)) { + n++; + } + } + + if (n == 0) { + return; + } + + tempClients = malloc(n * sizeof(Client *)); + if (!tempClients) { + return; + } + + n = 0; + wl_list_for_each(c, &clients, link) { + if (VISIBLEON(c, m) && ISTILED(c)) { + tempClients[n] = c; + n++; + } + } + + if (n == 1) { + c = tempClients[0]; + target_geom.width = m->w.width - 2 * cur_gappoh; + target_geom.height = + (m->w.height - 2 * cur_gappov) * scroller_default_proportion_single; + target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; + target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; + resize(c, target_geom, 0); + free(tempClients); + return; + } + + if (m->sel && !client_is_unmanaged(m->sel) && !m->sel->isfloating && + !m->sel->ismaxmizescreen && !m->sel->isfullscreen) { + root_client = m->sel; + } else if (m->prevsel && !client_is_unmanaged(m->prevsel) && + !m->prevsel->isfloating && !m->prevsel->ismaxmizescreen && + !m->prevsel->isfullscreen) { + root_client = m->prevsel; + } else { + root_client = center_select(m); + } + + if (!root_client) { + free(tempClients); + return; + } + + for (i = 0; i < n; i++) { + c = tempClients[i]; + if (root_client == c) { + if (!c->is_open_animation && + c->geom.y >= m->w.y + scroller_structs && + c->geom.y + c->geom.height <= + m->w.y + m->w.height - scroller_structs) { + need_scroller = false; + } else { + need_scroller = true; + } + focus_client_index = i; + break; + } + } + + target_geom.width = m->w.width - 2 * cur_gappoh; + target_geom.height = max_client_height * c->scroller_proportion; + target_geom.x = m->w.x + (m->w.width - target_geom.width) / 2; + + if (need_scroller) { + if (scroller_focus_center || + ((!m->prevsel || + (m->prevsel->scroller_proportion * max_client_height) + + (root_client->scroller_proportion * max_client_height) > + m->w.height - 2 * scroller_structs - cur_gappiv) && + scroller_prefer_center)) { + target_geom.y = m->w.y + (m->w.height - target_geom.height) / 2; + } else { + target_geom.y = root_client->geom.y > m->w.y + (m->w.height) / 2 + ? m->w.y + (m->w.height - + root_client->scroller_proportion * + max_client_height - + scroller_structs) + : m->w.y + scroller_structs; + } + resize(tempClients[focus_client_index], target_geom, 0); + } else { + target_geom.y = c->geom.y; + resize(tempClients[focus_client_index], target_geom, 0); + } + + for (i = 1; i <= focus_client_index; i++) { + c = tempClients[focus_client_index - i]; + target_geom.height = max_client_height * c->scroller_proportion; + target_geom.y = tempClients[focus_client_index - i + 1]->geom.y - + cur_gappiv - target_geom.height; + resize(c, target_geom, 0); + } + + for (i = 1; i < n - focus_client_index; i++) { + c = tempClients[focus_client_index + i]; + target_geom.height = max_client_height * c->scroller_proportion; + target_geom.y = tempClients[focus_client_index + i - 1]->geom.y + + cur_gappiv + + tempClients[focus_client_index + i - 1]->geom.height; + resize(c, target_geom, 0); + } + + free(tempClients); +} + +void vertical_tile(Monitor *m) { + unsigned int i, n = 0, w, r, ie = enablegaps, mh, mx, tx; + Client *c; + + wl_list_for_each(c, &clients, link) if (VISIBLEON(c, m) && ISTILED(c)) n++; + if (n == 0) + return; + + unsigned int cur_gappih = enablegaps ? m->gappih : 0; + unsigned int cur_gappiv = enablegaps ? m->gappiv : 0; + unsigned int cur_gappoh = enablegaps ? m->gappoh : 0; + unsigned int cur_gappov = enablegaps ? m->gappov : 0; + + cur_gappih = smartgaps && m->visible_clients == 1 ? 0 : cur_gappih; + cur_gappiv = smartgaps && m->visible_clients == 1 ? 0 : cur_gappiv; + cur_gappoh = smartgaps && m->visible_clients == 1 ? 0 : cur_gappoh; + cur_gappov = smartgaps && m->visible_clients == 1 ? 0 : cur_gappov; + + if (n > selmon->pertag->nmasters[selmon->pertag->curtag]) + mh = selmon->pertag->nmasters[selmon->pertag->curtag] + ? (m->w.height + cur_gappih * ie) * + selmon->pertag->mfacts[selmon->pertag->curtag] + : 0; + else + mh = m->w.height - 2 * cur_gappov + cur_gappih * ie; + i = 0; + mx = tx = cur_gappoh; + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || !ISTILED(c)) + continue; + if (i < selmon->pertag->nmasters[selmon->pertag->curtag]) { + r = MIN(n, selmon->pertag->nmasters[selmon->pertag->curtag]) - i; + w = (m->w.width - mx - cur_gappoh - cur_gappih * ie * (r - 1)) / r; + resize(c, + (struct wlr_box){.x = m->w.x + mx, + .y = m->w.y + cur_gappov, + .width = w, + .height = mh - cur_gappiv * ie}, + 0); + mx += c->geom.width + cur_gappih * ie; + } else { + r = n - i; + w = (m->w.width - tx - cur_gappoh - cur_gappih * ie * (r - 1)) / r; + resize( + c, + (struct wlr_box){.x = m->w.x + tx, + .y = m->w.y + mh + cur_gappov, + .width = w, + .height = m->w.height - mh - 2 * cur_gappov}, + 0); + tx += c->geom.width + cur_gappih * ie; + } + i++; + } +} + +void vertical_monocle(Monitor *m) { + Client *c; + + wl_list_for_each(c, &clients, link) { + if (!VISIBLEON(c, m) || !ISTILED(c)) + continue; + resize(c, m->w, 0); + } + if ((c = focustop(m))) + wlr_scene_node_raise_to_top(&c->scene->node); +} \ No newline at end of file diff --git a/src/maomao.c b/src/maomao.c index 9dac2f9..b9a1b08 100644 --- a/src/maomao.c +++ b/src/maomao.c @@ -526,7 +526,6 @@ static void locksession(struct wl_listener *listener, void *data); static void mapnotify(struct wl_listener *listener, void *data); static void maximizenotify(struct wl_listener *listener, void *data); static void minimizenotify(struct wl_listener *listener, void *data); -static void monocle(Monitor *m); static void motionabsolute(struct wl_listener *listener, void *data); static void motionnotify(unsigned int time, struct wlr_input_device *device, double sx, double sy, double sx_unaccel, @@ -565,13 +564,6 @@ static void setsel(struct wl_listener *listener, void *data); static void setup(void); static void startdrag(struct wl_listener *listener, void *data); -static void tile(Monitor *m); -static void overview(Monitor *m); -static void grid(Monitor *m); -static void scroller(Monitor *m); -static void deck(Monitor *mon); -static void dwindle(Monitor *mon); -static void spiral(Monitor *mon); static void unlocksession(struct wl_listener *listener, void *data); static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void unmapnotify(struct wl_listener *listener, void *data); @@ -635,6 +627,7 @@ static void pending_kill_client(Client *c); #include "data/static_keymap.h" #include "dispatch/dispatch.h" +#include "layout/layout.h" /* variables */ static const char broken[] = "broken"; @@ -779,7 +772,8 @@ static struct wlr_xwayland *xwayland; #include "client/client.h" #include "config/parse_config.h" #include "ext-protocol/all.h" -#include "layout/layout.h" +#include "layout/horizontal.h" +#include "layout/vertical.h" struct dvec2 calculate_animation_curve_at(double t, int type) { struct dvec2 point; @@ -2023,6 +2017,15 @@ applyrules(Client *c) { setborder_color(c); } +bool is_scroller_layout(Monitor *m) { + if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, "scroller") == 0) + return true; + if (strcmp(m->pertag->ltidxs[m->pertag->curtag]->name, + "vertical_scroller") == 0) + return true; + return false; +} + void // 17 arrange(Monitor *m, bool want_animation) { Client *c; @@ -2052,8 +2055,7 @@ arrange(Monitor *m, bool want_animation) { } if (!c->is_clip_to_hide || !ISTILED(c) || - strcmp(c->mon->pertag->ltidxs[c->mon->pertag->curtag]->name, - "scroller") != 0) { + !is_scroller_layout(c->mon)) { c->is_clip_to_hide = false; wlr_scene_node_set_enabled(&c->scene->node, true); } @@ -3872,9 +3874,7 @@ void focusclient(Client *c, int lift) { if (c && selmon->prevsel && !selmon->prevsel->isfloating && (selmon->prevsel->tags & selmon->tagset[selmon->seltags]) && (c->tags & selmon->tagset[selmon->seltags]) && !c->isfloating && - !c->isfullscreen && - strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name, - "scroller") == 0) { + !c->isfullscreen && is_scroller_layout(selmon)) { arrange(selmon, false); } else if (selmon->prevsel) { selmon->prevsel = NULL; @@ -4632,15 +4632,10 @@ mapnotify(struct wl_listener *listener, void *data) { c->nofadeout = 0; c->no_force_center = 0; - if (new_is_master && selmon && - strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name, - "scroller") != 0) + if (new_is_master && selmon && !is_scroller_layout(selmon)) // tile at the top wl_list_insert(&clients, &c->link); // 新窗口是master,头部入栈 - else if (selmon && - strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name, - "scroller") == 0 && - center_select(selmon)) { + else if (selmon && is_scroller_layout(selmon) && center_select(selmon)) { Client *at_client = center_select(selmon); at_client->link.next->prev = &c->link; c->link.prev = &at_client->link; @@ -4857,9 +4852,7 @@ void motionnotify(unsigned int time, struct wlr_input_device *device, double dx, !(c && c->mon && (c->geom.x + c->geom.width > c->mon->m.x + c->mon->m.width || c->geom.x < c->mon->m.x))) { - if (c && c->mon && - strcmp(c->mon->pertag->ltidxs[c->mon->pertag->curtag]->name, - "scroller") == 0 && + if (c && c->mon && is_scroller_layout(c->mon) && (c->geom.x + c->geom.width > c->mon->m.x + c->mon->m.width || c->geom.x < c->mon->m.x)) { should_lock = true; @@ -5300,9 +5293,7 @@ int is_special_animaiton_rule(Client *c) { } } - if (strcmp(selmon->pertag->ltidxs[selmon->pertag->curtag]->name, - "scroller") == 0 && - !c->isfloating) { + if (is_scroller_layout(selmon) && !c->isfloating) { return DOWN; } else if (visible_client_number < 2 && !c->isfloating) { return DOWN; @@ -5401,9 +5392,7 @@ void resize(Client *c, struct wlr_box geo, int interact) { // oldgeom = c->geom; bbox = (interact || c->isfloating || c->isfullscreen) ? &sgeom : &c->mon->w; - if (strcmp(c->mon->pertag->ltidxs[c->mon->pertag->curtag]->name, - "scroller") == 0 && - (!c->isfloating || c == grabc)) { + if (is_scroller_layout(c->mon) && (!c->isfloating || c == grabc)) { c->geom = geo; c->geom.width = MAX(1 + 2 * (int)c->bw, c->geom.width); c->geom.height = MAX(1 + 2 * (int)c->bw, c->geom.height);