Skip to content

Commit c8e4324

Browse files
nikicatclaude
andcommitted
fix: refresh Taffy root size when scaled margin changes
When a second tab is created and the tab bar transitions from hidden to visible, `update_scaled_margin` updated only the stored margin — Taffy's root size still reflected the old, larger available area. The subsequent layout pass then kept the panel at its old height and the PTY was never reflowed, so the bottom rows ended up clipped behind the freshly appeared tab bar. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> (cherry picked from commit 8cd7ea6)
1 parent 330ed70 commit c8e4324

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

frontends/rioterm/src/layout/compute_tests.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,73 @@ fn test_split_inside_resized_panel_preserves_proportions() {
647647
"Bottom (bottom half) should be ~400px tall, got {bottom_h}"
648648
);
649649
}
650+
651+
// --- update_scaled_margin ------------------------------------------------
652+
653+
fn margin_test_dimension() -> ContextDimension {
654+
let dims = TextDimensions {
655+
width: 8.0,
656+
height: 16.0,
657+
scale: 1.0,
658+
};
659+
ContextDimension::build(
660+
800.0,
661+
600.0,
662+
dims,
663+
cell_for(dims),
664+
1.0,
665+
14.0,
666+
Margin::all(0.0),
667+
)
668+
}
669+
670+
/// Build a single-panel grid off sugarloaf (positions come from
671+
/// `calculate_positions`, not `apply_taffy_layout`).
672+
fn single_panel_grid() -> ContextGrid<rio_backend::event::VoidListener> {
673+
use crate::context::create_mock_context;
674+
use rio_backend::event::VoidListener;
675+
use rio_window::window::WindowId;
676+
677+
let first = create_mock_context(
678+
VoidListener {},
679+
WindowId::from(0),
680+
0,
681+
margin_test_dimension(),
682+
);
683+
ContextGrid::new(
684+
first,
685+
Margin::all(0.0),
686+
[0.0; 4],
687+
[0.0; 4],
688+
rio_backend::config::layout::Panel::default(),
689+
)
690+
}
691+
692+
/// Regression: when the top window margin grows (e.g. the tab bar
693+
/// becomes visible after a second tab is created), `update_scaled_margin`
694+
/// must refresh Taffy's root size. Otherwise the next layout pass uses
695+
/// the stale available area and the panel keeps its old height — leaving
696+
/// the bottom rows clipped behind the tab bar.
697+
#[test]
698+
fn test_update_scaled_margin_shrinks_panel_when_top_margin_grows() {
699+
let mut grid = single_panel_grid();
700+
let panel = grid.current;
701+
702+
let initial_height = grid.inner[&panel].layout_rect[3];
703+
assert!(
704+
initial_height > 0.0,
705+
"panel should have a positive initial height"
706+
);
707+
708+
let tab_bar_height = 34.0;
709+
grid.update_scaled_margin(Margin::new(tab_bar_height, 0.0, 0.0, 0.0));
710+
grid.calculate_positions();
711+
712+
let new_height = grid.inner[&panel].layout_rect[3];
713+
assert!(
714+
(initial_height - new_height - tab_bar_height).abs() < 1.0,
715+
"panel height should shrink by the new top margin: was {initial_height}, \
716+
now {new_height}, expected ~{}",
717+
initial_height - tab_bar_height
718+
);
719+
}

frontends/rioterm/src/layout/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,12 @@ impl<T: rio_backend::event::EventListener> ContextGrid<T> {
11691169

11701170
pub fn update_scaled_margin(&mut self, scaled_margin: Margin) {
11711171
self.scaled_margin = scaled_margin;
1172+
// The Taffy root size is `window - scaled_margin`. Changing the
1173+
// margin without refreshing it leaves the next `compute_layout`
1174+
// running against a stale available area, so panels keep their
1175+
// old size (e.g. the tab bar appearing eats into the terminal
1176+
// height but the PTY never shrinks).
1177+
let _ = self.try_update_size(self.width, self.height);
11721178
}
11731179

11741180
pub fn update_line_height(&mut self, line_height: f32) {

0 commit comments

Comments
 (0)