1 use std::time::Duration;
2 
3 use crossterm_winapi::{Console, Handle, InputRecord};
4 
5 use crate::event::{sys::windows::poll::WinApiPoll, Event};
6 
7 #[cfg(feature = "event-stream")]
8 use super::super::sys::Waker;
9 use super::super::{
10     source::EventSource,
11     sys::windows::parse::{handle_key_event, handle_mouse_event},
12     timeout::PollTimeout,
13     InternalEvent, Result,
14 };
15 
16 pub(crate) struct WindowsEventSource {
17     console: Console,
18     poll: WinApiPoll,
19 }
20 
21 impl WindowsEventSource {
new() -> Result<WindowsEventSource>22     pub(crate) fn new() -> Result<WindowsEventSource> {
23         let console = Console::from(Handle::current_in_handle()?);
24         Ok(WindowsEventSource {
25             console,
26             poll: WinApiPoll::new()?,
27         })
28     }
29 }
30 
31 impl EventSource for WindowsEventSource {
try_read(&mut self, timeout: Option<Duration>) -> Result<Option<InternalEvent>>32     fn try_read(&mut self, timeout: Option<Duration>) -> Result<Option<InternalEvent>> {
33         let poll_timeout = PollTimeout::new(timeout);
34 
35         loop {
36             if let Some(event_ready) = self.poll.poll(poll_timeout.leftover())? {
37                 if event_ready && self.console.number_of_console_input_events()? != 0 {
38                     let event = match self.console.read_single_input_event()? {
39                         InputRecord::KeyEvent(record) => handle_key_event(record)?,
40                         InputRecord::MouseEvent(record) => handle_mouse_event(record)?,
41                         InputRecord::WindowBufferSizeEvent(record) => {
42                             Some(Event::Resize(record.size.x as u16, record.size.y as u16))
43                         }
44                         _ => None,
45                     };
46 
47                     if let Some(event) = event {
48                         return Ok(Some(InternalEvent::Event(event)));
49                     }
50                 }
51             }
52 
53             if poll_timeout.elapsed() {
54                 return Ok(None);
55             }
56         }
57     }
58 
59     #[cfg(feature = "event-stream")]
waker(&self) -> Waker60     fn waker(&self) -> Waker {
61         self.poll.waker()
62     }
63 }
64