diff --git a/src/emulate.rs b/src/emulate.rs index 368939f..7dd4e66 100644 --- a/src/emulate.rs +++ b/src/emulate.rs @@ -2,7 +2,9 @@ use async_trait::async_trait; use std::future; use crate::{ - client::{ClientEvent, ClientHandle}, config::EmulationBackend, event::Event + client::{ClientEvent, ClientHandle}, + config::EmulationBackend, + event::Event, }; use anyhow::Result; @@ -43,7 +45,18 @@ pub trait InputEmulation: Send { async fn destroy(&mut self); } -pub async fn create(backend: Option) -> Result, EmulationCreationError> { +pub async fn create( + backend: Option, +) -> Result, EmulationCreationError> { + if let Some(backend) = backend { + return match backend { + EmulationBackend::Libei => Ok(Box::new(libei::LibeiEmulation::new().await?)), + EmulationBackend::Wlroots => Ok(Box::new(wlroots::WlrootsEmulation::new()?)), + EmulationBackend::X11 => Ok(Box::new(x11::X11Emulation::new()?)), + EmulationBackend::Dummy => Ok(Box::new(dummy::DummyEmulation::new())), + }; + } + #[cfg(windows)] match windows::WindowsEmulation::new() { Ok(c) => return Ok(Box::new(c)), diff --git a/src/emulate/error.rs b/src/emulate/error.rs index 03e7dba..36ce7a6 100644 --- a/src/emulate/error.rs +++ b/src/emulate/error.rs @@ -1,8 +1,11 @@ use std::{fmt::Display, io}; use thiserror::Error; -use wayland_client::{backend::WaylandError, globals::{BindError, GlobalError}, ConnectError, DispatchError}; - +use wayland_client::{ + backend::WaylandError, + globals::{BindError, GlobalError}, + ConnectError, DispatchError, +}; #[derive(Debug, Error)] pub enum EmulationCreationError { @@ -20,9 +23,9 @@ impl Display for EmulationCreationError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let reason = match self { EmulationCreationError::Wlroots(e) => format!("wlroots backend: {e}"), - EmulationCreationError::Libei(e) => todo!("libei backend: {e}"), - EmulationCreationError::Xdp(e) => todo!("desktop portal backend: {e}"), - EmulationCreationError::X11(e) => todo!("x11 backend: {e}"), + EmulationCreationError::Libei(e) => format!("libei backend: {e}"), + EmulationCreationError::Xdp(e) => format!("desktop portal backend: {e}"), + EmulationCreationError::X11(e) => format!("x11 backend: {e}"), }; write!(f, "could not create input emulation backend: {reason}") } @@ -52,7 +55,6 @@ impl WaylandBindError { } } - #[cfg(all(unix, feature = "wayland", not(target_os = "macos")))] impl Display for WaylandBindError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -84,15 +86,36 @@ impl Display for WlrootsEmulationCreationError { #[cfg(all(unix, feature = "libei", not(target_os = "macos")))] #[derive(Debug, Error)] -pub enum LibeiEmulationCreationError {} +pub enum LibeiEmulationCreationError { + Ashpd(#[from] ashpd::Error), + Io(#[from] io::Error), +} +#[cfg(all(unix, feature = "libei", not(target_os = "macos")))] +impl Display for LibeiEmulationCreationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LibeiEmulationCreationError::Ashpd(e) => write!(f, "xdg-desktop-portal: {e}"), + LibeiEmulationCreationError::Io(e) => write!(f, "io error: {e}"), + } + } +} #[cfg(all(unix, feature = "xdg_desktop_portal", not(target_os = "macos")))] #[derive(Debug, Error)] pub enum XdpEmulationCreationError {} - - #[cfg(all(unix, feature = "x11", not(target_os = "macos")))] #[derive(Debug, Error)] -pub enum X11EmulationCreationError {} +pub enum X11EmulationCreationError { + OpenDisplay, +} + +#[cfg(all(unix, feature = "x11", not(target_os = "macos")))] +impl Display for X11EmulationCreationError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + X11EmulationCreationError::OpenDisplay => write!(f, "could not open display!"), + } + } +} diff --git a/src/emulate/libei.rs b/src/emulate/libei.rs index 1ee7645..eff7f7a 100644 --- a/src/emulate/libei.rs +++ b/src/emulate/libei.rs @@ -1,6 +1,7 @@ use anyhow::{anyhow, Result}; use std::{ collections::HashMap, + io, os::{fd::OwnedFd, unix::net::UnixStream}, time::{SystemTime, UNIX_EPOCH}, }; @@ -27,6 +28,8 @@ use crate::{ event::Event, }; +use super::error::LibeiEmulationCreationError; + pub struct LibeiEmulation { handshake: bool, context: ei::Context, @@ -77,14 +80,14 @@ async fn get_ei_fd() -> Result { } impl LibeiEmulation { - pub async fn new() -> Result { + pub async fn new() -> Result { // fd is owned by the message, so we need to dup it let eifd = get_ei_fd().await?; let stream = UnixStream::from(eifd); // let stream = UnixStream::connect("/run/user/1000/eis-0")?; stream.set_nonblocking(true)?; let context = ei::Context::new(stream)?; - context.flush()?; + context.flush().map_err(|e| io::Error::new(e.kind(), e))?; let events = EiEventStream::new(context.clone())?; Ok(Self { handshake: false, diff --git a/src/emulate/wlroots.rs b/src/emulate/wlroots.rs index 9473765..5d1f7c4 100644 --- a/src/emulate/wlroots.rs +++ b/src/emulate/wlroots.rs @@ -1,5 +1,5 @@ use crate::client::{ClientEvent, ClientHandle}; -use crate::emulate::{InputEmulation, error::WlrootsEmulationCreationError}; +use crate::emulate::{error::WlrootsEmulationCreationError, InputEmulation}; use async_trait::async_trait; use std::collections::HashMap; use std::io; @@ -53,12 +53,15 @@ impl WlrootsEmulation { let (globals, queue) = registry_queue_init::(&conn)?; let qh = queue.handle(); - let seat: wl_seat::WlSeat = globals.bind(&qh, 7..=8, ()) + 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 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, ()) + 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(); diff --git a/src/emulate/x11.rs b/src/emulate/x11.rs index 24cdb9d..8a0deb6 100644 --- a/src/emulate/x11.rs +++ b/src/emulate/x11.rs @@ -1,4 +1,3 @@ -use anyhow::{anyhow, Result}; use async_trait::async_trait; use std::ptr; use x11::{ @@ -14,6 +13,8 @@ use crate::{ }, }; +use super::error::X11EmulationCreationError; + pub struct X11Emulation { display: *mut xlib::Display, } @@ -21,11 +22,11 @@ pub struct X11Emulation { unsafe impl Send for X11Emulation {} impl X11Emulation { - pub fn new() -> Result { + pub fn new() -> Result { let display = unsafe { match xlib::XOpenDisplay(ptr::null()) { d if d == ptr::null::() as *mut xlib::Display => { - Err(anyhow!("could not open display")) + Err(X11EmulationCreationError::OpenDisplay) } display => Ok(display), } diff --git a/src/main.rs b/src/main.rs index 5dc50d3..28434d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,7 +71,9 @@ 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, config.emulation_backend).await?; + server + .run(config.capture_backend, config.emulation_backend) + .await?; log::debug!("service exiting"); anyhow::Ok(()) diff --git a/src/server/emulation_task.rs b/src/server/emulation_task.rs index 3055b9c..4064df6 100644 --- a/src/server/emulation_task.rs +++ b/src/server/emulation_task.rs @@ -7,7 +7,12 @@ use tokio::{ }; use crate::{ - client::{ClientEvent, ClientHandle}, config::EmulationBackend, emulate::{self, error::EmulationCreationError, 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};