pub struct Computer<B: Backend> { /* private fields */ }Expand description
A computer-use session over a Backend.
Observe an app with get_app_state, then act on it by element index or by
screenshot pixel. It remembers the latest state per app so indexes stay valid until the
next capture of that app.
use computer_use::{CaptureOptions, ClickOptions, ClickTarget, Computer};
let mut computer = Computer::new()?;
let state = computer.get_app_state("TextEdit", &CaptureOptions::default())?;
println!("{}", state.render());
computer.click("TextEdit", ClickTarget::Element(3), ClickOptions::default())?;
computer.type_text("TextEdit", "Hello from Rust")?;
computer.press_key("TextEdit", "super+s")?;Implementations§
Source§impl Computer<NativeBackend>
impl Computer<NativeBackend>
Sourcepub fn new() -> Result<Self>
Available on Linux or macOS or Windows only.
pub fn new() -> Result<Self>
Creates a session over this platform’s native backend.
§Errors
Fails if the platform’s accessibility stack cannot be initialized.
Examples found in repository?
6fn main() -> computer_use::Result<()> {
7 let computer = computer_use::Computer::new()?;
8 for app in computer.list_apps()? {
9 let status = match (app.is_running, app.is_active, app.needs_restart) {
10 (true, _, true) => "restart",
11 (true, true, _) => "active",
12 (true, false, _) => "running",
13 _ => "installed",
14 };
15 let pid = app.pid.map(|p| format!(" pid {p}")).unwrap_or_default();
16 println!("{:<9} {} [{}]{pid}", status, app.name, app.reference());
17 }
18 Ok(())
19}More examples
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}11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}Source§impl<B: Backend> Computer<B>
impl<B: Backend> Computer<B>
Sourcepub fn with_backend(backend: B) -> Self
pub fn with_backend(backend: B) -> Self
Creates a session over a custom backend.
Sourcepub const fn delivery(self, delivery: Delivery) -> Self
pub const fn delivery(self, delivery: Delivery) -> Self
Sets the default input delivery for synthesized events.
Sourcepub const fn settle_delay(self, delay: Duration) -> Self
pub const fn settle_delay(self, delay: Duration) -> Self
Sleeps this long after every action so the UI can settle before the next capture.
Examples found in repository?
11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}Sourcepub fn permissions(&self) -> Permissions
pub fn permissions(&self) -> Permissions
Permissions currently held by this process.
Examples found in repository?
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}Sourcepub fn request_permissions(&self) -> Permissions
pub fn request_permissions(&self) -> Permissions
Prompts for missing permissions where the OS supports it.
Sourcepub fn list_apps(&self) -> Result<Vec<AppInfo>>
pub fn list_apps(&self) -> Result<Vec<AppInfo>>
Lists running apps first (frontmost first), then installed apps, by name.
§Errors
Fails if the platform cannot enumerate apps.
Examples found in repository?
6fn main() -> computer_use::Result<()> {
7 let computer = computer_use::Computer::new()?;
8 for app in computer.list_apps()? {
9 let status = match (app.is_running, app.is_active, app.needs_restart) {
10 (true, _, true) => "restart",
11 (true, true, _) => "active",
12 (true, false, _) => "running",
13 _ => "installed",
14 };
15 let pid = app.pid.map(|p| format!(" pid {p}")).unwrap_or_default();
16 println!("{:<9} {} [{}]{pid}", status, app.name, app.reference());
17 }
18 Ok(())
19}Sourcepub fn resolve_app(&self, query: &str) -> Result<AppInfo>
pub fn resolve_app(&self, query: &str) -> Result<AppInfo>
Resolves an app query (name, bundle ID, path, or pid:<n>), preferring running apps.
§Errors
Returns Error::AppNotFound when nothing matches, or Error::AmbiguousApp when several
running apps match equally well.
Sourcepub fn get_app_state(
&mut self,
app: &str,
options: &CaptureOptions,
) -> Result<&AppState>
pub fn get_app_state( &mut self, app: &str, options: &CaptureOptions, ) -> Result<&AppState>
Captures the app’s current window, replacing any earlier state (and element indexes) for that app.
§Errors
Fails if the app cannot be found or launched, has no window, or permissions are missing.
Examples found in repository?
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}More examples
11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}Sourcepub fn list_windows(&self, app: &str) -> Result<Vec<WindowInfo>>
pub fn list_windows(&self, app: &str) -> Result<Vec<WindowInfo>>
The app’s windows, front to back where the platform knows the order. Pass one to
CaptureOptions::window to capture it instead of the focused or main window.
§Errors
Fails if the app is not running or the backend cannot list windows.
Sourcepub fn state(&self, app: &str) -> Option<&AppState>
pub fn state(&self, app: &str) -> Option<&AppState>
The latest captured state of an app, if any.
Sourcepub fn query(
&mut self,
app: &str,
query: &ElementQuery,
max_nodes: usize,
) -> Result<Vec<Element>>
pub fn query( &mut self, app: &str, query: &ElementQuery, max_nodes: usize, ) -> Result<Vec<Element>>
Finds elements in the app’s current window without taking a screenshot.
The fresh tree replaces the app’s remembered state, so the returned indexes can be used with element actions. A previous screenshot is kept when the window has not moved.
§Errors
Fails like get_app_state or if the query is empty.
Sourcepub fn click(
&mut self,
app: &str,
target: ClickTarget,
options: ClickOptions,
) -> Result<ClickOutcome>
pub fn click( &mut self, app: &str, target: ClickTarget, options: ClickOptions, ) -> Result<ClickOutcome>
Clicks an element, a screenshot pixel, or a screen point.
§Errors
Fails if there is no state for the app, the target is invalid, or delivery fails.
Examples found in repository?
11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}Sourcepub fn perform_secondary_action(
&mut self,
app: &str,
index: usize,
action: &str,
) -> Result<()>
pub fn perform_secondary_action( &mut self, app: &str, index: usize, action: &str, ) -> Result<()>
Invokes a named accessibility action on an element (e.g. Show Menu, AXRaise).
§Errors
Fails if the element does not expose the action.
Sourcepub fn scroll(
&mut self,
app: &str,
index: usize,
direction: ScrollDirection,
pages: f64,
) -> Result<()>
pub fn scroll( &mut self, app: &str, index: usize, direction: ScrollDirection, pages: f64, ) -> Result<()>
Scrolls an element by a number of pages (fractions allowed).
Whole pages use the element’s own scroll-by-page action when it has one; otherwise wheel events are posted at the element’s center.
§Errors
Fails if pages is not positive or the element has no frame.
Sourcepub fn scroll_at(
&mut self,
app: &str,
target: ClickTarget,
direction: ScrollDirection,
pages: f64,
) -> Result<()>
pub fn scroll_at( &mut self, app: &str, target: ClickTarget, direction: ScrollDirection, pages: f64, ) -> Result<()>
Scrolls at an element, a screenshot pixel, or a screen point, by a number of pages (fractions allowed).
An element target behaves like scroll. For a point, wheel events are
posted there; a page is 80% of the scroll area under the point when the latest state
has one, else of the captured window, else 400 points.
§Errors
Fails if pages is not positive, a pixel lies outside the screenshot, or delivery fails.
Sourcepub fn drag(
&mut self,
app: &str,
from: (f64, f64),
to: (f64, f64),
) -> Result<()>
pub fn drag( &mut self, app: &str, from: (f64, f64), to: (f64, f64), ) -> Result<()>
Drags between two screenshot pixels.
§Errors
Fails if there is no screenshot or a point lies outside it.
Sourcepub fn drag_screen(&mut self, app: &str, from: Point, to: Point) -> Result<()>
pub fn drag_screen(&mut self, app: &str, from: Point, to: Point) -> Result<()>
Drags between two screen points. Needs no earlier capture.
§Errors
Fails if the app is not running or delivery fails.
Sourcepub fn type_text(&mut self, app: &str, text: &str) -> Result<()>
pub fn type_text(&mut self, app: &str, text: &str) -> Result<()>
Types literal text into the app’s focused element.
With background delivery, text is inserted through accessibility when the focused element supports it, and synthesized as keystrokes otherwise.
§Errors
Fails if the app is not running or delivery fails.
Examples found in repository?
11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}Sourcepub fn press_key(&mut self, app: &str, key: &str) -> Result<()>
pub fn press_key(&mut self, app: &str, key: &str) -> Result<()>
Presses a key chord in xdotool syntax, e.g. Return, super+c, KP_0.
§Errors
Fails if the chord cannot be parsed or delivered.
Examples found in repository?
11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}Sourcepub fn set_value(&mut self, app: &str, index: usize, value: &str) -> Result<()>
pub fn set_value(&mut self, app: &str, index: usize, value: &str) -> Result<()>
Examples found in repository?
11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}Sourcepub fn select_text(
&mut self,
app: &str,
index: usize,
selection: &TextSelection,
) -> Result<()>
pub fn select_text( &mut self, app: &str, index: usize, selection: &TextSelection, ) -> Result<()>
Selects text inside a text element, or places the caret before or after it.
§Errors
Fails if the text is missing or ambiguous, or the element does not support selection.
Examples found in repository?
11fn main() -> computer_use::Result<()> {
12 use std::time::Duration;
13
14 use computer_use::{
15 CaptureOptions, ClickMethod, ClickOptions, ClickTarget, Computer, ElementQuery, Error, TextSelection,
16 };
17
18 const APP: &str = "TextEdit";
19 let mut computer = Computer::new()?.settle_delay(Duration::from_millis(300));
20 let tree_only = CaptureOptions::default().include_screenshot(false);
21
22 let state = computer.get_app_state(APP, &tree_only)?;
23 let new_doc = state.find(&ElementQuery::text("New Document").with_role("button").exact(true)).next();
24 if let Some(button) = new_doc.map(|e| e.index) {
25 println!(
26 "click New Document: {:?}",
27 computer.click(APP, ClickTarget::Element(button), ClickOptions::default())?
28 );
29 }
30
31 let state = computer.get_app_state(APP, &tree_only)?;
32 let text_area = state
33 .find(&ElementQuery::role("AXTextArea"))
34 .next()
35 .map(|e| e.index)
36 .ok_or_else(|| Error::StateUnavailable("no text area".into()))?;
37 println!(
38 "click text area {text_area}: {:?}",
39 computer.click(APP, ClickTarget::Element(text_area), ClickOptions::default())?
40 );
41 computer.set_value(APP, text_area, "")?;
42 computer.type_text(APP, "Hello from computer-use-rs!\nSecond line.")?;
43
44 let state = computer.get_app_state(APP, &tree_only)?;
45 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
46 println!("text area now contains: {value:?}");
47
48 computer.select_text(APP, text_area, &TextSelection::new("computer-use-rs"))?;
49 let state = computer.get_app_state(APP, &tree_only)?;
50 println!("selected text: {:?}", state.selected_text);
51
52 computer.press_key(APP, "BackSpace")?;
53 let state = computer.get_app_state(APP, &tree_only)?;
54 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
55 println!("after BackSpace: {value:?}");
56
57 computer.press_key(APP, "super+a")?;
58 let state = computer.get_app_state(APP, &tree_only)?;
59 println!("after super+a, selected: {:?}", state.selected_text);
60
61 let focused = ClickOptions::default().method(ClickMethod::FocusedBackground);
62 println!("focused click: {:?}", computer.click(APP, ClickTarget::Element(text_area), focused)?);
63 computer.type_text(APP, " The end.")?;
64 let state = computer.get_app_state(APP, &tree_only)?;
65 let value = state.find(&ElementQuery::role("AXTextArea")).next().and_then(|e| e.value.clone());
66 println!("final text: {value:?}");
67
68 Ok(())
69}