|
1 | 1 | use image::{imageops::FilterType, DynamicImage, GenericImageView};
|
2 | 2 | use libc::{
|
3 |
| - ioctl, tcgetattr, tcsetattr, termios, winsize, ECHO, ICANON, STDIN_FILENO, STDOUT_FILENO, |
4 |
| - TCSANOW, TIOCGWINSZ, |
| 3 | + c_void, ioctl, poll, pollfd, read, tcgetattr, tcsetattr, termios, winsize, ECHO, ICANON, |
| 4 | + POLLIN, STDIN_FILENO, STDOUT_FILENO, TCSANOW, TIOCGWINSZ, |
5 | 5 | };
|
6 |
| -use std::io::Read; |
7 |
| -use std::sync::mpsc::{self, TryRecvError}; |
8 |
| -use std::time::Duration; |
| 6 | +use std::time::Instant; |
9 | 7 |
|
10 | 8 | pub struct KittyBackend {}
|
11 | 9 |
|
@@ -41,38 +39,37 @@ impl KittyBackend {
|
41 | 39 | base64::encode(&test_image)
|
42 | 40 | );
|
43 | 41 |
|
44 |
| - // a new thread is required to avoid blocking the main thread if the terminal doesn't respond |
45 |
| - let (sender, receiver) = mpsc::channel::<()>(); |
46 |
| - let (stop_sender, stop_receiver) = mpsc::channel::<()>(); |
47 |
| - std::thread::spawn(move || { |
48 |
| - let mut buf = Vec::<u8>::new(); |
49 |
| - let allowed_bytes = [0x1B, b'_', b'G', b'\\']; |
50 |
| - for byte in std::io::stdin().lock().bytes() { |
51 |
| - let byte = byte.unwrap(); |
52 |
| - if allowed_bytes.contains(&byte) { |
53 |
| - buf.push(byte); |
54 |
| - } |
55 |
| - if buf.starts_with(&[0x1B, b'_', b'G']) && buf.ends_with(&[0x1B, b'\\']) { |
56 |
| - sender.send(()).unwrap(); |
57 |
| - return; |
58 |
| - } |
59 |
| - match stop_receiver.try_recv() { |
60 |
| - Err(TryRecvError::Empty) => {} |
61 |
| - _ => return, |
| 42 | + let start_time = Instant::now(); |
| 43 | + let mut stdin_pollfd = pollfd { |
| 44 | + fd: STDIN_FILENO, |
| 45 | + events: POLLIN, |
| 46 | + revents: 0, |
| 47 | + }; |
| 48 | + let allowed_bytes = [0x1B, b'_', b'G', b'\\']; |
| 49 | + let mut buf = Vec::<u8>::new(); |
| 50 | + loop { |
| 51 | + // check for timeout while polling to avoid blocking the main thread |
| 52 | + while unsafe { poll(&mut stdin_pollfd, 1, 0) < 1 } { |
| 53 | + if start_time.elapsed().as_millis() > 50 { |
| 54 | + unsafe { |
| 55 | + tcsetattr(STDIN_FILENO, TCSANOW, &old_attributes); |
| 56 | + } |
| 57 | + return false; |
62 | 58 | }
|
63 | 59 | }
|
64 |
| - }); |
65 |
| - if receiver.recv_timeout(Duration::from_millis(50)).is_ok() { |
| 60 | + let mut byte = 0; |
66 | 61 | unsafe {
|
67 |
| - tcsetattr(STDIN_FILENO, TCSANOW, &old_attributes); |
| 62 | + read(STDIN_FILENO, &mut byte as *mut _ as *mut c_void, 1); |
68 | 63 | }
|
69 |
| - true |
70 |
| - } else { |
71 |
| - unsafe { |
72 |
| - tcsetattr(STDIN_FILENO, TCSANOW, &old_attributes); |
| 64 | + if allowed_bytes.contains(&byte) { |
| 65 | + buf.push(byte); |
| 66 | + } |
| 67 | + if buf.starts_with(&[0x1B, b'_', b'G']) && buf.ends_with(&[0x1B, b'\\']) { |
| 68 | + unsafe { |
| 69 | + tcsetattr(STDIN_FILENO, TCSANOW, &old_attributes); |
| 70 | + } |
| 71 | + return true; |
73 | 72 | }
|
74 |
| - stop_sender.send(()).ok(); |
75 |
| - false |
76 | 73 | }
|
77 | 74 | }
|
78 | 75 | }
|
|
0 commit comments