refactor error types

This commit is contained in:
Ferdinand Schober
2024-06-30 19:35:34 +02:00
parent 9cbe1ed8d8
commit 2ac193a5b2
7 changed files with 71 additions and 59 deletions

View File

@@ -16,8 +16,9 @@ pub const DEFAULT_PORT: u16 = 4242;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct ConfigToml { pub struct ConfigToml {
pub capture_backend: Option<CaptureBackend>, pub capture_backend: Option<CaptureBackend>,
pub emulation_backend: Option<EmulationBackend>,
pub port: Option<u16>, pub port: Option<u16>,
pub frontend: Option<String>, pub frontend: Option<Frontend>,
pub release_bind: Option<Vec<scancode::Linux>>, pub release_bind: Option<Vec<scancode::Linux>>,
pub left: Option<TomlClient>, pub left: Option<TomlClient>,
pub right: Option<TomlClient>, pub right: Option<TomlClient>,
@@ -53,7 +54,7 @@ struct CliArgs {
/// the frontend to use [cli | gtk] /// the frontend to use [cli | gtk]
#[arg(short, long)] #[arg(short, long)]
frontend: Option<String>, frontend: Option<Frontend>,
/// non-default config file location /// non-default config file location
#[arg(short, long)] #[arg(short, long)]
@@ -95,18 +96,41 @@ pub enum CaptureBackend {
Dummy, Dummy,
} }
#[derive(Debug, Clone, Copy, ValueEnum)] #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, ValueEnum)]
pub enum EmulationBackend {} 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 { pub enum Frontend {
Gtk, Gtk,
Cli, Cli,
} }
impl Default for Frontend {
fn default() -> Self {
if cfg!(feature = "gtk") {
Self::Gtk
} else {
Self::Cli
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct Config { pub struct Config {
pub capture_backend: Option<CaptureBackend>, pub capture_backend: Option<CaptureBackend>,
pub emulation_backend: Option<EmulationBackend>,
pub frontend: Frontend, pub frontend: Frontend,
pub port: u16, pub port: u16,
pub clients: Vec<(TomlClient, Position)>, pub clients: Vec<(TomlClient, Position)>,
@@ -158,33 +182,14 @@ impl Config {
Ok(c) => Some(c), Ok(c) => Some(c),
}; };
let frontend = match args.frontend { let frontend_arg = args.frontend;
None => match &config_toml { let frontend_cfg = config_toml.as_ref().and_then(|c| c.frontend);
Some(c) => c.frontend.clone(), let frontend = frontend_arg.or(frontend_cfg).unwrap_or_default();
None => None,
},
frontend => frontend,
};
let frontend = match frontend { let port = args
#[cfg(feature = "gtk")] .port
None => Frontend::Gtk, .or(config_toml.as_ref().and_then(|c| c.port))
#[cfg(not(feature = "gtk"))] .unwrap_or(DEFAULT_PORT);
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,
},
};
log::debug!("{config_toml:?}"); log::debug!("{config_toml:?}");
let release_bind = config_toml let release_bind = config_toml
@@ -192,10 +197,13 @@ impl Config {
.and_then(|c| c.release_bind.clone()) .and_then(|c| c.release_bind.clone())
.unwrap_or(Vec::from_iter(DEFAULT_RELEASE_KEYS.iter().cloned())); .unwrap_or(Vec::from_iter(DEFAULT_RELEASE_KEYS.iter().cloned()));
let capture_backend = match args.capture_backend { let capture_backend = args
Some(b) => Some(b), .capture_backend
None => config_toml.as_ref().and_then(|c| c.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![]; let mut clients: Vec<(TomlClient, Position)> = vec![];
@@ -220,6 +228,7 @@ impl Config {
Ok(Config { Ok(Config {
capture_backend, capture_backend,
emulation_backend,
daemon, daemon,
frontend, frontend,
clients, clients,

View File

@@ -27,6 +27,7 @@ pub mod macos;
/// fallback input emulation (logs events) /// fallback input emulation (logs events)
pub mod dummy; pub mod dummy;
pub mod error;
#[async_trait] #[async_trait]
pub trait InputEmulation: Send { pub trait InputEmulation: Send {
@@ -41,7 +42,7 @@ pub trait InputEmulation: Send {
async fn destroy(&mut self); async fn destroy(&mut self);
} }
pub async fn create() -> Box<dyn InputEmulation> { pub async fn create(backend: Option<EmulationBackend>) -> Box<dyn InputEmulation> {
#[cfg(windows)] #[cfg(windows)]
match windows::WindowsEmulation::new() { match windows::WindowsEmulation::new() {
Ok(c) => return Box::new(c), Ok(c) => return Box::new(c),

View File

@@ -4,7 +4,6 @@ use std::{
time::{SystemTime, UNIX_EPOCH}, time::{SystemTime, UNIX_EPOCH},
}; };
use anyhow::{anyhow, Result};
use ashpd::{ use ashpd::{
desktop::{ desktop::{
remote_desktop::{DeviceType, RemoteDesktop}, remote_desktop::{DeviceType, RemoteDesktop},

View File

@@ -1,5 +1,5 @@
use crate::client::{ClientEvent, ClientHandle}; use crate::client::{ClientEvent, ClientHandle};
use crate::emulate::InputEmulation; use crate::emulate::{InputEmulation, error::WlrootsEmulationCreationError};
use async_trait::async_trait; use async_trait::async_trait;
use std::collections::HashMap; use std::collections::HashMap;
use std::io; use std::io;
@@ -7,7 +7,6 @@ use std::os::fd::{AsFd, OwnedFd};
use wayland_client::backend::WaylandError; use wayland_client::backend::WaylandError;
use wayland_client::WEnum; use wayland_client::WEnum;
use anyhow::{anyhow, Result};
use wayland_client::protocol::wl_keyboard::{self, WlKeyboard}; use wayland_client::protocol::wl_keyboard::{self, WlKeyboard};
use wayland_client::protocol::wl_pointer::{Axis, ButtonState}; use wayland_client::protocol::wl_pointer::{Axis, ButtonState};
use wayland_client::protocol::wl_seat::WlSeat; use wayland_client::protocol::wl_seat::WlSeat;
@@ -30,6 +29,8 @@ use wayland_client::{
use crate::event::{Event, KeyboardEvent, PointerEvent}; use crate::event::{Event, KeyboardEvent, PointerEvent};
use super::error::WaylandBindError;
struct State { struct State {
keymap: Option<(u32, OwnedFd, u32)>, keymap: Option<(u32, OwnedFd, u32)>,
input_for_client: HashMap<ClientHandle, VirtualInput>, input_for_client: HashMap<ClientHandle, VirtualInput>,
@@ -47,18 +48,18 @@ pub(crate) struct WlrootsEmulation {
} }
impl WlrootsEmulation { impl WlrootsEmulation {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self, WlrootsEmulationCreationError> {
let conn = Connection::connect_to_env()?; let conn = Connection::connect_to_env()?;
let (globals, queue) = registry_queue_init::<State>(&conn)?; let (globals, queue) = registry_queue_init::<State>(&conn)?;
let qh = queue.handle(); let qh = queue.handle();
let seat: wl_seat::WlSeat = match globals.bind(&qh, 7..=8, ()) { let seat: wl_seat::WlSeat = globals.bind(&qh, 7..=8, ())
Ok(wl_seat) => wl_seat, .map_err(|e| WaylandBindError::new(e, "wl_seat 7..=8"))?;
Err(_) => return Err(anyhow!("wl_seat >= v7 not supported")),
};
let vpm: VpManager = globals.bind(&qh, 1..=1, ())?; let vpm: VpManager = globals.bind(&qh, 1..=1, ())
let vkm: VkManager = 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<ClientHandle, VirtualInput> = HashMap::new(); let input_for_client: HashMap<ClientHandle, VirtualInput> = HashMap::new();
@@ -75,7 +76,7 @@ impl WlrootsEmulation {
queue, queue,
}; };
while emulate.state.keymap.is_none() { 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 fd = unsafe { &File::from_raw_fd(emulate.state.keymap.unwrap().1.as_raw_fd()) };
// let mmap = unsafe { MmapOptions::new().map_copy(fd).unwrap() }; // let mmap = unsafe { MmapOptions::new().map_copy(fd).unwrap() };

View File

@@ -71,7 +71,7 @@ fn run_service(config: &Config) -> Result<()> {
log::info!("Press {:?} to release the mouse", config.release_bind); log::info!("Press {:?} to release the mouse", config.release_bind);
let server = Server::new(config); let server = Server::new(config);
server.run(config.capture_backend).await?; server.run(config.capture_backend, config.emulation_backend).await?;
log::debug!("service exiting"); log::debug!("service exiting");
anyhow::Ok(()) anyhow::Ok(())

View File

@@ -8,7 +8,7 @@ use tokio::signal;
use crate::{ use crate::{
client::{ClientConfig, ClientHandle, ClientManager, ClientState}, client::{ClientConfig, ClientHandle, ClientManager, ClientState},
config::{CaptureBackend, Config}, config::{CaptureBackend, Config, EmulationBackend},
dns, dns,
frontend::{FrontendListener, FrontendRequest}, frontend::{FrontendListener, FrontendRequest},
server::capture_task::CaptureEvent, server::capture_task::CaptureEvent,
@@ -77,7 +77,11 @@ impl Server {
} }
} }
pub async fn run(&self, backend: Option<CaptureBackend>) -> anyhow::Result<()> { pub async fn run(
&self,
capture_backend: Option<CaptureBackend>,
emulation_backend: Option<EmulationBackend>,
) -> anyhow::Result<()> {
// create frontend communication adapter // create frontend communication adapter
let frontend = match FrontendListener::new().await { let frontend = match FrontendListener::new().await {
Some(f) => f?, Some(f) => f?,
@@ -97,7 +101,7 @@ impl Server {
// input capture // input capture
let (mut capture_task, capture_channel) = capture_task::new( let (mut capture_task, capture_channel) = capture_task::new(
backend, capture_backend,
self.clone(), self.clone(),
sender_tx.clone(), sender_tx.clone(),
timer_tx.clone(), timer_tx.clone(),
@@ -106,12 +110,13 @@ impl Server {
// input emulation // input emulation
let (mut emulation_task, emulate_channel) = emulation_task::new( let (mut emulation_task, emulate_channel) = emulation_task::new(
emulation_backend,
self.clone(), self.clone(),
receiver_rx, receiver_rx,
sender_tx.clone(), sender_tx.clone(),
capture_channel.clone(), capture_channel.clone(),
timer_tx, timer_tx,
); )?;
// create dns resolver // create dns resolver
let resolver = dns::DnsResolver::new().await?; let resolver = dns::DnsResolver::new().await?;

View File

@@ -7,11 +7,7 @@ use tokio::{
}; };
use crate::{ use crate::{
client::{ClientEvent, ClientHandle}, client::{ClientEvent, ClientHandle}, config::EmulationBackend, emulate::{self, error::EmulationCreationError, InputEmulation}, event::{Event, KeyboardEvent}, scancode, server::State
emulate::{self, InputEmulation},
event::{Event, KeyboardEvent},
scancode,
server::State,
}; };
use super::{CaptureEvent, Server}; use super::{CaptureEvent, Server};
@@ -27,15 +23,16 @@ pub enum EmulationEvent {
} }
pub fn new( pub fn new(
backend: Option<EmulationBackend>,
server: Server, server: Server,
mut udp_rx: Receiver<Result<(Event, SocketAddr)>>, mut udp_rx: Receiver<Result<(Event, SocketAddr)>>,
sender_tx: Sender<(Event, SocketAddr)>, sender_tx: Sender<(Event, SocketAddr)>,
capture_tx: Sender<CaptureEvent>, capture_tx: Sender<CaptureEvent>,
timer_tx: Sender<()>, timer_tx: Sender<()>,
) -> (JoinHandle<Result<()>>, Sender<EmulationEvent>) { ) -> Result<(JoinHandle<Result<()>>, Sender<EmulationEvent>), EmulationCreationError> {
let (tx, mut rx) = tokio::sync::mpsc::channel(32); let (tx, mut rx) = tokio::sync::mpsc::channel(32);
let emulate_task = tokio::task::spawn_local(async move { 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; let mut last_ignored = None;
loop { loop {