Skip to main content

lamco_rdp_input/
keyboard.rs

1//! Keyboard Event Handling
2//!
3//! Handles keyboard events with scancode translation, modifier tracking,
4//! and keyboard layout support.
5
6use crate::error::Result;
7use crate::mapper::ScancodeMapper;
8use std::collections::HashSet;
9use std::time::Instant;
10use tracing::debug;
11
12/// Keyboard modifiers
13#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
14pub struct KeyModifiers {
15    /// Left or right Shift pressed
16    pub shift: bool,
17    /// Left or right Ctrl pressed
18    pub ctrl: bool,
19    /// Left or right Alt pressed
20    pub alt: bool,
21    /// Left or right Meta/Super/Windows key pressed
22    pub meta: bool,
23    /// Caps Lock active
24    pub caps_lock: bool,
25    /// Num Lock active
26    pub num_lock: bool,
27    /// Scroll Lock active
28    pub scroll_lock: bool,
29}
30
31/// Keyboard event types
32#[derive(Debug, Clone)]
33pub enum KeyboardEvent {
34    /// Key pressed
35    KeyDown {
36        /// Linux evdev keycode
37        keycode: u32,
38        /// RDP scancode
39        scancode: u16,
40        /// Current modifiers
41        modifiers: KeyModifiers,
42        /// Event timestamp
43        timestamp: Instant,
44    },
45
46    /// Key released
47    KeyUp {
48        /// Linux evdev keycode
49        keycode: u32,
50        /// RDP scancode
51        scancode: u16,
52        /// Current modifiers
53        modifiers: KeyModifiers,
54        /// Event timestamp
55        timestamp: Instant,
56    },
57
58    /// Key repeat
59    KeyRepeat {
60        /// Linux evdev keycode
61        keycode: u32,
62        /// RDP scancode
63        scancode: u16,
64        /// Current modifiers
65        modifiers: KeyModifiers,
66        /// Event timestamp
67        timestamp: Instant,
68    },
69}
70
71/// Keyboard event handler
72pub struct KeyboardHandler {
73    /// Scancode mapper
74    mapper: ScancodeMapper,
75
76    /// Currently pressed keys
77    pressed_keys: HashSet<u32>,
78
79    /// Current modifiers
80    modifiers: KeyModifiers,
81
82    /// Last event timestamp for each key (for repeat detection)
83    last_key_times: std::collections::HashMap<u32, Instant>,
84
85    /// Key repeat delay (milliseconds)
86    repeat_delay_ms: u64,
87
88    /// Key repeat rate (milliseconds between repeats)
89    repeat_rate_ms: u64,
90}
91
92impl KeyboardHandler {
93    /// Create a new keyboard handler
94    pub fn new() -> Self {
95        Self {
96            mapper: ScancodeMapper::new(),
97            pressed_keys: HashSet::new(),
98            modifiers: KeyModifiers::default(),
99            last_key_times: std::collections::HashMap::new(),
100            repeat_delay_ms: 500,
101            repeat_rate_ms: 33,
102        }
103    }
104
105    /// Process key down event from RDP
106    pub fn handle_key_down(&mut self, scancode: u16, extended: bool, e1_prefix: bool) -> Result<KeyboardEvent> {
107        // Translate scancode to keycode
108        let keycode = self.mapper.translate_scancode(scancode as u32, extended, e1_prefix)?;
109
110        let timestamp = Instant::now();
111
112        // Check if this is a repeat (key already pressed)
113        let is_repeat = self.pressed_keys.contains(&keycode);
114
115        if is_repeat {
116            // Check repeat timing
117            if let Some(last_time) = self.last_key_times.get(&keycode) {
118                let elapsed = timestamp.duration_since(*last_time).as_millis() as u64;
119                if elapsed < self.repeat_rate_ms {
120                    // Too soon for repeat, return repeat event to maintain state
121                    debug!("Key repeat within rate limit: keycode {}", keycode);
122                    return Ok(KeyboardEvent::KeyRepeat {
123                        keycode,
124                        scancode,
125                        modifiers: self.modifiers,
126                        timestamp,
127                    });
128                }
129            }
130        }
131
132        // Update pressed keys
133        self.pressed_keys.insert(keycode);
134        self.last_key_times.insert(keycode, timestamp);
135
136        // Update modifiers
137        self.update_modifiers(keycode, true);
138
139        debug!(
140            "Key down: scancode=0x{:04X}, keycode={}, modifiers={:?}",
141            scancode, keycode, self.modifiers
142        );
143
144        if is_repeat {
145            Ok(KeyboardEvent::KeyRepeat {
146                keycode,
147                scancode,
148                modifiers: self.modifiers,
149                timestamp,
150            })
151        } else {
152            Ok(KeyboardEvent::KeyDown {
153                keycode,
154                scancode,
155                modifiers: self.modifiers,
156                timestamp,
157            })
158        }
159    }
160
161    /// Process key up event from RDP
162    pub fn handle_key_up(&mut self, scancode: u16, extended: bool, e1_prefix: bool) -> Result<KeyboardEvent> {
163        // Translate scancode to keycode
164        let keycode = self.mapper.translate_scancode(scancode as u32, extended, e1_prefix)?;
165
166        let timestamp = Instant::now();
167
168        // Remove from pressed keys
169        self.pressed_keys.remove(&keycode);
170        self.last_key_times.remove(&keycode);
171
172        // Update modifiers
173        self.update_modifiers(keycode, false);
174
175        debug!(
176            "Key up: scancode=0x{:04X}, keycode={}, modifiers={:?}",
177            scancode, keycode, self.modifiers
178        );
179
180        Ok(KeyboardEvent::KeyUp {
181            keycode,
182            scancode,
183            modifiers: self.modifiers,
184            timestamp,
185        })
186    }
187
188    /// Update modifier states based on key event
189    fn update_modifiers(&mut self, keycode: u32, pressed: bool) {
190        #[allow(clippy::wildcard_imports)]
191        use crate::mapper::keycodes::*;
192
193        match keycode {
194            KEY_LEFTSHIFT | KEY_RIGHTSHIFT => {
195                if pressed {
196                    self.modifiers.shift = true;
197                } else {
198                    // Only clear if neither shift is pressed
199                    self.modifiers.shift = self.is_key_pressed(KEY_LEFTSHIFT) || self.is_key_pressed(KEY_RIGHTSHIFT);
200                }
201            }
202            KEY_LEFTCTRL | KEY_RIGHTCTRL => {
203                if pressed {
204                    self.modifiers.ctrl = true;
205                } else {
206                    self.modifiers.ctrl = self.is_key_pressed(KEY_LEFTCTRL) || self.is_key_pressed(KEY_RIGHTCTRL);
207                }
208            }
209            KEY_LEFTALT | KEY_RIGHTALT => {
210                if pressed {
211                    self.modifiers.alt = true;
212                } else {
213                    self.modifiers.alt = self.is_key_pressed(KEY_LEFTALT) || self.is_key_pressed(KEY_RIGHTALT);
214                }
215            }
216            KEY_LEFTMETA | KEY_RIGHTMETA => {
217                if pressed {
218                    self.modifiers.meta = true;
219                } else {
220                    self.modifiers.meta = self.is_key_pressed(KEY_LEFTMETA) || self.is_key_pressed(KEY_RIGHTMETA);
221                }
222            }
223            KEY_CAPSLOCK if pressed => {
224                self.modifiers.caps_lock = !self.modifiers.caps_lock;
225            }
226            KEY_NUMLOCK if pressed => {
227                self.modifiers.num_lock = !self.modifiers.num_lock;
228            }
229            KEY_SCROLLLOCK if pressed => {
230                self.modifiers.scroll_lock = !self.modifiers.scroll_lock;
231            }
232            _ => {}
233        }
234    }
235
236    /// Check if a key is currently pressed
237    pub fn is_key_pressed(&self, keycode: u32) -> bool {
238        self.pressed_keys.contains(&keycode)
239    }
240
241    /// Get current modifiers
242    pub fn modifiers(&self) -> KeyModifiers {
243        self.modifiers
244    }
245
246    /// Set keyboard layout
247    pub fn set_layout(&mut self, layout: &str) {
248        self.mapper.set_layout(layout);
249        debug!("Keyboard layout changed to: {}", layout);
250    }
251
252    /// Get current keyboard layout
253    pub fn layout(&self) -> &str {
254        self.mapper.layout()
255    }
256
257    /// Set key repeat delay
258    pub fn set_repeat_delay(&mut self, delay_ms: u64) {
259        self.repeat_delay_ms = delay_ms;
260    }
261
262    /// Set key repeat rate
263    pub fn set_repeat_rate(&mut self, rate_ms: u64) {
264        self.repeat_rate_ms = rate_ms;
265    }
266
267    /// Reset keyboard state (release all keys)
268    pub fn reset(&mut self) {
269        self.pressed_keys.clear();
270        self.last_key_times.clear();
271        self.modifiers = KeyModifiers::default();
272        debug!("Keyboard state reset");
273    }
274
275    /// Get number of currently pressed keys
276    pub fn pressed_key_count(&self) -> usize {
277        self.pressed_keys.len()
278    }
279
280    /// Get all currently pressed keys
281    pub fn get_pressed_keys(&self) -> Vec<u32> {
282        self.pressed_keys.iter().copied().collect()
283    }
284}
285
286impl Default for KeyboardHandler {
287    fn default() -> Self {
288        Self::new()
289    }
290}
291
292#[cfg(test)]
293mod tests {
294    use super::*;
295
296    #[test]
297    fn test_keyboard_handler_creation() {
298        let handler = KeyboardHandler::new();
299        assert_eq!(handler.pressed_key_count(), 0);
300        assert!(!handler.modifiers().shift);
301    }
302
303    #[test]
304    fn test_key_press_release() {
305        let mut handler = KeyboardHandler::new();
306
307        // Press A key (scancode 0x1E)
308        let event = handler.handle_key_down(0x1E, false, false).unwrap();
309
310        match event {
311            KeyboardEvent::KeyDown { keycode, .. } => {
312                assert!(keycode > 0);
313                assert!(handler.is_key_pressed(keycode));
314            }
315            _ => panic!("Expected KeyDown event"),
316        }
317
318        assert_eq!(handler.pressed_key_count(), 1);
319
320        // Release A key
321        let event = handler.handle_key_up(0x1E, false, false).unwrap();
322
323        match event {
324            KeyboardEvent::KeyUp { keycode, .. } => {
325                assert!(!handler.is_key_pressed(keycode));
326            }
327            _ => panic!("Expected KeyUp event"),
328        }
329
330        assert_eq!(handler.pressed_key_count(), 0);
331    }
332
333    #[test]
334    fn test_modifier_tracking() {
335        let mut handler = KeyboardHandler::new();
336
337        // Press left shift (scancode 0x2A)
338        handler.handle_key_down(0x2A, false, false).unwrap();
339        assert!(handler.modifiers().shift);
340
341        // Press left ctrl (scancode 0x1D)
342        handler.handle_key_down(0x1D, false, false).unwrap();
343        assert!(handler.modifiers().ctrl);
344
345        // Release left shift
346        handler.handle_key_up(0x2A, false, false).unwrap();
347        assert!(!handler.modifiers().shift);
348        assert!(handler.modifiers().ctrl);
349
350        // Release left ctrl
351        handler.handle_key_up(0x1D, false, false).unwrap();
352        assert!(!handler.modifiers().ctrl);
353    }
354
355    #[test]
356    fn test_caps_lock_toggle() {
357        let mut handler = KeyboardHandler::new();
358
359        assert!(!handler.modifiers().caps_lock);
360
361        // Press Caps Lock (scancode 0x3A)
362        handler.handle_key_down(0x3A, false, false).unwrap();
363        assert!(handler.modifiers().caps_lock);
364
365        // Release Caps Lock
366        handler.handle_key_up(0x3A, false, false).unwrap();
367        assert!(handler.modifiers().caps_lock); // Should stay on
368
369        // Press again to toggle off
370        handler.handle_key_down(0x3A, false, false).unwrap();
371        assert!(!handler.modifiers().caps_lock);
372    }
373
374    #[test]
375    fn test_multiple_modifiers() {
376        let mut handler = KeyboardHandler::new();
377
378        // Press Shift + Ctrl + Alt
379        handler.handle_key_down(0x2A, false, false).unwrap(); // Left Shift
380        handler.handle_key_down(0x1D, false, false).unwrap(); // Left Ctrl
381        handler.handle_key_down(0x38, false, false).unwrap(); // Left Alt
382
383        let mods = handler.modifiers();
384        assert!(mods.shift);
385        assert!(mods.ctrl);
386        assert!(mods.alt);
387    }
388
389    #[test]
390    fn test_both_shifts() {
391        let mut handler = KeyboardHandler::new();
392
393        // Press left shift
394        handler.handle_key_down(0x2A, false, false).unwrap();
395        assert!(handler.modifiers().shift);
396
397        // Press right shift too
398        handler.handle_key_down(0x36, false, false).unwrap();
399        assert!(handler.modifiers().shift);
400
401        // Release left shift
402        handler.handle_key_up(0x2A, false, false).unwrap();
403        assert!(handler.modifiers().shift); // Should still be on (right shift still pressed)
404
405        // Release right shift
406        handler.handle_key_up(0x36, false, false).unwrap();
407        assert!(!handler.modifiers().shift);
408    }
409
410    #[test]
411    fn test_extended_key() {
412        let mut handler = KeyboardHandler::new();
413
414        // Press right ctrl (extended scancode 0xE01D)
415        let event = handler.handle_key_down(0x1D, true, false).unwrap();
416
417        match event {
418            KeyboardEvent::KeyDown { keycode, .. } => {
419                assert!(keycode > 0);
420            }
421            _ => panic!("Expected KeyDown event"),
422        }
423
424        assert!(handler.modifiers().ctrl);
425    }
426
427    #[test]
428    fn test_layout_change() {
429        let mut handler = KeyboardHandler::new();
430
431        assert_eq!(handler.layout(), "us");
432
433        handler.set_layout("de");
434        assert_eq!(handler.layout(), "de");
435    }
436
437    #[test]
438    fn test_reset() {
439        let mut handler = KeyboardHandler::new();
440
441        // Press several keys
442        handler.handle_key_down(0x1E, false, false).unwrap(); // A
443        handler.handle_key_down(0x2A, false, false).unwrap(); // Shift
444        handler.handle_key_down(0x1D, false, false).unwrap(); // Ctrl
445
446        assert!(handler.pressed_key_count() > 0);
447        assert!(handler.modifiers().shift);
448
449        // Reset
450        handler.reset();
451
452        assert_eq!(handler.pressed_key_count(), 0);
453        assert!(!handler.modifiers().shift);
454        assert!(!handler.modifiers().ctrl);
455    }
456
457    #[test]
458    fn test_get_pressed_keys() {
459        let mut handler = KeyboardHandler::new();
460
461        handler.handle_key_down(0x1E, false, false).unwrap(); // A
462        handler.handle_key_down(0x1F, false, false).unwrap(); // S
463
464        let pressed = handler.get_pressed_keys();
465        assert_eq!(pressed.len(), 2);
466    }
467
468    #[test]
469    fn test_repeat_rate() {
470        let mut handler = KeyboardHandler::new();
471
472        handler.set_repeat_delay(100);
473        handler.set_repeat_rate(50);
474
475        assert_eq!(handler.repeat_delay_ms, 100);
476        assert_eq!(handler.repeat_rate_ms, 50);
477    }
478
479    #[test]
480    fn test_unknown_scancode() {
481        let mut handler = KeyboardHandler::new();
482
483        // Try invalid scancode
484        let result = handler.handle_key_down(0xFF, false, false);
485        assert!(result.is_err());
486    }
487
488    #[test]
489    fn test_function_keys() {
490        let mut handler = KeyboardHandler::new();
491
492        // F1 (scancode 0x3B)
493        let event = handler.handle_key_down(0x3B, false, false).unwrap();
494        match event {
495            KeyboardEvent::KeyDown { keycode, .. } => {
496                assert!(keycode > 0);
497            }
498            _ => panic!("Expected KeyDown event"),
499        }
500
501        // F12 (scancode 0x58)
502        let event = handler.handle_key_down(0x58, false, false).unwrap();
503        match event {
504            KeyboardEvent::KeyDown { keycode, .. } => {
505                assert!(keycode > 0);
506            }
507            _ => panic!("Expected KeyDown event"),
508        }
509    }
510}