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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
use crate::tab::Pane;
use crate::{os_input_output::ServerOsApi, panes::PaneId, ClientId};
use std::collections::{BTreeMap, HashMap, HashSet};
#[derive(Clone)]
pub struct ActivePanes {
active_panes: HashMap<ClientId, PaneId>,
shadow_clients: HashSet<ClientId>,
last_panes: HashMap<ClientId, PaneId>,
os_api: Box<dyn ServerOsApi>,
}
impl std::fmt::Debug for ActivePanes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:?}", self.active_panes)
}
}
impl ActivePanes {
pub fn new(os_api: &Box<dyn ServerOsApi>) -> Self {
let os_api = os_api.clone();
ActivePanes {
active_panes: HashMap::new(),
shadow_clients: HashSet::new(),
last_panes: HashMap::new(),
os_api,
}
}
pub fn is_shadow_client(&self, client_id: &ClientId) -> bool {
self.shadow_clients.contains(client_id)
}
pub fn iter_shadow_clients(&self) -> impl Iterator<Item = &ClientId> {
self.shadow_clients.iter()
}
pub fn has_shadow_focus_on(&self, client_id: ClientId, pane_id: PaneId) -> bool {
self.shadow_clients.contains(&client_id)
&& self.active_panes.get(&client_id) == Some(&pane_id)
}
pub fn get(&self, client_id: &ClientId) -> Option<&PaneId> {
self.active_panes.get(client_id)
}
pub fn get_last(&self, client_id: &ClientId) -> Option<&PaneId> {
self.last_panes.get(client_id)
}
pub fn insert(
&mut self,
client_id: ClientId,
pane_id: PaneId,
panes: &mut BTreeMap<PaneId, Box<dyn Pane>>,
) {
self.shadow_clients.remove(&client_id);
let previously_focused = self.active_panes.get(&client_id).copied();
self.unfocus_pane_for_client(client_id, panes);
self.active_panes.insert(client_id, pane_id);
self.focus_pane(pane_id, panes);
// Both the pane losing focus and the pane gaining it may need to be
// repainted in full; see Pane::refresh_for_focus_change.
for id in previously_focused.into_iter().chain(std::iter::once(pane_id)) {
if let Some(pane) = panes.get_mut(&id) {
pane.refresh_for_focus_change();
}
}
}
pub fn insert_silent(&mut self, client_id: ClientId, pane_id: PaneId) {
self.active_panes.insert(client_id, pane_id);
self.shadow_clients.insert(client_id);
}
pub fn remove_silent(&mut self, client_id: &ClientId) -> Option<PaneId> {
self.shadow_clients.remove(client_id);
self.active_panes.remove(client_id)
}
pub fn set_last_pane(&mut self, client_id: ClientId, pane_id: PaneId) {
self.last_panes.insert(client_id, pane_id);
}
pub fn clear(&mut self, panes: &mut BTreeMap<PaneId, Box<dyn Pane>>) {
for pane_id in self.active_panes.values() {
self.unfocus_pane(*pane_id, panes);
}
self.active_panes.clear();
self.shadow_clients.clear();
}
pub fn is_empty(&self) -> bool {
self.active_panes.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&ClientId, &PaneId)> {
self.active_panes.iter()
}
pub fn values(&self) -> impl Iterator<Item = &PaneId> {
self.active_panes.values()
}
pub fn remove(
&mut self,
client_id: &ClientId,
panes: &mut BTreeMap<PaneId, Box<dyn Pane>>,
) -> Option<PaneId> {
if let Some(pane_id_to_unfocus) = self.active_panes.get(&client_id) {
self.unfocus_pane(*pane_id_to_unfocus, panes);
}
self.shadow_clients.remove(client_id);
self.active_panes.remove(client_id)
}
pub fn unfocus_all_panes(&self, panes: &mut BTreeMap<PaneId, Box<dyn Pane>>) {
for (_client_id, pane_id) in &self.active_panes {
self.unfocus_pane(*pane_id, panes);
}
}
pub fn focus_all_panes(&self, panes: &mut BTreeMap<PaneId, Box<dyn Pane>>) {
for (_client_id, pane_id) in &self.active_panes {
self.focus_pane(*pane_id, panes);
}
}
pub fn clone_active_panes(&self) -> HashMap<ClientId, PaneId> {
self.active_panes.clone()
}
pub fn contains_key(&self, client_id: &ClientId) -> bool {
self.active_panes.contains_key(client_id)
}
fn unfocus_pane_for_client(
&self,
client_id: ClientId,
panes: &mut BTreeMap<PaneId, Box<dyn Pane>>,
) {
if let Some(pane_id_to_unfocus) = self.active_panes.get(&client_id) {
self.unfocus_pane(*pane_id_to_unfocus, panes);
}
}
fn unfocus_pane(&self, pane_id: PaneId, panes: &mut BTreeMap<PaneId, Box<dyn Pane>>) {
if let PaneId::Terminal(terminal_id) = pane_id {
if let Some(focus_event) = panes.get(&pane_id).and_then(|p| p.unfocus_event()) {
let _ = self
.os_api
.write_to_tty_stdin(terminal_id, focus_event.as_bytes());
}
}
}
fn focus_pane(&self, pane_id: PaneId, panes: &mut BTreeMap<PaneId, Box<dyn Pane>>) {
if let PaneId::Terminal(terminal_id) = pane_id {
if let Some(focus_event) = panes.get(&pane_id).and_then(|p| p.focus_event()) {
let _ = self
.os_api
.write_to_tty_stdin(terminal_id, focus_event.as_bytes());
}
}
}
pub fn pane_id_is_focused(&self, pane_id: &PaneId) -> bool {
self.active_panes
.values()
.find(|p_id| **p_id == *pane_id)
.is_some()
}
}
|