Forward input on input/rawinput switch

Input thread listens on stdin input and forwards the input to the main
process. When an embedded terminal is launched within the main process,
the input thread is asked to switch to raw input, that is to send the
parsed input and the raw bytes to the main process in order to get them
forwarded to the embedded terminal. The switch happens by calling
get_events and get_events_raw.

When the input thread receives an InputCommand::{No,}Raw, it has already
received an input event, since the `select!` is within the
stdin events for loop. (There's no way to `select` on blocking iterators
or raw fds, which is unfortunate.).

This commit forwards the input to the next function instead of dropping
it.
memfd
Manos Pitsidianakis 2020-02-27 16:41:58 +02:00
parent 7807f565ec
commit 126b65817e
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
2 changed files with 19 additions and 9 deletions

View File

@ -68,6 +68,7 @@ impl InputHandler {
tx.send(ThreadEvent::InputRaw(i)).unwrap();
},
&rx,
None,
)
})
.unwrap();

View File

@ -24,7 +24,6 @@ use crossbeam::{channel::Receiver, select};
use serde::{Serialize, Serializer};
use termion::event::Event as TermionEvent;
use termion::event::Key as TermionKey;
use termion::input::TermRead;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Key {
@ -167,18 +166,23 @@ pub fn get_events(
mut closure: impl FnMut(Key),
closure_raw: impl FnMut((Key, Vec<u8>)),
rx: &Receiver<InputCommand>,
input: Option<(TermionEvent, Vec<u8>)>,
) -> () {
let stdin = std::io::stdin();
let mut input_mode = InputMode::Normal;
let mut paste_buf = String::with_capacity(256);
for c in stdin.events() {
for c in input
.map(|v| Ok(v))
.into_iter()
.chain(stdin.events_and_raw())
{
select! {
default => {},
recv(rx) -> cmd => {
match cmd.unwrap() {
InputCommand::Kill => return,
InputCommand::Raw => {
get_events_raw(closure, closure_raw, rx);
get_events_raw(closure, closure_raw, rx, c.ok());
return;
}
InputCommand::NoRaw => unreachable!(),
@ -187,16 +191,16 @@ pub fn get_events(
};
match c {
Ok(TermionEvent::Key(k)) if input_mode == InputMode::Normal => {
Ok((TermionEvent::Key(k), _)) if input_mode == InputMode::Normal => {
closure(Key::from(k));
}
Ok(TermionEvent::Key(TermionKey::Char(k))) if input_mode == InputMode::Paste => {
Ok((TermionEvent::Key(TermionKey::Char(k)), _)) if input_mode == InputMode::Paste => {
paste_buf.push(k);
}
Ok(TermionEvent::Unsupported(ref k)) if k.as_slice() == BRACKET_PASTE_START => {
Ok((TermionEvent::Unsupported(ref k), _)) if k.as_slice() == BRACKET_PASTE_START => {
input_mode = InputMode::Paste;
}
Ok(TermionEvent::Unsupported(ref k)) if k.as_slice() == BRACKET_PASTE_END => {
Ok((TermionEvent::Unsupported(ref k), _)) if k.as_slice() == BRACKET_PASTE_END => {
input_mode = InputMode::Normal;
let ret = Key::from(&paste_buf);
paste_buf.clear();
@ -212,18 +216,23 @@ pub fn get_events_raw(
closure_nonraw: impl FnMut(Key),
mut closure: impl FnMut((Key, Vec<u8>)),
rx: &Receiver<InputCommand>,
input: Option<(TermionEvent, Vec<u8>)>,
) -> () {
let stdin = std::io::stdin();
let mut input_mode = InputMode::Normal;
let mut paste_buf = String::with_capacity(256);
for c in stdin.events_and_raw() {
for c in input
.map(|v| Ok(v))
.into_iter()
.chain(stdin.events_and_raw())
{
select! {
default => {},
recv(rx) -> cmd => {
match cmd.unwrap() {
InputCommand::Kill => return,
InputCommand::NoRaw => {
get_events(closure_nonraw, closure, rx);
get_events(closure_nonraw, closure, rx, c.ok());
return;
}
InputCommand::Raw => unreachable!(),