summaryrefslogtreecommitdiffstats
path: root/zellij-server/src
diff options
context:
space:
mode:
Diffstat (limited to 'zellij-server/src')
-rw-r--r--zellij-server/src/screen.rs177
-rw-r--r--zellij-server/src/tab.rs119
-rw-r--r--zellij-server/src/ui/pane_boundaries_frame.rs18
-rw-r--r--zellij-server/src/ui/pane_contents_and_ui.rs33
-rw-r--r--zellij-server/src/unit/screen_tests.rs2
-rw-r--r--zellij-server/src/unit/tab_tests.rs9
6 files changed, 231 insertions, 127 deletions
diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs
index f5beade59..7fa632752 100644
--- a/zellij-server/src/screen.rs
+++ b/zellij-server/src/screen.rs
@@ -1,7 +1,9 @@
//! Things related to [`Screen`]s.
+use std::cell::RefCell;
use std::collections::{BTreeMap, HashSet};
use std::os::unix::io::RawFd;
+use std::rc::Rc;
use std::str;
use zellij_utils::pane_size::Size;
@@ -182,6 +184,7 @@ pub(crate) struct Screen {
size: Size,
/// The overlay that is drawn on top of [`Pane`]'s', [`Tab`]'s and the [`Screen`]
overlay: OverlayWindow,
+ connected_clients: Rc<RefCell<HashSet<ClientId>>>,
/// The indices of this [`Screen`]'s active [`Tab`]s.
active_tab_indices: BTreeMap<ClientId, usize>,
tab_history: BTreeMap<ClientId, Vec<usize>>,
@@ -189,6 +192,7 @@ pub(crate) struct Screen {
default_mode_info: ModeInfo, // TODO: restructure ModeInfo to prevent this duplication
colors: Palette,
draw_pane_frames: bool,
+ session_is_mirrored: bool,
}
impl Screen {
@@ -199,12 +203,14 @@ impl Screen {
max_panes: Option<usize>,
mode_info: ModeInfo,
draw_pane_frames: bool,
+ session_is_mirrored: bool,
) -> Self {
Screen {
bus,
max_panes,
size: client_attributes.size,
colors: client_attributes.palette,
+ connected_clients: Rc::new(RefCell::new(HashSet::new())),
active_tab_indices: BTreeMap::new(),
tabs: BTreeMap::new(),
overlay: OverlayWindow::default(),
@@ -212,6 +218,7 @@ impl Screen {
mode_info: BTreeMap::new(),
default_mode_info: mode_info,
draw_pane_frames,
+ session_is_mirrored,
}
}
@@ -226,34 +233,50 @@ impl Screen {
}
}
- fn move_clients_from_closed_tab(&mut self, previous_tab_index: usize) {
- let client_ids_in_closed_tab: Vec<ClientId> = self
- .active_tab_indices
- .iter()
- .filter(|(_c_id, t_index)| **t_index == previous_tab_index)
- .map(|(c_id, _t_index)| c_id)
- .copied()
- .collect();
- for client_id in client_ids_in_closed_tab {
+ fn move_clients_from_closed_tab(
+ &mut self,
+ client_ids_and_mode_infos: Vec<(ClientId, ModeInfo)>,
+ ) {
+ for (client_id, client_mode_info) in client_ids_and_mode_infos {
let client_previous_tab = self.tab_history.get_mut(&client_id).unwrap().pop().unwrap();
self.active_tab_indices
.insert(client_id, client_previous_tab);
self.tabs
.get_mut(&client_previous_tab)
.unwrap()
- .add_client(client_id);
+ .add_client(client_id, Some(client_mode_info));
}
}
- fn move_clients(&mut self, source_index: usize, destination_index: usize) {
- let (connected_clients_in_source_tab, client_mode_infos_in_source_tab) = {
- let source_tab = self.tabs.get_mut(&source_index).unwrap();
- source_tab.drain_connected_clients()
- };
- let destination_tab = self.tabs.get_mut(&destination_index).unwrap();
- destination_tab.add_multiple_clients(
- connected_clients_in_source_tab,
- client_mode_infos_in_source_tab,
- );
+ fn move_clients_between_tabs(
+ &mut self,
+ source_tab_index: usize,
+ destination_tab_index: usize,
+ clients_to_move: Option<Vec<ClientId>>,
+ ) {
+ // None ==> move all clients
+ let drained_clients = self
+ .get_indexed_tab_mut(source_tab_index)
+ .map(|t| t.drain_connected_clients(clients_to_move));
+ if let Some(client_mode_info_in_source_tab) = drained_clients {
+ let destination_tab = self.get_indexed_tab_mut(destination_tab_index).unwrap();
+ destination_tab.add_multiple_clients(client_mode_info_in_source_tab);
+ destination_tab.update_input_modes();
+ destination_tab.set_force_render();
+ destination_tab.visible(true);
+ }
+ }
+ fn update_client_tab_focus(&mut self, client_id: ClientId, new_tab_index: usize) {
+ match self.active_tab_indices.remove(&client_id) {
+ Some(old_active_index) => {
+ self.active_tab_indices.insert(client_id, new_tab_index);
+ let client_tab_history = self.tab_history.entry(client_id).or_insert_with(Vec::new);
+ client_tab_history.retain(|&e| e != new_tab_index);
+ client_tab_history.push(old_active_index);
+ }
+ None => {
+ self.active_tab_indices.insert(client_id, new_tab_index);
+ }
+ }
}
/// A helper function to switch to a new tab at specified position.
fn switch_active_tab(&mut self, new_tab_pos: usize, client_id: ClientId) {
@@ -265,24 +288,29 @@ impl Screen {
return;
}
- current_tab.visible(false);
let current_tab_index = current_tab.index;
let new_tab_index = new_tab.index;
- let new_tab = self.get_indexed_tab_mut(new_tab_index).unwrap();
- new_tab.set_force_render();
- new_tab.visible(true);
-
- // currently all clients are just mirrors, so we perform the action for every entry in
- // tab_history
- // TODO: receive a client_id and only do it for the client
- for (client_id, tab_history) in &mut self.tab_history {
- let old_active_index = self.active_tab_indices.remove(client_id).unwrap();
- self.active_tab_indices.insert(*client_id, new_tab_index);
- tab_history.retain(|&e| e != new_tab_pos);
- tab_history.push(old_active_index);
+ if self.session_is_mirrored {
+ self.move_clients_between_tabs(current_tab_index, new_tab_index, None);
+ let all_connected_clients: Vec<ClientId> =
+ self.connected_clients.borrow().iter().copied().collect();
+ for client_id in all_connected_clients {
+ self.update_client_tab_focus(client_id, new_tab_index);
+ }
+ } else {
+ self.move_clients_between_tabs(
+ current_tab_index,
+ new_tab_index,
+ Some(vec![client_id]),
+ );
+ self.update_client_tab_focus(client_id, new_tab_index);
}
- self.move_clients(current_tab_index, new_tab_index);
+ if let Some(current_tab) = self.get_indexed_tab_mut(current_tab_index) {
+ if current_tab.has_no_connected_clients() {
+ current_tab.visible(false);
+ }
+ }
self.update_tabs();
self.render();
@@ -314,7 +342,7 @@ impl Screen {
}
fn close_tab_at_index(&mut self, tab_index: usize) {
- let tab_to_close = self.tabs.remove(&tab_index).unwrap();
+ let mut tab_to_close = self.tabs.remove(&tab_index).unwrap();
let pane_ids = tab_to_close.get_pane_ids();
// below we don't check the result of sending the CloseTab instruction to the pty thread
// because this might be happening when the app is closing, at which point the pty thread
@@ -330,7 +358,8 @@ impl Screen {
.send_to_server(ServerInstruction::Render(None))
.unwrap();
} else {
- self.move_clients_from_closed_tab(tab_index);
+ let client_mode_infos_in_closed_tab = tab_to_close.drain_connected_clients(None);
+ self.move_clients_from_closed_tab(client_mode_infos_in_closed_tab);
let visible_tab_indices: HashSet<usize> =
self.active_tab_indices.values().copied().collect();
for t in self.tabs.values_mut() {
@@ -446,28 +475,38 @@ impl Screen {
client_mode_info,
self.colors,
self.draw_pane_frames,
+ self.connected_clients.clone(),
+ self.session_is_mirrored,
client_id,
);
tab.apply_layout(layout, new_pids, tab_index, client_id);
- if let Some(active_tab) = self.get_active_tab_mut(client_id) {
- active_tab.visible(false);
- let (connected_clients_in_source_tab, client_mode_infos_in_source_tab) =
- active_tab.drain_connected_clients();
- tab.add_multiple_clients(
- connected_clients_in_source_tab,
- client_mode_infos_in_source_tab,
- );
- }
- for (client_id, tab_history) in &mut self.tab_history {
- let old_active_index = self.active_tab_indices.remove(client_id).unwrap();
- self.active_tab_indices.insert(*client_id, tab_index);
- tab_history.retain(|&e| e != tab_index);
- tab_history.push(old_active_index);
+ if self.session_is_mirrored {
+ if let Some(active_tab) = self.get_active_tab_mut(client_id) {
+ let client_mode_infos_in_source_tab = active_tab.drain_connected_clients(None);
+ tab.add_multiple_clients(client_mode_infos_in_source_tab);
+ if active_tab.has_no_connected_clients() {
+ active_tab.visible(false);
+ }
+ }
+ let all_connected_clients: Vec<ClientId> =
+ self.connected_clients.borrow().iter().copied().collect();
+ for client_id in all_connected_clients {
+ self.update_client_tab_focus(client_id, tab_index);
+ }
+ } else if let Some(active_tab) = self.get_active_tab_mut(client_id) {
+ let client_mode_info_in_source_tab =
+ active_tab.drain_connected_clients(Some(vec![client_id]));
+ tab.add_multiple_clients(client_mode_info_in_source_tab);
+ if active_tab.has_no_connected_clients() {
+ active_tab.visible(false);
+ }
+ self.update_client_tab_focus(client_id, tab_index);
}
tab.update_input_modes();
tab.visible(true);
self.tabs.insert(tab_index, tab);
if !self.active_tab_indices.contains_key(&client_id) {
+ // this means this is a new client and we need to add it to our state properly
self.add_client(client_id);
}
self.update_tabs();
@@ -486,12 +525,19 @@ impl Screen {
tab_history = first_tab_history.clone();
}
self.active_tab_indices.insert(client_id, tab_index);
+ self.connected_clients.borrow_mut().insert(client_id);
self.tab_history.insert(client_id, tab_history);
- self.tabs.get_mut(&tab_index).unwrap().add_client(client_id);
+ self.tabs
+ .get_mut(&tab_index)
+ .unwrap()
+ .add_client(client_id, None);
}
pub fn remove_client(&mut self, client_id: ClientId) {
if let Some(client_tab) = self.get_active_tab_mut(client_id) {
client_tab.remove_client(client_id);
+ if client_tab.has_no_connected_clients() {
+ client_tab.visible(false);
+ }
}
if self.active_tab_indices.contains_key(&client_id) {
self.active_tab_indices.remove(&client_id);
@@ -499,30 +545,41 @@ impl Screen {
if self.tab_history.contains_key(&client_id) {
self.tab_history.remove(&client_id);
}
+ self.connected_clients.borrow_mut().remove(&client_id);
+ self.update_tabs();
}
pub fn update_tabs(&self) {
- let mut tab_data = vec![];
- // TODO: right now all clients are synced, so we just take the first active_tab which is
- // the same for everyone - when this is no longer the case, we need to update the TabInfo
- // to account for this (or send multiple TabInfos)
- if let Some((_first_client, first_active_tab_index)) = self.active_tab_indices.iter().next()
- {
+ for (client_id, active_tab_index) in self.active_tab_indices.iter() {
+ let mut tab_data = vec![];
for tab in self.tabs.values() {
+ let other_focused_clients: Vec<ClientId> = if self.session_is_mirrored {
+ vec![]
+ } else {
+ self.active_tab_indices
+ .iter()
+ .filter(|(c_id, tab_position)| {
+ **tab_position == tab.index && *c_id != client_id
+ })
+ .map(|(c_id, _)| c_id)
+ .copied()
+ .collect()
+ };
tab_data.push(TabInfo {
position: tab.position,
name: tab.name.clone(),
- active: *first_active_tab_index == tab.index,
+ active: *active_tab_index == tab.index,
panes_to_hide: tab.panes_to_hide.len(),
is_fullscreen_active: tab.is_fullscreen_active(),
is_sync_panes_active: tab.is_sync_panes_active(),
+ other_focused_clients,
});
}
self.bus
.senders
.send_to_plugin(PluginInstruction::Update(
None,
- None,
+ Some(*client_id),
Event::TabUpdate(tab_data),
))
.unwrap();
@@ -607,6 +664,7 @@ pub(crate) fn screen_thread_main(
) {
let capabilities = config_options.simplified_ui;
let draw_pane_frames = config_options.pane_frames.unwrap_or(true);
+ let session_is_mirrored = config_options.mirror_session.unwrap_or(false);
let mut screen = Screen::new(
bus,
@@ -620,6 +678,7 @@ pub(crate) fn screen_thread_main(
},
),
draw_pane_frames,
+ session_is_mirrored,
);
loop {
let (event, mut err_ctx) = screen
diff --git a/zellij-server/src/tab.rs b/zellij-server/src/tab.rs
index ca8153ecf..fc5b0718f 100644
--- a/zellij-server/src/tab.rs
+++ b/zellij-server/src/tab.rs
@@ -17,7 +17,9 @@ use crate::{
ClientId, ServerInstruction,
};
use serde::{Deserialize, Serialize};
+use std::cell::RefCell;
use std::os::unix::io::RawFd;
+use std::rc::Rc;
use std::sync::mpsc::channel;
use std::time::Instant;
use std::{
@@ -111,9 +113,16 @@ impl Output {
.insert(*client_id, String::new());
}
}
- pub fn push_str_to_all_clients(&mut self, to_push: &str) {
- for render_instruction in self.client_render_instructions.values_mut() {
- render_instruction.push_str(to_push)
+ pub fn push_str_to_multiple_clients(
+ &mut self,
+ to_push: &str,
+ client_ids: impl Iterator<Item = ClientId>,
+ ) {
+ for client_id in client_ids {
+ self.client_render_instructions
+ .get_mut(&client_id)
+ .unwrap()
+ .push_str(to_push)
}
}
pub fn push_to_client(&mut self, client_id: ClientId, to_push: &str) {
@@ -141,6 +150,7 @@ pub(crate) struct Tab {
mode_info: HashMap<ClientId, ModeInfo>,
default_mode_info: ModeInfo,
pub colors: Palette,
+ connected_clients_in_app: Rc<RefCell<HashSet<ClientId>>>, // TODO: combine this and connected_clients
connected_clients: HashSet<ClientId>,
draw_pane_frames: bool,
session_is_mirrored: bool,
@@ -322,6 +332,8 @@ impl Tab {
mode_info: ModeInfo,
colors: Palette,
draw_pane_frames: bool,
+ connected_clients_in_app: Rc<RefCell<HashSet<ClientId>>>,
+ session_is_mirrored: bool,
client_id: ClientId,
) -> Self {
let panes = BTreeMap::new();
@@ -354,10 +366,9 @@ impl Tab {
default_mode_info: mode_info,
colors,
draw_pane_frames,
- // at the moment this is hard-coded while the feature is being developed
- // the only effect this has is to make sure the UI is drawn without additional information about other connected clients
- session_is_mirrored: true,
+ session_is_mirrored,
pending_vte_events: HashMap::new(),
+ connected_clients_in_app,
connected_clients,
}
}
@@ -491,14 +502,16 @@ impl Tab {
.unwrap();
}
}
- pub fn add_client(&mut self, client_id: ClientId) {
+ pub fn add_client(&mut self, client_id: ClientId, mode_info: Option<ModeInfo>) {
match self.connected_clients.iter().next() {
Some(first_client_id) => {
let first_active_pane_id = *self.active_panes.get(first_client_id).unwrap();
self.connected_clients.insert(client_id);
self.active_panes.insert(client_id, first_active_pane_id);
- self.mode_info
- .insert(client_id, self.default_mode_info.clone());
+ self.mode_info.insert(
+ client_id,
+ mode_info.unwrap_or_else(|| self.default_mode_info.clone()),
+ );
}
None => {
let mut pane_ids: Vec<PaneId> = self.panes.keys().copied().collect();
@@ -511,40 +524,53 @@ impl Tab {
let first_pane_id = pane_ids.get(0).unwrap();
self.connected_clients.insert(client_id);
self.active_panes.insert(client_id, *first_pane_id);
- self.mode_info
- .insert(client_id, self.default_mode_info.clone());
+ self.mode_info.insert(
+ client_id,
+ mode_info.unwrap_or_else(|| self.default_mode_info.clone()),
+ );
}
}
// TODO: we might be able to avoid this, we do this so that newly connected clients will
// necessarily get a full render
self.set_force_render();
+ self.update_input_modes();
}
pub fn change_mode_info(&mut self, mode_info: ModeInfo, client_id: ClientId) {
self.mode_info.insert(client_id, mode_info);
}
- pub fn add_multiple_clients(
- &mut self,
- client_ids: Vec<ClientId>,
- client_mode_infos: Vec<(ClientId, ModeInfo)>,
- ) {
- for client_id in client_ids {
- self.add_client(client_id);
- }
- for (client_id, client_mode_info) in client_mode_infos {
+ pub fn add_multiple_clients(&mut self, client_ids_to_mode_infos: Vec<(ClientId, ModeInfo)>) {
+ for (client_id, client_mode_info) in client_ids_to_mode_infos {
+ self.add_client(client_id, None);
self.mode_info.insert(client_id, client_mode_info);
}
}
pub fn remove_client(&mut self, client_id: ClientId) {
self.connected_clients.remove(&client_id);
- self.active_panes.remove(&client_id);
self.set_force_render();
}
- pub fn drain_connected_clients(&mut self) -> (Vec<ClientId>, Vec<(ClientId, ModeInfo)>) {
- let client_mode_info = self.mode_info.drain();
- (
- self.connected_clients.drain().collect(),
- client_mode_info.collect(),
- )
+ pub fn drain_connected_clients(
+ &mut self,
+ clients_to_drain: Option<Vec<ClientId>>,
+ ) -> Vec<(ClientId, ModeInfo)> {
+ // None => all clients
+ let mut client_ids_to_mode_infos = vec![];
+ let clients_to_drain =
+ clients_to_drain.unwrap_or_else(|| self.connected_clients.drain().collect());
+ for client_id in clients_to_drain {
+ client_ids_to_mode_infos.push(self.drain_single_client(client_id));
+ }
+ client_ids_to_mode_infos
+ }
+ pub fn drain_single_client(&mut self, client_id: ClientId) -> (ClientId, ModeInfo) {
+ let client_mode_info = self
+ .mode_info
+ .remove(&client_id)
+ .unwrap_or_else(|| self.default_mode_info.clone());
+ self.connected_clients.remove(&client_id);
+ (client_id, client_mode_info)
+ }
+ pub fn has_no_connected_clients(&self) -> bool {
+ self.connected_clients.is_empty()
}
pub fn new_pane(&mut self, pid: PaneId, client_id: Option<ClientId>) {
self.close_down_to_max_terminals();
@@ -786,7 +812,8 @@ impl Tab {
});
}
pub fn write_to_active_terminal(&mut self, input_bytes: Vec<u8>, client_id: ClientId) {
- self.write_to_pane_id(input_bytes, self.get_active_pane_id(client_id).unwrap());
+ let pane_id = self.get_active_pane_id(client_id).unwrap();
+ self.write_to_pane_id(input_bytes, pane_id);
}
pub fn write_to_pane_id(&mut self, input_bytes: Vec<u8>, pane_id: PaneId) {
match pane_id {
@@ -981,10 +1008,21 @@ impl Tab {
// render panes and their frames
for (kind, pane) in self.panes.iter_mut() {
if !self.panes_to_hide.contains(&pane.pid()) {
- let mut pane_contents_and_ui =
- PaneContentsAndUi::new(pane, output, self.colors, &self.active_panes);
+ let mut active_panes = self.active_panes.clone();
+ let multiple_users_exist_in_session =
+ { self.connected_clients_in_app.borrow().len() > 1 };
+ active_panes.retain(|c_id, _| self.connected_clients.contains(c_id));
+ let mut pane_contents_and_ui = PaneContentsAndUi::new(
+ pane,
+ output,
+ self.colors,
+ &active_panes,
+ multiple_users_exist_in_session,
+ );
if let PaneId::Terminal(..) = kind {
- pane_contents_and_ui.render_pane_contents_for_all_clients();
+ pane_contents_and_ui.render_pane_contents_to_multiple_clients(
+ self.connected_clients.iter().copied(),
+ );
}
for &client_id in &self.connected_clients {
let client_mode = self
@@ -1024,16 +1062,21 @@ impl Tab {
}
// FIXME: Once clients can be distinguished
if let Some(overlay_vte) = &overlay {
- output.push_str_to_all_clients(overlay_vte);
+ // output.push_str_to_all_clients(overlay_vte);
+ output
+ .push_str_to_multiple_clients(overlay_vte, self.connected_clients.iter().copied());
}
self.render_cursor(output);
}
fn hide_cursor_and_clear_display_as_needed(&mut self, output: &mut Output) {
let hide_cursor = "\u{1b}[?25l";
- output.push_str_to_all_clients(hide_cursor);
+ output.push_str_to_multiple_clients(hide_cursor, self.connected_clients.iter().copied());
if self.should_clear_display_before_rendering {
let clear_display = "\u{1b}[2J";
- output.push_str_to_all_clients(clear_display);
+ output.push_str_to_multiple_clients(
+ clear_display,
+ self.connected_clients.iter().copied(),
+ );
self.should_clear_display_before_rendering = false;
}
}
@@ -3400,10 +3443,10 @@ impl Tab {
fn write_selection_to_clipboard(&self, selection: &str) {
let mut output = Output::default();
output.add_clients(&self.connected_clients);
- output.push_str_to_all_clients(&format!(
- "\u{1b}]52;c;{}\u{1b}\\",
- base64::encode(selection)
- ));
+ output.push_str_to_multiple_clients(
+ &format!("\u{1b}]52;c;{}\u{1b}\\", base64::encode(selection)),
+ self.connected_clients.iter().copied(),
+ );
// TODO: ideally we should be sending the Render instruction from the screen
self.senders
diff --git a/zellij-server/src/ui/pane_boundaries_frame.rs b/zellij-server/src/ui/pane_boundaries_frame.rs
index 1ed29d838..419dea79c 100644
--- a/zellij-server/src/ui/pane_boundaries_frame.rs
+++ b/zellij-server/src/ui/pane_boundaries_frame.rs
@@ -3,7 +3,7 @@ use crate::ClientId;
use ansi_term::Colour::{Fixed, RGB};
use ansi_term::Style;
use zellij_utils::pane_size::Viewport;
-use zellij_utils::zellij_tile::prelude::{Palette, PaletteColor};
+use zellij_utils::zellij_tile::prelude::{client_id_to_colors, Palette, PaletteColor};
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
@@ -29,22 +29,6 @@ fn background_color(character: &str, color: Option<PaletteColor>) -> String {
}
}
-// TODO: move elsewhere
-pub(crate) fn client_id_to_colors(
- client_id: ClientId,
- colors: Palette,
-) -> Option<(PaletteColor, PaletteColor)> {
- // (primary color, secondary color)
- match client_id {
- 1 => Some((colors.green, colors.black)),
- 2 => Some((colors.blue, colors.black)),
- 3 => Some((colors.cyan, colors.black)),
- 4 => Some((colors.magenta, colors.black)),
- 5 => Some((colors.yellow, colors.black)),
- _ => None,
- }
-}
-
pub struct FrameParams {
pub focused_client: Option<ClientId>,
pub is_main_client: bool,
diff --git a/zellij-server/src/ui/pane_contents_and_ui.rs b/zellij-server/src/ui/pane_contents_and_ui.rs
index 25550fe9f..d8967f6ea 100644
--- a/zellij-server/src/ui/pane_contents_and_ui.rs
+++ b/zellij-server/src/ui/pane_contents_and_ui.rs
@@ -1,11 +1,12 @@
use crate::panes::PaneId;
use crate::tab::{Output, Pane};
use crate::ui::boundaries::Boundaries;
-use crate::ui::pane_boundaries_frame::client_id_to_colors;
use crate::ui::pane_boundaries_frame::FrameParams;
use crate::ClientId;
use std::collections::HashMap;
-use zellij_tile::data::{InputMode, Palette, PaletteColor};
+use zellij_tile::data::{
+ client_id_to_colors, single_client_color, InputMode, Palette, PaletteColor,
+};
pub struct PaneContentsAndUi<'a> {
pane: &'a mut Box<dyn Pane>,
@@ -21,13 +22,13 @@ impl<'a> PaneContentsAndUi<'a> {
output: &'a mut Output,
colors: Palette,
active_panes: &HashMap<ClientId, PaneId>,
+ multiple_users_exist_in_session: bool,
) -> Self {
let focused_clients: Vec<ClientId> = active_panes
.iter()
.filter(|(_c_id, p_id)| **p_id == pane.pid())
.map(|(c_id, _p_id)| *c_id)
.collect();
- let multiple_users_exist_in_session = active_panes.len() > 1;
PaneContentsAndUi {
pane,
output,
@@ -36,15 +37,21 @@ impl<'a> PaneContentsAndUi<'a> {
multiple_users_exist_in_session,
}
}
- pub fn render_pane_contents_for_all_clients(&mut self) {
+ pub fn render_pane_contents_to_multiple_clients(
+ &mut self,
+ clients: impl Iterator<Item = ClientId>,
+ ) {
if let Some(vte_output) = self.pane.render(None) {
// FIXME: Use Termion for cursor and style clearing?
- self.output.push_str_to_all_clients(&format!(
- "\u{1b}[{};{}H\u{1b}[m{}",
- self.pane.y() + 1,
- self.pane.x() + 1,
- vte_ou