diff options
Diffstat (limited to 'rsnix/src/ps2.rs')
| -rw-r--r-- | rsnix/src/ps2.rs | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/rsnix/src/ps2.rs b/rsnix/src/ps2.rs index 1b10b3b..8dd58a0 100644 --- a/rsnix/src/ps2.rs +++ b/rsnix/src/ps2.rs | |||
| @@ -22,8 +22,10 @@ pub enum KeyEvent { | |||
| 22 | Backspace, | 22 | Backspace, |
| 23 | Tab, | 23 | Tab, |
| 24 | Escape, | 24 | Escape, |
| 25 | CtrlC, | 25 | /// Ctrl + key (e.g. Ctrl('c') = ^C, Ctrl('s') = ^S). |
| 26 | CtrlD, | 26 | Ctrl(char), |
| 27 | /// Ctrl + arrow (0=up, 1=down, 2=left, 3=right) — word/page nav. | ||
| 28 | CtrlArrow(u8), | ||
| 27 | ArrowUp, | 29 | ArrowUp, |
| 28 | ArrowDown, | 30 | ArrowDown, |
| 29 | ArrowLeft, | 31 | ArrowLeft, |
| @@ -306,13 +308,14 @@ fn process_byte(byte: u8) -> Option<KeyEvent> { | |||
| 306 | ch.to_ascii_uppercase() | 308 | ch.to_ascii_uppercase() |
| 307 | }; | 309 | }; |
| 308 | } | 310 | } |
| 309 | // Ctrl+letter — the shell uses ^C (interrupt) and ^D (EOF). | 311 | // Ctrl+key — the terminal control-byte protocol (^C, ^D, ^S, ^X, …). |
| 310 | let ctrl = state.modifiers & (MOD_LCTRL | MOD_RCTRL) != 0; | 312 | let ctrl = state.modifiers & (MOD_LCTRL | MOD_RCTRL) != 0; |
| 311 | if ctrl { | 313 | if ctrl { |
| 312 | return match ch.to_ascii_lowercase() { | 314 | let lc = ch.to_ascii_lowercase(); |
| 313 | b'c' => Some(KeyEvent::CtrlC), | 315 | return if lc.is_ascii_graphic() { |
| 314 | b'd' => Some(KeyEvent::CtrlD), | 316 | Some(KeyEvent::Ctrl(lc as char)) |
| 315 | _ => None, // swallow other Ctrl+key combinations | 317 | } else { |
| 318 | None // swallow non-graphic Ctrl combos | ||
| 316 | }; | 319 | }; |
| 317 | } | 320 | } |
| 318 | if ch != 0 { | 321 | if ch != 0 { |
| @@ -334,10 +337,10 @@ fn process_e0(byte: u8) -> Option<KeyEvent> { | |||
| 334 | update_modifiers(byte, true, true); | 337 | update_modifiers(byte, true, true); |
| 335 | 338 | ||
| 336 | match byte { | 339 | match byte { |
| 337 | 0x48 => Some(KeyEvent::ArrowUp), | 340 | 0x48 => Some(if ctrl_held() { KeyEvent::CtrlArrow(0) } else { KeyEvent::ArrowUp }), |
| 338 | 0x50 => Some(KeyEvent::ArrowDown), | 341 | 0x50 => Some(if ctrl_held() { KeyEvent::CtrlArrow(1) } else { KeyEvent::ArrowDown }), |
| 339 | 0x4B => Some(KeyEvent::ArrowLeft), | 342 | 0x4B => Some(if ctrl_held() { KeyEvent::CtrlArrow(2) } else { KeyEvent::ArrowLeft }), |
| 340 | 0x4D => Some(KeyEvent::ArrowRight), | 343 | 0x4D => Some(if ctrl_held() { KeyEvent::CtrlArrow(3) } else { KeyEvent::ArrowRight }), |
| 341 | 0x47 => Some(KeyEvent::Home), | 344 | 0x47 => Some(KeyEvent::Home), |
| 342 | 0x4F => Some(KeyEvent::End), | 345 | 0x4F => Some(KeyEvent::End), |
| 343 | 0x49 => Some(KeyEvent::PageUp), | 346 | 0x49 => Some(KeyEvent::PageUp), |
| @@ -371,3 +374,9 @@ fn set_mod(state: &mut KbdState, bit: u8, pressed: bool) { | |||
| 371 | state.modifiers &= !bit; | 374 | state.modifiers &= !bit; |
| 372 | } | 375 | } |
| 373 | } | 376 | } |
| 377 | |||
| 378 | /// Is either Ctrl key held? | ||
| 379 | fn ctrl_held() -> bool { | ||
| 380 | let state = unsafe { &mut KBD }; | ||
| 381 | state.modifiers & (MOD_LCTRL | MOD_RCTRL) != 0 | ||
| 382 | } | ||
