use crate::error::Result;
use crate::hid::MouseReport;
use crate::platform::HidBackend;
use crate::Device;
use bitflags::bitflags;
use serde::{Deserialize, Serialize};
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct MouseButton: u8 {
const LEFT = 0x01;
const RIGHT = 0x02;
const MIDDLE = 0x04;
const BUTTON4 = 0x08;
const BUTTON5 = 0x10;
}
}
pub struct Mouse {
backend: Option<Box<dyn HidBackend>>,
report: MouseReport,
name: String,
}
impl Mouse {
pub fn new() -> Self {
Self::with_name("useHID Virtual Mouse")
}
pub fn with_name(name: &str) -> Self {
Self {
backend: None,
report: MouseReport::default(),
name: name.to_string(),
}
}
pub fn move_by(&mut self, dx: i32, dy: i32) -> Result<()> {
let steps_x = (dx.abs() + 126) / 127;
let steps_y = (dy.abs() + 126) / 127;
let steps = steps_x.max(steps_y).max(1);
for i in 0..steps {
let x = if i < steps_x {
(dx.signum() * (dx.abs() / steps).min(127)) as i8
} else {
0
};
let y = if i < steps_y {
(dy.signum() * (dy.abs() / steps).min(127)) as i8
} else {
0
};
self.report.x = x;
self.report.y = y;
self.send_report()?;
}
self.report.x = 0;
self.report.y = 0;
Ok(())
}
pub fn press(&mut self, button: MouseButton) -> Result<()> {
self.report.buttons |= button.bits();
self.send_report()
}
pub fn release(&mut self, button: MouseButton) -> Result<()> {
self.report.buttons &= !button.bits();
self.send_report()
}
pub fn click(&mut self, button: MouseButton) -> Result<()> {
self.press(button)?;
std::thread::sleep(std::time::Duration::from_millis(10));
self.release(button)
}
pub fn double_click(&mut self, button: MouseButton) -> Result<()> {
self.click(button)?;
std::thread::sleep(std::time::Duration::from_millis(50));
self.click(button)
}
pub fn scroll(&mut self, delta: i8) -> Result<()> {
self.report.wheel = delta;
self.send_report()?;
self.report.wheel = 0;
Ok(())
}
fn send_report(&self) -> Result<()> {
if let Some(backend) = &self.backend {
backend.send_report(self.report.as_bytes())
} else {
Err(crate::error::Error::DeviceNotCreated)
}
}
}
impl Default for Mouse {
fn default() -> Self {
Self::new()
}
}
impl Device for Mouse {
fn create(&mut self) -> Result<()> {
if self.backend.is_some() {
return Err(crate::error::Error::DeviceAlreadyExists);
}
let backend = crate::platform::create_mouse_backend(&self.name)?;
self.backend = Some(backend);
Ok(())
}
fn destroy(&mut self) -> Result<()> {
if let Some(backend) = self.backend.take() {
backend.destroy()
} else {
Err(crate::error::Error::DeviceNotCreated)
}
}
fn is_created(&self) -> bool {
self.backend.is_some()
}
}