use crate::macos::ax::{element_bbox, press_element, AXDispatchError, AXRef};
use crate::tools::ax_response;
use crate::tools::ax_session::{AxSession, LookupError};
use rmcp::model::CallToolResult;
use serde::Deserialize;
use std::sync::Arc;
const DISPATCHED_VIA: &str = "AXPress";
#[derive(Deserialize)]
pub struct AxClickParams {
pub uid: String,
}
pub async fn ax_click(params: AxClickParams, session: Arc<AxSession>) -> CallToolResult {
if let Some(err) = crate::tools::input::check_permission() {
return err;
}
let outcome = session
.dispatch(¶ms.uid, |ax_ref: &AXRef| {
let pre_bbox = unsafe { element_bbox(ax_ref.as_raw()) };
match press_element(ax_ref) {
Ok(()) => {
let post_bbox = unsafe { element_bbox(ax_ref.as_raw()) }.or(pre_bbox);
ax_response::success(DISPATCHED_VIA, post_bbox)
}
Err(AXDispatchError::NotDispatchable) => ax_response::error(
"not_dispatchable",
"element does not support AXPress",
pre_bbox,
),
Err(AXDispatchError::AxError(code)) => ax_response::error(
"ax_error",
&format!("AXUIElementPerformAction failed with AX error {}", code),
pre_bbox,
),
}
})
.await;
match outcome {
Ok(result) => result,
Err(LookupError::SnapshotExpired { reason }) => {
ax_response::error("snapshot_expired", &reason, None)
}
Err(LookupError::UidNotFound) => ax_response::error(
"uid_not_found",
&format!("uid {} is not present in the current snapshot", params.uid),
None,
),
}
}