diff options
| author | Aram Drevekenin <aram@poor.dev> | 2025-03-02 13:18:12 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-02 13:18:12 +0100 |
| commit | b7cc3f3a62930b233b36a5a51cf73c7a1be08bff (patch) | |
| tree | 23df1cefca8ff74ab878a500a4dae93d5d92b029 /zellij-server/src/ui | |
| parent | Fix compiler warnings (#4026) (diff) | |
| download | sl0ppij-b7cc3f3a62930b233b36a5a51cf73c7a1be08bff.tar.gz sl0ppij-b7cc3f3a62930b233b36a5a51cf73c7a1be08bff.tar.xz sl0ppij-b7cc3f3a62930b233b36a5a51cf73c7a1be08bff.zip | |
fix(panes): various fixes for rendering stacked panes without pane frames (#4035)
* initial work
* fix rendering issues with stacked panes without pane frames
* make mouse clicking work
* test: rendering stacked panes without frames
* style(fmt): rustfmt
* docs(changelog): update pr
Diffstat (limited to 'zellij-server/src/ui')
| -rw-r--r-- | zellij-server/src/ui/boundaries.rs | 67 | ||||
| -rw-r--r-- | zellij-server/src/ui/pane_boundaries_frame.rs | 24 | ||||
| -rw-r--r-- | zellij-server/src/ui/pane_contents_and_ui.rs | 12 |
3 files changed, 85 insertions, 18 deletions
diff --git a/zellij-server/src/ui/boundaries.rs b/zellij-server/src/ui/boundaries.rs index 7f70b1c7..f0fdebd6 100644 --- a/zellij-server/src/ui/boundaries.rs +++ b/zellij-server/src/ui/boundaries.rs @@ -1,4 +1,4 @@ -use zellij_utils::pane_size::Viewport; +use zellij_utils::pane_size::{Offset, Viewport}; use crate::output::CharacterChunk; use crate::panes::terminal_character::{TerminalCharacter, EMPTY_TERMINAL_CHARACTER, RESET_STYLES}; @@ -444,25 +444,40 @@ impl Boundaries { boundary_characters: HashMap::new(), } } - pub fn add_rect(&mut self, rect: &dyn Pane, color: Option<PaletteColor>) { + pub fn add_rect( + &mut self, + rect: &dyn Pane, + color: Option<PaletteColor>, + pane_is_on_top_of_stack: bool, + pane_is_on_bottom_of_stack: bool, + pane_is_stacked_under: bool, + ) { let pane_is_stacked = rect.current_geom().is_stacked(); + let should_skip_top_boundary = pane_is_stacked && !pane_is_on_top_of_stack; + let should_skip_bottom_boundary = pane_is_stacked && !pane_is_on_bottom_of_stack; + let content_offset = rect.get_content_offset(); if !self.is_fully_inside_screen(rect) { return; } if rect.x() > self.viewport.x { // left boundary let boundary_x_coords = rect.x() - 1; - let first_row_coordinates = self.rect_right_boundary_row_start(rect); + let first_row_coordinates = + self.rect_right_boundary_row_start(rect, pane_is_stacked_under, content_offset); let last_row_coordinates = self.rect_right_boundary_row_end(rect); for row in first_row_coordinates..last_row_coordinates { let coordinates = Coordinates::new(boundary_x_coords, row); let symbol_to_add = if row == first_row_coordinates && row != self.viewport.y { - BoundarySymbol::new(boundary_type::TOP_LEFT).color(color) + if pane_is_stacked { + BoundarySymbol::new(boundary_type::VERTICAL_RIGHT).color(color) + } else { + BoundarySymbol::new(boundary_type::TOP_LEFT).color(color) + } } else if row == first_row_coordinates && pane_is_stacked { BoundarySymbol::new(boundary_type::TOP_LEFT).color(color) } else if row == last_row_coordinates - 1 && row != self.viewport.y + self.viewport.rows - 1 - && !pane_is_stacked + && content_offset.bottom > 0 { BoundarySymbol::new(boundary_type::BOTTOM_LEFT).color(color) } else { @@ -476,7 +491,7 @@ impl Boundaries { self.boundary_characters.insert(coordinates, next_symbol); } } - if rect.y() > self.viewport.y && !pane_is_stacked { + if rect.y() > self.viewport.y && !should_skip_top_boundary { // top boundary let boundary_y_coords = rect.y() - 1; let first_col_coordinates = self.rect_bottom_boundary_col_start(rect); @@ -501,15 +516,22 @@ impl Boundaries { if self.rect_right_boundary_is_before_screen_edge(rect) { // right boundary let boundary_x_coords = rect.right_boundary_x_coords() - 1; - let first_row_coordinates = self.rect_right_boundary_row_start(rect); + let first_row_coordinates = + self.rect_right_boundary_row_start(rect, pane_is_stacked_under, content_offset); let last_row_coordinates = self.rect_right_boundary_row_end(rect); for row in first_row_coordinates..last_row_coordinates { let coordinates = Coordinates::new(boundary_x_coords, row); - let symbol_to_add = if row == first_row_coordinates && row != self.viewport.y { - BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color) + let symbol_to_add = if row == first_row_coordinates && pane_is_stacked { + BoundarySymbol::new(boundary_type::VERTICAL_LEFT).color(color) + } else if row == first_row_coordinates && row != self.viewport.y { + if pane_is_stacked { + BoundarySymbol::new(boundary_type::VERTICAL_LEFT).color(color) + } else { + BoundarySymbol::new(boundary_type::TOP_RIGHT).color(color) + } } else if row == last_row_coordinates - 1 && row != self.viewport.y + self.viewport.rows - 1 - && !pane_is_stacked + && content_offset.bottom > 0 { BoundarySymbol::new(boundary_type::BOTTOM_RIGHT).color(color) } else { @@ -523,7 +545,7 @@ impl Boundaries { self.boundary_characters.insert(coordinates, next_symbol); } } - if self.rect_bottom_boundary_is_before_screen_edge(rect) && !pane_is_stacked { + if self.rect_bottom_boundary_is_before_screen_edge(rect) && !should_skip_bottom_boundary { // bottom boundary let boundary_y_coords = rect.bottom_boundary_y_coords() - 1; let first_col_coordinates = self.rect_bottom_boundary_col_start(rect); @@ -575,11 +597,28 @@ impl Boundaries { fn rect_bottom_boundary_is_before_screen_edge(&self, rect: &dyn Pane) -> bool { rect.y() + rect.rows() < self.viewport.y + self.viewport.rows } - fn rect_right_boundary_row_start(&self, rect: &dyn Pane) -> usize { + fn rect_right_boundary_row_start( + &self, + rect: &dyn Pane, + pane_is_stacked_under: bool, + content_offset: Offset, + ) -> usize { let pane_is_stacked = rect.current_geom().is_stacked(); - let horizontal_frame_offset = if pane_is_stacked { 0 } else { 1 }; + let horizontal_frame_offset = if pane_is_stacked_under { + // these panes - panes that are in a stack below the flexible pane - need to have their + // content offset taken into account when rendering them (i.e. they are rendered + // one line above their actual y coordinates, since they are only 1 line) + // as opposed to panes that are in a stack above the flexible pane who do not because + // they are rendered in place (the content offset of the stack is "absorbed" by the + // flexible pane below them) + content_offset.bottom + } else if pane_is_stacked { + 0 + } else { + 1 + }; if rect.y() > self.viewport.y { - rect.y() - horizontal_frame_offset + rect.y().saturating_sub(horizontal_frame_offset) } else { self.viewport.y } diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs index 4e2c01fb..295e3bce 100644 --- a/zellij-server/src/ui/pane_boundaries_frame.rs +++ b/zellij-server/src/ui/pane_boundaries_frame.rs @@ -4,7 +4,7 @@ use crate::ui::boundaries::boundary_type; use crate::ClientId; use zellij_utils::data::{client_id_to_colors, PaletteColor, Style}; use zellij_utils::errors::prelude::*; -use zellij_utils::pane_size::Viewport; +use zellij_utils::pane_size::{Offset, Viewport}; use zellij_utils::position::Position; use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; @@ -62,6 +62,7 @@ pub struct FrameParams { pub pane_is_stacked_over: bool, pub should_draw_pane_frames: bool, pub pane_is_floating: bool, + pub content_offset: Offset, } #[derive(Default, PartialEq)] @@ -82,6 +83,7 @@ pub struct PaneFrame { should_draw_pane_frames: bool, is_pinned: bool, is_floating: bool, + content_offset: Offset, } impl PaneFrame { @@ -108,6 +110,7 @@ impl PaneFrame { should_draw_pane_frames: frame_params.should_draw_pane_frames, is_pinned: false, is_floating: frame_params.pane_is_floating, + content_offset: frame_params.content_offset, } } pub fn is_pinned(mut self, is_pinned: bool) -> Self { @@ -776,11 +779,26 @@ impl PaneFrame { // if this is a stacked pane with pane frames off (and it doesn't necessarily have only // 1 row because it could also be a flexible stacked pane) // in this case we should always draw the pane title line, and only the title line - let one_line_title = self.render_one_line_title().with_context(err_context)?; + let mut one_line_title = self.render_one_line_title().with_context(err_context)?; + + if self.content_offset.right != 0 && !self.should_draw_pane_frames { + // here what happens is that the title should be offset to the right + // in order to give room to the boundaries between the panes to be drawn + one_line_title.pop(); + } + let y_coords_of_title = if self.pane_is_stacked_under && !self.should_draw_pane_frames { + // we only want to use the bottom offset in this case because panes that are + // stacked above the flexible pane should actually appear exactly where they are on + // screen, the content offset being "absorbed" by the flexible pane below them + self.geom.y.saturating_sub(self.content_offset.bottom) + } else { + self.geom.y + }; + character_chunks.push(CharacterChunk::new( one_line_title, self.geom.x, - self.geom.y, + y_coords_of_title, )); } else { for row in 0..self.geom.rows { diff --git a/zellij-server/src/ui/pane_contents_and_ui.rs b/zellij-server/src/ui/pane_contents_and_ui.rs index 1be18fd8..c47e68d8 100644 --- a/zellij-server/src/ui/pane_contents_and_ui.rs +++ b/zellij-server/src/ui/pane_contents_and_ui.rs @@ -223,6 +223,7 @@ impl<'a> PaneContentsAndUi<'a> { pane_is_stacked_under: self.pane_is_stacked_under, should_draw_pane_frames: self.should_draw_pane_frames, pane_is_floating, + content_offset: self.pane.get_content_offset(), } } else { FrameParams { @@ -236,6 +237,7 @@ impl<'a> PaneContentsAndUi<'a> { pane_is_stacked_under: self.pane_is_stacked_under, should_draw_pane_frames: self.should_draw_pane_frames, pane_is_floating, + content_offset: self.pane.get_content_offset(), } }; @@ -260,9 +262,17 @@ impl<'a> PaneContentsAndUi<'a> { client_mode: InputMode, boundaries: &mut Boundaries, session_is_mirrored: bool, + pane_is_on_top_of_stack: bool, + pane_is_on_bottom_of_stack: bool, ) { let color = self.frame_color(client_id, client_mode, session_is_mirrored); - boundaries.add_rect(self.pane.as_ref(), color); + boundaries.add_rect( + self.pane.as_ref(), + color, + pane_is_on_top_of_stack, + pane_is_on_bottom_of_stack, + self.pane_is_stacked_under, + ); } fn frame_color( &self, |
