summaryrefslogtreecommitdiffstats
path: root/zellij-server/src/panes
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2023-02-17 12:05:50 +0100
committerGitHub <noreply@github.com>2023-02-17 12:05:50 +0100
commitf1ff272b0b65f6d328fef24531ada67ea585ce85 (patch)
tree0e33aa4a1af21c0785fa30118ee42a21972497cf /zellij-server/src/panes
parent1517036c2489b2a7dc43230e2ba8a05841a69dbe (diff)
feat(ui): swap layouts and stacked panes (#2167)
* relayout working with hard coded layout * work * refactor(layout): PaneLayout => TiledPaneLayout * tests passing * tests passing * tests passing * stacked panes and passing tests * tests for stacked panes * refactor(panes): stacked panes * fix: focusing into stacked panes from the left/right * fix(layouts): handle stacked layouts in the middle of the screen * fix(pane-stack): focus correctly when coming to stack from above/below * fix(stacked-panes): resize stack * fix(stacked-panes): focus with mouse * fix(stacked-panes): focus next pane * fix(layout-applier): sane focus order * fix(stacked-panes): better titles for one-liners * fix(stacked-panes): handle moving pane location in stack * fix(relayout): properly calculate display area * fix(relayout): properly calculate rounding errors * fix(stacked-panes): properly handle closing a pane near a stack * fix(swap-layouts): adjust swap layout sort order * feat(swap-layouts): ui + ux * fix(swap-layouts): include base layout * refactor(layout): remove unused method * fix(swap-layouts): respect pane contents and focus * work * fix(swap-layouts): load swap layouts from external file * fix(swap-layouts): properly truncate layout children * fix(stacked-panes): allow stacked panes to become fullscreen * fix(swap-layouts): work with multiple tabs * fix(swap-layouts): embed/eject panes properly with auto-layout * fix(stacked-panes): close last pane in stack * fix(stacked-panes): move focus for all clients in stack * fix(floating-panes): set layout damaged when moving panes * fix(relayout): move out of unfitting layout when resizing whole tab * fix(ui): background color for swap layout indicator * fix(keybinds): add switch next layout in tmux * fix(ui): swap layout indication in compact layout * fix(compact): correct swap constraint * fix(tests): tmux swap config shortcut * fix(resizes): cache resizes so as not to confuse panes (eg. vim) with multiple resizes that it debounces weirdly * feat(cli): dump swap layouts * fix(ui): stacked panes without pane frames * fix(ux): move pane forward/backwards also with floating panes * refactor(lint): remove unused stuff * refactor(tab): move swap layouts to separate file * style(fmt): rustfmt * style(fmt): rustfmt * refactor(panes): various cleanups * chore(deps): upgrade termwiz to get alt left-bracket * fix(assets): merge conflicts of binary files * style(fmt): rustfmt * style(clippy): no thank you! * chore(repo): remove garbage file
Diffstat (limited to 'zellij-server/src/panes')
-rw-r--r--zellij-server/src/panes/active_panes.rs1
-rw-r--r--zellij-server/src/panes/floating_panes/floating_pane_grid.rs55
-rw-r--r--zellij-server/src/panes/floating_panes/mod.rs126
-rw-r--r--zellij-server/src/panes/plugin_pane.rs24
-rw-r--r--zellij-server/src/panes/terminal_pane.rs32
-rw-r--r--zellij-server/src/panes/tiled_panes/mod.rs364
-rw-r--r--zellij-server/src/panes/tiled_panes/pane_resizer.rs137
-rw-r--r--zellij-server/src/panes/tiled_panes/stacked_panes.rs630
-rw-r--r--zellij-server/src/panes/tiled_panes/tiled_pane_grid.rs445
-rw-r--r--zellij-server/src/panes/unit/search_in_pane_tests.rs1
-rw-r--r--zellij-server/src/panes/unit/terminal_pane_tests.rs12
11 files changed, 1584 insertions, 243 deletions
diff --git a/zellij-server/src/panes/active_panes.rs b/zellij-server/src/panes/active_panes.rs
index 3fce0a9ff..c726bafe1 100644
--- a/zellij-server/src/panes/active_panes.rs
+++ b/zellij-server/src/panes/active_panes.rs
@@ -3,6 +3,7 @@ use crate::tab::Pane;
use crate::{os_input_output::ServerOsApi, panes::PaneId, ClientId};
use std::collections::{BTreeMap, HashMap};
+#[derive(Clone)]
pub struct ActivePanes {
active_panes: HashMap<ClientId, PaneId>,
os_api: Box<dyn ServerOsApi>,
diff --git a/zellij-server/src/panes/floating_panes/floating_pane_grid.rs b/zellij-server/src/panes/floating_panes/floating_pane_grid.rs
index 2245ee16a..afeecc8d2 100644
--- a/zellij-server/src/panes/floating_panes/floating_pane_grid.rs
+++ b/zellij-server/src/panes/floating_panes/floating_pane_grid.rs
@@ -703,6 +703,56 @@ impl<'a> FloatingPaneGrid<'a> {
.copied();
next_index
}
+ pub fn next_selectable_pane_id(&self, current_pane_id: &PaneId) -> Option<PaneId> {
+ let panes = self.panes.borrow();
+ let mut panes: Vec<(PaneId, &&mut Box<dyn Pane>)> = panes
+ .iter()
+ .filter(|(_, p)| p.selectable())
+ .map(|(p_id, p)| (*p_id, p))
+ .collect();
+ panes.sort_by(|(_a_id, a_pane), (_b_id, b_pane)| {
+ if a_pane.y() == b_pane.y() {
+ a_pane.x().cmp(&b_pane.x())
+ } else {
+ a_pane.y().cmp(&b_pane.y())
+ }
+ });
+ let active_pane_position = panes
+ .iter()
+ .position(|(id, _)| id == current_pane_id)
+ .unwrap();
+
+ let next_active_pane_id = panes
+ .get(active_pane_position + 1)
+ .or_else(|| panes.get(0))
+ .map(|p| p.0)
+ .unwrap();
+ Some(next_active_pane_id)
+ }
+ pub fn previous_selectable_pane_id(&self, current_pane_id: &PaneId) -> Option<PaneId> {
+ let panes = self.panes.borrow();
+ let mut panes: Vec<(PaneId, &&mut Box<dyn Pane>)> = panes
+ .iter()
+ .filter(|(_, p)| p.selectable())
+ .map(|(p_id, p)| (*p_id, p))
+ .collect();
+ panes.sort_by(|(_a_id, a_pane), (_b_id, b_pane)| {
+ if a_pane.y() == b_pane.y() {
+ a_pane.x().cmp(&b_pane.x())
+ } else {
+ a_pane.y().cmp(&b_pane.y())
+ }
+ });
+ let active_pane_position = panes.iter().position(|(id, _)| id == current_pane_id)?;
+
+ let last_pane = panes.last()?;
+ let previous_active_pane_id = if active_pane_position == 0 {
+ last_pane.0
+ } else {
+ panes.get(active_pane_position - 1)?.0
+ };
+ Some(previous_active_pane_id)
+ }
pub fn find_room_for_new_pane(&self) -> Option<PaneGeom> {
let panes = self.panes.borrow();
let pane_geoms: Vec<PaneGeom> = panes.values().map(|p| p.position_and_size()).collect();
@@ -766,6 +816,7 @@ fn half_size_middle_geom(space: &Viewport, offset: usize) -> PaneGeom {
y: space.y + (space.rows as f64 / 4.0).round() as usize + offset,
cols: Dimension::fixed(space.cols / 2),
rows: Dimension::fixed(space.rows / 2),
+ is_stacked: false,
};
geom.cols.set_inner(space.cols / 2);
geom.rows.set_inner(space.rows / 2);
@@ -778,6 +829,7 @@ fn half_size_top_left_geom(space: &Viewport, offset: usize) -> PaneGeom {
y: space.y + 2 + offset,
cols: Dimension::fixed(space.cols / 3),
rows: Dimension::fixed(space.rows / 3),
+ is_stacked: false,
};
geom.cols.set_inner(space.cols / 3);
geom.rows.set_inner(space.rows / 3);
@@ -790,6 +842,7 @@ fn half_size_top_right_geom(space: &Viewport, offset: usize) -> PaneGeom {
y: space.y + 2 + offset,
cols: Dimension::fixed(space.cols / 3),
rows: Dimension::fixed(space.rows / 3),
+ is_stacked: false,
};
geom.cols.set_inner(space.cols / 3);
geom.rows.set_inner(space.rows / 3);
@@ -802,6 +855,7 @@ fn half_size_bottom_left_geom(space: &Viewport, offset: usize) -> PaneGeom {
y: ((space.y + space.rows) - (space.rows / 3) - 2).saturating_sub(offset),
cols: Dimension::fixed(space.cols / 3),
rows: Dimension::fixed(space.rows / 3),
+ is_stacked: false,
};
geom.cols.set_inner(space.cols / 3);
geom.rows.set_inner(space.rows / 3);
@@ -814,6 +868,7 @@ fn half_size_bottom_right_geom(space: &Viewport, offset: usize) -> PaneGeom {
y: ((space.y + space.rows) - (space.rows / 3) - 2).saturating_sub(offset),
cols: Dimension::fixed(space.cols / 3),
rows: Dimension::fixed(space.rows / 3),
+ is_stacked: false,
};
geom.cols.set_inner(space.cols / 3);
geom.rows.set_inner(space.rows / 3);
diff --git a/zellij-server/src/panes/floating_panes/mod.rs b/zellij-server/src/panes/floating_panes/mod.rs
index 47b3e2f25..399d16c98 100644
--- a/zellij-server/src/panes/floating_panes/mod.rs
+++ b/zellij-server/src/panes/floating_panes/mod.rs
@@ -25,7 +25,7 @@ use zellij_utils::{
data::{ModeInfo, Style},
errors::prelude::*,
input::command::RunCommand,
- input::layout::FloatingPanesLayout,
+ input::layout::FloatingPaneLayout,
pane_size::{Dimension, Offset, PaneGeom, Size, Viewport},
};
@@ -200,6 +200,14 @@ impl FloatingPanes {
pub fn active_pane_id(&self, client_id: ClientId) -> Option<PaneId> {
self.active_panes.get(&client_id).copied()
}
+ pub fn active_pane_id_or_focused_pane_id(&self, client_id: Option<ClientId>) -> Option<PaneId> {
+ // returns the focused pane of any client_id - should be safe because the way things are
+ // set up at the time of writing, all clients are focused on the same floating pane due to
+ // z_index issues
+ client_id
+ .and_then(|client_id| self.active_panes.get(&client_id).copied())
+ .or_else(|| self.panes.keys().next().copied())
+ }
pub fn toggle_show_panes(&mut self, should_show_floating_panes: bool) {
self.show_panes = should_show_floating_panes;
if should_show_floating_panes {
@@ -227,7 +235,7 @@ impl FloatingPanes {
}
pub fn position_floating_pane_layout(
&mut self,
- floating_pane_layout: &FloatingPanesLayout,
+ floating_pane_layout: &FloatingPaneLayout,
) -> PaneGeom {
let display_area = *self.display_area.borrow();
let viewport = *self.viewport.borrow();
@@ -239,32 +247,32 @@ impl FloatingPanes {
);
let mut position = floating_pane_grid.find_room_for_new_pane().unwrap(); // TODO: no unwrap
if let Some(x) = &floating_pane_layout.x {
- position.x = x.to_position(display_area.cols);
+ position.x = x.to_position(viewport.cols);
}
if let Some(y) = &floating_pane_layout.y {
- position.y = y.to_position(display_area.rows);
+ position.y = y.to_position(viewport.rows);
}
if let Some(width) = &floating_pane_layout.width {
- position.cols = Dimension::fixed(width.to_position(display_area.cols));
+ position.cols = Dimension::fixed(width.to_position(viewport.cols));
}
if let Some(height) = &floating_pane_layout.height {
- position.rows = Dimension::fixed(height.to_position(display_area.rows));
+ position.rows = Dimension::fixed(height.to_position(viewport.rows));
}
- if position.cols.as_usize() > display_area.cols {
- position.cols = Dimension::fixed(display_area.cols);
+ if position.cols.as_usize() > viewport.cols {
+ position.cols = Dimension::fixed(viewport.cols);
}
- if position.rows.as_usize() > display_area.rows {
- position.rows = Dimension::fixed(display_area.rows);
+ if position.rows.as_usize() > viewport.rows {
+ position.rows = Dimension::fixed(viewport.rows);
}
- if position.x + position.cols.as_usize() > display_area.cols {
+ if position.x + position.cols.as_usize() > viewport.cols {
position.x = position
.x
- .saturating_sub((position.x + position.cols.as_usize()) - display_area.cols);
+ .saturating_sub((position.x + position.cols.as_usize()) - viewport.cols);
}
- if position.y + position.rows.as_usize() > display_area.rows {
+ if position.y + position.rows.as_usize() > viewport.rows {
position.y = position
.y
- .saturating_sub((position.y + position.rows.as_usize()) - display_area.rows);
+ .saturating_sub((position.y + position.rows.as_usize()) - viewport.rows);
}
position
}
@@ -333,6 +341,9 @@ impl FloatingPanes {
&active_panes,
multiple_users_exist_in_session,
Some(z_index + 1), // +1 because 0 is reserved for non-floating panes
+ false,
+ false,
+ true,
);
for client_id in &connected_clients {
let client_mode = self
@@ -570,6 +581,50 @@ impl FloatingPanes {
self.set_force_render();
}
}
+ pub fn move_active_pane(
+ &mut self,
+ search_backwards: bool,
+ os_api: &mut Box<dyn ServerOsApi>,
+ client_id: ClientId,
+ ) {
+ let active_pane_id = self.get_active_pane_id(client_id).unwrap();
+
+ let new_position_id = {
+ let pane_grid = FloatingPaneGrid::new(
+ &mut self.panes,
+ &mut self.desired_pane_positions,
+ *self.display_area.borrow(),
+ *self.viewport.borrow(),
+ );
+ if search_backwards {
+ pane_grid.previous_selectable_pane_id(&active_pane_id)
+ } else {
+ pane_grid.next_selectable_pane_id(&active_pane_id)
+ }
+ };
+ if let Some(new_position_id) = new_position_id {
+ let current_position = self.panes.get(&active_pane_id).unwrap();
+ let prev_geom = current_position.position_and_size();
+ let prev_geom_override = current_position.geom_override();
+
+ let new_position = self.panes.get_mut(&new_position_id).unwrap();
+ let next_geom = new_position.position_and_size();
+ let next_geom_override = new_position.geom_override();
+ new_position.set_geom(prev_geom);
+ if let Some(geom) = prev_geom_override {
+ new_position.set_geom_override(geom);
+ }
+ new_position.set_should_render(true);
+
+ let current_position = self.panes.get_mut(&active_pane_id).unwrap();
+ current_position.set_geom(next_geom);
+ if let Some(geom) = next_geom_override {
+ current_position.set_geom_override(geom);
+ }
+ current_position.set_should_render(true);
+ let _ = self.set_pane_frames(os_api);
+ }
+ }
pub fn move_clients_out_of_pane(&mut self, pane_id: PaneId) {
let active_panes: Vec<(ClientId, PaneId)> = self
.active_panes
@@ -735,6 +790,17 @@ impl FloatingPanes {
pub fn get_panes(&self) -> impl Iterator<Item = (&PaneId, &Box<dyn Pane>)> {
self.panes.iter()
}
+ pub fn visible_panes_count(&self) -> usize {
+ self.panes.len()
+ }
+ pub fn drain(&mut self) -> BTreeMap<PaneId, Box<dyn Pane>> {
+ self.z_indices.clear();
+ self.desired_pane_positions.clear();
+ match self.panes.iter().next().map(|(pid, _p)| *pid) {
+ Some(first_pid) => self.panes.split_off(&first_pid),
+ None => BTreeMap::new(),
+ }
+ }
fn move_clients_between_panes(&mut self, from_pane_id: PaneId, to_pane_id: PaneId) {
let clients_in_pane: Vec<ClientId> = self
.active_panes
@@ -748,4 +814,36 @@ impl FloatingPanes {
.insert(client_id, to_pane_id, &mut self.panes);
}
}
+ pub fn reapply_pane_focus(&mut self) {
+ if let Some(focused_pane) = self.first_active_floating_pane_id() {
+ // floating pane focus is the same for all clients
+ self.focus_pane_for_all_clients(focused_pane);
+ }
+ }
+ pub fn switch_active_pane_with(&mut self, os_api: &mut Box<dyn ServerOsApi>, pane_id: PaneId) {
+ if let Some(active_pane_id) = self.first_active_floating_pane_id() {
+ let current_position = self.panes.get(&active_pane_id).unwrap();
+ let prev_geom = current_position.position_and_size();
+ let prev_geom_override = current_position.geom_override();
+
+ let new_position = self.panes.get_mut(&pane_id).unwrap();
+ let next_geom = new_position.position_and_size();
+ let next_geom_override = new_position.geom_override();
+ new_position.set_geom(prev_geom);
+ if let Some(geom) = prev_geom_override {
+ new_position.set_geom_override(geom);
+ }
+ resize_pty!(new_position, os_api, self.senders).unwrap();
+ new_position.set_should_render(true);
+
+ let current_position = self.panes.get_mut(&active_pane_id).unwrap();
+ current_position.set_geom(next_geom);
+ if let Some(geom) = next_geom_override {
+ current_position.set_geom_override(geom);
+ }
+ resize_pty!(current_position, os_api, self.senders).unwrap();
+ current_position.set_should_render(true);
+ self.focus_pane_for_all_clients(active_pane_id);
+ }
+ }
}
diff --git a/zellij-server/src/panes/plugin_pane.rs b/zellij-server/src/panes/plugin_pane.rs
index babb66b67..c6896f90d 100644
--- a/zellij-server/src/panes/plugin_pane.rs
+++ b/zellij-server/src/panes/plugin_pane.rs
@@ -16,6 +16,7 @@ use zellij_utils::{
channels::SenderWithContext,
data::{Event, InputMode, Mouse, Palette, PaletteColor, Style},
errors::prelude::*,
+ input::layout::Run,
pane_size::PaneGeom,
shared::make_terminal_title,
vte,
@@ -65,6 +66,7 @@ pub(crate) struct PluginPane {
frame: HashMap<ClientId, PaneFrame>,
borderless: bool,
pane_frame_color_override: Option<(PaletteColor, Option<String>)>,
+ invoked_with: Option<Run>,
}
impl PluginPane {
@@ -80,6 +82,7 @@ impl PluginPane {
link_handler: Rc<RefCell<LinkHandler>>,
character_cell_size: Rc<RefCell<Option<SizeInPixels>>>,
style: Style,
+ invoked_with: Option<Run>,
) -> Self {
Self {
pid,
@@ -104,6 +107,7 @@ impl PluginPane {
grids: HashMap::new(),
style,
pane_frame_color_override: None,
+ invoked_with,
}
}
}
@@ -222,6 +226,11 @@ impl Pane for PluginPane {
if self.should_render.get(&client_id).copied().unwrap_or(false) {
let content_x = self.get_content_x();
let content_y = self.get_content_y();
+ let rows = self.get_content_rows();
+ let columns = self.get_content_columns();
+ if rows < 1 || columns < 1 {
+ return Ok(None);
+ }
if let Some(grid) = self.grids.get_mut(&client_id) {
match grid.render(content_x, content_y, &self.style) {
Ok(rendered_assets) => {
@@ -265,8 +274,15 @@ impl Pane for PluginPane {
self.pane_name.clone()
};
+ let mut frame_geom = self.current_geom();
+ if !frame_params.should_draw_pane_frames {
+ // in this case the width of the frame needs not include the pane corners
+ frame_geom
+ .cols
+ .set_inner(frame_geom.cols.as_usize().saturating_sub(1));
+ }
let mut frame = PaneFrame::new(
- self.current_geom().into(),
+ frame_geom.into(),
grid.scrollback_position_and_length(),
pane_title,
frame_params,
@@ -491,6 +507,12 @@ impl Pane for PluginPane {
.as_ref()
.map(|(color, _text)| *color)
}
+ fn invoked_with(&self) -> &Option<Run> {
+ &self.invoked_with
+ }
+ fn set_title(&mut self, title: String) {
+ self.pane_title = title;
+ }
}
impl PluginPane {
diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs
index d206245ad..e9fffb186 100644
--- a/zellij-server/src/panes/terminal_pane.rs
+++ b/zellij-server/src/panes/terminal_pane.rs
@@ -18,6 +18,7 @@ use zellij_utils::pane_size::Offset;
use zellij_utils::{
data::{InputMode, Palette, PaletteColor, Style},
errors::prelude::*,
+ input::layout::Run,
pane_size::PaneGeom,
pane_size::SizeInPixels,
position::Position,
@@ -111,6 +112,7 @@ pub struct TerminalPane {
banner: Option<String>, // a banner to be rendered inside this TerminalPane, used for panes
// held on startup and can possibly be used to display some errors
pane_frame_color_override: Option<(PaletteColor, Option<String>)>,
+ invoked_with: Option<Run>,
}
impl Pane for TerminalPane {
@@ -165,6 +167,10 @@ impl Pane for TerminalPane {
}
fn cursor_coordinates(&self) -> Option<(usize, usize)> {
// (x, y)
+ if self.get_content_rows() < 1 || self.get_content_columns() < 1 {
+ // do not render cursor if there's no room for it
+ return None;
+ }
let Offset { top, left, .. } = self.content_offset;
self.grid
.cursor_coordinates()
@@ -283,6 +289,11 @@ impl Pane for TerminalPane {
if self.should_render() {
let content_x = self.get_content_x();
let content_y = self.get_content_y();
+ let rows = self.get_content_rows();
+ let columns = self.get_content_columns();
+ if rows < 1 || columns < 1 {
+ return Ok(None);
+ }
match self.grid.render(content_x, content_y, &self.style) {
Ok(rendered_assets) => {
self.set_should_render(false);
@@ -347,8 +358,15 @@ impl Pane for TerminalPane {
self.pane_name.clone()
};
+ let mut frame_geom = self.current_geom();
+ if !frame_params.should_draw_pane_frames {
+ // in this case the width of the frame needs not include the pane corners
+ frame_geom
+ .cols
+ .set_inner(frame_geom.cols.as_usize().saturating_sub(1));
+ }
let mut frame = PaneFrame::new(
- self.current_geom().into(),
+ frame_geom.into(),
self.grid.scrollback_position_and_length(),
pane_title,
frame_params,
@@ -690,6 +708,12 @@ impl Pane for TerminalPane {
.as_ref()
.map(|(color, _text)| *color)
}
+ fn invoked_with(&self) -> &Option<Run> {
+ &self.invoked_with
+ }
+ fn set_title(&mut self, title: String) {
+ self.pane_title = title;
+ }
}
impl TerminalPane {
@@ -706,6 +730,7 @@ impl TerminalPane {
terminal_emulator_colors: Rc<RefCell<Palette>>,
terminal_emulator_color_codes: Rc<RefCell<HashMap<usize, String>>>,
initial_pane_title: Option<String>,
+ invoked_with: Option<Run>,
) -> TerminalPane {
let initial_pane_title =
initial_pane_title.unwrap_or_else(|| format!("Pane #{}", pane_index));
@@ -739,6 +764,7 @@ impl TerminalPane {
is_held: None,
banner: None,
pane_frame_color_override: None,
+ invoked_with,
}
}
pub fn get_x(&self) -> usize {
@@ -780,6 +806,10 @@ impl TerminalPane {
}
pub fn cursor_coordinates(&self) -> Option<(usize, usize)> {
// (x, y)
+ if self.get_content_rows() < 1 || self.get_content_columns() < 1 {
+ // do not render cursor if there's no room for it
+ return None;
+ }
self.grid.cursor_coordinates()
}
fn render_first_run_banner(&mut self) {
diff --git a/zellij-server/src/panes/tiled_panes/mod.rs b/zellij-server/src/panes/tiled_panes/mod.rs
index cad53e3f1..bd6470c90 100644
--- a/zellij-server/src/panes/tiled_panes/mod.rs
+++ b/zellij-server/src/panes/tiled_panes/mod.rs
@@ -1,4 +1,5 @@
mod pane_resizer;
+mod stacked_panes;
mod tiled_pane_grid;
use crate::resize_pty;
@@ -15,6 +16,7 @@ use crate::{
ui::pane_contents_and_ui::PaneContentsAndUi,
ClientId,
};
+use stacked_panes::StackedPanes;
use zellij_utils::{
data::{ModeInfo, ResizeStrategy, Style},
errors::prelude::*,
@@ -249,6 +251,10 @@ impl TiledPanes {
self.set_pane_frames(self.draw_pane_frames);
}
+ pub fn reapply_pane_frames(&mut self) {
+ // same as set_pane_frames except it reapplies the current situation
+ self.set_pane_frames(self.draw_pane_frames);
+ }
pub fn set_pane_frames(&mut self, draw_pane_frames: bool) {
self.draw_pane_frames = draw_pane_frames;
let viewport = *self.viewport.borrow();
@@ -276,7 +282,12 @@ impl TiledPanes {
let position_and_size = pane.current_geom();
let (pane_columns_offset, pane_rows_offset) =
pane_content_offset(&position_and_size, &viewport);
- pane.set_content_offset(Offset::shift(pane_rows_offset, pane_columns_offset));
+ if !draw_pane_frames && pane.current_geom().is_stacked {
+ // stacked panes should always leave 1 top row for a title
+ pane.set_content_offset(Offset::shift_right_and_top(pane_columns_offset, 1));
+ } else {
+ pane.set_content_offset(Offset::shift(pane_rows_offset, pane_columns_offset));
+ }
}
resize_pty!(pane, self.os_api, self.senders).unwrap();
@@ -287,