wip: fix for mouse capture bug

This commit is contained in:
Jack Wills
2023-02-28 04:10:31 +00:00
parent 846e0641d0
commit 31bfaa7a95
4 changed files with 78 additions and 55 deletions
+6
View File
@@ -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);
}
}
+5
View File
@@ -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);
}
}
+8
View File
@@ -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();
+59 -55
View File
@@ -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<B: Backend + Send>(
now: &mut Instant,
terminal: &mut Terminal<B>,
) -> 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<B: Backend + Send>( app_data: Arc<Mutex<AppData>>,
docker_sx: Sender<DockerMessage>,
gui_state: Arc<Mutex<GuiState>>,
is_running: Arc<AtomicBool>,
sender: Sender<InputMessages>,
terminal: &mut Terminal<B>) -> 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<B: Backend + Send>(
app_data: Arc<Mutex<AppData>>,
@@ -107,45 +144,12 @@ async fn run_app<B: Backend + Send>(
sender: Sender<InputMessages>,
terminal: &mut Terminal<B>,
) -> 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(())
}