use std::sync::{ Arc, atomic::{AtomicU8, Ordering}, }; use std::thread::{self, JoinHandle}; /// 使用 rdev 监听系统级键盘事件。 /// bit0 = Up, bit1 = Left, bit2 = Right pub fn spawn_listener() -> (JoinHandle<()>, Arc) { let state = Arc::new(AtomicU8::new(0)); let state_cloned = Arc::clone(&state); let handle = thread::spawn(move || { if let Err(err) = rdev::listen(move |event| { match event.event_type { rdev::EventType::KeyPress(key) => { let bit = match key { rdev::Key::UpArrow => Some(0x1), rdev::Key::LeftArrow => Some(0x2), rdev::Key::RightArrow => Some(0x4), _ => None, }; if let Some(mask) = bit { state_cloned.fetch_or(mask, Ordering::SeqCst); let s = state_cloned.load(Ordering::SeqCst); println!("[CMD] {:?} (state=0b{:03b})", state_to_vector(s), s); } } rdev::EventType::KeyRelease(key) => { let bit = match key { rdev::Key::UpArrow => Some(0x1), rdev::Key::LeftArrow => Some(0x2), rdev::Key::RightArrow => Some(0x4), _ => None, }; if let Some(mask) = bit { state_cloned.fetch_and(!mask, Ordering::SeqCst); let s = state_cloned.load(Ordering::SeqCst); println!("[CMD] {:?} (state=0b{:03b})", state_to_vector(s), s); } } _ => {} } }) { eprintln!("rdev listen failed: {:?}", err); } }); (handle, state) } pub fn state_from_arc(state: &Arc) -> [f32; 3] { state_to_vector(state.load(Ordering::SeqCst)) } /// 状态位转成控制向量。 pub fn state_to_vector(state: u8) -> [f32; 3] { if state & 0x1 != 0 { if state & 0x2 != 0 { [0.2, 0.0, -0.5] } else if state & 0x4 != 0 { [0.2, 0.0, 0.5] } else { [0.2, 0.0, 0.0] } } else { [0.0, 0.0, 0.0] } } #[cfg(test)] mod tests { use super::*; #[test] fn test_no_key() { assert_eq!(state_to_vector(0), [0.0, 0.0, 0.0]); } #[test] fn test_up_only() { assert_eq!(state_to_vector(0x1), [0.2, 0.0, 0.0]); } #[test] fn test_up_left() { assert_eq!(state_to_vector(0x1 | 0x2), [0.2, 0.0, -0.5]); } #[test] fn test_up_right() { assert_eq!(state_to_vector(0x1 | 0x4), [0.2, 0.0, 0.5]); } }