fix: focus pane on left-click even when mouse reporting is active
The Down(Left) handler called forward_pane_mouse_button before focus_pane and early-returned when the forward succeeded, which happens for any pane running a TUI that has enabled mouse reporting (e.g. Claude Code). As a result, clicking such a pane forwarded the click to the inner TUI but never updated herdr's focus state, leaving the previous pane highlighted. Reorder the handler to focus first and forward after, matching the pattern already used by handle_terminal_wheel. Shells and TUIs without mouse reporting (e.g. Codex) were unaffected because their forward returned false and the focus update happened in the fallthrough branch. Add a regression test that installs a pane runtime with mouse reporting enabled via the '\x1b[?1002h' DECSET sequence and asserts that a Down(Left) event retargets focus.
This commit is contained in:
parent
a6cbc97651
commit
5e711fb7d3
|
|
@ -2155,6 +2155,11 @@ impl AppState {
|
|||
return None;
|
||||
}
|
||||
} else if let Some(info) = self.pane_at(mouse.column, mouse.row).cloned() {
|
||||
self.focus_pane(info.id);
|
||||
if self.mode != Mode::Terminal {
|
||||
self.mode = Mode::Terminal;
|
||||
}
|
||||
|
||||
if self.forward_pane_mouse_button(&info, mouse) {
|
||||
self.selection = None;
|
||||
return None;
|
||||
|
|
@ -2170,11 +2175,6 @@ impl AppState {
|
|||
col,
|
||||
self.pane_scroll_metrics(info.id),
|
||||
));
|
||||
|
||||
self.focus_pane(info.id);
|
||||
if self.mode != Mode::Terminal {
|
||||
self.mode = Mode::Terminal;
|
||||
}
|
||||
} else if let Some(info) = self.view.pane_infos.iter().find(|p| {
|
||||
mouse.column >= p.rect.x
|
||||
&& mouse.column < p.rect.x + p.rect.width
|
||||
|
|
@ -4573,4 +4573,70 @@ mod tests {
|
|||
|
||||
assert_eq!(wheel_routing(input_state), WheelRouting::HostScroll);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn clicking_unfocused_pane_with_mouse_reporting_focuses_it_via_left_button() {
|
||||
let mut app = app_for_mouse_test();
|
||||
let mut ws = Workspace::test_new("test");
|
||||
let first_pane = ws.tabs[0].root_pane;
|
||||
let second_pane = ws.test_split(ratatui::layout::Direction::Vertical);
|
||||
|
||||
let terminal_area = Rect::new(26, 2, 80, 18);
|
||||
let pane_infos = ws.tabs[0].layout.panes(terminal_area);
|
||||
let first_info = pane_infos
|
||||
.iter()
|
||||
.find(|p| p.id == first_pane)
|
||||
.expect("first pane info")
|
||||
.clone();
|
||||
let second_info = pane_infos
|
||||
.iter()
|
||||
.find(|p| p.id == second_pane)
|
||||
.expect("second pane info")
|
||||
.clone();
|
||||
|
||||
ws.tabs[0].runtimes.insert(
|
||||
first_pane,
|
||||
crate::pane::PaneRuntime::test_with_screen_bytes(
|
||||
first_info.inner_rect.width.max(1),
|
||||
first_info.inner_rect.height.max(1),
|
||||
b"",
|
||||
),
|
||||
);
|
||||
ws.tabs[0].runtimes.insert(
|
||||
second_pane,
|
||||
crate::pane::PaneRuntime::test_with_screen_bytes(
|
||||
second_info.inner_rect.width.max(1),
|
||||
second_info.inner_rect.height.max(1),
|
||||
b"\x1b[?1002h",
|
||||
),
|
||||
);
|
||||
|
||||
ws.tabs[0].layout.focus_pane(first_pane);
|
||||
|
||||
app.state.workspaces = vec![ws];
|
||||
app.state.active = Some(0);
|
||||
app.state.selected = 0;
|
||||
app.state.mode = Mode::Terminal;
|
||||
app.state.view.pane_infos = pane_infos;
|
||||
|
||||
assert_eq!(
|
||||
app.state.workspaces[0].tabs[0].layout.focused(),
|
||||
first_pane,
|
||||
"first pane should be focused before click"
|
||||
);
|
||||
|
||||
app.handle_mouse(mouse(
|
||||
MouseEventKind::Down(MouseButton::Left),
|
||||
second_info.inner_rect.x + 2,
|
||||
second_info.inner_rect.y + 2,
|
||||
));
|
||||
|
||||
assert_eq!(
|
||||
app.state.workspaces[0].tabs[0].layout.focused(),
|
||||
second_pane,
|
||||
"left-clicking a pane with mouse reporting should move focus to it"
|
||||
);
|
||||
assert_eq!(app.state.mode, Mode::Terminal);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue