fix last line cursor visual mismatch
- SHA
32adda571a39c159534627efed176f17f42681ee- Parents
-
7d2548c - Tree
2ad2850
32adda5
32adda571a39c159534627efed176f17f42681ee7d2548c
2ad2850| Status | File | + | - |
|---|---|---|---|
| M |
src/editor/state.rs
|
6 | 5 |
| M |
src/render/screen.rs
|
11 | 1 |
| M |
src/workspace/state.rs
|
3 | 2 |
src/editor/state.rsmodified@@ -1638,7 +1638,8 @@ impl Editor { | |||
| 1638 | } else { | 1638 | } else { |
| 1639 | 0 | 1639 | 0 |
| 1640 | }; | 1640 | }; |
| 1641 | - let top_offset = if self.workspace.tabs.len() > 1 { 1 } else { 0 }; | 1641 | + // Tab bar is always rendered (takes 1 row) |
| 1642 | + let top_offset = 1; | ||
| 1642 | 1643 | ||
| 1643 | // Calculate line number column width (same as in screen.rs) | 1644 | // Calculate line number column width (same as in screen.rs) |
| 1644 | let line_num_width = { | 1645 | let line_num_width = { |
@@ -1766,8 +1767,8 @@ impl Editor { | |||
| 1766 | } | 1767 | } |
| 1767 | Mouse::ScrollDown { .. } => { | 1768 | Mouse::ScrollDown { .. } => { |
| 1768 | // Scroll down 3 lines | 1769 | // Scroll down 3 lines |
| 1769 | - // Calculate visible rows (accounting for tab bar, gap, and status bar) | 1770 | + // Calculate visible rows (tab bar always rendered, plus gap and status bar) |
| 1770 | - let top_offset = if self.workspace.tabs.len() > 1 { 1 } else { 0 }; | 1771 | + let top_offset = 1; |
| 1771 | let visible_rows = (self.screen.rows as usize).saturating_sub(2 + top_offset); | 1772 | let visible_rows = (self.screen.rows as usize).saturating_sub(2 + top_offset); |
| 1772 | // Max viewport is when the last line is at the bottom of visible area | 1773 | // Max viewport is when the last line is at the bottom of visible area |
| 1773 | let max_viewport = self.buffer().line_count().saturating_sub(visible_rows).max(0); | 1774 | let max_viewport = self.buffer().line_count().saturating_sub(visible_rows).max(0); |
@@ -4448,8 +4449,8 @@ impl Editor { | |||
| 4448 | // === Viewport === | 4449 | // === Viewport === |
| 4449 | 4450 | ||
| 4450 | fn scroll_to_cursor(&mut self) { | 4451 | fn scroll_to_cursor(&mut self) { |
| 4451 | - // Calculate top offset (tab bar takes 1 row if multiple tabs) | 4452 | + // Tab bar is always rendered (takes 1 row) |
| 4452 | - let top_offset = if self.workspace.tabs.len() > 1 { 1 } else { 0 }; | 4453 | + let top_offset = 1; |
| 4453 | // Vertical scrolling (2 rows reserved: gap + status bar, plus top_offset for tab bar) | 4454 | // Vertical scrolling (2 rows reserved: gap + status bar, plus top_offset for tab bar) |
| 4454 | let visible_rows = (self.screen.rows as usize).saturating_sub(2 + top_offset); | 4455 | let visible_rows = (self.screen.rows as usize).saturating_sub(2 + top_offset); |
| 4455 | 4456 | ||
src/render/screen.rsmodified@@ -285,7 +285,7 @@ impl Screen { | |||
| 285 | 285 | ||
| 286 | // Calculate available screen area | 286 | // Calculate available screen area |
| 287 | let available_width = self.cols.saturating_sub(left_offset) as f32; | 287 | let available_width = self.cols.saturating_sub(left_offset) as f32; |
| 288 | - let available_height = self.rows.saturating_sub(1 + top_offset) as f32; // -1 for status bar | 288 | + let available_height = self.rows.saturating_sub(2 + top_offset) as f32; // -2 for gap + status bar |
| 289 | 289 | ||
| 290 | // Track where to place the hardware cursor (active pane's primary cursor) | 290 | // Track where to place the hardware cursor (active pane's primary cursor) |
| 291 | let mut cursor_screen_pos: Option<(u16, u16)> = None; | 291 | let mut cursor_screen_pos: Option<(u16, u16)> = None; |
@@ -342,6 +342,16 @@ impl Screen { | |||
| 342 | } | 342 | } |
| 343 | } | 343 | } |
| 344 | 344 | ||
| 345 | + // Render the gap row (empty line between text and status bar) | ||
| 346 | + let gap_row = top_offset + available_height as u16; | ||
| 347 | + execute!( | ||
| 348 | + self.stdout, | ||
| 349 | + MoveTo(left_offset, gap_row), | ||
| 350 | + SetBackgroundColor(BG_COLOR), | ||
| 351 | + Clear(ClearType::UntilNewLine), | ||
| 352 | + ResetColor | ||
| 353 | + )?; | ||
| 354 | + | ||
| 345 | // Render status bar (use active pane's info) | 355 | // Render status bar (use active pane's info) |
| 346 | if let Some(active_pane) = panes.iter().find(|p| p.is_active) { | 356 | if let Some(active_pane) = panes.iter().find(|p| p.is_active) { |
| 347 | self.render_status_bar_with_offset( | 357 | self.render_status_bar_with_offset( |
src/workspace/state.rsmodified@@ -599,7 +599,7 @@ impl Tab { | |||
| 599 | pub fn pane_at_screen_position(&self, col: u16, row: u16, screen_cols: u16, screen_rows: u16, left_offset: u16, top_offset: u16) -> usize { | 599 | pub fn pane_at_screen_position(&self, col: u16, row: u16, screen_cols: u16, screen_rows: u16, left_offset: u16, top_offset: u16) -> usize { |
| 600 | // Available space for panes (excluding fuss width and tab bar) | 600 | // Available space for panes (excluding fuss width and tab bar) |
| 601 | let available_width = screen_cols.saturating_sub(left_offset) as f32; | 601 | let available_width = screen_cols.saturating_sub(left_offset) as f32; |
| 602 | - let available_height = screen_rows.saturating_sub(1 + top_offset) as f32; // -1 for status bar | 602 | + let available_height = screen_rows.saturating_sub(2 + top_offset) as f32; // -2 for gap + status bar |
| 603 | 603 | ||
| 604 | // Adjust click coordinates for offsets | 604 | // Adjust click coordinates for offsets |
| 605 | let adj_col = col.saturating_sub(left_offset) as f32; | 605 | let adj_col = col.saturating_sub(left_offset) as f32; |
@@ -1423,7 +1423,8 @@ impl Workspace { | |||
| 1423 | } else { | 1423 | } else { |
| 1424 | 0 | 1424 | 0 |
| 1425 | }; | 1425 | }; |
| 1426 | - let top_offset = if self.tabs.len() > 1 { 1u16 } else { 0 }; | 1426 | + // Tab bar is always rendered (takes 1 row) |
| 1427 | + let top_offset = 1u16; | ||
| 1427 | 1428 | ||
| 1428 | self.tabs[self.active_tab].pane_at_screen_position( | 1429 | self.tabs[self.active_tab].pane_at_screen_position( |
| 1429 | col, row, screen_cols, screen_rows, fuss_width, top_offset | 1430 | col, row, screen_cols, screen_rows, fuss_width, top_offset |