mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-01 23:41:27 +03:00
add tests for capture and emulation
This commit is contained in:
@@ -25,7 +25,7 @@ pub mod x11;
|
|||||||
/// fallback input capture (does not produce events)
|
/// fallback input capture (does not produce events)
|
||||||
pub mod dummy;
|
pub mod dummy;
|
||||||
|
|
||||||
pub async fn create() -> Box<dyn InputCapture> {
|
pub async fn create() -> Box<dyn InputCapture<Item = io::Result<(ClientHandle, Event)>>> {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
match macos::MacOSInputCapture::new() {
|
match macos::MacOSInputCapture::new() {
|
||||||
Ok(p) => return Box::new(p),
|
Ok(p) => return Box::new(p),
|
||||||
|
|||||||
42
src/capture_test.rs
Normal file
42
src/capture_test.rs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
use crate::capture;
|
||||||
|
use crate::client::{ClientEvent, Position};
|
||||||
|
use crate::event::{Event, KeyboardEvent};
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use futures::StreamExt;
|
||||||
|
use tokio::task::LocalSet;
|
||||||
|
|
||||||
|
pub fn run() -> Result<()> {
|
||||||
|
log::info!("running input capture test");
|
||||||
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_io()
|
||||||
|
.enable_time()
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
runtime.block_on(LocalSet::new().run_until(input_capture_test()))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn input_capture_test() -> Result<()> {
|
||||||
|
log::info!("creating input capture");
|
||||||
|
let mut input_capture = capture::create().await;
|
||||||
|
log::info!("creating clients");
|
||||||
|
input_capture.notify(ClientEvent::Create(0, Position::Left))?;
|
||||||
|
input_capture.notify(ClientEvent::Create(1, Position::Right))?;
|
||||||
|
input_capture.notify(ClientEvent::Create(2, Position::Top))?;
|
||||||
|
input_capture.notify(ClientEvent::Create(3, Position::Bottom))?;
|
||||||
|
loop {
|
||||||
|
let (client, event) = input_capture
|
||||||
|
.next()
|
||||||
|
.await
|
||||||
|
.ok_or(anyhow!("capture stream closed"))??;
|
||||||
|
let pos = match client {
|
||||||
|
0 => Position::Left,
|
||||||
|
1 => Position::Right,
|
||||||
|
2 => Position::Top,
|
||||||
|
_ => Position::Bottom,
|
||||||
|
};
|
||||||
|
log::info!("position: {pos}, event: {event}");
|
||||||
|
if let Event::Keyboard(KeyboardEvent::Key { key: 1, .. }) = event {
|
||||||
|
input_capture.release()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,6 +59,14 @@ struct CliArgs {
|
|||||||
/// run only the service as a daemon without the frontend
|
/// run only the service as a daemon without the frontend
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
daemon: bool,
|
daemon: bool,
|
||||||
|
|
||||||
|
/// test input capture
|
||||||
|
#[arg(long)]
|
||||||
|
test_capture: bool,
|
||||||
|
|
||||||
|
/// test input emulation
|
||||||
|
#[arg(long)]
|
||||||
|
test_emulation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
@@ -74,6 +82,8 @@ pub struct Config {
|
|||||||
pub clients: Vec<(TomlClient, Position)>,
|
pub clients: Vec<(TomlClient, Position)>,
|
||||||
pub daemon: bool,
|
pub daemon: bool,
|
||||||
pub release_bind: Vec<scancode::Linux>,
|
pub release_bind: Vec<scancode::Linux>,
|
||||||
|
pub test_capture: bool,
|
||||||
|
pub test_emulation: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ConfigClient {
|
pub struct ConfigClient {
|
||||||
@@ -169,6 +179,8 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let daemon = args.daemon;
|
let daemon = args.daemon;
|
||||||
|
let test_capture = args.test_capture;
|
||||||
|
let test_emulation = args.test_emulation;
|
||||||
|
|
||||||
Ok(Config {
|
Ok(Config {
|
||||||
daemon,
|
daemon,
|
||||||
@@ -176,6 +188,8 @@ impl Config {
|
|||||||
clients,
|
clients,
|
||||||
port,
|
port,
|
||||||
release_bind,
|
release_bind,
|
||||||
|
test_capture,
|
||||||
|
test_emulation,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
46
src/emulation_test.rs
Normal file
46
src/emulation_test.rs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
use std::f64::consts::PI;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
use anyhow::Result;
|
||||||
|
use tokio::task::LocalSet;
|
||||||
|
use crate::client::{ClientEvent, Position};
|
||||||
|
use crate::emulate;
|
||||||
|
use crate::event::{Event, PointerEvent};
|
||||||
|
|
||||||
|
pub fn run() -> Result<()> {
|
||||||
|
log::info!("running input emulation test");
|
||||||
|
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||||
|
.enable_io()
|
||||||
|
.enable_time()
|
||||||
|
.build()?;
|
||||||
|
|
||||||
|
runtime.block_on(LocalSet::new().run_until(input_emulation_test()))
|
||||||
|
}
|
||||||
|
|
||||||
|
const FREQUENCY_HZ: f64 = 1.0;
|
||||||
|
const RADIUS: f64 = 100.0;
|
||||||
|
|
||||||
|
async fn input_emulation_test() -> Result<()> {
|
||||||
|
let mut emulation = emulate::create().await;
|
||||||
|
emulation.notify(ClientEvent::Create(0, Position::Left)).await;
|
||||||
|
let start = Instant::now();
|
||||||
|
let mut offset = (0, 0);
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
_ = emulation.dispatch() => {}
|
||||||
|
_ = tokio::time::sleep(Duration::from_millis(1)) => {
|
||||||
|
let elapsed = start.elapsed();
|
||||||
|
let elapsed_sec_f64 = elapsed.as_secs_f64();
|
||||||
|
let second_fraction = elapsed_sec_f64 - elapsed_sec_f64 as u64 as f64;
|
||||||
|
let radians = second_fraction * 2. * PI * FREQUENCY_HZ;
|
||||||
|
let new_offset_f = (radians.cos() * RADIUS * 2., (radians * 2.).sin() * RADIUS);
|
||||||
|
let new_offset = (new_offset_f.0 as i32, new_offset_f.1 as i32);
|
||||||
|
if new_offset != offset {
|
||||||
|
let relative_motion = (new_offset.0 - offset.0, new_offset.1 - offset.1);
|
||||||
|
offset = new_offset;
|
||||||
|
let (relative_x, relative_y) = (relative_motion.0 as f64, relative_motion.1 as f64);
|
||||||
|
emulation.consume(Event::Pointer(PointerEvent::Motion {time: 0, relative_x, relative_y }), 0).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/event.rs
10
src/event.rs
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::scancode;
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use std::{
|
use std::{
|
||||||
error::Error,
|
error::Error,
|
||||||
@@ -101,7 +102,14 @@ impl Display for KeyboardEvent {
|
|||||||
time: _,
|
time: _,
|
||||||
key,
|
key,
|
||||||
state,
|
state,
|
||||||
} => write!(f, "key({key}, {state})"),
|
} => {
|
||||||
|
let scan = scancode::Linux::try_from(*key);
|
||||||
|
if let Ok(scan) = scan {
|
||||||
|
write!(f, "key({scan:?}, {state})")
|
||||||
|
} else {
|
||||||
|
write!(f, "key({key}, {state})")
|
||||||
|
}
|
||||||
|
}
|
||||||
KeyboardEvent::Modifiers {
|
KeyboardEvent::Modifiers {
|
||||||
mods_depressed,
|
mods_depressed,
|
||||||
mods_latched,
|
mods_latched,
|
||||||
|
|||||||
@@ -7,5 +7,7 @@ pub mod server;
|
|||||||
pub mod capture;
|
pub mod capture;
|
||||||
pub mod emulate;
|
pub mod emulate;
|
||||||
|
|
||||||
|
pub mod capture_test;
|
||||||
|
pub mod emulation_test;
|
||||||
pub mod frontend;
|
pub mod frontend;
|
||||||
pub mod scancode;
|
pub mod scancode;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use anyhow::Result;
|
|||||||
use std::process::{self, Child, Command};
|
use std::process::{self, Child, Command};
|
||||||
|
|
||||||
use env_logger::Env;
|
use env_logger::Env;
|
||||||
use lan_mouse::{config::Config, frontend, server::Server};
|
use lan_mouse::{capture_test, config::Config, emulation_test, frontend, server::Server};
|
||||||
|
|
||||||
use tokio::task::LocalSet;
|
use tokio::task::LocalSet;
|
||||||
|
|
||||||
@@ -31,7 +31,11 @@ pub fn run() -> Result<()> {
|
|||||||
log::debug!("{config:?}");
|
log::debug!("{config:?}");
|
||||||
log::info!("release bind: {:?}", config.release_bind);
|
log::info!("release bind: {:?}", config.release_bind);
|
||||||
|
|
||||||
if config.daemon {
|
if config.test_capture {
|
||||||
|
capture_test::run()?;
|
||||||
|
} else if config.test_emulation {
|
||||||
|
emulation_test::run()?;
|
||||||
|
} else if config.daemon {
|
||||||
// if daemon is specified we run the service
|
// if daemon is specified we run the service
|
||||||
run_service(&config)?;
|
run_service(&config)?;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user