mirror of
https://github.com/lahfir/agent-desktop.git
synced 2026-08-01 11:49:20 +00:00
fix(ci): regenerate FFI header + gitignore AGENTS.md
Committed header had drifted from source (missing ad_window_list_*, ad_release_window_fields rename, etc.). Regenerated cleanly from source and added AGENTS.md to gitignore.
This commit is contained in:
parent
f73c023eac
commit
61172dc8d7
2 changed files with 585 additions and 143 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -23,6 +23,7 @@ Cargo.lock
|
|||
# Claude Code
|
||||
.claude/
|
||||
.agents/
|
||||
AGENTS.md
|
||||
|
||||
# Environment
|
||||
.env
|
||||
|
|
|
|||
|
|
@ -5,68 +5,12 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
enum AdActionKind {
|
||||
AD_ACTION_KIND_CLICK = 0,
|
||||
AD_ACTION_KIND_DOUBLE_CLICK = 1,
|
||||
AD_ACTION_KIND_RIGHT_CLICK = 2,
|
||||
AD_ACTION_KIND_TRIPLE_CLICK = 3,
|
||||
AD_ACTION_KIND_SET_VALUE = 4,
|
||||
AD_ACTION_KIND_SET_FOCUS = 5,
|
||||
AD_ACTION_KIND_EXPAND = 6,
|
||||
AD_ACTION_KIND_COLLAPSE = 7,
|
||||
AD_ACTION_KIND_SELECT = 8,
|
||||
AD_ACTION_KIND_TOGGLE = 9,
|
||||
AD_ACTION_KIND_CHECK = 10,
|
||||
AD_ACTION_KIND_UNCHECK = 11,
|
||||
AD_ACTION_KIND_SCROLL = 12,
|
||||
AD_ACTION_KIND_SCROLL_TO = 13,
|
||||
AD_ACTION_KIND_PRESS_KEY = 14,
|
||||
AD_ACTION_KIND_KEY_DOWN = 15,
|
||||
AD_ACTION_KIND_KEY_UP = 16,
|
||||
AD_ACTION_KIND_TYPE_TEXT = 17,
|
||||
AD_ACTION_KIND_CLEAR = 18,
|
||||
AD_ACTION_KIND_HOVER = 19,
|
||||
AD_ACTION_KIND_DRAG = 20,
|
||||
};
|
||||
typedef int32_t AdActionKind;
|
||||
|
||||
enum AdDirection {
|
||||
AD_DIRECTION_UP = 0,
|
||||
AD_DIRECTION_DOWN = 1,
|
||||
AD_DIRECTION_LEFT = 2,
|
||||
AD_DIRECTION_RIGHT = 3,
|
||||
};
|
||||
typedef int32_t AdDirection;
|
||||
|
||||
enum AdImageFormat {
|
||||
AD_IMAGE_FORMAT_PNG = 0,
|
||||
AD_IMAGE_FORMAT_JPG = 1,
|
||||
};
|
||||
typedef int32_t AdImageFormat;
|
||||
|
||||
enum AdModifier {
|
||||
AD_MODIFIER_CMD = 0,
|
||||
AD_MODIFIER_CTRL = 1,
|
||||
AD_MODIFIER_ALT = 2,
|
||||
AD_MODIFIER_SHIFT = 3,
|
||||
};
|
||||
typedef int32_t AdModifier;
|
||||
|
||||
enum AdMouseButton {
|
||||
AD_MOUSE_BUTTON_LEFT = 0,
|
||||
AD_MOUSE_BUTTON_RIGHT = 1,
|
||||
AD_MOUSE_BUTTON_MIDDLE = 2,
|
||||
};
|
||||
typedef int32_t AdMouseButton;
|
||||
|
||||
enum AdMouseEventKind {
|
||||
AD_MOUSE_EVENT_KIND_MOVE = 0,
|
||||
AD_MOUSE_EVENT_KIND_DOWN = 1,
|
||||
AD_MOUSE_EVENT_KIND_UP = 2,
|
||||
AD_MOUSE_EVENT_KIND_CLICK = 3,
|
||||
};
|
||||
typedef int32_t AdMouseEventKind;
|
||||
|
||||
enum AdResult {
|
||||
AD_RESULT_OK = 0,
|
||||
AD_RESULT_ERR_PERM_DENIED = -1,
|
||||
|
|
@ -84,47 +28,71 @@ enum AdResult {
|
|||
};
|
||||
typedef int32_t AdResult;
|
||||
|
||||
enum AdScreenshotKind {
|
||||
AD_SCREENSHOT_KIND_SCREEN = 0,
|
||||
AD_SCREENSHOT_KIND_WINDOW = 1,
|
||||
AD_SCREENSHOT_KIND_FULL_SCREEN = 2,
|
||||
};
|
||||
typedef int32_t AdScreenshotKind;
|
||||
|
||||
enum AdSnapshotSurface {
|
||||
AD_SNAPSHOT_SURFACE_WINDOW = 0,
|
||||
AD_SNAPSHOT_SURFACE_FOCUSED = 1,
|
||||
AD_SNAPSHOT_SURFACE_MENU = 2,
|
||||
AD_SNAPSHOT_SURFACE_MENUBAR = 3,
|
||||
AD_SNAPSHOT_SURFACE_SHEET = 4,
|
||||
AD_SNAPSHOT_SURFACE_POPOVER = 5,
|
||||
AD_SNAPSHOT_SURFACE_ALERT = 6,
|
||||
};
|
||||
typedef int32_t AdSnapshotSurface;
|
||||
|
||||
enum AdWindowOpKind {
|
||||
AD_WINDOW_OP_KIND_RESIZE = 0,
|
||||
AD_WINDOW_OP_KIND_MOVE = 1,
|
||||
AD_WINDOW_OP_KIND_MINIMIZE = 2,
|
||||
AD_WINDOW_OP_KIND_MAXIMIZE = 3,
|
||||
AD_WINDOW_OP_KIND_RESTORE = 4,
|
||||
};
|
||||
typedef int32_t AdWindowOpKind;
|
||||
|
||||
typedef struct AdAdapter AdAdapter;
|
||||
|
||||
/**
|
||||
* Opaque list handle emitted by `ad_list_apps`. See
|
||||
* [`crate::types::window_list::AdWindowList`] for the pattern.
|
||||
*/
|
||||
typedef struct AdAppList AdAppList;
|
||||
|
||||
/**
|
||||
* Opaque image-buffer handle returned by `ad_screenshot`. The backing
|
||||
* byte buffer and its length live inside the Rust-owned struct — a
|
||||
* consumer cannot accidentally desynchronize the pair and trigger a
|
||||
* heap-corruption double-free. Walk it through `ad_image_buffer_*`
|
||||
* accessors and free it with `ad_image_buffer_free`.
|
||||
*/
|
||||
typedef struct AdImageBuffer AdImageBuffer;
|
||||
|
||||
typedef struct AdNotificationList AdNotificationList;
|
||||
|
||||
/**
|
||||
* Opaque list handle emitted by `ad_list_surfaces`. See
|
||||
* [`crate::types::window_list::AdWindowList`] for the pattern.
|
||||
*/
|
||||
typedef struct AdSurfaceList AdSurfaceList;
|
||||
|
||||
/**
|
||||
* Opaque list handle emitted by `ad_list_windows`.
|
||||
*
|
||||
* The struct intentionally has no `#[repr(C)]` so cbindgen emits a
|
||||
* forward declaration only (`typedef struct AdWindowList AdWindowList;`).
|
||||
* Consumers cannot read the backing pointer or length and cannot
|
||||
* construct a count mismatch — they walk the list through
|
||||
* `ad_window_list_count`, `ad_window_list_get`, and free it with
|
||||
* `ad_window_list_free`.
|
||||
*/
|
||||
typedef struct AdWindowList AdWindowList;
|
||||
|
||||
typedef struct AdNativeHandle {
|
||||
const void *ptr;
|
||||
} AdNativeHandle;
|
||||
|
||||
/**
|
||||
* Scroll parameters embedded in `AdAction` when `kind == SCROLL`.
|
||||
*
|
||||
* `direction` is stored as `int32_t` for the same boundary-safety
|
||||
* reason `AdAction.kind` is. Valid values are the discriminants of
|
||||
* `AdDirection`.
|
||||
*/
|
||||
typedef struct AdScrollParams {
|
||||
AdDirection direction;
|
||||
int32_t direction;
|
||||
uint32_t amount;
|
||||
} AdScrollParams;
|
||||
|
||||
/**
|
||||
* Key combination: a named key plus optional modifier list.
|
||||
*
|
||||
* `modifiers` points to an array of `int32_t` values (not a typed Rust
|
||||
* enum array) so the C boundary cannot be tricked into writing an
|
||||
* out-of-range discriminant into a Rust enum slot. Each entry is
|
||||
* validated against `AdModifier` before use; an invalid discriminant
|
||||
* returns `AD_RESULT_ERR_INVALID_ARGS`.
|
||||
*/
|
||||
typedef struct AdKeyCombo {
|
||||
const char *key;
|
||||
const AdModifier *modifiers;
|
||||
const int32_t *modifiers;
|
||||
uint32_t modifier_count;
|
||||
} AdKeyCombo;
|
||||
|
||||
|
|
@ -139,8 +107,17 @@ typedef struct AdDragParams {
|
|||
uint64_t duration_ms;
|
||||
} AdDragParams;
|
||||
|
||||
/**
|
||||
* Action dispatched by `ad_execute_action`.
|
||||
*
|
||||
* `kind` is stored as `int32_t` so a buggy or malicious C caller
|
||||
* cannot write an out-of-range discriminant into a Rust enum slot —
|
||||
* an out-of-range value is rejected with
|
||||
* `AD_RESULT_ERR_INVALID_ARGS` at the boundary. Valid values are the
|
||||
* discriminants of `AdActionKind`.
|
||||
*/
|
||||
typedef struct AdAction {
|
||||
AdActionKind kind;
|
||||
int32_t kind;
|
||||
const char *text;
|
||||
struct AdScrollParams scroll;
|
||||
struct AdKeyCombo key;
|
||||
|
|
@ -191,27 +168,57 @@ typedef struct AdAppInfo {
|
|||
const char *bundle_id;
|
||||
} AdAppInfo;
|
||||
|
||||
/**
|
||||
* Mouse event dispatched by `ad_mouse_event`.
|
||||
*
|
||||
* `kind` and `button` are stored as `int32_t` for the same reason
|
||||
* `AdAction.kind` is — foreign callers cannot place invalid
|
||||
* discriminants into Rust enum slots. Valid values are the
|
||||
* discriminants of `AdMouseEventKind` and `AdMouseButton`.
|
||||
*/
|
||||
typedef struct AdMouseEvent {
|
||||
AdMouseEventKind kind;
|
||||
int32_t kind;
|
||||
struct AdPoint point;
|
||||
AdMouseButton button;
|
||||
int32_t button;
|
||||
uint32_t click_count;
|
||||
} AdMouseEvent;
|
||||
|
||||
typedef struct AdNotificationFilter {
|
||||
const char *app;
|
||||
const char *text;
|
||||
uint32_t limit;
|
||||
bool has_limit;
|
||||
} AdNotificationFilter;
|
||||
|
||||
typedef struct AdNotificationInfo {
|
||||
uint32_t index;
|
||||
const char *app_name;
|
||||
const char *title;
|
||||
const char *body;
|
||||
char **actions;
|
||||
uint32_t action_count;
|
||||
} AdNotificationInfo;
|
||||
|
||||
typedef struct AdFindQuery {
|
||||
const char *role;
|
||||
const char *name_substring;
|
||||
const char *value_substring;
|
||||
} AdFindQuery;
|
||||
|
||||
/**
|
||||
* Screenshot target for `ad_screenshot`.
|
||||
*
|
||||
* `kind` is stored as `int32_t` to keep the enum-discriminant check
|
||||
* at the boundary. Valid values are the discriminants of
|
||||
* `AdScreenshotKind`. `screen_index` is only consulted when kind is
|
||||
* `SCREEN`; `pid` only when kind is `WINDOW`.
|
||||
*/
|
||||
typedef struct AdScreenshotTarget {
|
||||
AdScreenshotKind kind;
|
||||
int32_t kind;
|
||||
uint64_t screen_index;
|
||||
int32_t pid;
|
||||
} AdScreenshotTarget;
|
||||
|
||||
typedef struct AdImageBuffer {
|
||||
const uint8_t *data;
|
||||
uint64_t data_len;
|
||||
AdImageFormat format;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
} AdImageBuffer;
|
||||
|
||||
typedef struct AdSurfaceInfo {
|
||||
const char *kind;
|
||||
const char *title;
|
||||
|
|
@ -239,16 +246,33 @@ typedef struct AdNodeTree {
|
|||
uint32_t count;
|
||||
} AdNodeTree;
|
||||
|
||||
/**
|
||||
* Options for `ad_get_tree`.
|
||||
*
|
||||
* `surface` is stored as `int32_t` so foreign callers cannot write
|
||||
* an invalid discriminant into a Rust enum slot. Valid values are the
|
||||
* discriminants of `AdSnapshotSurface`; out-of-range values return
|
||||
* `AD_RESULT_ERR_INVALID_ARGS`.
|
||||
*/
|
||||
typedef struct AdTreeOptions {
|
||||
uint8_t max_depth;
|
||||
bool include_bounds;
|
||||
bool interactive_only;
|
||||
bool compact;
|
||||
AdSnapshotSurface surface;
|
||||
int32_t surface;
|
||||
} AdTreeOptions;
|
||||
|
||||
/**
|
||||
* Window-manager operation dispatched by `ad_window_op`.
|
||||
*
|
||||
* `kind` is stored as `int32_t` to keep the enum-discriminant check at
|
||||
* the boundary — out-of-range values return
|
||||
* `AD_RESULT_ERR_INVALID_ARGS`. Valid values are the discriminants of
|
||||
* `AdWindowOpKind`. `width`/`height`/`x`/`y` are only consulted for
|
||||
* the variants that use them.
|
||||
*/
|
||||
typedef struct AdWindowOp {
|
||||
AdWindowOpKind kind;
|
||||
int32_t kind;
|
||||
double width;
|
||||
double height;
|
||||
double x;
|
||||
|
|
@ -269,22 +293,32 @@ AdResult ad_execute_action(const struct AdAdapter *adapter,
|
|||
struct AdActionResult *out);
|
||||
|
||||
/**
|
||||
* Releases a handle previously returned by `ad_resolve_element`.
|
||||
* Releases a handle previously returned by `ad_resolve_element` and
|
||||
* zeroes the caller's struct so accidentally calling this twice is
|
||||
* a deterministic no-op instead of a double-free on the underlying
|
||||
* `CFRelease`.
|
||||
*
|
||||
* On macOS this calls `CFRelease` on the underlying `AXUIElementRef`,
|
||||
* balancing the `CFRetain` that happened during `ad_resolve_element`.
|
||||
* On Windows/Linux the call is a no-op that returns `AD_RESULT_OK`
|
||||
* (platform adapters inherit the default `not_supported` impl, which
|
||||
* the FFI surface rewrites to `Ok` here so callers can apply the same
|
||||
* release pattern everywhere).
|
||||
* (platform adapters inherit the default `not_supported` impl; the
|
||||
* FFI surface translates it so callers apply the same release
|
||||
* pattern everywhere).
|
||||
*
|
||||
* Ownership contract: the FFI owns the handle from the moment
|
||||
* `ad_resolve_element` writes `ptr`. Copying the struct after that
|
||||
* point and calling `ad_free_handle` on either copy is undefined —
|
||||
* there is no way for the library to detect forged non-null pointers.
|
||||
* Callers that legitimately need a "copy" should re-resolve.
|
||||
*
|
||||
* # Safety
|
||||
*
|
||||
* `adapter` must be a non-null pointer returned by `ad_adapter_create`.
|
||||
* `handle` must be null or a pointer previously populated by
|
||||
* `ad_resolve_element`. Double-free is undefined behavior.
|
||||
* `handle` must be null or a `*mut AdNativeHandle` previously
|
||||
* populated by `ad_resolve_element`. On return `(*handle).ptr` is
|
||||
* `NULL` so a double-call is a no-op instead of a double-free.
|
||||
*/
|
||||
AdResult ad_free_handle(const struct AdAdapter *adapter, const struct AdNativeHandle *handle);
|
||||
AdResult ad_free_handle(const struct AdAdapter *adapter, struct AdNativeHandle *handle);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
|
|
@ -305,6 +339,15 @@ AdResult ad_resolve_element(const struct AdAdapter *adapter,
|
|||
*/
|
||||
void ad_free_action_result(struct AdActionResult *result);
|
||||
|
||||
/**
|
||||
* Builds a platform adapter for the current OS and returns an opaque
|
||||
* handle. Returns null on allocation failure or if a Rust panic is
|
||||
* caught at the FFI boundary (inspect `ad_last_error_*` for details).
|
||||
*
|
||||
* The returned pointer is owned by the caller and must be released with
|
||||
* `ad_adapter_destroy`. Creating and destroying adapters is cheap; the
|
||||
* common pattern is one adapter per process lifetime.
|
||||
*/
|
||||
struct AdAdapter *ad_adapter_create(void);
|
||||
|
||||
/**
|
||||
|
|
@ -324,14 +367,29 @@ void ad_adapter_destroy(struct AdAdapter *adapter);
|
|||
AdResult ad_check_permissions(const struct AdAdapter *adapter);
|
||||
|
||||
/**
|
||||
* Closes the application identified by `id` (bundle id on macOS,
|
||||
* executable path on other platforms). `force = true` skips the
|
||||
* graceful-shutdown path (equivalent to `kill -9`).
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be valid. `id` must be a valid C string.
|
||||
* `adapter` must be non-null. `id` must be a non-null UTF-8 C string.
|
||||
*/
|
||||
AdResult ad_close_app(const struct AdAdapter *adapter, const char *id, bool force);
|
||||
|
||||
/**
|
||||
* Launches the application identified by `id` (bundle id on macOS,
|
||||
* executable path on other platforms) and, on success, writes the
|
||||
* first window that becomes available into `*out`. Waits up to
|
||||
* `timeout_ms` for the window to appear; zero means "no wait".
|
||||
*
|
||||
* The returned `AdWindowInfo` owns heap-allocated interior strings that
|
||||
* must be released with `ad_release_window_fields` once done. On error
|
||||
* the out-param is zero-initialized, so calling the release fn on it
|
||||
* is a safe no-op.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be valid. `id` must be a valid C string. `out` must be writable.
|
||||
* `adapter` must be non-null. `id` must be a non-null UTF-8 C string.
|
||||
* `out` must be a non-null writable `*mut AdWindowInfo`.
|
||||
*/
|
||||
AdResult ad_launch_app(const struct AdAdapter *adapter,
|
||||
const char *id,
|
||||
|
|
@ -341,15 +399,35 @@ AdResult ad_launch_app(const struct AdAdapter *adapter,
|
|||
/**
|
||||
* # Safety
|
||||
* `adapter` must be a valid pointer from `ad_adapter_create`.
|
||||
* `out` and `out_count` must be valid writable pointers.
|
||||
* `out` must be a valid writable `*mut *mut AdAppList`.
|
||||
* On success, `*out` is a newly-allocated opaque list freed with
|
||||
* `ad_app_list_free`. On error, `*out` is null and last-error is set.
|
||||
*/
|
||||
AdResult ad_list_apps(const struct AdAdapter *adapter, struct AdAppInfo **out, uint32_t *out_count);
|
||||
AdResult ad_list_apps(const struct AdAdapter *adapter, struct AdAppList **out);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* `apps` must be null or a pointer previously returned by `ad_list_apps`.
|
||||
* `list` must be null or a pointer returned by `ad_list_apps`.
|
||||
*/
|
||||
void ad_free_apps(struct AdAppInfo *apps, uint32_t count);
|
||||
uint32_t ad_app_list_count(const struct AdAppList *list);
|
||||
|
||||
/**
|
||||
* Returns a borrowed pointer into the list; valid until the list is freed.
|
||||
* Out-of-range `index` returns null.
|
||||
*
|
||||
* # Safety
|
||||
* `list` must be null or a pointer returned by `ad_list_apps`.
|
||||
*/
|
||||
const struct AdAppInfo *ad_app_list_get(const struct AdAppList *list, uint32_t index);
|
||||
|
||||
/**
|
||||
* Frees the list and every `AdAppInfo` it owns, including the interior
|
||||
* C-strings.
|
||||
*
|
||||
* # Safety
|
||||
* `list` must be null or a pointer returned by `ad_list_apps`.
|
||||
*/
|
||||
void ad_app_list_free(struct AdAppList *list);
|
||||
|
||||
/**
|
||||
* Last-error lifetime — errno-style.
|
||||
|
|
@ -367,91 +445,374 @@ void ad_free_apps(struct AdAppInfo *apps, uint32_t count);
|
|||
* This matches the POSIX `errno` / `strerror` contract and is scoped
|
||||
* per-thread via thread-local storage — Thread A's last-error never
|
||||
* leaks to Thread B.
|
||||
* Returns the `AdResult` code of the last error on the calling thread,
|
||||
* or `AD_RESULT_OK` if no error has been recorded.
|
||||
*/
|
||||
AdResult ad_last_error_code(void);
|
||||
|
||||
/**
|
||||
* Returns a borrowed C string describing the last error, or null if no
|
||||
* error has been recorded on the calling thread. The pointer remains
|
||||
* valid across any number of subsequent *successful* FFI calls; only
|
||||
* the next failing call overwrites it.
|
||||
*/
|
||||
const char *ad_last_error_message(void);
|
||||
|
||||
/**
|
||||
* Returns a borrowed C string with a human-readable suggestion for how
|
||||
* to recover from the last error, or null if the adapter didn't emit
|
||||
* one. Same lifetime rules as `ad_last_error_message`.
|
||||
*/
|
||||
const char *ad_last_error_suggestion(void);
|
||||
|
||||
/**
|
||||
* Returns a borrowed C string carrying a platform-specific diagnostic
|
||||
* for the last error (AX error codes, COM HRESULTs, AT-SPI messages,
|
||||
* etc.), or null if the adapter didn't supply one. Same lifetime rules
|
||||
* as `ad_last_error_message`.
|
||||
*/
|
||||
const char *ad_last_error_platform_detail(void);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* Reads the current clipboard text and writes an owned C string into
|
||||
* `*out`. The caller must free the returned pointer with
|
||||
* `ad_free_string`. On error `*out` is left null.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be a non-null pointer returned by `ad_adapter_create`.
|
||||
* `out` must be a non-null pointer to a `*mut c_char` to receive the allocated string.
|
||||
* Free the result with `ad_free_string`.
|
||||
* `out` must be a non-null writable `*mut *mut c_char`.
|
||||
*/
|
||||
AdResult ad_get_clipboard(const struct AdAdapter *adapter, char **out);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* Writes UTF-8 `text` to the clipboard. Null or non-UTF-8 input returns
|
||||
* `AD_RESULT_ERR_INVALID_ARGS` with a diagnostic last-error.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be a non-null pointer returned by `ad_adapter_create`.
|
||||
* `text` must be a non-null, valid UTF-8 C string.
|
||||
* `text` must be a non-null, NUL-terminated UTF-8 C string.
|
||||
*/
|
||||
AdResult ad_set_clipboard(const struct AdAdapter *adapter, const char *text);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* Clears the clipboard.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be a non-null pointer returned by `ad_adapter_create`.
|
||||
*/
|
||||
AdResult ad_clear_clipboard(const struct AdAdapter *adapter);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* Frees a C string previously returned by `ad_get_clipboard` or any
|
||||
* other FFI call documented as allocating a C string for the caller.
|
||||
* Null-tolerant — safe to call on `NULL`. Double-free is undefined.
|
||||
*
|
||||
* `s` must be a pointer previously returned by `ad_get_clipboard`, or null.
|
||||
* # Safety
|
||||
* `s` must be null or a pointer previously handed out by this crate.
|
||||
* After this call the pointer is invalid and must not be used.
|
||||
*/
|
||||
void ad_free_string(char *s);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* Synthesizes a mouse drag from `params.from` to `params.to`. When
|
||||
* `params.duration_ms` is zero the drag is instantaneous; a non-zero
|
||||
* value asks the platform adapter to interpolate.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be a non-null pointer returned by `ad_adapter_create`.
|
||||
* `params` must be a non-null pointer to a valid `AdDragParams`.
|
||||
*/
|
||||
AdResult ad_drag(const struct AdAdapter *adapter, const struct AdDragParams *params);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* Dispatches a mouse event (move / down / up / click) at the given
|
||||
* screen point. Click count is only consulted when `event.kind` is
|
||||
* `CLICK` (e.g., `click_count == 2` for a double-click).
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be a non-null pointer returned by `ad_adapter_create`.
|
||||
* `event` must be a non-null pointer to a valid `AdMouseEvent`.
|
||||
*/
|
||||
AdResult ad_mouse_event(const struct AdAdapter *adapter, const struct AdMouseEvent *event);
|
||||
|
||||
/**
|
||||
* Triggers the named action on the notification at `index`. Typical
|
||||
* action names are those reported in `AdNotificationInfo.actions`
|
||||
* (e.g. `"Reply"`, `"Open"`).
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` and `target` must be valid. `out` must be writable.
|
||||
* `adapter` must be valid. `action_name` must be a non-null UTF-8
|
||||
* C string. `out` must be a valid writable `*mut AdActionResult`;
|
||||
* on error it is zero-initialized.
|
||||
*/
|
||||
AdResult ad_notification_action(const struct AdAdapter *adapter,
|
||||
uint32_t index,
|
||||
const char *action_name,
|
||||
struct AdActionResult *out);
|
||||
|
||||
/**
|
||||
* Dismisses the notification at `index`. Indexes are only valid within
|
||||
* the response to the most recent `ad_list_notifications` call on this
|
||||
* thread — the adapter re-queries internally, so dismissing by a stale
|
||||
* index returns `AD_RESULT_ERR_NOTIFICATION_NOT_FOUND`.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be valid. `app_filter` may be null.
|
||||
*/
|
||||
AdResult ad_dismiss_notification(const struct AdAdapter *adapter,
|
||||
uint32_t index,
|
||||
const char *app_filter);
|
||||
|
||||
/**
|
||||
* Dismisses every notification matching `app_filter` (null = all apps).
|
||||
*
|
||||
* Returns two lists: `dismissed_out` carries the notifications that
|
||||
* were successfully dismissed; `failed_out` holds error strings for
|
||||
* notifications where the platform rejected the dismiss. Partial
|
||||
* failures do not set last-error — inspect `failed_out` for details.
|
||||
*
|
||||
* `failed_out` uses the notification-list handle to stay ABI-consistent
|
||||
* with the other list-returning FFI calls; the entries carry the
|
||||
* original notification shape with `body` populated by the platform
|
||||
* error message.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be valid. `app_filter` may be null. `dismissed_out`
|
||||
* and `failed_out` must both be valid writable `*mut *mut AdNotificationList`.
|
||||
*/
|
||||
AdResult ad_dismiss_all_notifications(const struct AdAdapter *adapter,
|
||||
const char *app_filter,
|
||||
struct AdNotificationList **dismissed_out,
|
||||
struct AdNotificationList **failed_out);
|
||||
|
||||
/**
|
||||
* Convenience wrapper: free both lists returned by
|
||||
* `ad_dismiss_all_notifications`. Equivalent to calling
|
||||
* `ad_notification_list_free` on each; provided for symmetry.
|
||||
*
|
||||
* # Safety
|
||||
* Both arguments must be null or pointers from
|
||||
* `ad_dismiss_all_notifications`.
|
||||
*/
|
||||
void ad_dismiss_all_notifications_free(struct AdNotificationList *dismissed,
|
||||
struct AdNotificationList *failed);
|
||||
|
||||
/**
|
||||
* Lists the notifications currently on-screen.
|
||||
*
|
||||
* Notification indexes are only stable within a single list response.
|
||||
* Pass them straight to `ad_dismiss_notification` /
|
||||
* `ad_notification_action` without caching across ticks — the adapter
|
||||
* re-queries Notification Center internally on every call.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be valid. `filter` may be null. `out` must be a valid
|
||||
* writable `*mut *mut AdNotificationList`. On success `*out` is a
|
||||
* non-null handle freed with `ad_notification_list_free`.
|
||||
*/
|
||||
AdResult ad_list_notifications(const struct AdAdapter *adapter,
|
||||
const struct AdNotificationFilter *filter,
|
||||
struct AdNotificationList **out);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* `list` must be null or a pointer returned by `ad_list_notifications`.
|
||||
*/
|
||||
uint32_t ad_notification_list_count(const struct AdNotificationList *list);
|
||||
|
||||
/**
|
||||
* Borrows a notification entry. Null if `index` is out of range.
|
||||
*
|
||||
* # Safety
|
||||
* `list` must be null or a pointer returned by `ad_list_notifications`.
|
||||
*/
|
||||
const struct AdNotificationInfo *ad_notification_list_get(const struct AdNotificationList *list,
|
||||
uint32_t index);
|
||||
|
||||
/**
|
||||
* Frees the list and each entry's interior strings.
|
||||
*
|
||||
* # Safety
|
||||
* `list` must be null or a pointer returned by `ad_list_notifications`.
|
||||
*/
|
||||
void ad_notification_list_free(struct AdNotificationList *list);
|
||||
|
||||
/**
|
||||
* Finds the first element in `win`'s accessibility tree matching the
|
||||
* query and resolves it to an opaque `AdNativeHandle`. The caller owns
|
||||
* the handle and must release it with `ad_free_handle(adapter, handle)`
|
||||
* once done.
|
||||
*
|
||||
* Matching is DFS order, first hit wins. All query fields are optional
|
||||
* (null = "don't care") and case-insensitive substring matches:
|
||||
* - `role` against `AccessibilityNode.role`
|
||||
* - `name_substring` against `AccessibilityNode.name`
|
||||
* - `value_substring` against `AccessibilityNode.value`
|
||||
*
|
||||
* # Safety
|
||||
* `adapter`, `win`, and `query` must be valid pointers. `out_handle`
|
||||
* must be a valid writable `*mut AdNativeHandle`. On
|
||||
* `AD_RESULT_ERR_ELEMENT_NOT_FOUND` the out-handle is zero-initialized.
|
||||
*/
|
||||
AdResult ad_find(const struct AdAdapter *adapter,
|
||||
const struct AdWindowInfo *win,
|
||||
const struct AdFindQuery *query,
|
||||
struct AdNativeHandle *out_handle);
|
||||
|
||||
/**
|
||||
* Reads a single property off a previously-resolved element handle.
|
||||
*
|
||||
* Supported properties:
|
||||
* - `"value"` — live textual value (text fields, sliders, progress
|
||||
* indicators). Null out-string when the element has no value.
|
||||
* - `"bounds"` — JSON-encoded `{"x":..,"y":..,"width":..,"height":..}`.
|
||||
* Null out-string when bounds are unavailable.
|
||||
*
|
||||
* The returned string must be freed with `ad_free_string`.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` must be valid. `handle` must be a non-null `AdNativeHandle`.
|
||||
* `property` must be a non-null UTF-8 C string. `out` must be a valid
|
||||
* writable `*mut *mut c_char`; it is null-initialized on entry.
|
||||
*/
|
||||
AdResult ad_get(const struct AdAdapter *adapter,
|
||||
const struct AdNativeHandle *handle,
|
||||
const char *property,
|
||||
char **out);
|
||||
|
||||
/**
|
||||
* Checks whether a named boolean state is set on the first element
|
||||
* matching `query` inside `win`'s accessibility tree. Intended for
|
||||
* the common agent idiom `find → is("focused") → if yes, act`.
|
||||
*
|
||||
* Supported property names reflect the strings the macOS tree
|
||||
* builder actually emits in `AccessibilityNode.states`:
|
||||
*
|
||||
* - `"focused"` — true when the node carries the `focused` state.
|
||||
* - `"disabled"` — true when the adapter surfaced `disabled`.
|
||||
* - `"enabled"` — derived: true iff `disabled` is NOT present. There
|
||||
* is no `enabled` string in the adapter output; asking for it
|
||||
* returns the logical negation so agents don't have to invert
|
||||
* themselves.
|
||||
*
|
||||
* `"selected"`, `"checked"`, and `"expanded"` are not currently
|
||||
* emitted by any platform adapter; asking for them returns
|
||||
* `AD_RESULT_ERR_INVALID_ARGS` with a diagnostic last-error rather
|
||||
* than silently answering `false`. The set will widen as adapters
|
||||
* grow support; future additions stay backwards-compatible
|
||||
* (unknown → InvalidArgs, known → deterministic answer).
|
||||
*
|
||||
* On entry `*out` is always cleared to `false` so a caller inspecting
|
||||
* the slot after an error sees a predictable sentinel, not whatever
|
||||
* was there before. If the query matches nothing, returns
|
||||
* `AD_RESULT_ERR_ELEMENT_NOT_FOUND` with `*out` still `false`.
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid. `property` must be a non-null UTF-8
|
||||
* C string. `out` must be a valid writable `*mut bool`.
|
||||
*/
|
||||
AdResult ad_is(const struct AdAdapter *adapter,
|
||||
const struct AdWindowInfo *win,
|
||||
const struct AdFindQuery *query,
|
||||
const char *property,
|
||||
bool *out);
|
||||
|
||||
/**
|
||||
* Borrowed pointer to the image bytes; valid until the buffer is freed.
|
||||
* Returns null if `buf` is null.
|
||||
*
|
||||
* # Safety
|
||||
* `buf` must be null or returned by `ad_screenshot`.
|
||||
*/
|
||||
const uint8_t *ad_image_buffer_data(const struct AdImageBuffer *buf);
|
||||
|
||||
/**
|
||||
* Byte length of the buffer returned by `ad_image_buffer_data`.
|
||||
* Always consistent with the actual allocation (no C-mutable mismatch).
|
||||
*
|
||||
* # Safety
|
||||
* `buf` must be null or returned by `ad_screenshot`.
|
||||
*/
|
||||
uint64_t ad_image_buffer_size(const struct AdImageBuffer *buf);
|
||||
|
||||
/**
|
||||
* Pixel width of the image.
|
||||
*
|
||||
* # Safety
|
||||
* `buf` must be null or returned by `ad_screenshot`.
|
||||
*/
|
||||
uint32_t ad_image_buffer_width(const struct AdImageBuffer *buf);
|
||||
|
||||
/**
|
||||
* Pixel height of the image.
|
||||
*
|
||||
* # Safety
|
||||
* `buf` must be null or returned by `ad_screenshot`.
|
||||
*/
|
||||
uint32_t ad_image_buffer_height(const struct AdImageBuffer *buf);
|
||||
|
||||
/**
|
||||
* Encoding format of the image bytes. Defaults to `PNG` on a null
|
||||
* handle — callers must still null-check.
|
||||
*
|
||||
* # Safety
|
||||
* `buf` must be null or returned by `ad_screenshot`.
|
||||
*/
|
||||
AdImageFormat ad_image_buffer_format(const struct AdImageBuffer *buf);
|
||||
|
||||
/**
|
||||
* Allocates and returns an opaque `AdImageBuffer`. The handle owns its
|
||||
* byte buffer; inspect it through `ad_image_buffer_data` /
|
||||
* `ad_image_buffer_size` / `ad_image_buffer_format` / `_width` / `_height`
|
||||
* and free it with `ad_image_buffer_free`.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` and `target` must be valid pointers. `out` must be a valid
|
||||
* writable `*mut *mut AdImageBuffer`. On error `*out` is null and
|
||||
* last-error is set.
|
||||
*/
|
||||
AdResult ad_screenshot(const struct AdAdapter *adapter,
|
||||
const struct AdScreenshotTarget *target,
|
||||
struct AdImageBuffer *out);
|
||||
struct AdImageBuffer **out);
|
||||
|
||||
/**
|
||||
* Frees the image buffer allocated by `ad_screenshot`.
|
||||
*
|
||||
* # Safety
|
||||
* `buf` must be null or a pointer previously returned by `ad_screenshot`.
|
||||
* Double-free is undefined behavior.
|
||||
*/
|
||||
void ad_image_buffer_free(struct AdImageBuffer *buf);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* `img` must be null or point to an `AdImageBuffer` from `ad_screenshot`.
|
||||
* `adapter` must be valid. `out` must be a valid writable
|
||||
* `*mut *mut AdSurfaceList`. Success produces a list handle freed via
|
||||
* `ad_surface_list_free`.
|
||||
*/
|
||||
void ad_free_image(struct AdImageBuffer *img);
|
||||
AdResult ad_list_surfaces(const struct AdAdapter *adapter, int32_t pid, struct AdSurfaceList **out);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* `adapter` must be valid. `out` and `out_count` must be writable.
|
||||
* `list` must be null or a pointer returned by `ad_list_surfaces`.
|
||||
*/
|
||||
AdResult ad_list_surfaces(const struct AdAdapter *adapter,
|
||||
int32_t pid,
|
||||
struct AdSurfaceInfo **out,
|
||||
uint32_t *out_count);
|
||||
uint32_t ad_surface_list_count(const struct AdSurfaceList *list);
|
||||
|
||||
/**
|
||||
* Borrow a surface info entry. Null if `index` is out of range.
|
||||
*
|
||||
* # Safety
|
||||
* `surfaces` must be null or from `ad_list_surfaces`.
|
||||
* `list` must be null or a pointer returned by `ad_list_surfaces`.
|
||||
*/
|
||||
void ad_free_surfaces(struct AdSurfaceInfo *surfaces, uint32_t count);
|
||||
const struct AdSurfaceInfo *ad_surface_list_get(const struct AdSurfaceList *list, uint32_t index);
|
||||
|
||||
/**
|
||||
* Frees the list and each entry's interior strings.
|
||||
*
|
||||
* # Safety
|
||||
* `list` must be null or a pointer returned by `ad_list_surfaces`.
|
||||
*/
|
||||
void ad_surface_list_free(struct AdSurfaceList *list);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
|
|
@ -461,8 +822,45 @@ void ad_free_surfaces(struct AdSurfaceInfo *surfaces, uint32_t count);
|
|||
void ad_free_tree(struct AdNodeTree *tree);
|
||||
|
||||
/**
|
||||
* Snapshots `win`'s accessibility tree into the flat BFS layout
|
||||
* described in the types module. The result is written into `*out`
|
||||
* and must be freed with `ad_free_tree`. Direct children of any node
|
||||
* live contiguously at `nodes[child_start..child_start + child_count]`.
|
||||
*
|
||||
* `opts.max_depth` caps tree depth. `opts.surface` selects which
|
||||
* surface to snapshot (window body, menu, menubar, sheet, popover,
|
||||
* alert, or focused subtree); see `AdSnapshotSurface`.
|
||||
* `opts.interactive_only` prunes non-interactive nodes; `opts.compact`
|
||||
* collapses containers with no semantic payload.
|
||||
*
|
||||
* # Raw-tree contract
|
||||
*
|
||||
* This is a **raw adapter tree**, not the snapshot the CLI `snapshot`
|
||||
* subcommand returns. Differences the caller must know about:
|
||||
*
|
||||
* - `ref_id` is always null on every `AdNode`. The FFI surface does
|
||||
* not run `ref_alloc::allocate_refs`; refs are a CLI/JSON pipeline
|
||||
* concern, so agent-facing code that needs them should drive them
|
||||
* externally (resolve via `ad_find` + `ad_free_handle`, or call the
|
||||
* CLI if refs are required).
|
||||
* - `interactive_only` and `compact` follow the adapter's semantics,
|
||||
* which may diverge in small ways from the post-processed shapes
|
||||
* the CLI emits (e.g. the compact path in the CLI also considers
|
||||
* descriptive metadata not reachable from here).
|
||||
* - No skeleton/drill-down pipeline is wired through — `skeleton` is
|
||||
* always false on the underlying `TreeOptions`.
|
||||
*
|
||||
* If parity with the CLI snapshot is important to your consumer,
|
||||
* either use `ad_find` + `ad_get` / `ad_is` for point lookups (which
|
||||
* bypass tree shape entirely) or invoke the CLI binary for the
|
||||
* snapshot call. A future revision may layer a "normalized snapshot"
|
||||
* FFI function on top of this raw path.
|
||||
*
|
||||
* On error `*out` is zeroed so `ad_free_tree` on it is a safe no-op.
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid. `out` must be writable.
|
||||
* All pointers must be non-null. `win.id` and `win.title` must be
|
||||
* valid UTF-8 C strings. `out` must be writable.
|
||||
*/
|
||||
AdResult ad_get_tree(const struct AdAdapter *adapter,
|
||||
const struct AdWindowInfo *win,
|
||||
|
|
@ -470,36 +868,79 @@ AdResult ad_get_tree(const struct AdAdapter *adapter,
|
|||
struct AdNodeTree *out);
|
||||
|
||||
/**
|
||||
* Brings `win` to the foreground on the current space. Returns
|
||||
* `AD_RESULT_ERR_WINDOW_NOT_FOUND` when the referenced window no longer
|
||||
* exists (the caller should re-list and retry).
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` and `win` must be valid pointers.
|
||||
* `adapter` must be a non-null pointer from `ad_adapter_create`. `win`
|
||||
* must be a non-null pointer to an `AdWindowInfo` whose `id` and
|
||||
* `title` fields are non-null, valid UTF-8 C strings.
|
||||
*/
|
||||
AdResult ad_focus_window(const struct AdAdapter *adapter, const struct AdWindowInfo *win);
|
||||
|
||||
/**
|
||||
* Releases the heap-allocated string fields (`id`, `title`, `app_name`)
|
||||
* inside a single `AdWindowInfo` previously written by `ad_launch_app`
|
||||
* or returned through a list accessor. Does not free the `AdWindowInfo`
|
||||
* struct itself — that memory is owned by the caller's stack or by the
|
||||
* enclosing list.
|
||||
*
|
||||
* Named `ad_release_window_fields` (not `ad_free_window`) to disambiguate
|
||||
* from the now-removed list-free function and make the semantics clear
|
||||
* in the header.
|
||||
*
|
||||
* # Safety
|
||||
* `win` must be null or point to a valid `AdWindowInfo`.
|
||||
* `win` must be null or point to a valid `AdWindowInfo` whose string
|
||||
* fields were allocated by this crate. Do not call on pointers inside
|
||||
* an `AdWindowList` — free the list instead.
|
||||
*/
|
||||
void ad_free_window(struct AdWindowInfo *win);
|
||||
void ad_release_window_fields(struct AdWindowInfo *win);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* `adapter` must be valid. `out` and `out_count` must be writable.
|
||||
* `adapter` must be valid. `out` must be a valid writable
|
||||
* `*mut *mut AdWindowList`. `app_filter` may be null or a C string.
|
||||
* Success produces a list handle freed via `ad_window_list_free`.
|
||||
*/
|
||||
AdResult ad_list_windows(const struct AdAdapter *adapter,
|
||||
const char *app_filter,
|
||||
bool focused_only,
|
||||
struct AdWindowInfo **out,
|
||||
uint32_t *out_count);
|
||||
struct AdWindowList **out);
|
||||
|
||||
/**
|
||||
* # Safety
|
||||
* `windows` must be null or from `ad_list_windows`.
|
||||
* `list` must be null or a pointer returned by `ad_list_windows`.
|
||||
*/
|
||||
void ad_free_windows(struct AdWindowInfo *windows, uint32_t count);
|
||||
uint32_t ad_window_list_count(const struct AdWindowList *list);
|
||||
|
||||
/**
|
||||
* Borrow a window info entry. Null if `index` is out of range.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` and `win` must be valid pointers.
|
||||
* `list` must be null or a pointer returned by `ad_list_windows`.
|
||||
*/
|
||||
const struct AdWindowInfo *ad_window_list_get(const struct AdWindowList *list, uint32_t index);
|
||||
|
||||
/**
|
||||
* Frees the list and each entry's interior strings.
|
||||
*
|
||||
* # Safety
|
||||
* `list` must be null or a pointer returned by `ad_list_windows`.
|
||||
*/
|
||||
void ad_window_list_free(struct AdWindowList *list);
|
||||
|
||||
/**
|
||||
* Performs a window-manager operation (`Resize`, `Move`, `Minimize`,
|
||||
* `Maximize`, `Restore`) on `win`. Width / height / x / y are consulted
|
||||
* only for the variants that use them; other kinds ignore them.
|
||||
*
|
||||
* An invalid `op.kind` discriminant is rejected with
|
||||
* `AD_RESULT_ERR_INVALID_ARGS` before any adapter call.
|
||||
*
|
||||
* # Safety
|
||||
* `adapter` and `win` must be non-null pointers. `win.id` and
|
||||
* `win.title` must be non-null valid UTF-8 C strings.
|
||||
*/
|
||||
AdResult ad_window_op(const struct AdAdapter *adapter,
|
||||
const struct AdWindowInfo *win,
|
||||
|
|
|
|||
Loading…
Reference in a new issue