mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-30 08:30:55 +03:00
remove cli frontend in favour of cli subcommand (#278)
this removes the cli frontend entirely, replacing it with a subcommand instead
This commit is contained in:
committed by
GitHub
parent
7898f2362c
commit
2f6a3629ad
@@ -1,9 +1,13 @@
|
||||
use crate::config::Config;
|
||||
use clap::Args;
|
||||
use futures::StreamExt;
|
||||
use input_capture::{self, CaptureError, CaptureEvent, InputCapture, InputCaptureError, Position};
|
||||
use input_event::{Event, KeyboardEvent};
|
||||
|
||||
pub async fn run(config: Config) -> Result<(), InputCaptureError> {
|
||||
#[derive(Args, Debug, Eq, PartialEq)]
|
||||
pub struct TestCaptureArgs {}
|
||||
|
||||
pub async fn run(config: Config, _args: TestCaptureArgs) -> Result<(), InputCaptureError> {
|
||||
log::info!("running input capture test");
|
||||
log::info!("creating input capture");
|
||||
let backend = config.capture_backend.map(|b| b.into());
|
||||
|
||||
@@ -199,6 +199,13 @@ impl ClientManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// update the enter hook command of the client
|
||||
pub(crate) fn set_enter_hook(&self, handle: ClientHandle, enter_hook: Option<String>) {
|
||||
if let Some((c, _s)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||
c.cmd = enter_hook;
|
||||
}
|
||||
}
|
||||
|
||||
/// set resolving status of the client
|
||||
pub(crate) fn set_resolving(&self, handle: ClientHandle, status: bool) {
|
||||
if let Some((_, s)) = self.clients.borrow_mut().get_mut(handle as usize) {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use clap::{Parser, ValueEnum};
|
||||
use crate::capture_test::TestCaptureArgs;
|
||||
use crate::emulation_test::TestEmulationArgs;
|
||||
use clap::{Parser, Subcommand, ValueEnum};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::env::{self, VarError};
|
||||
@@ -10,6 +12,7 @@ use std::{collections::HashSet, io};
|
||||
use thiserror::Error;
|
||||
use toml;
|
||||
|
||||
use lan_mouse_cli::CliArgs;
|
||||
use lan_mouse_ipc::{Position, DEFAULT_PORT};
|
||||
|
||||
use input_event::scancode::{
|
||||
@@ -55,7 +58,7 @@ impl ConfigToml {
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version=build::CLAP_LONG_VERSION, about, long_about = None)]
|
||||
struct CliArgs {
|
||||
pub struct Args {
|
||||
/// the listen port for lan-mouse
|
||||
#[arg(short, long)]
|
||||
port: Option<u16>,
|
||||
@@ -66,31 +69,34 @@ struct CliArgs {
|
||||
|
||||
/// non-default config file location
|
||||
#[arg(short, long)]
|
||||
config: Option<String>,
|
||||
pub config: Option<PathBuf>,
|
||||
|
||||
/// run only the service as a daemon without the frontend
|
||||
#[arg(short, long)]
|
||||
daemon: bool,
|
||||
|
||||
/// test input capture
|
||||
#[arg(long)]
|
||||
test_capture: bool,
|
||||
|
||||
/// test input emulation
|
||||
#[arg(long)]
|
||||
test_emulation: bool,
|
||||
#[command(subcommand)]
|
||||
pub command: Option<Command>,
|
||||
|
||||
/// capture backend override
|
||||
#[arg(long)]
|
||||
capture_backend: Option<CaptureBackend>,
|
||||
pub capture_backend: Option<CaptureBackend>,
|
||||
|
||||
/// emulation backend override
|
||||
#[arg(long)]
|
||||
emulation_backend: Option<EmulationBackend>,
|
||||
pub emulation_backend: Option<EmulationBackend>,
|
||||
|
||||
/// path to non-default certificate location
|
||||
#[arg(long)]
|
||||
cert_path: Option<PathBuf>,
|
||||
pub cert_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug, Eq, PartialEq)]
|
||||
pub enum Command {
|
||||
/// test input emulation
|
||||
TestEmulation(TestEmulationArgs),
|
||||
/// test input capture
|
||||
TestCapture(TestCaptureArgs),
|
||||
/// Lan Mouse commandline interface
|
||||
Cli(CliArgs),
|
||||
/// run in daemon mode
|
||||
Daemon,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, ValueEnum)]
|
||||
@@ -218,8 +224,8 @@ impl Display for EmulationBackend {
|
||||
pub enum Frontend {
|
||||
#[serde(rename = "gtk")]
|
||||
Gtk,
|
||||
#[serde(rename = "cli")]
|
||||
Cli,
|
||||
#[serde(rename = "none")]
|
||||
None,
|
||||
}
|
||||
|
||||
impl Default for Frontend {
|
||||
@@ -227,7 +233,7 @@ impl Default for Frontend {
|
||||
if cfg!(feature = "gtk") {
|
||||
Self::Gtk
|
||||
} else {
|
||||
Self::Cli
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -248,8 +254,6 @@ pub struct Config {
|
||||
pub port: u16,
|
||||
/// list of clients
|
||||
pub clients: Vec<(TomlClient, Position)>,
|
||||
/// whether or not to run as a daemon
|
||||
pub daemon: bool,
|
||||
/// configured release bind
|
||||
pub release_bind: Vec<scancode::Linux>,
|
||||
/// test capture instead of running the app
|
||||
@@ -283,8 +287,7 @@ const DEFAULT_RELEASE_KEYS: [scancode::Linux; 4] =
|
||||
[KeyLeftCtrl, KeyLeftShift, KeyLeftMeta, KeyLeftAlt];
|
||||
|
||||
impl Config {
|
||||
pub fn new() -> Result<Self, ConfigError> {
|
||||
let args = CliArgs::parse();
|
||||
pub fn new(args: &Args) -> Result<Self, ConfigError> {
|
||||
const CONFIG_FILE_NAME: &str = "config.toml";
|
||||
const CERT_FILE_NAME: &str = "lan-mouse.pem";
|
||||
|
||||
@@ -306,7 +309,7 @@ impl Config {
|
||||
let config_file = config_path.join(CONFIG_FILE_NAME);
|
||||
|
||||
// --config <file> overrules default location
|
||||
let config_file = args.config.map(PathBuf::from).unwrap_or(config_file);
|
||||
let config_file = args.config.clone().unwrap_or(config_file);
|
||||
|
||||
let mut config_toml = match ConfigToml::new(&config_file) {
|
||||
Err(e) => {
|
||||
@@ -342,6 +345,7 @@ impl Config {
|
||||
|
||||
let cert_path = args
|
||||
.cert_path
|
||||
.clone()
|
||||
.or(config_toml.as_ref().and_then(|c| c.cert_path.clone()))
|
||||
.unwrap_or(config_path.join(CERT_FILE_NAME));
|
||||
|
||||
@@ -367,16 +371,14 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
let daemon = args.daemon;
|
||||
let test_capture = args.test_capture;
|
||||
let test_emulation = args.test_emulation;
|
||||
let test_capture = matches!(args.command, Some(Command::TestCapture(_)));
|
||||
let test_emulation = matches!(args.command, Some(Command::TestEmulation(_)));
|
||||
|
||||
Ok(Config {
|
||||
path: config_path,
|
||||
authorized_fingerprints,
|
||||
capture_backend,
|
||||
emulation_backend,
|
||||
daemon,
|
||||
frontend,
|
||||
clients,
|
||||
port,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::config::Config;
|
||||
use clap::Args;
|
||||
use input_emulation::{InputEmulation, InputEmulationError};
|
||||
use input_event::{Event, PointerEvent};
|
||||
use std::f64::consts::PI;
|
||||
@@ -7,7 +8,17 @@ use std::time::{Duration, Instant};
|
||||
const FREQUENCY_HZ: f64 = 1.0;
|
||||
const RADIUS: f64 = 100.0;
|
||||
|
||||
pub async fn run(config: Config) -> Result<(), InputEmulationError> {
|
||||
#[derive(Args, Debug, Eq, PartialEq)]
|
||||
pub struct TestEmulationArgs {
|
||||
#[arg(long)]
|
||||
mouse: bool,
|
||||
#[arg(long)]
|
||||
keyboard: bool,
|
||||
#[arg(long)]
|
||||
scroll: bool,
|
||||
}
|
||||
|
||||
pub async fn run(config: Config, _args: TestEmulationArgs) -> Result<(), InputEmulationError> {
|
||||
log::info!("running input emulation test");
|
||||
|
||||
let backend = config.emulation_backend.map(|b| b.into());
|
||||
|
||||
69
src/main.rs
69
src/main.rs
@@ -1,12 +1,14 @@
|
||||
use clap::Parser;
|
||||
use env_logger::Env;
|
||||
use input_capture::InputCaptureError;
|
||||
use input_emulation::InputEmulationError;
|
||||
use lan_mouse::{
|
||||
capture_test,
|
||||
config::{Config, ConfigError, Frontend},
|
||||
config::{self, Config, ConfigError, Frontend},
|
||||
emulation_test,
|
||||
service::{Service, ServiceError},
|
||||
};
|
||||
use lan_mouse_cli::CliError;
|
||||
use lan_mouse_ipc::{IpcError, IpcListenerCreationError};
|
||||
use std::{
|
||||
future::Future,
|
||||
@@ -30,6 +32,8 @@ enum LanMouseError {
|
||||
Capture(#[from] InputCaptureError),
|
||||
#[error(transparent)]
|
||||
Emulation(#[from] InputEmulationError),
|
||||
#[error(transparent)]
|
||||
Cli(#[from] CliError),
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -45,34 +49,39 @@ fn main() {
|
||||
|
||||
fn run() -> Result<(), LanMouseError> {
|
||||
// parse config file + cli args
|
||||
let config = Config::new()?;
|
||||
if config.test_capture {
|
||||
run_async(capture_test::run(config))?;
|
||||
} else if config.test_emulation {
|
||||
run_async(emulation_test::run(config))?;
|
||||
} else if config.daemon {
|
||||
// if daemon is specified we run the service
|
||||
match run_async(run_service(config)) {
|
||||
Err(LanMouseError::Service(ServiceError::IpcListen(
|
||||
IpcListenerCreationError::AlreadyRunning,
|
||||
))) => log::info!("service already running!"),
|
||||
r => r?,
|
||||
}
|
||||
} else {
|
||||
// otherwise start the service as a child process and
|
||||
// run a frontend
|
||||
let mut service = start_service()?;
|
||||
run_frontend(&config)?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
// on unix we give the service a chance to terminate gracefully
|
||||
let pid = service.id() as libc::pid_t;
|
||||
unsafe {
|
||||
libc::kill(pid, libc::SIGINT);
|
||||
let args = config::Args::parse();
|
||||
let config = config::Config::new(&args)?;
|
||||
match args.command {
|
||||
Some(command) => match command {
|
||||
config::Command::TestEmulation(args) => run_async(emulation_test::run(config, args))?,
|
||||
config::Command::TestCapture(args) => run_async(capture_test::run(config, args))?,
|
||||
config::Command::Cli(cli_args) => run_async(lan_mouse_cli::run(cli_args))?,
|
||||
config::Command::Daemon => {
|
||||
// if daemon is specified we run the service
|
||||
match run_async(run_service(config)) {
|
||||
Err(LanMouseError::Service(ServiceError::IpcListen(
|
||||
IpcListenerCreationError::AlreadyRunning,
|
||||
))) => log::info!("service already running!"),
|
||||
r => r?,
|
||||
}
|
||||
}
|
||||
service.wait()?;
|
||||
},
|
||||
None => {
|
||||
// otherwise start the service as a child process and
|
||||
// run a frontend
|
||||
let mut service = start_service()?;
|
||||
run_frontend(&config)?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
// on unix we give the service a chance to terminate gracefully
|
||||
let pid = service.id() as libc::pid_t;
|
||||
unsafe {
|
||||
libc::kill(pid, libc::SIGINT);
|
||||
}
|
||||
service.wait()?;
|
||||
}
|
||||
service.kill()?;
|
||||
}
|
||||
service.kill()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -96,7 +105,7 @@ where
|
||||
fn start_service() -> Result<Child, io::Error> {
|
||||
let child = Command::new(std::env::current_exe()?)
|
||||
.args(std::env::args().skip(1))
|
||||
.arg("--daemon")
|
||||
.arg("daemon")
|
||||
.spawn()?;
|
||||
Ok(child)
|
||||
}
|
||||
@@ -118,8 +127,8 @@ fn run_frontend(config: &Config) -> Result<(), IpcError> {
|
||||
}
|
||||
#[cfg(not(feature = "gtk"))]
|
||||
Frontend::Gtk => panic!("gtk frontend requested but feature not enabled!"),
|
||||
Frontend::Cli => {
|
||||
lan_mouse_cli::run()?;
|
||||
Frontend::None => {
|
||||
log::warn!("no frontend available!");
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
|
||||
@@ -193,6 +193,9 @@ impl Service {
|
||||
FrontendRequest::ResolveDns(handle) => self.resolve(handle),
|
||||
FrontendRequest::Sync => self.sync_frontend(),
|
||||
FrontendRequest::RemoveAuthorizedKey(key) => self.remove_authorized_key(key),
|
||||
FrontendRequest::UpdateEnterHook(handle, enter_hook) => {
|
||||
self.update_enter_hook(handle, enter_hook)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,6 +479,11 @@ impl Service {
|
||||
self.broadcast_client(handle);
|
||||
}
|
||||
|
||||
fn update_enter_hook(&mut self, handle: ClientHandle, enter_hook: Option<String>) {
|
||||
self.client_manager.set_enter_hook(handle, enter_hook);
|
||||
self.broadcast_client(handle);
|
||||
}
|
||||
|
||||
fn broadcast_client(&mut self, handle: ClientHandle) {
|
||||
let event = self
|
||||
.client_manager
|
||||
|
||||
Reference in New Issue
Block a user