diff --git a/src/docker_data/mod.rs b/src/docker_data/mod.rs index 5d998e6..3d71a1a 100644 --- a/src/docker_data/mod.rs +++ b/src/docker_data/mod.rs @@ -3,6 +3,7 @@ use bollard::{ service::ContainerSummary, Docker, }; +use crossterm::{event::DisableMouseCapture, execute}; use futures_util::StreamExt; use parking_lot::Mutex; use std::{ @@ -407,6 +408,11 @@ impl DockerData { .values() .into_iter() .for_each(tokio::task::JoinHandle::abort); + // This is a fix for a weird bug on Linux + WSL which will output mouse movement to the stdout + // execute!(std::io::stdout(), DisableMouseCapture).unwrap_or(()); + std::thread::spawn(||{ + execute!(std::io::stdout(), DisableMouseCapture).unwrap_or(()); + }); self.is_running.store(false, Ordering::SeqCst); } } diff --git a/src/input_handler/mod.rs b/src/input_handler/mod.rs index 7e1f649..0a01fcd 100644 --- a/src/input_handler/mod.rs +++ b/src/input_handler/mod.rs @@ -134,6 +134,11 @@ impl InputHandler { .lock() .status_contains(&[Status::Error, Status::Init]); if error_init || self.docker_sender.send(DockerMessage::Quit).await.is_err() { + // This is a fix for a weird bug on Linux + WSL which will output mouse movement to the stdout + + std::thread::spawn(||{ + execute!(std::io::stdout(), DisableMouseCapture).unwrap_or(()); + }); self.is_running.store(false, Ordering::SeqCst); } } diff --git a/src/main.rs b/src/main.rs index 27611a3..59deece 100644 --- a/src/main.rs +++ b/src/main.rs @@ -149,6 +149,14 @@ async fn main() { .await; } } + + // let mut child = std::process::Command::new("tput").arg("reset").spawn().unwrap_or_else(|e| panic!("Could not run tput: {}", e)); + // let result = child.wait().unwrap_or_else(|e| panic!("Could not wait for tput process: {}", e)); + + // if ! result.success() { + // panic!("tput failed with error code {}", result.code().unwrap()); + // } + // Clear screen // std::io::stdout().lock().flush().unwrap_or(()); // std::io::stdout().lock().write(b"").unwrap_or_default(); diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 54c92a3..65a2db0 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -7,6 +7,7 @@ use crossterm::{ use parking_lot::Mutex; use std::{ io::{self, Write}, + process::Stdio, sync::{atomic::Ordering, Arc}, }; use std::{sync::atomic::AtomicBool, time::Instant}; @@ -59,45 +60,81 @@ pub async fn create_ui( LeaveAlternateScreen, DisableMouseCapture )?; - terminal.show_cursor()?; - // if let Err(err) = res { - // println!("error: {err}"); - // } - std::io::stdout().flush().unwrap_or(()); + terminal.show_cursor()?; Ok(()) } -/// Display error message for 5 seconds, with countdown +/// Run the error message loop, for 5 seconds, with countdown fn err_loop( - now: &mut Instant, terminal: &mut Terminal, ) -> Result<(), AppError> { let mut seconds = 5; + let mut now = Instant::now(); loop { + // This is a fix for a weird bug on Linux + WSL which will output mouse movement to the stdout + execute!(io::stdout(), EnableMouseCapture).unwrap_or(()); + execute!(io::stdout(), DisableMouseCapture).unwrap_or(()); if seconds < 1 { - // terminal.clear().unwrap_or(()); break; } - if now.elapsed() >= std::time::Duration::from_secs(1) { seconds -= 1; - *now = Instant::now(); + now = Instant::now(); } - terminal + if terminal .draw(|f| draw_blocks::error(f, AppError::DockerConnect, Some(seconds))) - .unwrap(); - // { - // return Err(AppError::Terminal); - // } - // terminal - // .draw(|f| draw_blocks::error(f, AppError::DockerConnect, Some(seconds))) - // .unwrap(); + .is_err() + { + return Err(AppError::Terminal); + } } Ok(()) } +/// Run the normal application ui loop +async fn run_loop( app_data: Arc>, + docker_sx: Sender, + gui_state: Arc>, + is_running: Arc, + sender: Sender, + terminal: &mut Terminal) -> Result<(), AppError>{ + let input_poll_rate = std::time::Duration::from_millis(100); + let update_duration = + std::time::Duration::from_millis(u64::from(app_data.lock().args.docker_interval)); + let mut now = Instant::now(); + while is_running.load(Ordering::SeqCst) { + if terminal.draw(|f| ui(f, &app_data, &gui_state)).is_err() { + return Err(AppError::Terminal); + } + if crossterm::event::poll(input_poll_rate).unwrap_or(false) { + if let Ok(event) = event::read() { + if let Event::Key(key) = event { + sender + .send(InputMessages::ButtonPress(key.code)) + .await + .unwrap_or(()); + } else if let Event::Mouse(m) = event { + sender + .send(InputMessages::MouseEvent(m)) + .await + .unwrap_or(()); + } else if let Event::Resize(_, _) = event { + gui_state.lock().clear_area_map(); + terminal.autoresize().unwrap_or(()); + } + } + } + + if now.elapsed() >= update_duration { + docker_sx.send(DockerMessage::Update).await.unwrap_or(()); + now = Instant::now(); + } + } + Ok(()) +} + /// Run a loop to draw the gui async fn run_app( app_data: Arc>, @@ -107,45 +144,12 @@ async fn run_app( sender: Sender, terminal: &mut Terminal, ) -> Result<(), AppError> { - let update_duration = - std::time::Duration::from_millis(u64::from(app_data.lock().args.docker_interval)); - let input_poll_rate = std::time::Duration::from_millis(75); let status_dockerconnect = gui_state.lock().status_contains(&[Status::DockerConnect]); - let mut now = Instant::now(); - - if !status_dockerconnect { - err_loop(&mut now, terminal).unwrap_or(()); + if status_dockerconnect { + err_loop(terminal).unwrap_or(()); } else { - while is_running.load(Ordering::SeqCst) { - if crossterm::event::poll(input_poll_rate).unwrap_or(false) { - if let Ok(event) = event::read() { - if let Event::Key(key) = event { - sender - .send(InputMessages::ButtonPress(key.code)) - .await - .unwrap_or(()); - } else if let Event::Mouse(m) = event { - sender - .send(InputMessages::MouseEvent(m)) - .await - .unwrap_or(()); - } else if let Event::Resize(_, _) = event { - gui_state.lock().clear_area_map(); - terminal.autoresize().unwrap_or(()); - } - } - } - - if now.elapsed() >= update_duration { - docker_sx.send(DockerMessage::Update).await.unwrap_or(()); - now = Instant::now(); - } - if terminal.draw(|f| ui(f, &app_data, &gui_state)).is_err() { - return Err(AppError::Terminal); - } - } - } - + run_loop(app_data, docker_sx, gui_state, is_running, sender, terminal).await?; + } Ok(()) }