Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(borders): properly handle in-viewport borderless panes #697

Merged
merged 6 commits into from
Sep 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Fix bug when in some cases closing a tab would not clear the previous pane's contents (https://github.com/zellij-org/zellij/pull/684)
* Fix bug where tabs would sometimes be created with the wrong index in their name (https://github.com/zellij-org/zellij/pull/686)
* Fix bug where wide chars would mess up pane titles (https://github.com/zellij-org/zellij/pull/698)
* Fix various borderless-frame in viewport bugs (https://github.com/zellij-org/zellij/pull/697)

## [0.16.0] - 2021-08-31
* Plugins don't crash zellij anymore on receiving mouse events (https://github.com/zellij-org/zellij/pull/620)
Expand Down
4 changes: 3 additions & 1 deletion zellij-server/src/panes/terminal_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,9 @@ impl Pane for TerminalPane {
color: self.frame_color,
};
if &frame != last_frame {
vte_output.push_str(&frame.render());
if !self.borderless {
vte_output.push_str(&frame.render());
}
self.frame = Some(frame);
}
}
Expand Down
42 changes: 31 additions & 11 deletions zellij-server/src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -684,22 +684,35 @@ impl Tab {
}
pub fn set_pane_frames(&mut self, draw_pane_frames: bool) {
self.draw_pane_frames = draw_pane_frames;
self.should_clear_display_before_rendering = true;
let viewport = self.viewport;
for (pane_id, pane) in self.panes.iter_mut() {
pane.set_frame(draw_pane_frames);
if draw_pane_frames {
if !pane.borderless() {
pane.set_frame(draw_pane_frames);
}

#[allow(clippy::if_same_then_else)]
if draw_pane_frames & !pane.borderless() {
// there's definitely a frame around this pane, offset its contents
pane.set_content_offset(Offset::frame(1));
} else if draw_pane_frames && pane.borderless() {
// there's no frame around this pane, and the tab isn't handling the boundaries
// between panes (they each draw their own frames as they please)
// this one doesn't - do not offset its content
pane.set_content_offset(Offset::default());
} else if !is_inside_viewport(&viewport, pane) {
// this pane is outside the viewport and has no border - it should not have an offset
pane.set_content_offset(Offset::default());
} else {
// no draw_pane_frames and this pane should have a separation to other panes
// according to its position in the viewport (eg. no separation if its at the
// viewport bottom) - offset its content accordingly
let position_and_size = pane.current_geom();
let (pane_columns_offset, pane_rows_offset) =
pane_content_offset(&position_and_size, &self.viewport);
pane.set_content_offset(Offset::shift(pane_rows_offset, pane_columns_offset));
}

// FIXME: this should also override the above logic
if pane.borderless() {
pane.set_content_offset(Offset::default());
}

// FIXME: This, and all other `set_terminal_size_using_fd` calls, would be best in
// `TerminalPane::reflow_lines`
if let PaneId::Terminal(pid) = pane_id {
Expand Down Expand Up @@ -2345,10 +2358,9 @@ impl Tab {
.unwrap();
}
fn is_inside_viewport(&self, pane_id: &PaneId) -> bool {
let pane_position_and_size = self.panes.get(pane_id).unwrap().current_geom();
pane_position_and_size.y >= self.viewport.y
&& pane_position_and_size.y + pane_position_and_size.rows.as_usize()
<= self.viewport.y + self.viewport.rows
// this is mostly separated to an outside function in order to allow us to pass a clone to
// it sometimes when we need to get around the borrow checker
is_inside_viewport(&self.viewport, self.panes.get(pane_id).unwrap())
}
fn offset_viewport(&mut self, position_and_size: &Viewport) {
if position_and_size.x == self.viewport.x
Expand Down Expand Up @@ -2378,6 +2390,14 @@ impl Tab {
}
}

#[allow(clippy::borrowed_box)]
fn is_inside_viewport(viewport: &Viewport, pane: &Box<dyn Pane>) -> bool {
let pane_position_and_size = pane.current_geom();
pane_position_and_size.y >= viewport.y
&& pane_position_and_size.y + pane_position_and_size.rows.as_usize()
<= viewport.y + viewport.rows
}

#[cfg(test)]
#[path = "./unit/tab_tests.rs"]
mod tab_tests;