From 6bb16d2638a48ebaad3ebe475df6587c29cb774c Mon Sep 17 00:00:00 2001 From: rabite Date: Sun, 17 Mar 2019 23:14:09 +0100 Subject: [PATCH] don't steal input from foreground subprocs --- src/file_browser.rs | 7 ++++++ src/widget.rs | 56 +++++++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/file_browser.rs b/src/file_browser.rs index 1d9933d..abf144f 100644 --- a/src/file_browser.rs +++ b/src/file_browser.rs @@ -237,10 +237,17 @@ impl FileBrowser { if file.is_dir() { self.main_widget_goto(&file).log(); } else { + self.core.get_sender().send(Events::InputEnabled(false))?; + let status = std::process::Command::new("rifle") .args(file.path.file_name()) .status(); + self.clear().log(); + self.core.screen.cursor_hide().log(); + + self.core.get_sender().send(Events::InputEnabled(true))?; + match status { Ok(status) => self.show_status(&format!("\"{}\" exited with {}", diff --git a/src/widget.rs b/src/widget.rs index 09a5d0a..1d48bdf 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -19,6 +19,8 @@ pub enum Events { InputEvent(Event), WidgetReady, ExclusiveEvent(Option>), + InputEnabled(bool), + RequestInput, Status(String) } @@ -233,6 +235,7 @@ pub trait Widget { fn run_widget(&mut self) -> HResult<()> { let (tx_event, rx_event) = channel(); self.get_core()?.get_sender().send(Events::ExclusiveEvent(Some(tx_event)))?; + self.get_core()?.get_sender().send(Events::RequestInput)?; self.clear()?; self.refresh().log(); @@ -248,10 +251,14 @@ pub trait Widget { err @ Err(_) => err.log(), Ok(_) => {} } + self.get_core()?.get_sender().send(Events::RequestInput)?; } Events::WidgetReady => { self.refresh().log(); } + Events::Status(status) => { + self.show_status(&status).log(); + } _ => {} } self.refresh().log(); @@ -303,13 +310,10 @@ pub trait Widget { } fn handle_input(&mut self) -> HResult<()> { - let (tx_event, rx_event) = channel(); let (tx_internal_event, rx_internal_event) = channel(); let rx_global_event = self.get_core()?.event_receiver.lock()?.take()?; - input_thread(tx_event.clone()); - global_event_thread(rx_global_event, tx_event.clone()); - dispatch_events(rx_event, tx_internal_event); + dispatch_events(tx_internal_event, rx_global_event); for event in rx_internal_event.iter() { match event { @@ -318,16 +322,15 @@ pub trait Widget { Err(HError::Quit) => { HError::quit()?; }, _ => {} } - self.draw().ok(); - }, + self.get_core()?.get_sender().send(Events::RequestInput)?; + } Events::Status(status) => { self.show_status(&status).log(); } - _ => { - self.refresh().ok(); - self.draw().ok(); - }, + _ => {} } + self.refresh().ok(); + self.draw().ok(); } Ok(()) } @@ -386,26 +389,44 @@ pub trait Widget { } } -fn dispatch_events(rx: Receiver, tx: Sender) { +fn dispatch_events(tx_internal: Sender, rx_global: Receiver) { + let (tx_event, rx_event) = channel(); + let (tx_input_req, rx_input_req) = channel(); + + input_thread(tx_event.clone(), rx_input_req); + event_thread(rx_global, tx_event.clone()); + std::thread::spawn(move || { let mut tx_exclusive_event: Option> = None; - for event in rx.iter() { + let mut input_enabled = true; + + for event in rx_event.iter() { match &event { Events::ExclusiveEvent(tx_event) => { tx_exclusive_event = tx_event.clone(); } + Events::InputEnabled(state) => { + input_enabled = *state; + continue; + } + Events::RequestInput => { + if input_enabled { + tx_input_req.send(()).unwrap(); + } + continue; + } _ => {} } - if let Some(tx_event) = &tx_exclusive_event { - tx_event.send(event).ok(); + if let Some(tx_exclusive) = &tx_exclusive_event { + tx_exclusive.send(event).unwrap(); } else { - tx.send(event).ok(); + tx_internal.send(event).unwrap(); } } }); } -fn global_event_thread(rx_global: Receiver, +fn event_thread(rx_global: Receiver, tx: Sender) { std::thread::spawn(move || { for event in rx_global.iter() { @@ -414,11 +435,12 @@ fn global_event_thread(rx_global: Receiver, }); } -fn input_thread(tx: Sender) { +fn input_thread(tx: Sender, rx_input_request: Receiver<()>) { std::thread::spawn(move || { for input in stdin().events() { let input = input.unwrap(); tx.send(Events::InputEvent(input)).unwrap(); + rx_input_request.recv().unwrap(); } }); }