client side threads should send messages directly to server and router threads should do the actual routing

This commit is contained in:
Kunal Mohan 2021-03-29 22:43:54 +05:30
parent 4f088e8185
commit ea732166e3
9 changed files with 228 additions and 287 deletions

View file

@ -25,7 +25,7 @@ use crate::common::{
command_is_executing::CommandIsExecuting, command_is_executing::CommandIsExecuting,
errors::{AppContext, ContextType, PluginContext, ScreenContext}, errors::{AppContext, ContextType, PluginContext, ScreenContext},
input::handler::input_loop, input::handler::input_loop,
os_input_output::{ClientOsApi, ServerOsApiInstruction}, os_input_output::ClientOsApi,
pty_bus::PtyInstruction, pty_bus::PtyInstruction,
screen::{Screen, ScreenInstruction}, screen::{Screen, ScreenInstruction},
wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginEnv, PluginInstruction}, wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginEnv, PluginInstruction},
@ -50,22 +50,15 @@ pub enum AppInstruction {
Exit, Exit,
Error(String), Error(String),
ToPty(PtyInstruction), ToPty(PtyInstruction),
ToScreen(ScreenInstruction),
ToPlugin(PluginInstruction),
OsApi(ServerOsApiInstruction),
DoneClosingPane, DoneClosingPane,
} }
impl From<ClientInstruction> for AppInstruction { impl From<ClientInstruction> for AppInstruction {
fn from(item: ClientInstruction) -> Self { fn from(item: ClientInstruction) -> Self {
match item { match item {
ClientInstruction::ToScreen(s) => AppInstruction::ToScreen(s),
ClientInstruction::Error(e) => AppInstruction::Error(e), ClientInstruction::Error(e) => AppInstruction::Error(e),
ClientInstruction::ClosePluginPane(p) => {
AppInstruction::ToPlugin(PluginInstruction::Unload(p))
}
ClientInstruction::DoneClosingPane => AppInstruction::DoneClosingPane, ClientInstruction::DoneClosingPane => AppInstruction::DoneClosingPane,
ClientInstruction::Exit => AppInstruction::Exit, _ => panic!("Unsupported AppInstruction"),
} }
} }
} }
@ -137,6 +130,10 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs) {
.expect("failed to receive event on channel"); .expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event))); err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event)));
screen.send_app_instructions.update(err_ctx); screen.send_app_instructions.update(err_ctx);
screen.os_api.update_senders(err_ctx);
if let Some(t) = screen.get_active_tab_mut() {
t.os_api.update_senders(err_ctx);
}
match event { match event {
ScreenInstruction::Pty(pid, vte_event) => { ScreenInstruction::Pty(pid, vte_event) => {
screen screen
@ -407,12 +404,22 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs) {
let router_thread = thread::Builder::new() let router_thread = thread::Builder::new()
.name("router".to_string()) .name("router".to_string())
.spawn({ .spawn({
let mut send_screen_instructions = send_screen_instructions.clone();
let mut send_plugin_instructions = send_plugin_instructions.clone();
let os_input = os_input.clone(); let os_input = os_input.clone();
move || loop { move || loop {
let (instruction, err_ctx) = os_input.client_recv(); let (instruction, err_ctx) = os_input.client_recv();
send_app_instructions.update(err_ctx); send_app_instructions.update(err_ctx);
send_screen_instructions.update(err_ctx);
send_plugin_instructions.update(err_ctx);
match instruction { match instruction {
ClientInstruction::Exit => break, ClientInstruction::Exit => break,
ClientInstruction::ClosePluginPane(p) => {
send_plugin_instructions
.send(PluginInstruction::Unload(p))
.unwrap();
}
ClientInstruction::ToScreen(s) => send_screen_instructions.send(s).unwrap(),
_ => { _ => {
send_app_instructions send_app_instructions
.send(AppInstruction::from(instruction)) .send(AppInstruction::from(instruction))
@ -449,17 +456,8 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>, opts: CliArgs) {
.unwrap(); .unwrap();
std::process::exit(1); std::process::exit(1);
} }
AppInstruction::ToScreen(instruction) => {
send_screen_instructions.send(instruction).unwrap();
}
AppInstruction::ToPlugin(instruction) => {
send_plugin_instructions.send(instruction).unwrap();
}
AppInstruction::ToPty(instruction) => { AppInstruction::ToPty(instruction) => {
let _ = os_input.send_to_server(ServerInstruction::ToPty(instruction)); os_input.send_to_server(ServerInstruction::ToPty(instruction));
}
AppInstruction::OsApi(instruction) => {
let _ = os_input.send_to_server(ServerInstruction::OsApi(instruction));
} }
AppInstruction::DoneClosingPane => command_is_executing.done_closing_pane(), AppInstruction::DoneClosingPane => command_is_executing.done_closing_pane(),
} }

View file

@ -8,6 +8,7 @@ use crate::layout::Layout;
use crate::os_input_output::{ClientOsApi, ServerOsApiInstruction}; use crate::os_input_output::{ClientOsApi, ServerOsApiInstruction};
use crate::panes::{PaneId, PositionAndSize, TerminalPane}; use crate::panes::{PaneId, PositionAndSize, TerminalPane};
use crate::pty_bus::{PtyInstruction, VteEvent}; use crate::pty_bus::{PtyInstruction, VteEvent};
use crate::server::ServerInstruction;
use crate::utils::shared::pad_to_size; use crate::utils::shared::pad_to_size;
use crate::wasm_vm::PluginInstruction; use crate::wasm_vm::PluginInstruction;
use crate::{boundaries::Boundaries, panes::PluginPane}; use crate::{boundaries::Boundaries, panes::PluginPane};
@ -67,7 +68,7 @@ pub struct Tab {
max_panes: Option<usize>, max_panes: Option<usize>,
full_screen_ws: PositionAndSize, full_screen_ws: PositionAndSize,
fullscreen_is_active: bool, fullscreen_is_active: bool,
os_api: Box<dyn ClientOsApi>, pub os_api: Box<dyn ClientOsApi>,
pub send_plugin_instructions: SenderWithContext<PluginInstruction>, pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
pub send_app_instructions: SenderWithContext<AppInstruction>, pub send_app_instructions: SenderWithContext<AppInstruction>,
should_clear_display_before_rendering: bool, should_clear_display_before_rendering: bool,
@ -234,15 +235,13 @@ impl Tab {
) -> Self { ) -> Self {
let panes = if let Some(PaneId::Terminal(pid)) = pane_id { let panes = if let Some(PaneId::Terminal(pid)) = pane_id {
let new_terminal = TerminalPane::new(pid, *full_screen_ws); let new_terminal = TerminalPane::new(pid, *full_screen_ws);
send_app_instructions os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, new_terminal.columns() as u16,
new_terminal.columns() as u16, new_terminal.rows() as u16,
new_terminal.rows() as u16, ),
), ));
))
.unwrap();
let mut panes: BTreeMap<PaneId, Box<dyn Pane>> = BTreeMap::new(); let mut panes: BTreeMap<PaneId, Box<dyn Pane>> = BTreeMap::new();
panes.insert(PaneId::Terminal(pid), Box::new(new_terminal)); panes.insert(PaneId::Terminal(pid), Box::new(new_terminal));
panes panes
@ -295,15 +294,13 @@ impl Tab {
terminal_pane.set_max_width(max_columns); terminal_pane.set_max_width(max_columns);
} }
terminal_pane.change_pos_and_size(&position_and_size); terminal_pane.change_pos_and_size(&position_and_size);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( *pid,
*pid, position_and_size.columns as u16,
position_and_size.columns as u16, position_and_size.rows as u16,
position_and_size.rows as u16, ),
), ));
))
.unwrap();
} }
None => { None => {
// we filled the entire layout, no room for this pane // we filled the entire layout, no room for this pane
@ -345,15 +342,13 @@ impl Tab {
// there are still panes left to fill, use the pids we received in this method // there are still panes left to fill, use the pids we received in this method
let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout
let new_terminal = TerminalPane::new(*pid, *position_and_size); let new_terminal = TerminalPane::new(*pid, *position_and_size);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, new_terminal.columns() as u16,
new_terminal.columns() as u16, new_terminal.rows() as u16,
new_terminal.rows() as u16, ),
), ));
))
.unwrap();
self.panes self.panes
.insert(PaneId::Terminal(*pid), Box::new(new_terminal)); .insert(PaneId::Terminal(*pid), Box::new(new_terminal));
} }
@ -362,11 +357,10 @@ impl Tab {
// this is a bit of a hack and happens because we don't have any central location that // this is a bit of a hack and happens because we don't have any central location that
// can query the screen as to how many panes it needs to create a layout // can query the screen as to how many panes it needs to create a layout
// fixing this will require a bit of an architecture change // fixing this will require a bit of an architecture change
self.send_app_instructions self.os_api
.send(AppInstruction::ToPty(PtyInstruction::ClosePane( .send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(
PaneId::Terminal(*unused_pid), PaneId::Terminal(*unused_pid),
))) )));
.unwrap();
} }
self.active_terminal = self.panes.iter().map(|(id, _)| id.to_owned()).next(); self.active_terminal = self.panes.iter().map(|(id, _)| id.to_owned()).next();
self.render(); self.render();
@ -379,15 +373,13 @@ impl Tab {
if !self.has_panes() { if !self.has_panes() {
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, new_terminal.columns() as u16,
new_terminal.columns() as u16, new_terminal.rows() as u16,
new_terminal.rows() as u16, ),
), ));
))
.unwrap();
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
} }
@ -413,9 +405,8 @@ impl Tab {
}, },
); );
if terminal_id_to_split.is_none() { if terminal_id_to_split.is_none() {
self.send_app_instructions self.os_api
.send(AppInstruction::ToPty(PtyInstruction::ClosePane(pid))) // we can't open this pane, close the pty .send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid))); // we can't open this pane, close the pty
.unwrap();
return; // likely no terminal large enough to split return; // likely no terminal large enough to split
} }
let terminal_id_to_split = terminal_id_to_split.unwrap(); let terminal_id_to_split = terminal_id_to_split.unwrap();
@ -433,27 +424,23 @@ impl Tab {
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws); let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws);
let new_terminal = TerminalPane::new(term_pid, bottom_winsize); let new_terminal = TerminalPane::new(term_pid, bottom_winsize);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, bottom_winsize.columns as u16,
bottom_winsize.columns as u16, bottom_winsize.rows as u16,
bottom_winsize.rows as u16, ),
), ));
))
.unwrap();
terminal_to_split.change_pos_and_size(&top_winsize); terminal_to_split.change_pos_and_size(&top_winsize);
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(terminal_id_to_split) = terminal_id_to_split { if let PaneId::Terminal(terminal_id_to_split) = terminal_id_to_split {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( terminal_id_to_split,
terminal_id_to_split, top_winsize.columns as u16,
top_winsize.columns as u16, top_winsize.rows as u16,
top_winsize.rows as u16, ),
), ));
))
.unwrap();
} }
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
} }
@ -461,27 +448,23 @@ impl Tab {
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws); let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws);
let new_terminal = TerminalPane::new(term_pid, right_winsize); let new_terminal = TerminalPane::new(term_pid, right_winsize);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, right_winsize.columns as u16,
right_winsize.columns as u16, right_winsize.rows as u16,
right_winsize.rows as u16, ),
), ));
))
.unwrap();
terminal_to_split.change_pos_and_size(&left_winsize); terminal_to_split.change_pos_and_size(&left_winsize);
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(terminal_id_to_split) = terminal_id_to_split { if let PaneId::Terminal(terminal_id_to_split) = terminal_id_to_split {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( terminal_id_to_split,
terminal_id_to_split, left_winsize.columns as u16,
left_winsize.columns as u16, left_winsize.rows as u16,
left_winsize.rows as u16, ),
), ));
))
.unwrap();
} }
} }
} }
@ -497,15 +480,13 @@ impl Tab {
if !self.has_panes() { if !self.has_panes() {
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, new_terminal.columns() as u16,
new_terminal.columns() as u16, new_terminal.rows() as u16,
new_terminal.rows() as u16, ),
), ));
))
.unwrap();
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
} }
@ -514,9 +495,8 @@ impl Tab {
let active_pane_id = &self.get_active_pane_id().unwrap(); let active_pane_id = &self.get_active_pane_id().unwrap();
let active_pane = self.panes.get_mut(active_pane_id).unwrap(); let active_pane = self.panes.get_mut(active_pane_id).unwrap();
if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 { if active_pane.rows() < MIN_TERMINAL_HEIGHT * 2 + 1 {
self.send_app_instructions self.os_api
.send(AppInstruction::ToPty(PtyInstruction::ClosePane(pid))) // we can't open this pane, close the pty .send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid))); // we can't open this pane, close the pty
.unwrap();
return; return;
} }
let terminal_ws = PositionAndSize { let terminal_ws = PositionAndSize {
@ -530,27 +510,23 @@ impl Tab {
active_pane.change_pos_and_size(&top_winsize); active_pane.change_pos_and_size(&top_winsize);
let new_terminal = TerminalPane::new(term_pid, bottom_winsize); let new_terminal = TerminalPane::new(term_pid, bottom_winsize);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, bottom_winsize.columns as u16,
bottom_winsize.columns as u16, bottom_winsize.rows as u16,
bottom_winsize.rows as u16, ),
), ));
))
.unwrap();
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(active_terminal_pid) = active_pane_id { if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( *active_terminal_pid,
*active_terminal_pid, top_winsize.columns as u16,
top_winsize.columns as u16, top_winsize.rows as u16,
top_winsize.rows as u16, ),
), ));
))
.unwrap();
} }
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
@ -565,15 +541,13 @@ impl Tab {
if !self.has_panes() { if !self.has_panes() {
if let PaneId::Terminal(term_pid) = pid { if let PaneId::Terminal(term_pid) = pid {
let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, new_terminal.columns() as u16,
new_terminal.columns() as u16, new_terminal.rows() as u16,
new_terminal.rows() as u16, ),
), ));
))
.unwrap();
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
} }
@ -582,9 +556,8 @@ impl Tab {
let active_pane_id = &self.get_active_pane_id().unwrap(); let active_pane_id = &self.get_active_pane_id().unwrap();
let active_pane = self.panes.get_mut(active_pane_id).unwrap(); let active_pane = self.panes.get_mut(active_pane_id).unwrap();
if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 { if active_pane.columns() < MIN_TERMINAL_WIDTH * 2 + 1 {
self.send_app_instructions self.os_api
.send(AppInstruction::ToPty(PtyInstruction::ClosePane(pid))) // we can't open this pane, close the pty .send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid))); // we can't open this pane, close the pty
.unwrap();
return; return;
} }
let terminal_ws = PositionAndSize { let terminal_ws = PositionAndSize {
@ -598,27 +571,23 @@ impl Tab {
active_pane.change_pos_and_size(&left_winsize); active_pane.change_pos_and_size(&left_winsize);
let new_terminal = TerminalPane::new(term_pid, right_winsize); let new_terminal = TerminalPane::new(term_pid, right_winsize);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( new_terminal.pid,
new_terminal.pid, right_winsize.columns as u16,
right_winsize.columns as u16, right_winsize.rows as u16,
right_winsize.rows as u16, ),
), ));
))
.unwrap();
self.panes.insert(pid, Box::new(new_terminal)); self.panes.insert(pid, Box::new(new_terminal));
if let PaneId::Terminal(active_terminal_pid) = active_pane_id { if let PaneId::Terminal(active_terminal_pid) = active_pane_id {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( *active_terminal_pid,
*active_terminal_pid, left_winsize.columns as u16,
left_winsize.columns as u16, left_winsize.rows as u16,
left_winsize.rows as u16, ),
), ));
))
.unwrap();
} }
self.active_terminal = Some(pid); self.active_terminal = Some(pid);
@ -676,16 +645,12 @@ impl Tab {
Some(PaneId::Terminal(active_terminal_id)) => { Some(PaneId::Terminal(active_terminal_id)) => {
let active_terminal = self.get_active_pane().unwrap(); let active_terminal = self.get_active_pane().unwrap();
let adjusted_input = active_terminal.adjust_input_to_terminal(input_bytes); let adjusted_input = active_terminal.adjust_input_to_terminal(input_bytes);
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::WriteToTtyStdin(active_terminal_id, adjusted_input),
ServerOsApiInstruction::WriteToTtyStdin(active_terminal_id, adjusted_input), ));
)) self.os_api.send_to_server(ServerInstruction::OsApi(
.unwrap(); ServerOsApiInstruction::TcDrain(active_terminal_id),
self.send_app_instructions ));
.send(AppInstruction::OsApi(ServerOsApiInstruction::TcDrain(
active_terminal_id,
)))
.unwrap();
} }
Some(PaneId::Plugin(pid)) => { Some(PaneId::Plugin(pid)) => {
for key in parse_keys(&input_bytes) { for key in parse_keys(&input_bytes) {
@ -747,15 +712,13 @@ impl Tab {
} }
let active_terminal = self.panes.get(&active_pane_id).unwrap(); let active_terminal = self.panes.get(&active_pane_id).unwrap();
if let PaneId::Terminal(active_pid) = active_pane_id { if let PaneId::Terminal(active_pid) = active_pane_id {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( active_pid,
active_pid, active_terminal.columns() as u16,
active_terminal.columns() as u16, active_terminal.rows() as u16,
active_terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
self.render(); self.render();
self.toggle_fullscreen_is_active(); self.toggle_fullscreen_is_active();
@ -1315,120 +1278,104 @@ impl Tab {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.reduce_height_down(count); terminal.reduce_height_down(count);
if let PaneId::Terminal(pid) = id { if let PaneId::Terminal(pid) = id {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( *pid,
*pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn reduce_pane_height_up(&mut self, id: &PaneId, count: usize) { fn reduce_pane_height_up(&mut self, id: &PaneId, count: usize) {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.reduce_height_up(count); terminal.reduce_height_up(count);
if let PaneId::Terminal(pid) = id { if let PaneId::Terminal(pid) = id {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( *pid,
*pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn increase_pane_height_down(&mut self, id: &PaneId, count: usize) { fn increase_pane_height_down(&mut self, id: &PaneId, count: usize) {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.increase_height_down(count); terminal.increase_height_down(count);
if let PaneId::Terminal(pid) = terminal.pid() { if let PaneId::Terminal(pid) = terminal.pid() {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( pid,
pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn increase_pane_height_up(&mut self, id: &PaneId, count: usize) { fn increase_pane_height_up(&mut self, id: &PaneId, count: usize) {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.increase_height_up(count); terminal.increase_height_up(count);
if let PaneId::Terminal(pid) = terminal.pid() { if let PaneId::Terminal(pid) = terminal.pid() {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( pid,
pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn increase_pane_width_right(&mut self, id: &PaneId, count: usize) { fn increase_pane_width_right(&mut self, id: &PaneId, count: usize) {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.increase_width_right(count); terminal.increase_width_right(count);
if let PaneId::Terminal(pid) = terminal.pid() { if let PaneId::Terminal(pid) = terminal.pid() {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( pid,
pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn increase_pane_width_left(&mut self, id: &PaneId, count: usize) { fn increase_pane_width_left(&mut self, id: &PaneId, count: usize) {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.increase_width_left(count); terminal.increase_width_left(count);
if let PaneId::Terminal(pid) = terminal.pid() { if let PaneId::Terminal(pid) = terminal.pid() {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( pid,
pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn reduce_pane_width_right(&mut self, id: &PaneId, count: usize) { fn reduce_pane_width_right(&mut self, id: &PaneId, count: usize) {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.reduce_width_right(count); terminal.reduce_width_right(count);
if let PaneId::Terminal(pid) = terminal.pid() { if let PaneId::Terminal(pid) = terminal.pid() {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( pid,
pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn reduce_pane_width_left(&mut self, id: &PaneId, count: usize) { fn reduce_pane_width_left(&mut self, id: &PaneId, count: usize) {
let terminal = self.panes.get_mut(id).unwrap(); let terminal = self.panes.get_mut(id).unwrap();
terminal.reduce_width_left(count); terminal.reduce_width_left(count);
if let PaneId::Terminal(pid) = terminal.pid() { if let PaneId::Terminal(pid) = terminal.pid() {
self.send_app_instructions self.os_api.send_to_server(ServerInstruction::OsApi(
.send(AppInstruction::OsApi( ServerOsApiInstruction::SetTerminalSizeUsingFd(
ServerOsApiInstruction::SetTerminalSizeUsingFd( pid,
pid, terminal.columns() as u16,
terminal.columns() as u16, terminal.rows() as u16,
terminal.rows() as u16, ),
), ));
))
.unwrap();
} }
} }
fn pane_is_between_vertical_borders( fn pane_is_between_vertical_borders(
@ -2197,9 +2144,8 @@ impl Tab {
if let Some(max_panes) = self.max_panes { if let Some(max_panes) = self.max_panes {
let terminals = self.get_pane_ids(); let terminals = self.get_pane_ids();
for &pid in terminals.iter().skip(max_panes - 1) { for &pid in terminals.iter().skip(max_panes - 1) {
self.send_app_instructions self.os_api
.send(AppInstruction::ToPty(PtyInstruction::ClosePane(pid))) .send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(pid)));
.unwrap();
self.close_pane_without_rerender(pid); self.close_pane_without_rerender(pid);
} }
} }
@ -2309,11 +2255,10 @@ impl Tab {
pub fn close_focused_pane(&mut self) { pub fn close_focused_pane(&mut self) {
if let Some(active_pane_id) = self.get_active_pane_id() { if let Some(active_pane_id) = self.get_active_pane_id() {
self.close_pane(active_pane_id); self.close_pane(active_pane_id);
self.send_app_instructions self.os_api
.send(AppInstruction::ToPty(PtyInstruction::ClosePane( .send_to_server(ServerInstruction::ToPty(PtyInstruction::ClosePane(
active_pane_id, active_pane_id,
))) )));
.unwrap();
} }
} }
pub fn scroll_active_terminal_up(&mut self) { pub fn scroll_active_terminal_up(&mut self) {

View file

@ -350,11 +350,8 @@ impl From<&PluginInstruction> for PluginContext {
pub enum AppContext { pub enum AppContext {
Exit, Exit,
Error, Error,
ToPty,
ToPlugin,
ToScreen,
DoneClosingPane, DoneClosingPane,
OsApi, ToPty,
} }
impl From<&AppInstruction> for AppContext { impl From<&AppInstruction> for AppContext {
@ -362,11 +359,8 @@ impl From<&AppInstruction> for AppContext {
match *app_instruction { match *app_instruction {
AppInstruction::Exit => AppContext::Exit, AppInstruction::Exit => AppContext::Exit,
AppInstruction::Error(_) => AppContext::Error, AppInstruction::Error(_) => AppContext::Error,
AppInstruction::ToPty(_) => AppContext::ToPty,
AppInstruction::OsApi(_) => AppContext::OsApi,
AppInstruction::ToPlugin(_) => AppContext::ToPlugin,
AppInstruction::ToScreen(_) => AppContext::ToScreen,
AppInstruction::DoneClosingPane => AppContext::DoneClosingPane, AppInstruction::DoneClosingPane => AppContext::DoneClosingPane,
AppInstruction::ToPty(_) => AppContext::ToPty,
} }
} }
} }

View file

@ -8,6 +8,7 @@ use crate::errors::ContextType;
use crate::os_input_output::ClientOsApi; use crate::os_input_output::ClientOsApi;
use crate::pty_bus::PtyInstruction; use crate::pty_bus::PtyInstruction;
use crate::screen::ScreenInstruction; use crate::screen::ScreenInstruction;
use crate::server::ServerInstruction;
use crate::wasm_vm::PluginInstruction; use crate::wasm_vm::PluginInstruction;
use crate::CommandIsExecuting; use crate::CommandIsExecuting;
@ -56,6 +57,7 @@ impl InputHandler {
err_ctx.add_call(ContextType::StdinHandler); err_ctx.add_call(ContextType::StdinHandler);
self.send_app_instructions.update(err_ctx); self.send_app_instructions.update(err_ctx);
self.send_screen_instructions.update(err_ctx); self.send_screen_instructions.update(err_ctx);
self.os_input.update_senders(err_ctx);
if let Ok(keybinds) = get_default_keybinds() { if let Ok(keybinds) = get_default_keybinds() {
'input_loop: loop { 'input_loop: loop {
//@@@ I think this should actually just iterate over stdin directly //@@@ I think this should actually just iterate over stdin directly
@ -225,9 +227,8 @@ impl InputHandler {
None => PtyInstruction::SpawnTerminal(None), None => PtyInstruction::SpawnTerminal(None),
}; };
self.command_is_executing.opening_new_pane(); self.command_is_executing.opening_new_pane();
self.send_app_instructions self.os_input
.send(AppInstruction::ToPty(pty_instr)) .send_to_server(ServerInstruction::ToPty(pty_instr));
.unwrap();
self.command_is_executing.wait_until_new_pane_is_opened(); self.command_is_executing.wait_until_new_pane_is_opened();
} }
Action::CloseFocus => { Action::CloseFocus => {
@ -239,9 +240,8 @@ impl InputHandler {
} }
Action::NewTab => { Action::NewTab => {
self.command_is_executing.updating_tabs(); self.command_is_executing.updating_tabs();
self.send_app_instructions self.os_input
.send(AppInstruction::ToPty(PtyInstruction::NewTab)) .send_to_server(ServerInstruction::ToPty(PtyInstruction::NewTab));
.unwrap();
self.command_is_executing.wait_until_tabs_are_updated(); self.command_is_executing.wait_until_tabs_are_updated();
} }
Action::GoToNextTab => { Action::GoToNextTab => {

View file

@ -24,7 +24,7 @@ pub enum ClientType {
// Types of messages sent from the client to the server // Types of messages sent from the client to the server
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub enum ClientToServerMsg { pub enum _ClientToServerMsg {
// List which sessions are available // List which sessions are available
ListSessions, ListSessions,
// Create a new session // Create a new session

View file

@ -189,7 +189,7 @@ impl<T: Serialize> IpcSenderWithContext<T> {
/// Sends an event, along with the current [`ErrorContext`], on this /// Sends an event, along with the current [`ErrorContext`], on this
/// [`IpcSenderWithContext`]'s channel. /// [`IpcSenderWithContext`]'s channel.
fn send(&mut self, msg: T) -> ipmpsc::Result<()> { fn send(&self, msg: T) -> ipmpsc::Result<()> {
self.sender.send(&(msg, self.err_ctx)) self.sender.send(&(msg, self.err_ctx))
} }
} }
@ -335,7 +335,7 @@ pub trait ClientOsApi: Send + Sync {
/// Returns a [`Box`] pointer to this [`ClientOsApi`] struct. /// Returns a [`Box`] pointer to this [`ClientOsApi`] struct.
fn box_clone(&self) -> Box<dyn ClientOsApi>; fn box_clone(&self) -> Box<dyn ClientOsApi>;
/// Sends a message to the server. /// Sends a message to the server.
fn send_to_server(&mut self, msg: ServerInstruction); fn send_to_server(&self, msg: ServerInstruction);
/// Update ErrorContext of senders /// Update ErrorContext of senders
fn update_senders(&mut self, new_ctx: ErrorContext); fn update_senders(&mut self, new_ctx: ErrorContext);
/// Receives a message on client-side IPC channel /// Receives a message on client-side IPC channel
@ -372,7 +372,7 @@ impl ClientOsApi for ClientOsInputOutput {
let stdout = ::std::io::stdout(); let stdout = ::std::io::stdout();
Box::new(stdout) Box::new(stdout)
} }
fn send_to_server(&mut self, msg: ServerInstruction) { fn send_to_server(&self, msg: ServerInstruction) {
self.server_sender.send(msg).unwrap(); self.server_sender.send(msg).unwrap();
} }
fn update_senders(&mut self, new_ctx: ErrorContext) { fn update_senders(&mut self, new_ctx: ErrorContext) {

View file

@ -11,7 +11,8 @@ use crate::client::AppInstruction;
use crate::common::SenderWithContext; use crate::common::SenderWithContext;
use crate::os_input_output::ClientOsApi; use crate::os_input_output::ClientOsApi;
use crate::panes::PositionAndSize; use crate::panes::PositionAndSize;
use crate::pty_bus::{PtyInstruction, VteBytes}; use crate::pty_bus::{PtyInstruction, VteEvent};
use crate::server::ServerInstruction;
use crate::tab::Tab; use crate::tab::Tab;
use crate::{errors::ErrorContext, wasm_vm::PluginInstruction}; use crate::{errors::ErrorContext, wasm_vm::PluginInstruction};
use crate::{layout::Layout, panes::PaneId}; use crate::{layout::Layout, panes::PaneId};
@ -80,7 +81,7 @@ pub struct Screen {
/// The index of this [`Screen`]'s active [`Tab`]. /// The index of this [`Screen`]'s active [`Tab`].
active_tab_index: Option<usize>, active_tab_index: Option<usize>,
/// The [`ClientOsApi`] this [`Screen`] uses. /// The [`ClientOsApi`] this [`Screen`] uses.
os_api: Box<dyn ClientOsApi>, pub os_api: Box<dyn ClientOsApi>,
input_mode: InputMode, input_mode: InputMode,
} }
@ -210,9 +211,8 @@ impl Screen {
// below we don't check the result of sending the CloseTab instruction to the pty thread // 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 // because this might be happening when the app is closing, at which point the pty thread
// has already closed and this would result in an error // has already closed and this would result in an error
let _ = self self.os_api
.send_app_instructions .send_to_server(ServerInstruction::ToPty(PtyInstruction::CloseTab(pane_ids)));
.send(AppInstruction::ToPty(PtyInstruction::CloseTab(pane_ids)));
if self.tabs.is_empty() { if self.tabs.is_empty() {
self.active_tab_index = None; self.active_tab_index = None;
self.send_app_instructions self.send_app_instructions

View file

@ -165,11 +165,21 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread
.name("server_router".to_string()) .name("server_router".to_string())
.spawn({ .spawn({
let os_input = os_input.clone(); let os_input = os_input.clone();
let mut send_os_instructions = send_os_instructions.clone();
let mut send_pty_instructions = send_pty_instructions.clone();
move || loop { move || loop {
let (instruction, err_ctx) = os_input.server_recv(); let (instruction, err_ctx) = os_input.server_recv();
send_server_instructions.update(err_ctx); send_server_instructions.update(err_ctx);
send_pty_instructions.update(err_ctx);
send_os_instructions.update(err_ctx);
match instruction { match instruction {
ServerInstruction::Exit => break, ServerInstruction::Exit => break,
ServerInstruction::ToPty(instruction) => {
send_pty_instructions.send(instruction).unwrap();
}
ServerInstruction::OsApi(instruction) => {
send_os_instructions.send(instruction).unwrap();
}
_ => { _ => {
send_server_instructions.send(instruction).unwrap(); send_server_instructions.send(instruction).unwrap();
} }
@ -213,15 +223,9 @@ pub fn start_server(mut os_input: Box<dyn ServerOsApi>, opts: CliArgs) -> thread
send_pty_instructions.send(PtyInstruction::NewTab).unwrap(); send_pty_instructions.send(PtyInstruction::NewTab).unwrap();
os_input.add_client_sender(buffer_path); os_input.add_client_sender(buffer_path);
} }
ServerInstruction::ToPty(instr) => {
send_pty_instructions.send(instr).unwrap();
}
ServerInstruction::ToScreen(instr) => { ServerInstruction::ToScreen(instr) => {
os_input.send_to_client(ClientInstruction::ToScreen(instr)); os_input.send_to_client(ClientInstruction::ToScreen(instr));
} }
ServerInstruction::OsApi(instr) => {
send_os_instructions.send(instr).unwrap();
}
ServerInstruction::DoneClosingPane => { ServerInstruction::DoneClosingPane => {
os_input.send_to_client(ClientInstruction::DoneClosingPane); os_input.send_to_client(ClientInstruction::DoneClosingPane);
} }

View file

@ -183,7 +183,7 @@ impl ClientOsApi for FakeInputOutput {
fn get_stdout_writer(&self) -> Box<dyn Write> { fn get_stdout_writer(&self) -> Box<dyn Write> {
Box::new(self.stdout_writer.clone()) Box::new(self.stdout_writer.clone())
} }
fn send_to_server(&mut self, msg: ServerInstruction) { fn send_to_server(&self, msg: ServerInstruction) {
self.server_sender.send(msg).unwrap(); self.server_sender.send(msg).unwrap();
} }
fn update_senders(&mut self, new_ctx: ErrorContext) { fn update_senders(&mut self, new_ctx: ErrorContext) {