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