//! Linux key codes (what virtio-input reports) to keys, US layout. use port_input_device::Key; pub const LEFT_SHIFT: u16 = 42; pub const RIGHT_SHIFT: u16 = 54; pub const LEFT_CTRL: u16 = 29; pub const RIGHT_CTRL: u16 = 97; /// A letter typed with Ctrl held is its control character, as on a /// terminal: Ctrl+C is 3. Anything else is itself. pub fn with_ctrl(key: Key) -> Key { match key { Key::Char(c) if c.is_ascii_alphabetic() => Key::Char(c.to_ascii_lowercase() & 0x1f), k => k, } } /// Rows of the main block: the first key's code, then each key unshifted /// and shifted. const ROWS: [(u16, &[u8], &[u8]); 4] = [ (2, b"1234567890-=", b"!@#$%^&*()_+"), (16, b"qwertyuiop[]", b"QWERTYUIOP{}"), (30, b"asdfghjkl;'`", b"ASDFGHJKL:\"~"), (44, b"zxcvbnm,./", b"ZXCVBNM<>?"), ]; pub fn key(code: u16, shift: bool) -> Option { let named = match code { 1 => Some(Key::Escape), 14 => Some(Key::Backspace), 15 => Some(Key::Tab), 28 => Some(Key::Enter), 57 => Some(Key::Space), 103 => Some(Key::Up), 108 => Some(Key::Down), 105 => Some(Key::Left), 106 => Some(Key::Right), 43 => Some(Key::Char(if shift { b'|' } else { b'\\' })), _ => None, }; named.or_else(|| { ROWS.iter().find_map(|(first, plain, shifted)| { let i = usize::from(code.checked_sub(*first)?); let row = if shift { shifted } else { plain }; row.get(i).map(|c| Key::Char(*c)) }) }) } #[cfg(test)] mod tests { use super::*; #[test] fn ctrl_letters_are_control_characters() { assert_eq!(with_ctrl(Key::Char(b'c')), Key::Char(3)); assert_eq!(with_ctrl(Key::Char(b'C')), Key::Char(3)); assert_eq!(with_ctrl(Key::Char(b'1')), Key::Char(b'1')); assert_eq!(with_ctrl(Key::Enter), Key::Enter); } #[test] fn letters_digits_and_shift() { assert_eq!(key(35, false), Some(Key::Char(b'h'))); assert_eq!(key(35, true), Some(Key::Char(b'H'))); assert_eq!(key(11, false), Some(Key::Char(b'0'))); assert_eq!(key(12, true), Some(Key::Char(b'_'))); assert_eq!(key(53, false), Some(Key::Char(b'/'))); assert_eq!(key(41, true), Some(Key::Char(b'~'))); assert_eq!(key(28, false), Some(Key::Enter)); assert_eq!(key(103, false), Some(Key::Up)); assert_eq!(key(29, false), None, "left ctrl is not a character"); } }