summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock12
-rw-r--r--src/client/mod.rs17
-rw-r--r--src/client/pane_resizer.rs6
-rw-r--r--src/client/tab.rs17
-rw-r--r--src/common/errors.rs2
-rw-r--r--src/common/input/handler.rs2
-rw-r--r--src/common/os_input_output.rs16
-rw-r--r--src/common/screen.rs7
-rw-r--r--src/server/mod.rs18
-rw-r--r--src/tests/fakes.rs42
-rw-r--r--src/tests/integration/terminal_window_resize.rs24
11 files changed, 117 insertions, 46 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 72f684cc8..38937d8b7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -132,7 +132,7 @@ dependencies = [
"event-listener",
"futures-lite",
"once_cell",
- "signal-hook 0.3.6",
+ "signal-hook",
"winapi",
]
@@ -1563,16 +1563,6 @@ dependencies = [
[[package]]
name = "signal-hook"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
-dependencies = [
- "libc",
- "signal-hook-registry",
-]
-
-[[package]]
-name = "signal-hook"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7f3f92a1da3d6b1d32245d0cbcbbab0cfc45996d8df619c42bccfa6d2bbb5f"
diff --git a/src/client/mod.rs b/src/client/mod.rs
index ae298a5eb..b6a0231a1 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -69,6 +69,23 @@ pub fn start_client(mut os_input: Box<dyn ClientOsApi>) {
move || input_loop(os_input, command_is_executing, send_client_instructions)
});
+ let _signal_thread = thread::Builder::new()
+ .name("signal_listener".to_string())
+ .spawn({
+ let os_input = os_input.clone();
+ move || {
+ os_input.receive_sigwinch(Box::new({
+ let os_api = os_input.clone();
+ move || {
+ os_api.send_to_server(ServerInstruction::terminal_resize(
+ os_api.get_terminal_size_using_fd(0),
+ ));
+ }
+ }));
+ }
+ })
+ .unwrap();
+
let router_thread = thread::Builder::new()
.name("router".to_string())
.spawn({
diff --git a/src/client/pane_resizer.rs b/src/client/pane_resizer.rs
index f9ec71b82..73678499c 100644
--- a/src/client/pane_resizer.rs
+++ b/src/client/pane_resizer.rs
@@ -1,4 +1,4 @@
-use crate::os_input_output::OsApi;
+use crate::os_input_output::ServerOsApi;
use crate::panes::{PaneId, PositionAndSize};
use crate::tab::Pane;
use std::{
@@ -8,7 +8,7 @@ use std::{
pub struct PaneResizer<'a> {
panes: &'a mut BTreeMap<PaneId, Box<dyn Pane>>,
- os_api: &'a mut Box<dyn OsApi>,
+ os_api: &'a mut Box<dyn ServerOsApi>,
}
// TODO: currently there are some functions here duplicated with Tab
@@ -17,7 +17,7 @@ pub struct PaneResizer<'a> {
impl<'a> PaneResizer<'a> {
pub fn new(
panes: &'a mut BTreeMap<PaneId, Box<dyn Pane>>,
- os_api: &'a mut Box<dyn OsApi>,
+ os_api: &'a mut Box<dyn ServerOsApi>,
) -> Self {
PaneResizer { panes, os_api }
}
diff --git a/src/client/tab.rs b/src/client/tab.rs
index 4eabab100..3817a3274 100644
--- a/src/client/tab.rs
+++ b/src/client/tab.rs
@@ -2,22 +2,24 @@
//! as well as how they should be resized
use crate::boundaries::colors;
+use crate::client::pane_resizer::PaneResizer;
use crate::common::{input::handler::parse_keys, SenderWithContext};
use crate::layout::Layout;
use crate::os_input_output::ServerOsApi;
use crate::panes::{PaneId, PositionAndSize, TerminalPane};
use crate::pty_bus::{PtyInstruction, VteEvent};
use crate::server::ServerInstruction;
-use crate::utils::shared::pad_to_size;
+use crate::utils::shared::adjust_to_size;
use crate::wasm_vm::PluginInstruction;
use crate::{boundaries::Boundaries, panes::PluginPane};
+use serde::{Deserialize, Serialize};
use std::os::unix::io::RawFd;
use std::sync::mpsc::channel;
use std::{
cmp::Reverse,
collections::{BTreeMap, HashSet},
};
-use zellij_tile::data::{Event, InputMode};
+use zellij_tile::data::{Event, ModeInfo};
const CURSOR_HEIGHT_WIDTH_RATIO: usize = 4; // this is not accurate and kind of a magic number, TODO: look into this
@@ -729,9 +731,14 @@ impl Tab {
);
let hide_cursor = "\u{1b}[?25l";
output.push_str(hide_cursor);
- for (kind, terminal) in self.panes.iter_mut() {
- if !self.panes_to_hide.contains(&terminal.pid()) {
- match self.active_terminal.unwrap() == terminal.pid() {
+ if self.should_clear_display_before_rendering {
+ let clear_display = "\u{1b}[2J";
+ output.push_str(clear_display);
+ self.should_clear_display_before_rendering = false;
+ }
+ for (kind, pane) in self.panes.iter_mut() {
+ if !self.panes_to_hide.contains(&pane.pid()) {
+ match self.active_terminal.unwrap() == pane.pid() {
true => {
pane.set_active_at(Instant::now());
boundaries.add_rect(pane.as_ref(), self.mode_info.mode, Some(self.colors))
diff --git a/src/common/errors.rs b/src/common/errors.rs
index 720341a45..10b2165a0 100644
--- a/src/common/errors.rs
+++ b/src/common/errors.rs
@@ -259,7 +259,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::CloseTab => ScreenContext::CloseTab,
ScreenInstruction::GoToTab(_) => ScreenContext::GoToTab,
ScreenInstruction::UpdateTabName(_) => ScreenContext::UpdateTabName,
- ScreenInstruction::TerminalResize => ScreenContext::TerminalResize,
+ ScreenInstruction::TerminalResize(_) => ScreenContext::TerminalResize,
ScreenInstruction::ChangeMode(_) => ScreenContext::ChangeMode,
ScreenInstruction::ToggleActiveSyncPanes => ScreenContext::ToggleActiveSyncPanes,
}
diff --git a/src/common/input/handler.rs b/src/common/input/handler.rs
index 4015938a1..947a8d02a 100644
--- a/src/common/input/handler.rs
+++ b/src/common/input/handler.rs
@@ -127,7 +127,7 @@ impl InputHandler {
Event::ModeUpdate(get_mode_info(mode)),
));
self.os_input
- .send_to_server(ServerInstruction::change_input_mode(mode));
+ .send_to_server(ServerInstruction::change_mode(get_mode_info(mode)));
self.os_input.send_to_server(ServerInstruction::render());
}
Action::Resize(direction) => {
diff --git a/src/common/os_input_output.rs b/src/common/os_input_output.rs
index 53300424d..66957a4a1 100644
--- a/src/common/os_input_output.rs
+++ b/src/common/os_input_output.rs
@@ -7,6 +7,7 @@ use nix::sys::wait::waitpid;
use nix::unistd;
use nix::unistd::{ForkResult, Pid};
use serde::Serialize;
+use signal_hook::{consts::signal::*, iterator::Signals};
use std::env;
use std::io;
use std::io::prelude::*;
@@ -334,6 +335,7 @@ pub trait ClientOsApi: Send + Sync {
fn client_recv(&self) -> (ClientInstruction, ErrorContext);
/// Setup the client IpcChannel and notify server of new client
fn connect_to_server(&mut self, full_screen_ws: PositionAndSize);
+ fn receive_sigwinch(&self, cb: Box<dyn Fn()>);
}
impl ClientOsApi for ClientOsInputOutput {
@@ -389,6 +391,20 @@ impl ClientOsApi for ClientOsInputOutput {
.recv()
.unwrap()
}
+ fn receive_sigwinch(&self, cb: Box<dyn Fn()>) {
+ let mut signals = Signals::new(&[SIGWINCH, SIGTERM, SIGINT, SIGQUIT]).unwrap();
+ for signal in signals.forever() {
+ match signal {
+ SIGWINCH => {
+ cb();
+ }
+ SIGTERM | SIGINT | SIGQUIT => {
+ break;
+ }
+ _ => unreachable!(),
+ }
+ }
+ }
}
impl Clone for Box<dyn ClientOsApi> {
diff --git a/src/common/screen.rs b/src/common/screen.rs
index 8868febb4..92e1075c2 100644
--- a/src/common/screen.rs
+++ b/src/common/screen.rs
@@ -58,7 +58,7 @@ pub enum ScreenInstruction {
CloseTab,
GoToTab(u32),
UpdateTabName(Vec<u8>),
- TerminalResize,
+ TerminalResize(PositionAndSize),
ChangeMode(ModeInfo),
}
@@ -83,7 +83,7 @@ pub struct Screen {
active_tab_index: Option<usize>,
/// The [`ClientOsApi`] this [`Screen`] uses.
os_api: Box<dyn ServerOsApi>,
- input_mode: InputMode,
+ mode_info: ModeInfo,
}
impl Screen {
@@ -233,8 +233,7 @@ impl Screen {
}
}
- pub fn resize_to_screen(&mut self) {
- let new_screen_size = self.os_api.get_terminal_size_using_fd(0);
+ pub fn resize_to_screen(&mut self, new_screen_size: PositionAndSize) {
self.full_screen_ws = new_screen_size;
for (_, tab) in self.tabs.iter_mut() {
tab.resize_whole_tab(new_screen_size);
diff --git a/src/server/mod.rs b/src/server/mod.rs
index 5f1227993..2495c13d6 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -12,7 +12,7 @@ use std::{
};
use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
use wasmer_wasi::{Pipe, WasiState};
-use zellij_tile::data::{Event, EventType, InputMode};
+use zellij_tile::data::{Event, EventType, ModeInfo};
use crate::cli::CliArgs;
use crate::client::ClientInstruction;
@@ -168,12 +168,15 @@ impl ServerInstruction {
pub fn update_tab_name(tab_ids: Vec<u8>) -> Self {
Self::ToScreen(ScreenInstruction::UpdateTabName(tab_ids))
}
- pub fn change_input_mode(input_mode: InputMode) -> Self {
- Self::ToScreen(ScreenInstruction::ChangeInputMode(input_mode))
+ pub fn change_mode(mode_info: ModeInfo) -> Self {
+ Self::ToScreen(ScreenInstruction::ChangeMode(mode_info))
}
pub fn pty(fd: RawFd, event: VteEvent) -> Self {
Self::ToScreen(ScreenInstruction::Pty(fd, event))
}
+ pub fn terminal_resize(new_size: PositionAndSize) -> Self {
+ Self::ToScreen(ScreenInstruction::TerminalResize(new_size))
+ }
}
struct ClientMetaData {
@@ -450,7 +453,7 @@ fn init_client(
&full_screen_ws,
os_input,
max_panes,
- InputMode::Normal,
+ ModeInfo::default(),
);
loop {
let (event, mut err_ctx) = screen
@@ -625,8 +628,11 @@ fn init_client(
.send(ServerInstruction::DoneUpdatingTabs)
.unwrap();
}
- ScreenInstruction::ChangeInputMode(input_mode) => {
- screen.change_input_mode(input_mode);
+ ScreenInstruction::ChangeMode(mode_info) => {
+ screen.change_mode(mode_info);
+ }
+ ScreenInstruction::TerminalResize(new_size) => {
+ screen.resize_to_screen(new_size);
}
ScreenInstruction::Exit => {
break;
diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs
index f5b03fde2..8c608de34 100644
--- a/src/tests/fakes.rs
+++ b/src/tests/fakes.rs
@@ -3,8 +3,7 @@ use std::collections::{HashMap, VecDeque};
use std::io::Write;
use std::os::unix::io::RawFd;
use std::path::PathBuf;
-use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::{mpsc, Arc, Mutex};
+use std::sync::{mpsc, Arc, Condvar, Mutex};
use std::time::{Duration, Instant};
use crate::client::ClientInstruction;
@@ -13,8 +12,7 @@ use crate::errors::ErrorContext;
use crate::os_input_output::{ClientOsApi, ServerOsApi};
use crate::server::ServerInstruction;
use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes};
-use crate::utils::shared::default_palette;
-use zellij_tile::data::Palette;
+use crate::tests::utils::commands::{QUIT, SLEEP};
const MIN_TIME_BETWEEN_SNAPSHOTS: Duration = Duration::from_millis(150);
@@ -76,11 +74,12 @@ pub struct FakeInputOutput {
win_sizes: Arc<Mutex<HashMap<RawFd, PositionAndSize>>>,
possible_tty_inputs: HashMap<u16, Bytes>,
last_snapshot_time: Arc<Mutex<Instant>>,
- started_reading_from_pty: Arc<AtomicBool>,
client_sender: SenderWithContext<ClientInstruction>,
client_receiver: Arc<Mutex<mpsc::Receiver<(ClientInstruction, ErrorContext)>>>,
server_sender: SenderWithContext<ServerInstruction>,
server_receiver: Arc<Mutex<mpsc::Receiver<(ServerInstruction, ErrorContext)>>>,
+ should_trigger_sigwinch: Arc<(Mutex<bool>, Condvar)>,
+ sigwinch_event: Option<PositionAndSize>,
}
impl FakeInputOutput {
@@ -108,11 +107,12 @@ impl FakeInputOutput {
io_events: Arc::new(Mutex::new(vec![])),
win_sizes: Arc::new(Mutex::new(win_sizes)),
possible_tty_inputs: get_possible_tty_inputs(),
- started_reading_from_pty: Arc::new(AtomicBool::new(false)),
server_receiver: Arc::new(Mutex::new(server_receiver)),
server_sender,
client_receiver: Arc::new(Mutex::new(client_receiver)),
client_sender,
+ should_trigger_sigwinch: Arc::new((Mutex::new(false), Condvar::new())),
+ sigwinch_event: None,
}
}
pub fn with_tty_inputs(mut self, tty_inputs: HashMap<u16, Bytes>) -> Self {
@@ -171,14 +171,24 @@ impl ClientOsApi for FakeInputOutput {
::std::thread::sleep(MIN_TIME_BETWEEN_SNAPSHOTS - last_snapshot_time.elapsed());
}
}
- if self.stdin_commands.lock().unwrap().len() == 1 {
- std::thread::sleep(Duration::from_millis(100));
- }
- self.stdin_commands
+ let command = self
+ .stdin_commands
.lock()
.unwrap()
.pop_front()
- .unwrap_or(vec![])
+ .unwrap_or(vec![]);
+ if command == SLEEP {
+ std::thread::sleep(std::time::Duration::from_millis(200));
+ } else if command == QUIT && self.sigwinch_event.is_some() {
+ let (lock, cvar) = &*self.should_trigger_sigwinch;
+ let mut should_trigger_sigwinch = lock.lock().unwrap();
+ *should_trigger_sigwinch = true;
+ cvar.notify_one();
+ ::std::thread::sleep(MIN_TIME_BETWEEN_SNAPSHOTS); // give some time for the app to resize before quitting
+ } else if command == QUIT {
+ ::std::thread::sleep(MIN_TIME_BETWEEN_SNAPSHOTS);
+ }
+ command
}
fn get_stdout_writer(&self) -> Box<dyn Write> {
Box::new(self.stdout_writer.clone())
@@ -199,6 +209,16 @@ impl ClientOsApi for FakeInputOutput {
fn client_recv(&self) -> (ClientInstruction, ErrorContext) {
self.client_receiver.lock().unwrap().recv().unwrap()
}
+ fn receive_sigwinch(&self, cb: Box<dyn Fn()>) {
+ if self.sigwinch_event.is_some() {
+ let (lock, cvar) = &*self.should_trigger_sigwinch;
+ let mut should_trigger_sigwinch = lock.lock().unwrap();
+ while !*should_trigger_sigwinch {
+ should_trigger_sigwinch = cvar.wait(should_trigger_sigwinch).unwrap();
+ }
+ cb();
+ }
+ }
}
impl ServerOsApi for FakeInputOutput {
diff --git a/src/tests/integration/terminal_window_resize.rs b/src/tests/integration/terminal_window_resize.rs
index ebea82c0a..5aa13e150 100644
--- a/src/tests/integration/terminal_window_resize.rs
+++ b/src/tests/integration/terminal_window_resize.rs
@@ -30,7 +30,11 @@ pub fn window_width_decrease_with_one_pane() {
..Default::default()
});
let opts = CliArgs::default();
- start(Box::new(fake_input_output.clone()), opts, Config::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ opts,
+ Box::new(fake_input_output.clone()),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -61,7 +65,11 @@ pub fn window_width_increase_with_one_pane() {
..Default::default()
});
let opts = CliArgs::default();
- start(Box::new(fake_input_output.clone()), opts, Config::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ opts,
+ Box::new(fake_input_output.clone()),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -92,7 +100,11 @@ pub fn window_height_increase_with_one_pane() {
..Default::default()
});
let opts = CliArgs::default();
- start(Box::new(fake_input_output.clone()), opts, Config::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ opts,
+ Box::new(fake_input_output.clone()),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames
@@ -123,7 +135,11 @@ pub fn window_width_and_height_decrease_with_one_pane() {
..Default::default()
});
let opts = CliArgs::default();
- start(Box::new(fake_input_output.clone()), opts, Config::default());
+ start(
+ Box::new(fake_input_output.clone()),
+ opts,
+ Box::new(fake_input_output.clone()),
+ );
let output_frames = fake_input_output
.stdout_writer
.output_frames