use std::cmp::PartialOrd;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Result;
use std::sync::mpsc::Sender;
use std::thread;
use libc::c_int;
use libc::c_void;
use libc::pipe;
use libc::read;
use libc::signal;
use libc::size_t;
use libc::write;
use libc::SIGWINCH;
use libc::SIG_ERR;
use crate::Event;
static mut WRITE_FD: c_int = 0;
fn check<T>(result: T, error: T) -> Result<()>
where
T: Copy + PartialOrd<T>,
{
if result == error {
Err(Error::last_os_error())
} else {
Ok(())
}
}
extern "C" fn handler(signum: c_int) {
debug_assert_eq!(signum, SIGWINCH);
let buffer = [0];
let result = unsafe { write(WRITE_FD, buffer.as_ptr() as *const c_void, 1) };
check(result, -1).unwrap();
}
pub fn receive_window_resizes(send_event: Sender<Result<Event>>) -> Result<()> {
let mut fds = [0, 0];
unsafe {
check(pipe(fds.as_mut_ptr()), -1)?;
check(signal(SIGWINCH, handler as size_t), SIG_ERR)?;
WRITE_FD = fds[1]
}
let read_fd = fds[0];
thread::spawn(move || loop {
let mut buffer = [0];
let result = unsafe { read(read_fd, buffer.as_mut_ptr() as *mut c_void, 1) };
if result < 0 {
if Error::last_os_error().kind() != ErrorKind::Interrupted {
continue
}
}
let result = check(result, -1).map(|_| Event::Resize);
send_event.send(result).unwrap();
});
Ok(())
}