|
|
@ -1,7 +1,7 @@
|
|
|
|
|
|
|
|
use crate::{error::Error, key, log::*};
|
|
|
|
use anyhow::{Context, Result};
|
|
|
|
use anyhow::{Context, Result};
|
|
|
|
use crate::{error::Error, log::*, key};
|
|
|
|
|
|
|
|
use windows::Win32::System::Console;
|
|
|
|
|
|
|
|
use windows::Win32::Foundation::HANDLE;
|
|
|
|
use windows::Win32::Foundation::HANDLE;
|
|
|
|
|
|
|
|
use windows::Win32::System::Console;
|
|
|
|
|
|
|
|
|
|
|
|
fn log_input_mode(mode: Console::CONSOLE_MODE) {
|
|
|
|
fn log_input_mode(mode: Console::CONSOLE_MODE) {
|
|
|
|
// Characters read by the ReadFile or ReadConsole function are written to the active screen
|
|
|
|
// Characters read by the ReadFile or ReadConsole function are written to the active screen
|
|
|
@ -149,7 +149,11 @@ impl Reader {
|
|
|
|
// All buffered items have been processed, ask the OS for new event records
|
|
|
|
// All buffered items have been processed, ask the OS for new event records
|
|
|
|
if self.buf_idx as u32 >= self.buf_len {
|
|
|
|
if self.buf_idx as u32 >= self.buf_len {
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
Error::check(Console::ReadConsoleInputA(self.input, &mut self.buf, &mut self.buf_len))?;
|
|
|
|
Error::check(Console::ReadConsoleInputA(
|
|
|
|
|
|
|
|
self.input,
|
|
|
|
|
|
|
|
&mut self.buf,
|
|
|
|
|
|
|
|
&mut self.buf_len,
|
|
|
|
|
|
|
|
))?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.buf_idx = 0;
|
|
|
|
self.buf_idx = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -163,9 +167,12 @@ impl Reader {
|
|
|
|
#[derive(Debug)]
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Event {
|
|
|
|
pub enum Event {
|
|
|
|
Focus(bool),
|
|
|
|
Focus(bool),
|
|
|
|
Menu,
|
|
|
|
Menu(u32),
|
|
|
|
Key(key::Event),
|
|
|
|
Key(key::Event),
|
|
|
|
Mouse,
|
|
|
|
Mouse{
|
|
|
|
|
|
|
|
x: i16,
|
|
|
|
|
|
|
|
y: i16,
|
|
|
|
|
|
|
|
},
|
|
|
|
Size,
|
|
|
|
Size,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -178,52 +185,52 @@ impl From<Console::INPUT_RECORD> for Event {
|
|
|
|
// This is documented here:
|
|
|
|
// This is documented here:
|
|
|
|
// https://learn.microsoft.com/en-us/windows/console/input-record-str
|
|
|
|
// https://learn.microsoft.com/en-us/windows/console/input-record-str
|
|
|
|
match rec.EventType as u32 {
|
|
|
|
match rec.EventType as u32 {
|
|
|
|
Console::FOCUS_EVENT => {
|
|
|
|
Console::FOCUS_EVENT => unsafe {
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
let event = rec.Event.FocusEvent;
|
|
|
|
let event = rec.Event.FocusEvent;
|
|
|
|
Event::Focus(event.bSetFocus.as_bool())
|
|
|
|
Event::Focus(event.bSetFocus.as_bool())
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
Console::MENU_EVENT => unsafe {
|
|
|
|
Console::MENU_EVENT => {
|
|
|
|
|
|
|
|
// The Event member contains a MENU_EVENT_RECORD structure. These events are
|
|
|
|
|
|
|
|
// used internally and should be ignored.
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
let event = rec.Event.MenuEvent;
|
|
|
|
let event = rec.Event.MenuEvent;
|
|
|
|
debug!("Menu Event: {:?}", event);
|
|
|
|
Event::Menu(event.dwCommandId)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Event::Menu
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Console::KEY_EVENT => {
|
|
|
|
Console::KEY_EVENT => {
|
|
|
|
// https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
|
|
|
// https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
let event = rec.Event.KeyEvent;
|
|
|
|
let event = rec.Event.KeyEvent;
|
|
|
|
// pub struct KEY_EVENT_RECORD {
|
|
|
|
|
|
|
|
// pub bKeyDown: super::super::Foundation::BOOL,
|
|
|
|
|
|
|
|
// pub wRepeatCount: u16,
|
|
|
|
|
|
|
|
// pub wVirtualKeyCode: u16,
|
|
|
|
|
|
|
|
// pub wVirtualScanCode: u16,
|
|
|
|
|
|
|
|
// pub uChar: KEY_EVENT_RECORD_0,
|
|
|
|
|
|
|
|
// pub dwControlKeyState: u32,
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
let mstate = event.dwControlKeyState;
|
|
|
|
let mstate = event.dwControlKeyState;
|
|
|
|
|
|
|
|
let c = char::from_u32(event.uChar.UnicodeChar as u32).unwrap_or('💀');
|
|
|
|
|
|
|
|
|
|
|
|
Event::Key(key::Event{
|
|
|
|
Event::Key(key::Event {
|
|
|
|
down: event.bKeyDown.as_bool(),
|
|
|
|
down: event.bKeyDown.as_bool(),
|
|
|
|
repeats: event.wRepeatCount,
|
|
|
|
repeats: event.wRepeatCount,
|
|
|
|
code: event.wVirtualKeyCode,
|
|
|
|
code: event.wVirtualKeyCode,
|
|
|
|
alt: mstate & ALT_KEYS > 0,
|
|
|
|
alt: mstate & ALT_KEYS > 0,
|
|
|
|
ctrl: mstate & CTRL_KEYS > 0,
|
|
|
|
ctrl: mstate & CTRL_KEYS > 0,
|
|
|
|
shift: mstate & SHIFT_PRESSED > 0,
|
|
|
|
shift: mstate & SHIFT_PRESSED > 0,
|
|
|
|
|
|
|
|
char: c,
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Console::MOUSE_EVENT => {
|
|
|
|
Console::MOUSE_EVENT => {
|
|
|
|
Event::Mouse
|
|
|
|
// OK I think it's safe to ignore these events since we're using the terminal
|
|
|
|
|
|
|
|
// escape sequences. I think we never see them because terminal.exe is going to
|
|
|
|
|
|
|
|
// turn mouse events into virtual terminal sequences anyway
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
|
|
|
let event = rec.Event.MouseEvent;
|
|
|
|
|
|
|
|
// pub dwMousePosition: COORD, i16 i16
|
|
|
|
|
|
|
|
// pub dwButtonState: u32,
|
|
|
|
|
|
|
|
// pub dwControlKeyState: u32,
|
|
|
|
|
|
|
|
// pub dwEventFlags: u32,
|
|
|
|
|
|
|
|
Event::Mouse{
|
|
|
|
|
|
|
|
x: event.dwMousePosition.X,
|
|
|
|
|
|
|
|
y: event.dwMousePosition.Y,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Console::WINDOW_BUFFER_SIZE_EVENT => {
|
|
|
|
Console::WINDOW_BUFFER_SIZE_EVENT => Event::Size,
|
|
|
|
Event::Size
|
|
|
|
_ => {
|
|
|
|
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => { unreachable!() }
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|