Skip to main content

inspect/
inspect.rs

1//! Prints an app's accessibility tree and saves its screenshot.
2//!
3//! ```sh
4//! cargo run --example inspect -- Finder
5//! cargo run --example inspect -- com.apple.TextEdit /tmp/textedit.png
6//! ```
7
8#![allow(clippy::print_stdout)]
9
10use std::process::ExitCode;
11
12#[cfg(any(target_os = "macos", target_os = "windows", target_os = "linux"))]
13fn main() -> ExitCode {
14    use computer_use::{CaptureOptions, Computer};
15
16    let mut args = std::env::args().skip(1);
17    let Some(app) = args.next() else {
18        eprintln!("usage: inspect <app name | bundle id | pid:N> [screenshot.png]");
19        return ExitCode::FAILURE;
20    };
21    let output = args.next();
22
23    let run = || -> computer_use::Result<()> {
24        let mut computer = Computer::new()?;
25        let permissions = computer.permissions();
26        if !permissions.all_granted() {
27            eprintln!("warning: missing permissions: {permissions:?}");
28        }
29        let started = std::time::Instant::now();
30        let state = computer.get_app_state(&app, &CaptureOptions::default())?;
31        println!("{state}");
32        eprintln!("\ncaptured {} elements in {:?}", state.elements.len(), started.elapsed());
33        if let (Some(path), Some(shot)) = (output, &state.screenshot) {
34            std::fs::write(&path, shot.png())?;
35            eprintln!("saved {}x{} screenshot to {path}", shot.width(), shot.height());
36        }
37        Ok(())
38    };
39    match run() {
40        Ok(()) => ExitCode::SUCCESS,
41        Err(e) => {
42            eprintln!("error: {e}");
43            ExitCode::FAILURE
44        }
45    }
46}
47
48#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "linux")))]
49fn main() -> ExitCode {
50    eprintln!("this platform has no native backend");
51    ExitCode::FAILURE
52}