feat: Acutal fix the the mouse events output
The EnableMouseCapture from Crossterm was too broad, by only enabling a subject of the events, 1) performance is improvedand 2) and intermittent bug where mouse events were output to stdout has been removed
This commit is contained in:
@@ -14,7 +14,7 @@ COPY ./target/x86_64-unknown-linux-musl/release/oxker /app/
|
|||||||
ENTRYPOINT [ "/app/oxker"]
|
ENTRYPOINT [ "/app/oxker"]
|
||||||
|
|
||||||
# Dev build for testing
|
# Dev build for testing
|
||||||
# docker build -t oxker_dev -f Dockerfile . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev
|
# docker build -t oxker_dev -f containerised/Dockerfile_dev . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev
|
||||||
|
|
||||||
# Dev build one liner, x86 host
|
# Dev build one liner, x86 host
|
||||||
# docker image prune -a; cargo build --release --target x86_64-unknown-linux-musl && docker build -t oxker_dev -f containerised/Dockerfile_dev . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev
|
# docker image prune -a; cargo build --release --target x86_64-unknown-linux-musl && docker build -t oxker_dev -f containerised/Dockerfile_dev . && docker run --rm -it --volume /var/run/docker.sock:/var/run/docker.sock:ro oxker_dev
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ use crate::{
|
|||||||
app_data::{AppData, ContainerId, DockerControls},
|
app_data::{AppData, ContainerId, DockerControls},
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
parse_args::CliArgs,
|
parse_args::CliArgs,
|
||||||
stop_running,
|
|
||||||
ui::{GuiState, Status},
|
ui::{GuiState, Status},
|
||||||
ENTRY_POINT,
|
ENTRY_POINT,
|
||||||
};
|
};
|
||||||
@@ -405,7 +404,8 @@ impl DockerData {
|
|||||||
.values()
|
.values()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(tokio::task::JoinHandle::abort);
|
.for_each(tokio::task::JoinHandle::abort);
|
||||||
stop_running(&self.is_running);
|
self.is_running
|
||||||
|
.store(false, std::sync::atomic::Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ use std::sync::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event::{
|
event::{DisableMouseCapture, KeyCode, MouseButton, MouseEvent, MouseEventKind},
|
||||||
DisableMouseCapture, EnableMouseCapture, KeyCode, MouseButton, MouseEvent, MouseEventKind,
|
|
||||||
},
|
|
||||||
execute,
|
execute,
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -21,8 +19,7 @@ use crate::{
|
|||||||
app_data::{AppData, DockerControls, Header},
|
app_data::{AppData, DockerControls, Header},
|
||||||
app_error::AppError,
|
app_error::AppError,
|
||||||
docker_data::DockerMessage,
|
docker_data::DockerMessage,
|
||||||
stop_running,
|
ui::{enable_mouse_capture, GuiState, SelectablePanel, Status},
|
||||||
ui::{GuiState, SelectablePanel, Status},
|
|
||||||
};
|
};
|
||||||
pub use message::InputMessages;
|
pub use message::InputMessages;
|
||||||
|
|
||||||
@@ -95,15 +92,10 @@ impl InputHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match execute!(std::io::stdout(), EnableMouseCapture) {
|
enable_mouse_capture();
|
||||||
Ok(_) => self
|
self.gui_state
|
||||||
.gui_state
|
|
||||||
.lock()
|
.lock()
|
||||||
.set_info_box("✓ mouse capture enabled".to_owned()),
|
.set_info_box("✓ mouse capture enabled".to_owned());
|
||||||
Err(_) => {
|
|
||||||
self.app_data.lock().set_error(AppError::MouseCapture(true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// If the info box sleep handle is currently being executed, as in 'm' is pressed twice within a 4000ms window
|
// If the info box sleep handle is currently being executed, as in 'm' is pressed twice within a 4000ms window
|
||||||
@@ -135,7 +127,8 @@ impl InputHandler {
|
|||||||
.lock()
|
.lock()
|
||||||
.status_contains(&[Status::Error, Status::Init]);
|
.status_contains(&[Status::Error, Status::Init]);
|
||||||
if error_init || self.docker_sender.send(DockerMessage::Quit).await.is_err() {
|
if error_init || self.docker_sender.send(DockerMessage::Quit).await.is_err() {
|
||||||
stop_running(&self.is_running);
|
self.is_running
|
||||||
|
.store(false, std::sync::atomic::Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-13
@@ -19,10 +19,6 @@
|
|||||||
use app_data::AppData;
|
use app_data::AppData;
|
||||||
use app_error::AppError;
|
use app_error::AppError;
|
||||||
use bollard::Docker;
|
use bollard::Docker;
|
||||||
use crossterm::{
|
|
||||||
event::{DisableMouseCapture, EnableMouseCapture},
|
|
||||||
execute,
|
|
||||||
};
|
|
||||||
use docker_data::DockerData;
|
use docker_data::DockerData;
|
||||||
use input_handler::InputMessages;
|
use input_handler::InputMessages;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
@@ -67,15 +63,6 @@ fn check_if_containerised() -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set is_running to false, disable mouse capture, due to weird bug on Linux & WSL terminals
|
|
||||||
/// where mouse movement will be piped to the stdout
|
|
||||||
fn stop_running(is_running: &AtomicBool) {
|
|
||||||
std::thread::spawn(|| {
|
|
||||||
execute!(std::io::stdout(), EnableMouseCapture).unwrap_or(());
|
|
||||||
execute!(std::io::stdout(), DisableMouseCapture).unwrap_or(());
|
|
||||||
});
|
|
||||||
is_running.store(false, std::sync::atomic::Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
/// Create docker daemon handler, and only spawn up the docker data handler if a ping returns non-error
|
/// Create docker daemon handler, and only spawn up the docker data handler if a ping returns non-error
|
||||||
async fn docker_init(
|
async fn docker_init(
|
||||||
app_data: &Arc<Mutex<AppData>>,
|
app_data: &Arc<Mutex<AppData>>,
|
||||||
|
|||||||
+21
-12
@@ -1,12 +1,12 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event::{self, DisableMouseCapture, EnableMouseCapture, Event},
|
event::{self, DisableMouseCapture, Event},
|
||||||
execute,
|
execute,
|
||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
};
|
};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::{
|
use std::{
|
||||||
io::{self, Stdout},
|
io::{self, Stdout, Write},
|
||||||
sync::{atomic::Ordering, Arc},
|
sync::{atomic::Ordering, Arc},
|
||||||
};
|
};
|
||||||
use std::{sync::atomic::AtomicBool, time::Instant};
|
use std::{sync::atomic::AtomicBool, time::Instant};
|
||||||
@@ -39,6 +39,20 @@ pub struct Ui {
|
|||||||
terminal: Terminal<CrosstermBackend<Stdout>>,
|
terminal: Terminal<CrosstermBackend<Stdout>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable moust capture, but don't enable all the mouse movements, which improves performance, and fixes the weird mouse event output bug
|
||||||
|
pub fn enable_mouse_capture() {
|
||||||
|
io::stdout()
|
||||||
|
.write_all(
|
||||||
|
concat!(
|
||||||
|
crossterm::csi!("?1000h"),
|
||||||
|
crossterm::csi!("?1015h"),
|
||||||
|
crossterm::csi!("?1006h"),
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
|
.unwrap_or(());
|
||||||
|
}
|
||||||
|
|
||||||
impl Ui {
|
impl Ui {
|
||||||
/// Create a new Ui struct, and execute the drawing loop
|
/// Create a new Ui struct, and execute the drawing loop
|
||||||
pub async fn create(
|
pub async fn create(
|
||||||
@@ -73,7 +87,8 @@ impl Ui {
|
|||||||
fn setup_terminal() -> io::Result<Terminal<CrosstermBackend<Stdout>>> {
|
fn setup_terminal() -> io::Result<Terminal<CrosstermBackend<Stdout>>> {
|
||||||
enable_raw_mode()?;
|
enable_raw_mode()?;
|
||||||
let mut stdout = io::stdout();
|
let mut stdout = io::stdout();
|
||||||
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
|
execute!(stdout, EnterAlternateScreen)?;
|
||||||
|
enable_mouse_capture();
|
||||||
let backend = CrosstermBackend::new(stdout);
|
let backend = CrosstermBackend::new(stdout);
|
||||||
Terminal::new(backend)
|
Terminal::new(backend)
|
||||||
}
|
}
|
||||||
@@ -96,12 +111,6 @@ impl Ui {
|
|||||||
fn err_loop(&mut self) -> Result<(), AppError> {
|
fn err_loop(&mut self) -> Result<(), AppError> {
|
||||||
let mut seconds = 5;
|
let mut seconds = 5;
|
||||||
loop {
|
loop {
|
||||||
// This is a fix for a weird bug on Linux + WSL which will output mouse movement to stdout
|
|
||||||
std::thread::spawn(|| {
|
|
||||||
execute!(io::stdout(), EnableMouseCapture).unwrap_or(());
|
|
||||||
execute!(io::stdout(), DisableMouseCapture).unwrap_or(());
|
|
||||||
});
|
|
||||||
|
|
||||||
if self.now.elapsed() >= std::time::Duration::from_secs(1) {
|
if self.now.elapsed() >= std::time::Duration::from_secs(1) {
|
||||||
seconds -= 1;
|
seconds -= 1;
|
||||||
self.now = Instant::now();
|
self.now = Instant::now();
|
||||||
@@ -124,14 +133,14 @@ impl Ui {
|
|||||||
|
|
||||||
/// The loop for drawing the main UI to the terminal
|
/// The loop for drawing the main UI to the terminal
|
||||||
async fn gui_loop(&mut self) -> Result<(), AppError> {
|
async fn gui_loop(&mut self) -> Result<(), AppError> {
|
||||||
let input_poll_rate = std::time::Duration::from_millis(1);
|
let input_poll_rate = std::time::Duration::from_millis(100);
|
||||||
let update_duration =
|
let update_duration =
|
||||||
std::time::Duration::from_millis(u64::from(self.app_data.lock().args.docker_interval));
|
std::time::Duration::from_millis(u64::from(self.app_data.lock().args.docker_interval));
|
||||||
|
|
||||||
while self.is_running.load(Ordering::SeqCst) {
|
while self.is_running.load(Ordering::SeqCst) {
|
||||||
if self
|
if self
|
||||||
.terminal
|
.terminal
|
||||||
.draw(|frame| ui_frame(frame, &self.app_data, &self.gui_state))
|
.draw(|frame| draw_frame(frame, &self.app_data, &self.gui_state))
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
return Err(AppError::Terminal);
|
return Err(AppError::Terminal);
|
||||||
@@ -183,7 +192,7 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Draw the main ui to a frame of the terminal
|
/// Draw the main ui to a frame of the terminal
|
||||||
fn ui_frame<B: Backend>(
|
fn draw_frame<B: Backend>(
|
||||||
f: &mut Frame<'_, B>,
|
f: &mut Frame<'_, B>,
|
||||||
app_data: &Arc<Mutex<AppData>>,
|
app_data: &Arc<Mutex<AppData>>,
|
||||||
gui_state: &Arc<Mutex<GuiState>>,
|
gui_state: &Arc<Mutex<GuiState>>,
|
||||||
|
|||||||
Reference in New Issue
Block a user