Skip to content

Commit a64db30

Browse files
committed
Fix the kitty backend reading more bytes than it should
1 parent 7baa41a commit a64db30

File tree

1 file changed

+29
-32
lines changed

1 file changed

+29
-32
lines changed

Diff for: src/image_backends/kitty.rs

+29-32
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
use image::{imageops::FilterType, DynamicImage, GenericImageView};
22
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,
55
};
6-
use std::io::Read;
7-
use std::sync::mpsc::{self, TryRecvError};
8-
use std::time::Duration;
6+
use std::time::Instant;
97

108
pub struct KittyBackend {}
119

@@ -41,38 +39,37 @@ impl KittyBackend {
4139
base64::encode(&test_image)
4240
);
4341

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;
6258
}
6359
}
64-
});
65-
if receiver.recv_timeout(Duration::from_millis(50)).is_ok() {
60+
let mut byte = 0;
6661
unsafe {
67-
tcsetattr(STDIN_FILENO, TCSANOW, &old_attributes);
62+
read(STDIN_FILENO, &mut byte as *mut _ as *mut c_void, 1);
6863
}
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;
7372
}
74-
stop_sender.send(()).ok();
75-
false
7673
}
7774
}
7875
}

0 commit comments

Comments
 (0)