76 lines
2.4 KiB
Rust
76 lines
2.4 KiB
Rust
//! 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<Key> {
|
|
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");
|
|
}
|
|
}
|