1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use std::time::Duration;
use crossterm_winapi::{Console, Handle, InputRecord};
use crate::event::{
sys::windows::{parse::MouseButtonsPressed, poll::WinApiPoll},
Event,
};
#[cfg(feature = "event-stream")]
use super::super::sys::Waker;
use super::super::{
source::EventSource,
sys::windows::parse::{handle_key_event, handle_mouse_event},
timeout::PollTimeout,
InternalEvent, Result,
};
pub(crate) struct WindowsEventSource {
console: Console,
poll: WinApiPoll,
surrogate_buffer: Option<u16>,
mouse_buttons_pressed: MouseButtonsPressed,
}
impl WindowsEventSource {
pub(crate) fn new() -> Result<WindowsEventSource> {
let console = Console::from(Handle::current_in_handle()?);
Ok(WindowsEventSource {
console,
#[cfg(not(feature = "event-stream"))]
poll: WinApiPoll::new(),
#[cfg(feature = "event-stream")]
poll: WinApiPoll::new()?,
surrogate_buffer: None,
mouse_buttons_pressed: MouseButtonsPressed::default(),
})
}
}
impl EventSource for WindowsEventSource {
fn try_read(&mut self, timeout: Option<Duration>) -> Result<Option<InternalEvent>> {
let poll_timeout = PollTimeout::new(timeout);
loop {
if let Some(event_ready) = self.poll.poll(poll_timeout.leftover())? {
let number = self.console.number_of_console_input_events()?;
if event_ready && number != 0 {
let event = match self.console.read_single_input_event()? {
InputRecord::KeyEvent(record) => {
handle_key_event(record, &mut self.surrogate_buffer)
}
InputRecord::MouseEvent(record) => {
let mouse_event =
handle_mouse_event(record, &self.mouse_buttons_pressed);
self.mouse_buttons_pressed = MouseButtonsPressed {
left: record.button_state.left_button(),
right: record.button_state.right_button(),
middle: record.button_state.middle_button(),
};
mouse_event
}
InputRecord::WindowBufferSizeEvent(record) => {
Some(Event::Resize(
record.size.x as u16 + 1,
record.size.y as u16 + 1,
))
}
InputRecord::FocusEvent(record) => {
let event = if record.set_focus {
Event::FocusGained
} else {
Event::FocusLost
};
Some(event)
}
_ => None,
};
if let Some(event) = event {
return Ok(Some(InternalEvent::Event(event)));
}
}
}
if poll_timeout.elapsed() {
return Ok(None);
}
}
}
#[cfg(feature = "event-stream")]
fn waker(&self) -> Waker {
self.poll.waker()
}
}