fix: guard chrome input and stale pane frames

This commit is contained in:
kuddev committed 2026-07-16 18:39:27 +08:00
1 parent 76fc0250fd
commit 9ba22f114e
3 files changed
+29 -2

No files matched your search

+11
View File
@@ -1847,6 +1847,17 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
crate::display::ChromeHit::None => {},
}
// A press inside the chrome band (top bar / tab sidebar) that
// hit no control ends here. Falling through used to reach the
// terminal's selection arming, which clamps the point into the
// nearest grid cell — dragging from the sidebar then painted a
// stray selection across the pane (the "drag ghost").
let window_size = self.ctx.display().size_info;
let scale = self.ctx.window().scale_factor as f32;
if crate::display::in_chrome_bar(&window_size, scale, x, y) {
return;
}
// Nebula: grab the scrollback thumb (or jump on a track press).
// Only live while scrolled into history, since the bar auto-hides.
let view = self.ctx.size_info();
+8 -2
View File
@@ -1924,7 +1924,12 @@ impl WindowContext {
} else {
self.display.begin_pane_frame(&self.config);
let mut dim_rects = Vec::new();
for (i, (id, view)) in pane_rects.iter().enumerate() {
// The whole-window clear must not be tied to pane_rects[0]: a
// layout leaf whose pane is gone (or a doc sentinel) is skipped
// below, and skipping the clearing pane would leave every later
// frame compositing over stale buffer contents (ghost frames).
let mut cleared = false;
for (id, view) in pane_rects.iter() {
let Some(idx) = self.pane_index(*id) else { continue };
let is_focused = *id == focused;
if !is_focused {
@@ -1946,8 +1951,9 @@ impl WindowContext {
&mut pane.nebula_state,
*view,
is_focused,
i == 0,
!cleared,
);
cleared = true;
}
self.display.draw_split_overlays(&dim_rects, &divider_rects);
self.display.finish_pane_frame(scheduler);
+10
View File
@@ -411,6 +411,16 @@ impl WindowContext {
/// focus. Works at any depth, so repeated splits nest into a layout tree
/// (panes close via the close-pane action).
pub(super) fn split_focused(&mut self, direction: SplitDirection) {
// Doc/settings tabs own no real pane: splitting one would graft the
// DOC sentinel leaf into a split tree, whose draw pass then skips it
// and leaves that half of the frame stale.
if self
.tabs
.get(self.active_tab)
.is_some_and(|tab| tab.doc.is_some() || tab.settings)
{
return;
}
self.zoom = None;
let focused = self.focused_pane_id();
let cwd = self.focused_cwd();