key codes are neat

parse-tree
Jordan Orelli 2 years ago
parent 5a74f9308b
commit 79e41a376a

@ -1,5 +1,5 @@
use anyhow::{Context, Result};
use crate::{error::Error, log::*};
use crate::{error::Error, log::*, key};
use windows::Win32::System::Console;
use windows::Win32::Foundation::HANDLE;
@ -149,7 +149,7 @@ impl Reader {
// All buffered items have been processed, ask the OS for new event records
if self.buf_idx as u32 >= self.buf_len {
unsafe {
Error::check(Console::ReadConsoleInputW(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;
}
@ -159,3 +159,71 @@ impl Reader {
return Ok(rec);
}
}
#[derive(Debug)]
pub enum Event {
Focus(bool),
Menu,
Key(key::Event),
Mouse,
Size,
}
const ALT_KEYS: u32 = 0x0002 | 0x0001;
const CTRL_KEYS: u32 = 0x0008 | 0x0004;
const SHIFT_PRESSED: u32 = 0x0010;
impl From<Console::INPUT_RECORD> for Event {
fn from(rec: Console::INPUT_RECORD) -> Self {
// This is documented here:
// https://learn.microsoft.com/en-us/windows/console/input-record-str
match rec.EventType as u32 {
Console::FOCUS_EVENT => {
unsafe {
let event = rec.Event.FocusEvent;
Event::Focus(event.bSetFocus.as_bool())
}
}
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;
debug!("Menu Event: {:?}", event);
}
Event::Menu
}
Console::KEY_EVENT => {
// https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
unsafe {
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;
Event::Key(key::Event{
down: event.bKeyDown.as_bool(),
repeats: event.wRepeatCount,
code: event.wVirtualKeyCode,
alt: mstate & ALT_KEYS > 0,
ctrl: mstate & CTRL_KEYS > 0,
shift: mstate & SHIFT_PRESSED > 0,
})
}
}
Console::MOUSE_EVENT => {
Event::Mouse
}
Console::WINDOW_BUFFER_SIZE_EVENT => {
Event::Size
}
_ => { unreachable!() }
}
}
}

@ -0,0 +1,209 @@
type Code = u16;
#[derive(Debug)]
pub struct Event {
pub down: bool,
pub repeats: u16,
pub code: Code,
pub alt: bool,
pub ctrl: bool,
pub shift: bool,
}
macro_rules! keycodes {
($($c:literal $n:ident $x:literal)*) => {$(
#[allow(dead_code)]
pub const $n: Code = $c;
)*};
}
keycodes!{
0x08 BACKSPACE '⌫'
0x09 TAB '↹'
// 0x0A-0B Reserved
// 0x0C CLEAR
0x0D ENTER '↩'
// 0x0E-0F Undefined
0x10 SHIFT '⇧'
0x11 CTRL '⎈'
0x12 ALT '⎇'
0x13 BREAK '⎉'
0x14 CAPS_LOCK '⇪'
// 0x15 IME Kana mode
// 0x15 IME Hanguel mode (maintained for compatibility; use VK_HANGUL)
// 0x15 IME Hangul mode
// 0x16 IME On
// 0x17 IME Junja mode
// 0x18 IME final mode
// 0x19 IME Hanja mode
// 0x19 IME Kanji mode
// 0x1A IME Off
// 0x1C IME convert
0x1B ESC '⎋'
0x20 SPACE '␣'
0x23 END '⇲'
0x41 A 'a'
0x42 B 'b'
0x43 C 'c'
0x44 D 'd'
0x45 E 'e'
0x46 F 'f'
0x47 G 'g'
0x48 H 'h'
0x49 I 'i'
0x4A J 'j'
0x4B K 'k'
0x4C L 'l'
0x4D M 'm'
0x4E N 'n'
0x4F O 'o'
0x50 P 'p'
0x51 Q 'q'
0x52 R 'r'
0x53 S 's'
0x54 T 't'
0x55 U 'u'
0x56 V 'v'
0x57 W 'w'
0x58 X 'x'
0x59 Y 'y'
0x5A Z 'z'
0x30 NUM_0 '0'
0x31 NUM_1 '1'
0x32 NUM_2 '2'
0x33 NUM_3 '3'
0x34 NUM_4 '4'
0x35 NUM_5 '5'
0x36 NUM_6 '6'
0x37 NUM_7 '7'
0x38 NUM_8 '8'
0x39 NUM_9 '9'
// 0x70 F1
// 0x71 F2
// 0x72 F3
// 0x73 F4
// 0x74 F5
// 0x75 F6
// 0x76 F7
// 0x77 F8
// 0x78 F9
// 0x79 F10
// 0x7A F11
// 0x7B F12
// 0x7C F13
// 0x7D F14
// 0x7E F15
// 0x7F F16
// 0x80 F17
// 0x81 F18
// 0x82 F19
// 0x83 F20
// 0x84 F21
// 0x85 F22
// 0x86 F23
// 0x87 F24
0x21 PAGE_UP '↟'
0x22 PAGE_DOWN '↡'
0x25 LEFT '←'
0x26 UP '↑'
0x27 RIGHT '→'
0x28 DOWN '↓'
0xA0 LEFT_SHIFT '⇧'
0xA1 RIGHT_SHIFT '⇧'
}
/*
VK_NONCONVERT 0x1D IME nonconvert
VK_ACCEPT 0x1E IME accept
VK_MODECHANGE 0x1F IME mode change request
VK_HOME 0x24 HOME key
VK_SELECT 0x29 SELECT key
VK_PRINT 0x2A PRINT key
VK_EXECUTE 0x2B EXECUTE key
VK_SNAPSHOT 0x2C PRINT SCREEN key
VK_INSERT 0x2D INS key
VK_DELETE 0x2E DEL key
VK_HELP 0x2F HELP key
- 0x3A-40 Undefined
VK_LWIN 0x5B Left Windows key (Natural keyboard)
VK_RWIN 0x5C Right Windows key (Natural keyboard)
VK_APPS 0x5D Applications key (Natural keyboard)
- 0x5E Reserved
VK_SLEEP 0x5F Computer Sleep key
VK_NUMPAD0 0x60 Numeric keypad 0 key
VK_NUMPAD1 0x61 Numeric keypad 1 key
VK_NUMPAD2 0x62 Numeric keypad 2 key
VK_NUMPAD3 0x63 Numeric keypad 3 key
VK_NUMPAD4 0x64 Numeric keypad 4 key
VK_NUMPAD5 0x65 Numeric keypad 5 key
VK_NUMPAD6 0x66 Numeric keypad 6 key
VK_NUMPAD7 0x67 Numeric keypad 7 key
VK_NUMPAD8 0x68 Numeric keypad 8 key
VK_NUMPAD9 0x69 Numeric keypad 9 key
VK_MULTIPLY 0x6A Multiply key
VK_ADD 0x6B Add key
VK_SEPARATOR 0x6C Separator key
VK_SUBTRACT 0x6D Subtract key
VK_DECIMAL 0x6E Decimal key
VK_DIVIDE 0x6F Divide key
- 0x88-8F Unassigned
VK_NUMLOCK 0x90 NUM LOCK key
VK_SCROLL 0x91 SCROLL LOCK key
0x92-96 OEM specific
- 0x97-9F Unassigned
VK_LCONTROL 0xA2 Left CONTROL key
VK_RCONTROL 0xA3 Right CONTROL key
VK_LMENU 0xA4 Left ALT key
VK_RMENU 0xA5 Right ALT key
VK_BROWSER_BACK 0xA6 Browser Back key
VK_BROWSER_FORWARD 0xA7 Browser Forward key
VK_BROWSER_REFRESH 0xA8 Browser Refresh key
VK_BROWSER_STOP 0xA9 Browser Stop key
VK_BROWSER_SEARCH 0xAA Browser Search key
VK_BROWSER_FAVORITES 0xAB Browser Favorites key
VK_BROWSER_HOME 0xAC Browser Start and Home key
VK_VOLUME_MUTE 0xAD Volume Mute key
VK_VOLUME_DOWN 0xAE Volume Down key
VK_VOLUME_UP 0xAF Volume Up key
VK_MEDIA_NEXT_TRACK 0xB0 Next Track key
VK_MEDIA_PREV_TRACK 0xB1 Previous Track key
VK_MEDIA_STOP 0xB2 Stop Media key
VK_MEDIA_PLAY_PAUSE 0xB3 Play/Pause Media key
VK_LAUNCH_MAIL 0xB4 Start Mail key
VK_LAUNCH_MEDIA_SELECT 0xB5 Select Media key
VK_LAUNCH_APP1 0xB6 Start Application 1 key
VK_LAUNCH_APP2 0xB7 Start Application 2 key
- 0xB8-B9 Reserved
VK_OEM_1 0xBA Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the ';:' key
VK_OEM_PLUS 0xBB For any country/region, the '+' key
VK_OEM_COMMA 0xBC For any country/region, the ',' key
VK_OEM_MINUS 0xBD For any country/region, the '-' key
VK_OEM_PERIOD 0xBE For any country/region, the '.' key
VK_OEM_2 0xBF Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the '/?' key
VK_OEM_3 0xC0 Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the '`~' key
- 0xC1-D7 Reserved
- 0xD8-DA Unassigned
VK_OEM_4 0xDB Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the '[{' key
VK_OEM_5 0xDC Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the '\|' key
VK_OEM_6 0xDD Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the ']}' key
VK_OEM_7 0xDE Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the 'single-quote/double-quote' key
VK_OEM_8 0xDF Used for miscellaneous characters; it can vary by keyboard.
- 0xE0 Reserved
0xE1 OEM specific
VK_OEM_102 0xE2 The <> keys on the US standard keyboard, or the \\| key on the non-US 102-key keyboard
0xE3-E4 OEM specific
VK_PROCESSKEY 0xE5 IME PROCESS key
0xE6 OEM specific
VK_PACKET 0xE7 Used to pass Unicode characters as if they were keystrokes. The VK_PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT, SendInput, WM_KEYDOWN, and WM_KEYUP
- 0xE8 Unassigned
0xE9-F5 OEM specific
VK_ATTN 0xF6 Attn key
VK_CRSEL 0xF7 CrSel key
VK_EXSEL 0xF8 ExSel key
VK_EREOF 0xF9 Erase EOF key
VK_PLAY 0xFA Play key
VK_ZOOM 0xFB Zoom key
VK_NONAME 0xFC Reserved
VK_PA1 0xFD PA1 key
VK_OEM_CLEAR 0xFE Clear key
*/

@ -3,6 +3,7 @@ mod line;
mod log;
mod input;
mod prompt;
mod key;
use line::Line;
use prompt::Prompt;
@ -149,7 +150,14 @@ fn main() -> Result<()> {
prompt.print()?;
loop {
let rec = input.next()?;
let event: input::Event = rec.into();
debug!("Event Type: {}", rec.EventType);
if let input::Event::Key(event) = &event {
debug!("Key Event: {:?}", event);
if event.code == key::ENTER {
debug!("ENTER!!!");
}
}
match rec.EventType as u32 {
Console::FOCUS_EVENT => {
// The Event member contains a FOCUS_EVENT_RECORD structure. These events are

Loading…
Cancel
Save