1*7b32f508SLoGin use crate::app::AppResult; 2*7b32f508SLoGin use crate::backend::event::BackendEvent; 3*7b32f508SLoGin use crossterm::event::{self, Event as CrosstermEvent, KeyEvent, MouseEvent}; 4*7b32f508SLoGin use std::sync::mpsc; 5*7b32f508SLoGin use std::thread; 6*7b32f508SLoGin use std::time::{Duration, Instant}; 7*7b32f508SLoGin 8*7b32f508SLoGin /// Terminal events. 9*7b32f508SLoGin #[derive(Clone, Debug)] 10*7b32f508SLoGin pub enum Event { 11*7b32f508SLoGin /// Terminal tick. 12*7b32f508SLoGin Tick, 13*7b32f508SLoGin /// Key press. 14*7b32f508SLoGin Key(KeyEvent), 15*7b32f508SLoGin /// Mouse click/scroll. 16*7b32f508SLoGin Mouse(MouseEvent), 17*7b32f508SLoGin /// Terminal resize. 18*7b32f508SLoGin Resize(u16, u16), 19*7b32f508SLoGin Backend(BackendEvent), 20*7b32f508SLoGin } 21*7b32f508SLoGin 22*7b32f508SLoGin /// Terminal event handler. 23*7b32f508SLoGin #[allow(dead_code)] 24*7b32f508SLoGin #[derive(Debug)] 25*7b32f508SLoGin pub struct EventHandler { 26*7b32f508SLoGin /// Event sender channel. 27*7b32f508SLoGin sender: mpsc::Sender<Event>, 28*7b32f508SLoGin /// Event receiver channel. 29*7b32f508SLoGin receiver: mpsc::Receiver<Event>, 30*7b32f508SLoGin /// Event handler thread. 31*7b32f508SLoGin handler: thread::JoinHandle<()>, 32*7b32f508SLoGin } 33*7b32f508SLoGin 34*7b32f508SLoGin impl EventHandler { 35*7b32f508SLoGin /// Constructs a new instance of [`EventHandler`]. new(tick_rate: u64) -> Self36*7b32f508SLoGin pub fn new(tick_rate: u64) -> Self { 37*7b32f508SLoGin let tick_rate = Duration::from_millis(tick_rate); 38*7b32f508SLoGin let (sender, receiver) = mpsc::channel(); 39*7b32f508SLoGin let handler = { 40*7b32f508SLoGin let sender = sender.clone(); 41*7b32f508SLoGin thread::spawn(move || { 42*7b32f508SLoGin let mut last_tick = Instant::now(); 43*7b32f508SLoGin loop { 44*7b32f508SLoGin let timeout = tick_rate 45*7b32f508SLoGin .checked_sub(last_tick.elapsed()) 46*7b32f508SLoGin .unwrap_or(tick_rate); 47*7b32f508SLoGin 48*7b32f508SLoGin if event::poll(timeout).expect("no events available") { 49*7b32f508SLoGin match event::read().expect("unable to read event") { 50*7b32f508SLoGin CrosstermEvent::Key(e) => sender.send(Event::Key(e)), 51*7b32f508SLoGin CrosstermEvent::Mouse(e) => sender.send(Event::Mouse(e)), 52*7b32f508SLoGin CrosstermEvent::Resize(w, h) => sender.send(Event::Resize(w, h)), 53*7b32f508SLoGin _ => unimplemented!(), 54*7b32f508SLoGin } 55*7b32f508SLoGin .expect("failed to send terminal event") 56*7b32f508SLoGin } 57*7b32f508SLoGin 58*7b32f508SLoGin if last_tick.elapsed() >= tick_rate { 59*7b32f508SLoGin sender.send(Event::Tick).expect("failed to send tick event"); 60*7b32f508SLoGin last_tick = Instant::now(); 61*7b32f508SLoGin } 62*7b32f508SLoGin } 63*7b32f508SLoGin }) 64*7b32f508SLoGin }; 65*7b32f508SLoGin Self { 66*7b32f508SLoGin sender, 67*7b32f508SLoGin receiver, 68*7b32f508SLoGin handler, 69*7b32f508SLoGin } 70*7b32f508SLoGin } 71*7b32f508SLoGin 72*7b32f508SLoGin /// Receive the next event from the handler thread. 73*7b32f508SLoGin /// 74*7b32f508SLoGin /// This function will always block the current thread if 75*7b32f508SLoGin /// there is no data available and it's possible for more data to be sent. next(&self) -> AppResult<Event>76*7b32f508SLoGin pub fn next(&self) -> AppResult<Event> { 77*7b32f508SLoGin Ok(self.receiver.recv()?) 78*7b32f508SLoGin } 79*7b32f508SLoGin sender(&self) -> mpsc::Sender<Event>80*7b32f508SLoGin pub fn sender(&self) -> mpsc::Sender<Event> { 81*7b32f508SLoGin self.sender.clone() 82*7b32f508SLoGin } 83*7b32f508SLoGin } 84