rs_peekaboo 0.3.4

Rust-native cross-platform computer-use CLI and library
Documentation
use crate::models::{Bounds, ImageMode, Point};
use crate::platform::process;
use crate::{PeekabooError, Result};
use core_graphics::event::{CGEvent, CGEventTapLocation, CGEventType, CGMouseButton};
use core_graphics::event_source::{CGEventSource, CGEventSourceStateID};
use core_graphics::geometry::CGPoint;
use serde_json::{Value, json};
use std::path::Path;

pub fn capture_image(
    mode: ImageMode,
    path: &Path,
    retina: bool,
    region: Option<&Bounds>,
) -> Result<()> {
    let mut args = vec!["-x".to_string()];
    if mode == ImageMode::Window {
        args.push("-w".to_string());
    }
    if let Some(region) = region {
        args.push("-R".to_string());
        args.push(format!(
            "{},{},{},{}",
            region.x, region.y, region.width, region.height
        ));
    }
    if !retina {
        args.push("-r".to_string());
    }
    args.push(path.to_string_lossy().into_owned());
    let refs = args.iter().map(String::as_str).collect::<Vec<_>>();
    process::run("screencapture", &refs, None)?;
    Ok(())
}

pub fn move_cursor(point: Point) -> Result<Value> {
    move_cursor_to(&point)?;
    Ok(json!({ "point": point }))
}

fn move_cursor_to(point: &Point) -> Result<()> {
    post_mouse(CGEventType::MouseMoved, point, CGMouseButton::Left)
}

fn post_mouse(event_type: CGEventType, point: &Point, button: CGMouseButton) -> Result<()> {
    let source = CGEventSource::new(CGEventSourceStateID::HIDSystemState)
        .map_err(|_| PeekabooError::System("failed to create CoreGraphics event source".into()))?;
    let event = CGEvent::new_mouse_event(
        source,
        event_type,
        CGPoint::new(point.x as f64, point.y as f64),
        button,
    )
    .map_err(|_| PeekabooError::System("failed to create CoreGraphics mouse event".into()))?;
    event.post(CGEventTapLocation::HID);
    Ok(())
}