From 2ac193a5b20442e32fc7384f0c2cdc66ee1aed02 Mon Sep 17 00:00:00 2001 From: Ferdinand Schober Date: Sun, 30 Jun 2024 19:35:34 +0200 Subject: [PATCH] refactor error types --- src/config.rs | 79 ++++++++++++++++++++---------------- src/emulate.rs | 3 +- src/emulate/libei.rs | 1 - src/emulate/wlroots.rs | 21 +++++----- src/main.rs | 2 +- src/server.rs | 13 ++++-- src/server/emulation_task.rs | 11 ++--- 7 files changed, 71 insertions(+), 59 deletions(-) diff --git a/src/config.rs b/src/config.rs index c88af93..1b4a922 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,8 +16,9 @@ pub const DEFAULT_PORT: u16 = 4242; #[derive(Serialize, Deserialize, Debug)] pub struct ConfigToml { pub capture_backend: Option, + pub emulation_backend: Option, pub port: Option, - pub frontend: Option, + pub frontend: Option, pub release_bind: Option>, pub left: Option, pub right: Option, @@ -53,7 +54,7 @@ struct CliArgs { /// the frontend to use [cli | gtk] #[arg(short, long)] - frontend: Option, + frontend: Option, /// non-default config file location #[arg(short, long)] @@ -95,18 +96,41 @@ pub enum CaptureBackend { Dummy, } -#[derive(Debug, Clone, Copy, ValueEnum)] -pub enum EmulationBackend {} +#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, ValueEnum)] +pub enum EmulationBackend { + #[cfg(all(unix, feature = "libei", not(target_os = "macos")))] + Libei, + #[cfg(all(unix, feature = "wayland", not(target_os = "macos")))] + Wlroots, + #[cfg(all(unix, feature = "x11", not(target_os = "macos")))] + X11, + #[cfg(windows)] + Windows, + #[cfg(target_os = "macos")] + MacOs, + Dummy, +} -#[derive(Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Serialize, ValueEnum)] pub enum Frontend { Gtk, Cli, } +impl Default for Frontend { + fn default() -> Self { + if cfg!(feature = "gtk") { + Self::Gtk + } else { + Self::Cli + } + } +} + #[derive(Debug)] pub struct Config { pub capture_backend: Option, + pub emulation_backend: Option, pub frontend: Frontend, pub port: u16, pub clients: Vec<(TomlClient, Position)>, @@ -158,33 +182,14 @@ impl Config { Ok(c) => Some(c), }; - let frontend = match args.frontend { - None => match &config_toml { - Some(c) => c.frontend.clone(), - None => None, - }, - frontend => frontend, - }; + let frontend_arg = args.frontend; + let frontend_cfg = config_toml.as_ref().and_then(|c| c.frontend); + let frontend = frontend_arg.or(frontend_cfg).unwrap_or_default(); - let frontend = match frontend { - #[cfg(feature = "gtk")] - None => Frontend::Gtk, - #[cfg(not(feature = "gtk"))] - None => Frontend::Cli, - Some(s) => match s.as_str() { - "cli" => Frontend::Cli, - "gtk" => Frontend::Gtk, - _ => Frontend::Cli, - }, - }; - - let port = match args.port { - Some(port) => port, - None => match &config_toml { - Some(c) => c.port.unwrap_or(DEFAULT_PORT), - None => DEFAULT_PORT, - }, - }; + let port = args + .port + .or(config_toml.as_ref().and_then(|c| c.port)) + .unwrap_or(DEFAULT_PORT); log::debug!("{config_toml:?}"); let release_bind = config_toml @@ -192,10 +197,13 @@ impl Config { .and_then(|c| c.release_bind.clone()) .unwrap_or(Vec::from_iter(DEFAULT_RELEASE_KEYS.iter().cloned())); - let capture_backend = match args.capture_backend { - Some(b) => Some(b), - None => config_toml.as_ref().and_then(|c| c.capture_backend), - }; + let capture_backend = args + .capture_backend + .or(config_toml.as_ref().and_then(|c| c.capture_backend)); + + let emulation_backend = args + .emulation_backend + .or(config_toml.as_ref().and_then(|c| c.emulation_backend)); let mut clients: Vec<(TomlClient, Position)> = vec![]; @@ -220,6 +228,7 @@ impl Config { Ok(Config { capture_backend, + emulation_backend, daemon, frontend, clients, diff --git a/src/emulate.rs b/src/emulate.rs index 4819b5c..2ffe7a7 100644 --- a/src/emulate.rs +++ b/src/emulate.rs @@ -27,6 +27,7 @@ pub mod macos; /// fallback input emulation (logs events) pub mod dummy; +pub mod error; #[async_trait] pub trait InputEmulation: Send { @@ -41,7 +42,7 @@ pub trait InputEmulation: Send { async fn destroy(&mut self); } -pub async fn create() -> Box { +pub async fn create(backend: Option) -> Box { #[cfg(windows)] match windows::WindowsEmulation::new() { Ok(c) => return Box::new(c), diff --git a/src/emulate/libei.rs b/src/emulate/libei.rs index 7b6f159..226cd0e 100644 --- a/src/emulate/libei.rs +++ b/src/emulate/libei.rs @@ -4,7 +4,6 @@ use std::{ time::{SystemTime, UNIX_EPOCH}, }; -use anyhow::{anyhow, Result}; use ashpd::{ desktop::{ remote_desktop::{DeviceType, RemoteDesktop}, diff --git a/src/emulate/wlroots.rs b/src/emulate/wlroots.rs index d83e715..9473765 100644 --- a/src/emulate/wlroots.rs +++ b/src/emulate/wlroots.rs @@ -1,5 +1,5 @@ use crate::client::{ClientEvent, ClientHandle}; -use crate::emulate::InputEmulation; +use crate::emulate::{InputEmulation, error::WlrootsEmulationCreationError}; use async_trait::async_trait; use std::collections::HashMap; use std::io; @@ -7,7 +7,6 @@ use std::os::fd::{AsFd, OwnedFd}; use wayland_client::backend::WaylandError; use wayland_client::WEnum; -use anyhow::{anyhow, Result}; use wayland_client::protocol::wl_keyboard::{self, WlKeyboard}; use wayland_client::protocol::wl_pointer::{Axis, ButtonState}; use wayland_client::protocol::wl_seat::WlSeat; @@ -30,6 +29,8 @@ use wayland_client::{ use crate::event::{Event, KeyboardEvent, PointerEvent}; +use super::error::WaylandBindError; + struct State { keymap: Option<(u32, OwnedFd, u32)>, input_for_client: HashMap, @@ -47,18 +48,18 @@ pub(crate) struct WlrootsEmulation { } impl WlrootsEmulation { - pub fn new() -> Result { + pub fn new() -> Result { let conn = Connection::connect_to_env()?; let (globals, queue) = registry_queue_init::(&conn)?; let qh = queue.handle(); - let seat: wl_seat::WlSeat = match globals.bind(&qh, 7..=8, ()) { - Ok(wl_seat) => wl_seat, - Err(_) => return Err(anyhow!("wl_seat >= v7 not supported")), - }; + let seat: wl_seat::WlSeat = globals.bind(&qh, 7..=8, ()) + .map_err(|e| WaylandBindError::new(e, "wl_seat 7..=8"))?; - let vpm: VpManager = globals.bind(&qh, 1..=1, ())?; - let vkm: VkManager = globals.bind(&qh, 1..=1, ())?; + let vpm: VpManager = globals.bind(&qh, 1..=1, ()) + .map_err(|e| WaylandBindError::new(e, "wlr-virtual-pointer-unstable-v1"))?; + let vkm: VkManager = globals.bind(&qh, 1..=1, ()) + .map_err(|e| WaylandBindError::new(e, "virtual-keyboard-unstable-v1"))?; let input_for_client: HashMap = HashMap::new(); @@ -75,7 +76,7 @@ impl WlrootsEmulation { queue, }; while emulate.state.keymap.is_none() { - emulate.queue.blocking_dispatch(&mut emulate.state).unwrap(); + emulate.queue.blocking_dispatch(&mut emulate.state)?; } // let fd = unsafe { &File::from_raw_fd(emulate.state.keymap.unwrap().1.as_raw_fd()) }; // let mmap = unsafe { MmapOptions::new().map_copy(fd).unwrap() }; diff --git a/src/main.rs b/src/main.rs index b649c44..5dc50d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,7 +71,7 @@ fn run_service(config: &Config) -> Result<()> { log::info!("Press {:?} to release the mouse", config.release_bind); let server = Server::new(config); - server.run(config.capture_backend).await?; + server.run(config.capture_backend, config.emulation_backend).await?; log::debug!("service exiting"); anyhow::Ok(()) diff --git a/src/server.rs b/src/server.rs index d342b2b..596b125 100644 --- a/src/server.rs +++ b/src/server.rs @@ -8,7 +8,7 @@ use tokio::signal; use crate::{ client::{ClientConfig, ClientHandle, ClientManager, ClientState}, - config::{CaptureBackend, Config}, + config::{CaptureBackend, Config, EmulationBackend}, dns, frontend::{FrontendListener, FrontendRequest}, server::capture_task::CaptureEvent, @@ -77,7 +77,11 @@ impl Server { } } - pub async fn run(&self, backend: Option) -> anyhow::Result<()> { + pub async fn run( + &self, + capture_backend: Option, + emulation_backend: Option, + ) -> anyhow::Result<()> { // create frontend communication adapter let frontend = match FrontendListener::new().await { Some(f) => f?, @@ -97,7 +101,7 @@ impl Server { // input capture let (mut capture_task, capture_channel) = capture_task::new( - backend, + capture_backend, self.clone(), sender_tx.clone(), timer_tx.clone(), @@ -106,12 +110,13 @@ impl Server { // input emulation let (mut emulation_task, emulate_channel) = emulation_task::new( + emulation_backend, self.clone(), receiver_rx, sender_tx.clone(), capture_channel.clone(), timer_tx, - ); + )?; // create dns resolver let resolver = dns::DnsResolver::new().await?; diff --git a/src/server/emulation_task.rs b/src/server/emulation_task.rs index c688880..7e3f21a 100644 --- a/src/server/emulation_task.rs +++ b/src/server/emulation_task.rs @@ -7,11 +7,7 @@ use tokio::{ }; use crate::{ - client::{ClientEvent, ClientHandle}, - emulate::{self, InputEmulation}, - event::{Event, KeyboardEvent}, - scancode, - server::State, + client::{ClientEvent, ClientHandle}, config::EmulationBackend, emulate::{self, error::EmulationCreationError, InputEmulation}, event::{Event, KeyboardEvent}, scancode, server::State }; use super::{CaptureEvent, Server}; @@ -27,15 +23,16 @@ pub enum EmulationEvent { } pub fn new( + backend: Option, server: Server, mut udp_rx: Receiver>, sender_tx: Sender<(Event, SocketAddr)>, capture_tx: Sender, timer_tx: Sender<()>, -) -> (JoinHandle>, Sender) { +) -> Result<(JoinHandle>, Sender), EmulationCreationError> { let (tx, mut rx) = tokio::sync::mpsc::channel(32); let emulate_task = tokio::task::spawn_local(async move { - let mut emulate = emulate::create().await; + let mut emulate = emulate::create(backend).await?; let mut last_ignored = None; loop {