pub mod local;
pub use local::LocalBackend;
use image::RgbaImage;
use robost_template::{ScreenPoint, Target};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BackendError {
#[error("capture error: {0}")]
Capture(#[from] robost_capture::CaptureError),
#[error("input error: {0}")]
Input(#[from] robost_input::InputError),
#[error("not supported on this backend: {0}")]
NotSupported(String),
}
impl BackendError {
pub fn is_window_not_found(&self) -> bool {
matches!(
self,
BackendError::Capture(robost_capture::CaptureError::WindowNotFound(_))
)
}
}
pub type Result<T> = std::result::Result<T, BackendError>;
pub trait Backend: Send + Sync {
fn capture(&self, target: &Target) -> Result<RgbaImage>;
fn capture_with_origin(&self, target: &Target) -> Result<(RgbaImage, ScreenPoint)> {
let origin = match target {
Target::Window { title_contains } => robost_capture::window_origin(title_contains)?,
Target::Process { name } => robost_capture::window_origin(name)?,
Target::Region(rect) => ScreenPoint {
x: rect.x,
y: rect.y,
},
_ => ScreenPoint { x: 0, y: 0 },
};
let img = self.capture(target)?;
Ok((img, origin))
}
fn click(&self, point: ScreenPoint) -> Result<()>;
fn right_click(&self, point: ScreenPoint) -> Result<()>;
fn double_click(&self, point: ScreenPoint) -> Result<()>;
fn type_text(&self, text: &str) -> Result<()>;
fn press_key(&self, key: &str) -> Result<()>;
fn control_window(&self, _title_contains: &str, _action: &str) -> Result<()> {
Err(BackendError::NotSupported(format!(
"control_window({_action})"
)))
}
fn move_mouse(&self, _point: ScreenPoint) -> Result<()> {
Err(BackendError::NotSupported("move_mouse".into()))
}
fn drag(&self, _from: ScreenPoint, _to: ScreenPoint, _hold_ms: u64) -> Result<()> {
Err(BackendError::NotSupported("drag".into()))
}
fn scroll(&self, _direction: &str, _amount: i32) -> Result<()> {
Err(BackendError::NotSupported("scroll".into()))
}
fn key_combo(&self, _keys: &[&str]) -> Result<()> {
Err(BackendError::NotSupported("key_combo".into()))
}
}