diff --git a/Cargo.lock b/Cargo.lock index d747411..1638305 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,55 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "atomic" version = "0.6.0" @@ -53,6 +102,52 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + [[package]] name = "equivalent" version = "1.0.1" @@ -76,6 +171,7 @@ dependencies = [ name = "evdev-accel" version = "0.1.0" dependencies = [ + "clap", "evdev", "figment", "serde", @@ -106,6 +202,12 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "indexmap" version = "2.2.6" @@ -116,6 +218,12 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "libc" version = "0.2.155" @@ -203,6 +311,12 @@ dependencies = [ "serde", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.66" @@ -289,12 +403,91 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "winnow" version = "0.6.8" diff --git a/Cargo.toml b/Cargo.toml index a1dcea3..39ea26a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4.5.4", features = ["derive"] } evdev = "0.12.2" figment = { version = "0.10.19", features = ["toml"] } serde = { version = "1.0.202", features = ["derive"] } diff --git a/README.md b/README.md index b62ceaa..bce0e62 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,11 @@ Largely based on [systemofapwne/leetmouse](https://github.com/systemofapwne/leet - Add yourself to the `input` usergroup for access to `/dev/input`, and relog. - Copy [examples/config.toml](examples/config.toml) to `$HOME/.config/evdev-accel/config.toml` - Edit the config to your liking -- `cargo run` +- `evdev-accel --help` ## TODO - Add default config if no cfg file -- Add device selection to cfg file for non-interactive mode - Min/Max accel settings - Accel offset - Different accel curves diff --git a/src/main.rs b/src/main.rs index fd20398..3d91310 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use core::panic; +use clap::Parser; use evdev::{ raw_stream::RawDevice, uinput::VirtualDeviceBuilder, EventType, InputEvent, RelativeAxisType, Synchronization, @@ -8,8 +8,16 @@ use figment::{ Figment, }; use serde::Deserialize; +use std::io::prelude::*; use std::{env, path::Path, time::SystemTime}; +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct CliArgs { + #[arg(short, long)] + device_name: Option, +} + // TODO default values if no cfg file #[derive(Deserialize, Debug)] struct Config { @@ -19,33 +27,55 @@ struct Config { post_scale: f32, } -pub fn pick_device() -> RawDevice { - use std::io::prelude::*; +fn device_valid(device: &RawDevice) -> bool { + let axes = device.supported_relative_axes(); + return axes.map_or(false, |axes| { + axes.contains(RelativeAxisType::REL_X) && axes.contains(RelativeAxisType::REL_Y) + }); +} - let mut args = std::env::args_os(); - args.next(); - if let Some(dev_file) = args.next() { - RawDevice::open(dev_file).unwrap() - } else { - let mut devices = evdev::raw_stream::enumerate() - .map(|t| t.1) - .collect::>(); - assert!(devices.len() > 0); - // readdir returns them in reverse order from their eventN names for some reason - devices.reverse(); - for (i, d) in devices.iter().enumerate() { - println!("{}: {}", i, d.name().unwrap_or("Unnamed device")); - } - print!("Select the device [0-{}]: ", devices.len()); - let _ = std::io::stdout().flush(); - let mut chosen = String::new(); - std::io::stdin().read_line(&mut chosen).unwrap(); - let n = chosen.trim().parse::().unwrap(); - devices.into_iter().nth(n).unwrap() +fn pick_device(device_name: Option) -> Option { + let devices = evdev::raw_stream::enumerate() + .map(|t| t.1) + .filter(|d| device_valid(d)) + .collect::>(); + + if devices.len() == 0 { + println!("No valid devices found. Are you in the 'input' user group?"); + return None; } + + // Select by passed name + if let Some(name) = device_name { + let mut iter = devices.into_iter(); + let d = iter.find(|d| d.name().unwrap() == name); + if d.is_some() { + return d; + } + println!("Couldn't find a valid device named {}", name); + for d in iter { + println!("Valid devices:"); + println!("{}", d.name().unwrap_or("Unnamed device")); + } + return None; + } + + // Select interactively + for (i, d) in devices.iter().enumerate() { + println!("{}: {}", i, d.name().unwrap_or("Unnamed device")); + } + print!("Select the device [0-{}]: ", devices.len()); + let _ = std::io::stdout().flush(); + + let mut chosen = String::new(); + std::io::stdin().read_line(&mut chosen).unwrap(); + let n = chosen.trim().parse::().unwrap(); + return Some(devices.into_iter().nth(n).unwrap()); } fn main() { + let args = CliArgs::parse(); + let home_path = env::var_os("HOME").expect("Failed to find HOME path"); let cfg_path = Path::new(&home_path).join(".config/evdev-accel/config.toml"); let config: Config = Figment::from(Toml::file(cfg_path)) @@ -53,16 +83,10 @@ fn main() { .expect("Failed to load config.toml"); println!("{config:?}"); - let mut device = pick_device(); + let mut device = pick_device(args.device_name).expect("Failed to get device"); + println!("Device:"); println!("{device:?}"); - let axes = device.supported_relative_axes(); - if !axes.map_or(false, |axes| { - axes.contains(RelativeAxisType::REL_X) && axes.contains(RelativeAxisType::REL_Y) - }) { - panic!("Device does not support relative axis"); - } - device.grab().expect("Could not grab device"); let mut virt_device = VirtualDeviceBuilder::new()