-
-
Notifications
You must be signed in to change notification settings - Fork 707
/
Copy pathstdin_handler.rs
93 lines (88 loc) · 3.45 KB
/
stdin_handler.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use crate::os_input_output::ClientOsApi;
use crate::stdin_ansi_parser::StdinAnsiParser;
use crate::InputInstruction;
use std::sync::{Arc, Mutex};
use zellij_utils::channels::SenderWithContext;
use zellij_utils::termwiz::input::{InputEvent, InputParser, MouseButtons};
pub(crate) fn stdin_loop(
mut os_input: Box<dyn ClientOsApi>,
send_input_instructions: SenderWithContext<InputInstruction>,
stdin_ansi_parser: Arc<Mutex<StdinAnsiParser>>,
) {
let mut holding_mouse = false;
let mut input_parser = InputParser::new();
let mut current_buffer = vec![];
// on startup we send a query to the terminal emulator for stuff like the pixel size and colors
// we get a response through STDIN, so it makes sense to do this here
let terminal_emulator_query_string = stdin_ansi_parser
.lock()
.unwrap()
.terminal_emulator_query_string();
let _ = os_input
.get_stdout_writer()
.write(terminal_emulator_query_string.as_bytes())
.unwrap();
loop {
let buf = os_input.read_from_stdin();
{
// here we check if we need to parse specialized ANSI instructions sent over STDIN
// this happens either on startup (see above) or on SIGWINCH
//
// if we need to parse them, we do so with an internal timeout - anything else we
// receive on STDIN during that timeout is unceremoniously dropped
let mut stdin_ansi_parser = stdin_ansi_parser.lock().unwrap();
if stdin_ansi_parser.should_parse() {
let events = stdin_ansi_parser.parse(buf);
if !events.is_empty() {
let _ = send_input_instructions
.send(InputInstruction::AnsiStdinInstructions(events));
}
continue;
}
}
current_buffer.append(&mut buf.to_vec());
let maybe_more = false; // read_from_stdin should (hopefully) always empty the STDIN buffer completely
let mut events = vec![];
input_parser.parse(
&buf,
|input_event: InputEvent| {
events.push(input_event);
},
maybe_more,
);
let event_count = events.len();
for (i, input_event) in events.into_iter().enumerate() {
if holding_mouse && is_mouse_press_or_hold(&input_event) && i == event_count - 1 {
let mut poller = os_input.stdin_poller();
loop {
if poller.ready() {
break;
}
send_input_instructions
.send(InputInstruction::KeyEvent(
input_event.clone(),
current_buffer.clone(),
))
.unwrap();
}
}
holding_mouse = is_mouse_press_or_hold(&input_event);
send_input_instructions
.send(InputInstruction::KeyEvent(
input_event,
current_buffer.drain(..).collect(),
))
.unwrap();
}
}
}
fn is_mouse_press_or_hold(input_event: &InputEvent) -> bool {
if let InputEvent::Mouse(mouse_event) = input_event {
if mouse_event.mouse_buttons.contains(MouseButtons::LEFT)
|| mouse_event.mouse_buttons.contains(MouseButtons::RIGHT)
{
return true;
}
}
false
}