fix(startup): recover from race condition that causes Zellij to start in the wrong size (#3218)

* fix(startup): recover from Zellij starting up in the wrong size

* style(fmt): rustfmt

* fix tests
This commit is contained in:
Aram Drevekenin 2024-03-25 10:28:21 +01:00 committed by GitHub
parent b24386e6b1
commit 86e91ae137
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 24 additions and 2 deletions

View file

@ -51,6 +51,7 @@ pub(crate) enum ClientInstruction {
SetSynchronizedOutput(Option<SyncOutput>),
UnblockCliPipeInput(String), // String -> pipe name
CliPipeOutput(String, String), // String -> pipe name, String -> output
QueryTerminalSize,
}
impl From<ServerToClientMsg> for ClientInstruction {
@ -75,6 +76,7 @@ impl From<ServerToClientMsg> for ClientInstruction {
ServerToClientMsg::CliPipeOutput(pipe_name, output) => {
ClientInstruction::CliPipeOutput(pipe_name, output)
},
ServerToClientMsg::QueryTerminalSize => ClientInstruction::QueryTerminalSize,
}
}
}
@ -97,6 +99,7 @@ impl From<&ClientInstruction> for ClientContext {
ClientInstruction::SetSynchronizedOutput(..) => ClientContext::SetSynchronisedOutput,
ClientInstruction::UnblockCliPipeInput(..) => ClientContext::UnblockCliPipeInput,
ClientInstruction::CliPipeOutput(..) => ClientContext::CliPipeOutput,
ClientInstruction::QueryTerminalSize => ClientContext::QueryTerminalSize,
}
}
}
@ -499,6 +502,11 @@ pub fn start_client(
ClientInstruction::SetSynchronizedOutput(enabled) => {
synchronised_output = enabled;
},
ClientInstruction::QueryTerminalSize => {
os_input.send_to_server(ClientToServerMsg::TerminalResize(
os_input.get_terminal_size_using_fd(0),
));
},
_ => {},
}
}

View file

@ -3000,6 +3000,18 @@ pub(crate) fn screen_thread_main(
screen.unblock_input()?;
screen.render(None)?;
// we do this here in order to recover from a race condition on app start
// that sometimes causes Zellij to think the terminal window is a different size
// than it actually is - here, we query the client for its terminal size after
// we've finished the setup and handle it as we handle a normal resize,
// while this can affect other instances of a layout being applied, the query is
// very short and cheap and shouldn't cause any trouble
if let Some(os_input) = &mut screen.bus.os_input {
for client_id in screen.connected_clients.borrow().iter() {
let _ = os_input
.send_to_client(*client_id, ServerToClientMsg::QueryTerminalSize);
}
}
},
ScreenInstruction::GoToTab(tab_index, client_id) => {
let client_id_to_switch = if client_id.is_none() {

View file

@ -1,6 +1,6 @@
---
source: zellij-server/src/./unit/screen_tests.rs
assertion_line: 1711
assertion_line: 2465
expression: "format!(\"{:?}\", *\n mock_screen.os_input.server_to_client_messages.lock().unwrap())"
---
{1: [SwitchToMode(Locked)]}
{1: [QueryTerminalSize, SwitchToMode(Locked)]}

View file

@ -424,6 +424,7 @@ pub enum ClientContext {
SetSynchronisedOutput,
UnblockCliPipeInput,
CliPipeOutput,
QueryTerminalSize,
}
/// Stack call representations corresponding to the different types of [`ServerInstruction`]s.

View file

@ -105,6 +105,7 @@ pub enum ServerToClientMsg {
SwitchSession(ConnectToSession),
UnblockCliPipeInput(String), // String -> pipe name
CliPipeOutput(String, String), // String -> pipe name, String -> Output
QueryTerminalSize,
}
#[derive(Serialize, Deserialize, Debug, Clone)]