aboutsummaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorDavid Heinemeier Hansson <david@hey.com>2026-08-09 00:37:57 +0200
committerGitHub <noreply@github.com>2026-08-09 01:37:57 +0300
commit36a8d36a7258e08b40c01bf521b1f4006525f143 (patch)
treeedaf35204db558c4d6b5a79ab78b6d6e5138c9dc /src/ui
parent3a76fea2d858a7a5ef58615f1cc9aabaa30b80ee (diff)
feat: make outer pane borders configurable (#2535)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/panes.rs70
1 files changed, 66 insertions, 4 deletions
diff --git a/src/ui/panes.rs b/src/ui/panes.rs
index b904ce00..22daddf8 100644
--- a/src/ui/panes.rs
+++ b/src/ui/panes.rs
@@ -91,8 +91,21 @@ pub(crate) fn apply_pane_chrome(
panes: Vec<PaneInfo>,
pane_borders: bool,
pane_gaps: bool,
+ pane_outer_borders: bool,
) -> Vec<PaneInfo> {
let multi_pane = panes.len() > 1;
+ let outer_left = panes.iter().map(|info| info.rect.x).min().unwrap_or(0);
+ let outer_top = panes.iter().map(|info| info.rect.y).min().unwrap_or(0);
+ let outer_right = panes
+ .iter()
+ .map(|info| info.rect.x.saturating_add(info.rect.width))
+ .max()
+ .unwrap_or(0);
+ let outer_bottom = panes
+ .iter()
+ .map(|info| info.rect.y.saturating_add(info.rect.height))
+ .max()
+ .unwrap_or(0);
panes
.iter()
.cloned()
@@ -121,6 +134,20 @@ pub(crate) fn apply_pane_chrome(
borders.remove(Borders::BOTTOM);
}
}
+ if !pane_outer_borders {
+ if info.rect.x == outer_left {
+ borders.remove(Borders::LEFT);
+ }
+ if info.rect.y == outer_top {
+ borders.remove(Borders::TOP);
+ }
+ if info.rect.x.saturating_add(info.rect.width) == outer_right {
+ borders.remove(Borders::RIGHT);
+ }
+ if info.rect.y.saturating_add(info.rect.height) == outer_bottom {
+ borders.remove(Borders::BOTTOM);
+ }
+ }
borders
};
info
@@ -179,7 +206,7 @@ pub(super) fn resize_tab_panes(
if tab.zoomed {
let focused_id = tab.layout.focused();
if let Some((terminal_id, rt)) = runtime_for_tab_pane(terminal_runtimes, tab, focused_id) {
- let borders = if multi_pane && app.pane_borders {
+ let borders = if multi_pane && app.pane_borders && app.pane_outer_borders {
Borders::ALL
} else {
Borders::NONE
@@ -198,7 +225,12 @@ pub(super) fn resize_tab_panes(
return;
}
- for info in apply_pane_chrome(tab.layout.panes(area), app.pane_borders, app.pane_gaps) {
+ for info in apply_pane_chrome(
+ tab.layout.panes(area),
+ app.pane_borders,
+ app.pane_gaps,
+ app.pane_outer_borders,
+ ) {
let pane_inner = pane_inner_rect(info.rect, info.borders);
if let Some((terminal_id, rt)) = runtime_for_tab_pane(terminal_runtimes, tab, info.id) {
@@ -234,7 +266,7 @@ pub(super) fn compute_pane_infos(
if ws.zoomed {
let focused_id = ws.layout.focused();
- let borders = if multi_pane && app.pane_borders {
+ let borders = if multi_pane && app.pane_borders && app.pane_outer_borders {
Borders::ALL
} else {
Borders::NONE
@@ -268,7 +300,12 @@ pub(super) fn compute_pane_infos(
}];
}
- let mut pane_infos = apply_pane_chrome(ws.layout.panes(area), app.pane_borders, app.pane_gaps);
+ let mut pane_infos = apply_pane_chrome(
+ ws.layout.panes(area),
+ app.pane_borders,
+ app.pane_gaps,
+ app.pane_outer_borders,
+ );
for info in &mut pane_infos {
let pane_inner = pane_inner_rect(info.rect, info.borders);
@@ -1054,6 +1091,7 @@ mod tests {
workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)),
true,
false,
+ true,
);
let left = infos.iter().find(|info| info.id == root).unwrap();
let right = infos.iter().find(|info| info.id == right).unwrap();
@@ -1074,6 +1112,7 @@ mod tests {
workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)),
true,
false,
+ true,
);
let top = infos.iter().find(|info| info.id == root).unwrap();
let bottom = infos.iter().find(|info| info.id == bottom).unwrap();
@@ -1084,6 +1123,26 @@ mod tests {
}
#[test]
+ fn disabled_outer_borders_keep_only_shared_pane_dividers() {
+ let mut workspace = Workspace::test_new("test");
+ let root = workspace.tabs[0].root_pane;
+ let right = workspace.test_split(ratatui::layout::Direction::Horizontal);
+ workspace.tabs[0].layout.focus_pane(root);
+
+ let infos = apply_pane_chrome(
+ workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)),
+ true,
+ false,
+ false,
+ );
+ let left = infos.iter().find(|info| info.id == root).unwrap();
+ let right = infos.iter().find(|info| info.id == right).unwrap();
+
+ assert_eq!(left.borders, Borders::NONE);
+ assert_eq!(right.borders, Borders::LEFT);
+ }
+
+ #[test]
fn pane_gaps_keep_independent_bordered_panes() {
let mut workspace = Workspace::test_new("test");
let root = workspace.tabs[0].root_pane;
@@ -1094,6 +1153,7 @@ mod tests {
workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)),
true,
true,
+ true,
);
let left = infos.iter().find(|info| info.id == root).unwrap();
let right = infos.iter().find(|info| info.id == right).unwrap();
@@ -1114,6 +1174,7 @@ mod tests {
workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)),
false,
true,
+ true,
);
let left = infos.iter().find(|info| info.id == root).unwrap();
let right = infos.iter().find(|info| info.id == right).unwrap();
@@ -1133,6 +1194,7 @@ mod tests {
workspace.tabs[0].layout.panes(Rect::new(0, 0, 100, 20)),
false,
false,
+ true,
);
for info in infos {