// client/src/input/mouse.rs use evdev::{Device, EventType, InputEvent, KeyCode, RelativeAxisCode}; use tokio::sync::broadcast::{self, Sender}; use tracing::{debug, error, warn}; use navka_common::navka::MouseReport; pub struct MouseAggregator { dev: Device, tx: Sender, dev_mode: bool, buttons: u8, last_buttons: u8, dx: i8, dy: i8, wheel: i8, } impl MouseAggregator { pub fn new(dev: Device, dev_mode: bool, tx: Sender) -> Self { Self { dev, tx, dev_mode, buttons:0, last_buttons:0, dx:0, dy:0, wheel:0 } } #[inline] fn slog(&self, f: impl FnOnce()) { if self.dev_mode { f() } } pub fn process_events(&mut self) { let evts: Vec = match self.dev.fetch_events() { Ok(it) => it.collect(), Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => return, Err(e) => { if self.dev_mode { error!("mouse read err: {e}"); } return } }; if self.dev_mode && !evts.is_empty() { debug!("🖱️ {} evts from {}", evts.len(), self.dev.name().unwrap_or("?")); } for e in evts { match e.event_type() { EventType::KEY => match e.code() { c if c == KeyCode::BTN_LEFT.0 => self.set_btn(0, e.value()), c if c == KeyCode::BTN_RIGHT.0 => self.set_btn(1, e.value()), c if c == KeyCode::BTN_MIDDLE.0 => self.set_btn(2, e.value()), _ => {} }, EventType::RELATIVE => match e.code() { c if c == RelativeAxisCode::REL_X.0 => self.dx = self.dx.saturating_add(e.value().clamp(-127,127) as i8), c if c == RelativeAxisCode::REL_Y.0 => self.dy = self.dy.saturating_add(e.value().clamp(-127,127) as i8), c if c == RelativeAxisCode::REL_WHEEL.0 => self.wheel = self.wheel.saturating_add(e.value().clamp(-1,1) as i8), _ => {} }, EventType::SYNCHRONIZATION => self.flush(), _ => {} } } } fn flush(&mut self) { if self.dx==0 && self.dy==0 && self.wheel==0 && self.buttons==self.last_buttons { return; } let pkt = [ self.buttons, self.dx.clamp(-127,127) as u8, self.dy.clamp(-127,127) as u8, self.wheel as u8, ]; if let Err(broadcast::error::SendError(_)) = self.tx.send(MouseReport { data: pkt.to_vec() }) { if self.dev_mode { warn!("❌ no HID receiver (mouse)"); } } else if self.dev_mode { debug!("📤 mouse {:?}", pkt) } self.dx=0; self.dy=0; self.wheel=0; self.last_buttons=self.buttons; } #[inline] fn set_btn(&mut self, bit: u8, val: i32) { if val!=0 { self.buttons |= 1<