1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Focus and navigation operations for PaneManager
//!
//! Handles pane focus state, directional navigation, click-to-focus,
//! and closing panes with automatic focus transfer.
use super::PaneManager;
use crate::pane::types::{NavigationDirection, Pane, PaneId};
impl PaneManager {
/// Close a pane by ID
///
/// Returns true if this was the last pane (tab should close)
pub fn close_pane(&mut self, id: PaneId) -> bool {
crate::debug_info!("PANE_CLOSE", "close_pane called for pane {}", id);
if let Some(root) = self.root.take() {
match Self::remove_pane(root, id) {
crate::pane::tmux_helpers::RemoveResult::Removed(new_root) => {
self.root = new_root;
// If we closed the focused pane, focus another
if self.focused_pane_id == Some(id) {
let new_focus = self
.root
.as_ref()
.and_then(|r| r.all_pane_ids().first().copied());
crate::debug_info!(
"PANE_CLOSE",
"Closed focused pane {}, new focus: {:?}",
id,
new_focus
);
self.focused_pane_id = new_focus;
}
// Recalculate bounds
self.recalculate_bounds();
// Log remaining panes after closure
if let Some(ref root) = self.root {
for pane_id in root.all_pane_ids() {
if let Some(pane) = self.get_pane(pane_id) {
crate::debug_info!(
"PANE_CLOSE",
"Remaining pane {} bounds=({:.0},{:.0} {:.0}x{:.0})",
pane.id,
pane.bounds.x,
pane.bounds.y,
pane.bounds.width,
pane.bounds.height
);
}
}
}
crate::debug_info!("PANE_CLOSE", "Successfully closed pane {}", id);
}
crate::pane::tmux_helpers::RemoveResult::NotFound(root) => {
crate::debug_info!("PANE_CLOSE", "Pane {} not found in tree", id);
self.root = Some(root);
}
}
}
self.root.is_none()
}
/// Navigate to a pane in the given direction
pub fn navigate(&mut self, direction: NavigationDirection) {
if let Some(focused_id) = self.focused_pane_id
&& let Some(ref root) = self.root
&& let Some(new_id) = root.find_pane_in_direction(focused_id, direction)
{
self.focused_pane_id = Some(new_id);
log::debug!(
"Navigated {:?} from pane {} to pane {}",
direction,
focused_id,
new_id
);
}
}
/// Focus a specific pane by ID
pub fn focus_pane(&mut self, id: PaneId) {
if self
.root
.as_ref()
.is_some_and(|r| r.find_pane(id).is_some())
{
self.focused_pane_id = Some(id);
}
}
/// Focus the pane at a given pixel position
pub fn focus_pane_at(&mut self, x: f32, y: f32) -> Option<PaneId> {
if let Some(ref root) = self.root
&& let Some(pane) = root.find_pane_at(x, y)
{
let id = pane.id;
self.focused_pane_id = Some(id);
return Some(id);
}
None
}
/// Get the currently focused pane
pub fn focused_pane(&self) -> Option<&Pane> {
self.focused_pane_id
.and_then(|id| self.root.as_ref()?.find_pane(id))
}
/// Get the currently focused pane mutably
pub fn focused_pane_mut(&mut self) -> Option<&mut Pane> {
let id = self.focused_pane_id?;
self.root.as_mut()?.find_pane_mut(id)
}
/// Get the focused pane ID
pub fn focused_pane_id(&self) -> Option<PaneId> {
self.focused_pane_id
}
}