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 => {
224                if pressed {
225                    self.modifiers.caps_lock = !self.modifiers.caps_lock;
226                }
227            }
228            KEY_NUMLOCK => {
229                if pressed {
230                    self.modifiers.num_lock = !self.modifiers.num_lock;
231                }
232            }
233            KEY_SCROLLLOCK => {
234                if pressed {
235                    self.modifiers.scroll_lock = !self.modifiers.scroll_lock;
236                }
237            }
238            _ => {}
239        }
240    }
241
242    /// Check if a key is currently pressed
243    pub fn is_key_pressed(&self, keycode: u32) -> bool {
244        self.pressed_keys.contains(&keycode)
245    }
246
247    /// Get current modifiers
248    pub fn modifiers(&self) -> KeyModifiers {
249        self.modifiers
250    }
251
252    /// Set keyboard layout
253    pub fn set_layout(&mut self, layout: &str) {
254        self.mapper.set_layout(layout);
255        debug!("Keyboard layout changed to: {}", layout);
256    }
257
258    /// Get current keyboard layout
259    pub fn layout(&self) -> &str {
260        self.mapper.layout()
261    }
262
263    /// Set key repeat delay
264    pub fn set_repeat_delay(&mut self, delay_ms: u64) {
265        self.repeat_delay_ms = delay_ms;
266    }
267
268    /// Set key repeat rate
269    pub fn set_repeat_rate(&mut self, rate_ms: u64) {
270        self.repeat_rate_ms = rate_ms;
271    }
272
273    /// Reset keyboard state (release all keys)
274    pub fn reset(&mut self) {
275        self.pressed_keys.clear();
276        self.last_key_times.clear();
277        self.modifiers = KeyModifiers::default();
278        debug!("Keyboard state reset");
279    }
280
281    /// Get number of currently pressed keys
282    pub fn pressed_key_count(&self) -> usize {
283        self.pressed_keys.len()
284    }
285
286    /// Get all currently pressed keys
287    pub fn get_pressed_keys(&self) -> Vec<u32> {
288        self.pressed_keys.iter().copied().collect()
289    }
290}
291
292impl Default for KeyboardHandler {
293    fn default() -> Self {
294        Self::new()
295    }
296}
297
298#[cfg(test)]
299mod tests {
300    use super::*;
301
302    #[test]
303    fn test_keyboard_handler_creation() {
304        let handler = KeyboardHandler::new();
305        assert_eq!(handler.pressed_key_count(), 0);
306        assert!(!handler.modifiers().shift);
307    }
308
309    #[test]
310    fn test_key_press_release() {
311        let mut handler = KeyboardHandler::new();
312
313        // Press A key (scancode 0x1E)
314        let event = handler.handle_key_down(0x1E, false, false).unwrap();
315
316        match event {
317            KeyboardEvent::KeyDown { keycode, .. } => {
318                assert!(keycode > 0);
319                assert!(handler.is_key_pressed(keycode));
320            }
321            _ => panic!("Expected KeyDown event"),
322        }
323
324        assert_eq!(handler.pressed_key_count(), 1);
325
326        // Release A key
327        let event = handler.handle_key_up(0x1E, false, false).unwrap();
328
329        match event {
330            KeyboardEvent::KeyUp { keycode, .. } => {
331                assert!(!handler.is_key_pressed(keycode));
332            }
333            _ => panic!("Expected KeyUp event"),
334        }
335
336        assert_eq!(handler.pressed_key_count(), 0);
337    }
338
339    #[test]
340    fn test_modifier_tracking() {
341        let mut handler = KeyboardHandler::new();
342
343        // Press left shift (scancode 0x2A)
344        handler.handle_key_down(0x2A, false, false).unwrap();
345        assert!(handler.modifiers().shift);
346
347        // Press left ctrl (scancode 0x1D)
348        handler.handle_key_down(0x1D, false, false).unwrap();
349        assert!(handler.modifiers().ctrl);
350
351        // Release left shift
352        handler.handle_key_up(0x2A, false, false).unwrap();
353        assert!(!handler.modifiers().shift);
354        assert!(handler.modifiers().ctrl);
355
356        // Release left ctrl
357        handler.handle_key_up(0x1D, false, false).unwrap();
358        assert!(!handler.modifiers().ctrl);
359    }
360
361    #[test]
362    fn test_caps_lock_toggle() {
363        let mut handler = KeyboardHandler::new();
364
365        assert!(!handler.modifiers().caps_lock);
366
367        // Press Caps Lock (scancode 0x3A)
368        handler.handle_key_down(0x3A, false, false).unwrap();
369        assert!(handler.modifiers().caps_lock);
370
371        // Release Caps Lock
372        handler.handle_key_up(0x3A, false, false).unwrap();
373        assert!(handler.modifiers().caps_lock); // Should stay on
374
375        // Press again to toggle off
376        handler.handle_key_down(0x3A, false, false).unwrap();
377        assert!(!handler.modifiers().caps_lock);
378    }
379
380    #[test]
381    fn test_multiple_modifiers() {
382        let mut handler = KeyboardHandler::new();
383
384        // Press Shift + Ctrl + Alt
385        handler.handle_key_down(0x2A, false, false).unwrap(); // Left Shift
386        handler.handle_key_down(0x1D, false, false).unwrap(); // Left Ctrl
387        handler.handle_key_down(0x38, false, false).unwrap(); // Left Alt
388
389        let mods = handler.modifiers();
390        assert!(mods.shift);
391        assert!(mods.ctrl);
392        assert!(mods.alt);
393    }
394
395    #[test]
396    fn test_both_shifts() {
397        let mut handler = KeyboardHandler::new();
398
399        // Press left shift
400        handler.handle_key_down(0x2A, false, false).unwrap();
401        assert!(handler.modifiers().shift);
402
403        // Press right shift too
404        handler.handle_key_down(0x36, false, false).unwrap();
405        assert!(handler.modifiers().shift);
406
407        // Release left shift
408        handler.handle_key_up(0x2A, false, false).unwrap();
409        assert!(handler.modifiers().shift); // Should still be on (right shift still pressed)
410
411        // Release right shift
412        handler.handle_key_up(0x36, false, false).unwrap();
413        assert!(!handler.modifiers().shift);
414    }
415
416    #[test]
417    fn test_extended_key() {
418        let mut handler = KeyboardHandler::new();
419
420        // Press right ctrl (extended scancode 0xE01D)
421        let event = handler.handle_key_down(0x1D, true, false).unwrap();
422
423        match event {
424            KeyboardEvent::KeyDown { keycode, .. } => {
425                assert!(keycode > 0);
426            }
427            _ => panic!("Expected KeyDown event"),
428        }
429
430        assert!(handler.modifiers().ctrl);
431    }
432
433    #[test]
434    fn test_layout_change() {
435        let mut handler = KeyboardHandler::new();
436
437        assert_eq!(handler.layout(), "us");
438
439        handler.set_layout("de");
440        assert_eq!(handler.layout(), "de");
441    }
442
443    #[test]
444    fn test_reset() {
445        let mut handler = KeyboardHandler::new();
446
447        // Press several keys
448        handler.handle_key_down(0x1E, false, false).unwrap(); // A
449        handler.handle_key_down(0x2A, false, false).unwrap(); // Shift
450        handler.handle_key_down(0x1D, false, false).unwrap(); // Ctrl
451
452        assert!(handler.pressed_key_count() > 0);
453        assert!(handler.modifiers().shift);
454
455        // Reset
456        handler.reset();
457
458        assert_eq!(handler.pressed_key_count(), 0);
459        assert!(!handler.modifiers().shift);
460        assert!(!handler.modifiers().ctrl);
461    }
462
463    #[test]
464    fn test_get_pressed_keys() {
465        let mut handler = KeyboardHandler::new();
466
467        handler.handle_key_down(0x1E, false, false).unwrap(); // A
468        handler.handle_key_down(0x1F, false, false).unwrap(); // S
469
470        let pressed = handler.get_pressed_keys();
471        assert_eq!(pressed.len(), 2);
472    }
473
474    #[test]
475    fn test_repeat_rate() {
476        let mut handler = KeyboardHandler::new();
477
478        handler.set_repeat_delay(100);
479        handler.set_repeat_rate(50);
480
481        assert_eq!(handler.repeat_delay_ms, 100);
482        assert_eq!(handler.repeat_rate_ms, 50);
483    }
484
485    #[test]
486    fn test_unknown_scancode() {
487        let mut handler = KeyboardHandler::new();
488
489        // Try invalid scancode
490        let result = handler.handle_key_down(0xFF, false, false);
491        assert!(result.is_err());
492    }
493
494    #[test]
495    fn test_function_keys() {
496        let mut handler = KeyboardHandler::new();
497
498        // F1 (scancode 0x3B)
499        let event = handler.handle_key_down(0x3B, false, false).unwrap();
500        match event {
501            KeyboardEvent::KeyDown { keycode, .. } => {
502                assert!(keycode > 0);
503            }
504            _ => panic!("Expected KeyDown event"),
505        }
506
507        // F12 (scancode 0x58)
508        let event = handler.handle_key_down(0x58, false, false).unwrap();
509        match event {
510            KeyboardEvent::KeyDown { keycode, .. } => {
511                assert!(keycode > 0);
512            }
513            _ => panic!("Expected KeyDown event"),
514        }
515    }
516}