pub mod backend;
pub mod errors;
pub mod models;
pub mod perception;
pub mod safety;
pub mod tools;
#[cfg(feature = "macos")]
pub mod macos;
pub mod linux;
pub mod windows;
pub use backend::DesktopBackend;
pub use errors::{CarDesktopError, Permission, Result};
pub use models::{
A11yNode, Bounds, ClickRequest, DisplayId, Frame, Key, KeyPressRequest, Modifier,
MouseButton, PermissionRequest, PermissionSnapshot, TypeRequest, UiMap, WindowFilter,
WindowFrame, WindowHandle, WindowInfo,
};
pub use perception::{empty_a11y_uimap, populated_uimap, AX_DEPTH_CAP, AX_NODE_CAP};
pub use safety::{destructive_word_in, PerWindowRateLimiter, DESTRUCTIVE_WORDS, POST_EVENT_SETTLE};
#[cfg(feature = "macos")]
pub use macos::MacBackend;
pub use linux::LinuxBackend;
pub use windows::WindowsBackend;
pub fn default_backend() -> Box<dyn DesktopBackend> {
#[cfg(all(target_os = "macos", feature = "macos"))]
{
Box::new(macos::MacBackend::new())
}
#[cfg(all(target_os = "macos", not(feature = "macos")))]
{
Box::new(linux::LinuxBackend::new())
}
#[cfg(all(not(target_os = "macos"), target_os = "windows"))]
{
Box::new(windows::WindowsBackend::new())
}
#[cfg(all(not(target_os = "macos"), not(target_os = "windows")))]
{
Box::new(linux::LinuxBackend::new())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn default_backend_compiles_and_returns_a_boxed_trait_object() {
let backend = default_backend();
let result = backend.list_windows(WindowFilter::default()).await;
if cfg!(all(target_os = "macos", feature = "macos")) {
let windows = result.expect("list_windows must succeed on macOS+feature");
assert!(
!windows.is_empty(),
"macOS should surface at least one on-screen window"
);
} else {
assert!(
matches!(
result,
Err(CarDesktopError::PlatformUnsupported { .. })
| Err(CarDesktopError::NotYetImplemented { .. })
),
"unexpected error variant: {result:?}"
);
}
}
#[test]
fn scaffold_exports_core_types() {
let _e: CarDesktopError = CarDesktopError::PlatformUnsupported { platform: "x" };
let _s: PermissionSnapshot = PermissionSnapshot {
screen_recording: false,
accessibility: false,
needs_restart: false,
};
let _h: WindowHandle = WindowHandle::new(1, 1);
let _f: WindowFilter = WindowFilter::default();
let _p: Permission = Permission::ScreenRecording;
}
}