use tokio::sync::mpsc::Sender;
use rdev::{Event, EventType, Key, listen};
use anyhow::Result;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
use crate::event::scanner_event::ScannerEvent;
use crate::event::source::Source;
use crate::util::time::now_ms;
pub fn start_keyboard_worker(tx: Sender<ScannerEvent>) -> Result<()> {
let buffer = Arc::new(Mutex::new(String::new()));
let burst_start = Arc::new(Mutex::new(None::<Instant>));
let last_time = Arc::new(Mutex::new(Instant::now()));
thread::spawn(move || {
if let Err(e) = listen(move |event: Event| {
if let EventType::KeyPress(key) = event.event_type {
let now = Instant::now();
let mut last = last_time.lock().unwrap();
let mut buf = buffer.lock().unwrap();
let mut start = burst_start.lock().unwrap();
if now.duration_since(*last) > Duration::from_millis(200) && !buf.is_empty() {
buf.clear();
*start = None;
}
*last = now;
if buf.is_empty() && key != Key::Return {
*start = Some(now);
}
if key == Key::Return {
if !buf.is_empty() {
let s = buf.clone();
let ev = ScannerEvent {
source: Source::Keyboard,
text: Some(s.clone()),
raw: s.as_bytes().to_vec(),
timestamp: now_ms(),
};
let _ = tx.blocking_send(ev);
buf.clear();
*start = None;
}
return;
}
if let Some(ch) = crate::keyboard::keymap::key_to_char(key, event.name.as_deref()) {
buf.push(ch);
}
}
}) {
eprintln!("keyboard listen error: {:?}", e);
}
});
Ok(())
}