xa11y_core/provider.rs
1use crate::element::ElementData;
2use crate::error::{Error, Result};
3use crate::event_provider::Subscription;
4use crate::selector::{matches_simple, Combinator, Selector, SelectorGroup, SelectorSegment};
5use crate::shell::ShellSurfaceKind;
6
7/// Platform backend trait for accessibility tree access.
8///
9/// Providers implement lazy, on-demand tree navigation. Elements are identified
10/// by their [`ElementData`] (which contains a provider-specific `handle` for
11/// looking up the underlying platform object).
12///
13/// # Action model
14///
15/// Common actions are first-class methods with proper typed signatures.
16/// Platform-specific or custom actions use [`perform_action`](Self::perform_action)
17/// as an escape hatch — it takes a `snake_case` action name string.
18///
19/// Providers should check platform permissions in their constructor (`new()`)
20/// and return [`Error::PermissionDenied`](crate::Error::PermissionDenied) if
21/// required permissions are not granted.
22pub trait Provider: Send + Sync {
23 // ── Tree navigation ─────────────────────────────────────────────
24
25 /// Get direct children of an element.
26 ///
27 /// If `element` is `None`, returns top-level application elements.
28 fn get_children(&self, element: Option<&ElementData>) -> Result<Vec<ElementData>>;
29
30 /// Get the parent of an element.
31 ///
32 /// Returns `None` for top-level (application) elements.
33 fn get_parent(&self, element: &ElementData) -> Result<Option<ElementData>>;
34
35 /// Enumerate top-level applications visible to this provider.
36 ///
37 /// Backends return one `ElementData` per application, always with
38 /// `role=Application` as the **enumeration** contract. The direct-attach
39 /// path ([`app_by_pid`](Self::app_by_pid)) is the one exception: macOS
40 /// deliberately preserves `Role::Unknown` for a process that exposes no
41 /// AX application (Window Server), so that `windows()` fails honestly
42 /// instead of pretending the process has no windows. Windows synthesizes
43 /// one Application node per
44 /// process (UIA exposes applications as their top-level windows; the
45 /// provider groups them by pid — and calls the process's first window the
46 /// node's representative — see `xa11y-windows`). AT-SPI can return several
47 /// native registrations sharing a pid; the core collapses those into one
48 /// public `App` and uses [`app_roots`](Self::app_roots) for process-wide
49 /// traversal. The application's top-level
50 /// windows are its `get_children` results, so `App::windows` is the same
51 /// `get_children` + `Window|Dialog` filter on every platform.
52 /// This is the dedicated discovery primitive: it replaces the previous
53 /// `find_elements(None, application_selector, .., depth=0)` idiom and
54 /// lets each backend batch the platform-specific enumeration (CGWindowList
55 /// on macOS, the AT-SPI registry on Linux, UIA's desktop root on Windows)
56 /// in one place.
57 ///
58 /// Required: every `Provider` implements this explicitly. There's no
59 /// default impl — discovery and subtree search have different cost
60 /// profiles, and silently routing app discovery through `get_children`
61 /// would hide the difference from implementors.
62 fn list_apps(&self) -> Result<Vec<ElementData>>;
63
64 /// Whether [`list_apps`](Self::list_apps) can expose more than one
65 /// `Application` entry for a single process id.
66 ///
67 /// Only the AT-SPI backend can (a per-process entry plus per-event-loop
68 /// pieces such as a tray or a tooltip context); macOS and Windows
69 /// guarantee one entry per pid. When `false`, [`App::windows_with`]
70 /// skips the same-pid merge — and the full `list_apps` re-enumeration it
71 /// requires — because the calling entry's descendants already cover the
72 /// process, so no cross-entry merge can add anything.
73 ///
74 /// Defaults to `false`. A provider that overrides this with `true` must
75 /// answer `get_children` per same-pid entry and give each entry (and its
76 /// windows) a stable identity durable across `list_apps` calls, since
77 /// the merge deduplicates by that identity.
78 fn splits_app_across_entries(&self) -> bool {
79 false
80 }
81
82 /// Return every native application root that belongs to the same process
83 /// as `app`.
84 ///
85 /// Most accessibility APIs expose exactly one root per process, so the
86 /// default is the supplied root. AT-SPI providers override this because a
87 /// process may register several independent roots.
88 fn app_roots(&self, app: &ElementData) -> Result<Vec<ElementData>> {
89 Ok(vec![app.clone()])
90 }
91
92 /// Find the application owning process `pid` — one attempt, no polling.
93 ///
94 /// This is the single-shot discovery primitive behind `App::by_pid`; the
95 /// core's lookup loop owns the retry/timeout policy. Returns
96 /// [`Error::SelectorNotMatched`] when no accessible application for `pid`
97 /// exists *yet* — the signal the poll loop retries on — and any other
98 /// error when the lookup itself failed (permissions, platform API
99 /// failure), which short-circuits the poll.
100 ///
101 /// The default implementation filters [`list_apps`](Self::list_apps) by
102 /// `pid`, and its not-matched error carries enumeration diagnostics (how
103 /// many apps were visible and how many had no resolvable pid) so a
104 /// timeout on an opaque CI runner says *why* the app was invisible.
105 /// Backends override this where the platform supports reaching a process
106 /// directly (`AXUIElementCreateApplication` on macOS, a UIA `ProcessId`
107 /// property search on Windows): direct attach is immune to enumeration
108 /// blind spots such as top-level windows that are still unnamed while the
109 /// app starts up.
110 fn app_by_pid(&self, pid: u32) -> Result<ElementData> {
111 let apps = self.list_apps()?;
112 let total = apps.len();
113 let unresolved = apps.iter().filter(|a| a.pid.is_none()).count();
114 if let Some(data) = apps.into_iter().find(|a| a.pid == Some(pid)) {
115 return Ok(data);
116 }
117 // The enumeration counts are structured diagnosis fields (tenet 6),
118 // not prose baked into the selector — bindings expose them as
119 // attributes, and `App::by_pid_with` merges in the full candidate
120 // list at its terminal failure site. Cheap to build (two counters),
121 // so attaching it per poll tick is fine.
122 Err(
123 Error::selector_not_matched(format!("application[pid={pid}]")).diagnose(
124 crate::error::Diagnosis {
125 last_observed: Some(format!(
126 "enumerated {total} running apps, {unresolved} without a resolvable pid"
127 )),
128 ..Default::default()
129 },
130 ),
131 )
132 }
133
134 /// Identify the application that currently holds the system foreground /
135 /// input focus — one attempt, no polling.
136 ///
137 /// Each backend uses its platform's canonical foreground mechanism: the
138 /// system-wide `AXUIElement`'s focused-application attribute (macOS),
139 /// `GetForegroundWindow` + `ElementFromHandle` (Windows), and the focused
140 /// element's `Application` ancestor in the AT-SPI registry (Linux). The
141 /// returned `ElementData` has the same shape [`list_apps`](Self::list_apps)
142 /// produces for that app — in particular its `pid` lines up — so the core
143 /// can tag the foreground entry within an enumeration by pid.
144 ///
145 /// Returns [`Error::SelectorNotMatched`] when no application currently
146 /// holds focus (e.g. focus rests on the desktop / shell, or the screen is
147 /// locked). That is a legitimate state, not a failure: the core treats it
148 /// as "nothing is foreground" — every listed app stays untagged — rather
149 /// than surfacing an error. Any other error (permission, platform API
150 /// failure) is a real failure and propagates.
151 ///
152 /// Required: every `Provider` implements this explicitly. Like
153 /// [`list_apps`](Self::list_apps) there is no default impl — there is no
154 /// portable way to derive the foreground app, so a silent no-op default
155 /// would hide an unimplemented backend (tenet 1).
156 fn focused_app(&self) -> Result<ElementData>;
157
158 /// Enumerate OS shell surfaces — taskbars, panels, docks, menu bars,
159 /// status items, the desktop, and any transient shell flyout currently
160 /// open. One entry per surface, each a real platform element usable as a
161 /// search root.
162 ///
163 /// The listing is live: transient surfaces
164 /// ([`ShellSurfaceKind::Flyout`]) appear only while they are on screen,
165 /// and enumerating NEVER opens, closes, or presses anything. Required —
166 /// no default impl, for the same reason [`list_apps`](Self::list_apps)
167 /// has none: enumeration is platform-specific, and a silent empty default
168 /// would hide an unimplemented backend (tenet 1).
169 ///
170 /// The kind is part of the primitive's contract, so it travels in the
171 /// signature where the compiler sees it rather than being smuggled
172 /// through `raw`. Backends return the platform root untouched;
173 /// `ShellSurface::list_with` additionally stamps `raw["shell_kind"]` on
174 /// the surface root, in one place, so a consumer holding only an
175 /// [`Element`](crate::Element) can read the kind back. That stamp is a
176 /// readback, not a selector: it is on the root alone, a rooted locator
177 /// only emits descendants of its root, and `TreeNode` carries no `raw`.
178 fn list_shell_surfaces(&self) -> Result<Vec<(ShellSurfaceKind, ElementData)>>;
179
180 /// Search for elements matching a selector.
181 ///
182 /// The selector is already parsed by the core — providers match against it
183 /// during traversal and can prune subtrees that can't match.
184 ///
185 /// `root` is the subtree root to search under (always present; use
186 /// [`list_apps`](Self::list_apps) to discover application roots first).
187 /// If `limit` is `Some(n)`, stops after finding `n` matches.
188 /// If `max_depth` is `Some(d)`, does not descend deeper than `d` levels.
189 ///
190 /// This is a thin convenience wrapper that re-uses
191 /// [`find_elements_group`](Self::find_elements_group) with a single-clause
192 /// group. Backends do **not** override this method — they override
193 /// `find_elements_group`, and the single-clause case runs through the
194 /// same native code path as multi-clause queries.
195 fn find_elements(
196 &self,
197 root: &ElementData,
198 selector: &Selector,
199 limit: Option<usize>,
200 max_depth: Option<u32>,
201 ) -> Result<Vec<ElementData>> {
202 let group = SelectorGroup {
203 clauses: vec![selector.clone()],
204 };
205 self.find_elements_group(root, &group, limit, max_depth)
206 }
207
208 /// Search for elements matching any clause of a comma-separated selector
209 /// group, scoped to `root`'s subtree.
210 ///
211 /// This is the **primary search primitive** each backend should override.
212 /// A native implementation performs ONE platform-level subtree query/walk
213 /// (e.g. `FindAllBuildCache(TreeScope_Subtree)` on Windows, one DFS over
214 /// AT-SPI children on Linux, one AX walk on macOS) and evaluates every
215 /// clause inline against each visited element. This avoids the
216 /// per-clause-walk perf cliff and also keeps the cross-clause dedup
217 /// correct: because everything happens inside one call, each platform
218 /// node is visited once and platform identity is stable.
219 ///
220 /// `root` is non-optional: app discovery now goes through
221 /// [`list_apps`](Self::list_apps) and any rootless multi-app search is
222 /// performed by the caller (e.g. `Locator`) by enumerating apps and
223 /// invoking this method per app.
224 ///
225 /// The default implementation traverses via [`get_children`](Self::get_children)
226 /// and uses tree-path identity for cross-clause merging. It's the
227 /// fallback for backends that haven't shipped a native override yet —
228 /// the same path the test/mock provider exercises.
229 fn find_elements_group(
230 &self,
231 root: &ElementData,
232 group: &SelectorGroup,
233 limit: Option<usize>,
234 max_depth: Option<u32>,
235 ) -> Result<Vec<ElementData>> {
236 crate::selector::find_elements_in_tree_group(
237 |el| self.get_children(el),
238 Some(root),
239 group,
240 limit,
241 max_depth,
242 )
243 }
244
245 /// Narrow candidates through remaining selector segments (Child/Descendant
246 /// combinators), deduplicate, apply final :nth and limit.
247 fn narrow_multi_segment(
248 &self,
249 mut candidates: Vec<ElementData>,
250 segments: &[SelectorSegment],
251 max_depth: u32,
252 limit: Option<usize>,
253 ) -> Result<Vec<ElementData>> {
254 for segment in segments {
255 let mut next_candidates = Vec::new();
256 for candidate in &candidates {
257 match segment.combinator {
258 Combinator::Child => {
259 let children = self.get_children(Some(candidate))?;
260 for child in children {
261 if matches_simple(&child, &segment.simple) {
262 next_candidates.push(child);
263 }
264 }
265 }
266 Combinator::Descendant => {
267 let sub_selector = Selector {
268 segments: vec![SelectorSegment {
269 combinator: Combinator::Root,
270 simple: segment.simple.clone(),
271 }],
272 };
273 let mut sub_results =
274 self.find_elements(candidate, &sub_selector, None, Some(max_depth))?;
275 next_candidates.append(&mut sub_results);
276 }
277 Combinator::Root => unreachable!(),
278 }
279 }
280 let mut seen = std::collections::HashSet::new();
281 next_candidates.retain(|e| seen.insert(e.handle));
282 candidates = next_candidates;
283 }
284
285 // Apply :nth on last segment
286 if let Some(nth) = segments.last().and_then(|s| s.simple.nth) {
287 if nth <= candidates.len() {
288 candidates = vec![candidates.remove(nth - 1)];
289 } else {
290 candidates.clear();
291 }
292 }
293
294 if let Some(limit) = limit {
295 candidates.truncate(limit);
296 }
297
298 Ok(candidates)
299 }
300
301 // ── Common actions ──────────────────────────────────────────────
302
303 /// Click / tap / invoke the element.
304 fn press(&self, element: &ElementData) -> Result<()>;
305
306 /// Set keyboard focus to the element.
307 fn focus(&self, element: &ElementData) -> Result<()>;
308
309 /// Remove keyboard focus from the element.
310 fn blur(&self, element: &ElementData) -> Result<()>;
311
312 /// Toggle a checkbox or switch.
313 fn toggle(&self, element: &ElementData) -> Result<()>;
314
315 /// Select an item in a list, tab group, or menu.
316 fn select(&self, element: &ElementData) -> Result<()>;
317
318 /// Expand a collapsible element (combo box, tree item, disclosure).
319 fn expand(&self, element: &ElementData) -> Result<()>;
320
321 /// Collapse an expanded element.
322 fn collapse(&self, element: &ElementData) -> Result<()>;
323
324 /// Show the element's context menu or dropdown.
325 fn show_menu(&self, element: &ElementData) -> Result<()>;
326
327 /// Increment a slider or spinner by one step.
328 fn increment(&self, element: &ElementData) -> Result<()>;
329
330 /// Decrement a slider or spinner by one step.
331 fn decrement(&self, element: &ElementData) -> Result<()>;
332
333 /// Scroll the element into the visible area.
334 fn scroll_into_view(&self, element: &ElementData) -> Result<()>;
335
336 // ── Typed operations ────────────────────────────────────────────
337
338 /// Set the text value of the element.
339 fn set_value(&self, element: &ElementData, value: &str) -> Result<()>;
340
341 /// Set the numeric value of the element (slider, spinner).
342 fn set_numeric_value(&self, element: &ElementData, value: f64) -> Result<()>;
343
344 /// Insert text at the current cursor position.
345 fn type_text(&self, element: &ElementData, text: &str) -> Result<()>;
346
347 /// Select a text range (0-based character offsets).
348 fn set_text_selection(&self, element: &ElementData, start: u32, end: u32) -> Result<()>;
349
350 // ── Generic action escape hatch ─────────────────────────────────
351
352 /// Perform an action by `snake_case` name.
353 ///
354 /// This is the escape hatch for platform-specific actions not covered by
355 /// the first-class methods above. The provider converts the name to the
356 /// platform's convention (e.g. `"custom_thing"` → `"AXCustomThing"` on
357 /// macOS) and invokes it.
358 ///
359 /// Well-known action names (`"press"`, `"focus"`, etc.) should also work
360 /// here — providers should delegate to the corresponding method.
361 fn perform_action(&self, element: &ElementData, action: &str) -> Result<()>;
362
363 // ── Window management ──────────────────────────────────────────
364
365 /// The windows of an application are the `get_children` results of its
366 /// Application element filtered to `Role::Window | Role::Dialog`.
367 /// `App::windows` is that filter; no provider exposes its own
368 /// window-discovery path anymore, because macOS and Windows report one
369 /// Application node per process whose top-level windows are its children
370 /// (Windows synthesizes that Application node and answers
371 /// `get_children(Some(app))` from a process-wide UIA query; see
372 /// `xa11y-windows`).
373 ///
374 /// Linux refines the contract: an app may register several AT-SPI
375 /// Application entries (per-process instance plus per-event-loop pieces
376 /// such as a tray or the GTK IM context), so `App::windows_with` starts
377 /// from this entry's filtered children, then merges the filtered children
378 /// of every same-pid Application entry and deduplicates by stable id (see
379 /// `same_window_identity`). The result is process-complete rather than a
380 /// strict direct-children filter, and merged windows are not this node's
381 /// children, so no single z-order spans them. Providers that split an app
382 /// across entries must answer `get_children` per entry; the merge is
383 /// core's job.
384 ///
385 /// The filter lives in `App::windows_with`, so adding a provider never
386 /// requires an implementation here; `get_children` is the single
387 /// window-discovery primitive on every platform.
388 ///
389 /// Activate the window: bring it to the foreground and give it focus.
390 ///
391 /// Window verbs may use the platform accessibility API or a native
392 /// window-manager protocol. A native provider must establish a durable
393 /// association from this accessibility element to exactly one native
394 /// window before it mutates state; process lifetime, destroyed/reused
395 /// identifiers, and same-process ambiguity are errors rather than guesses.
396 /// Titles are never sufficient identity by themselves.
397 ///
398 /// Unless a backend documents a stronger postcondition, success means the
399 /// semantic platform request was accepted for delivery. Window managers
400 /// commonly apply it asynchronously; consumers can re-read the element's
401 /// tri-state window flags or bounds to observe completion. Unsupported
402 /// capabilities and refused requests must remain distinct errors, and a
403 /// backend must never substitute simulated input.
404 ///
405 /// Required: every `Provider` implements this explicitly. There is no
406 /// portable default — each platform's activation mechanism is unique
407 /// (AXRaise on macOS, `SetForegroundWindow` on Windows, GrabFocus on
408 /// Linux), and a silent no-op default would hide an unimplemented
409 /// backend (tenet 1).
410 fn activate(&self, element: &ElementData) -> Result<()>;
411
412 /// Minimize the window.
413 fn minimize(&self, element: &ElementData) -> Result<()>;
414
415 /// Maximize the window.
416 ///
417 /// Distinct from [`Self::enter_fullscreen`]: maximizing leaves the window
418 /// in its platform's maximized state (the macOS zoom equivalent, Windows
419 /// `WindowVisualState_Maximized`) while fullscreen is the native
420 /// fullscreen state. A platform without the operation fails surfaceably
421 /// rather than substituting the other.
422 fn maximize(&self, element: &ElementData) -> Result<()>;
423
424 /// Put the window in native fullscreen.
425 ///
426 /// Distinct from [`Self::maximize`]: fullscreen is the platform's native
427 /// fullscreen state (macOS `AXFullScreen`), not a maximized window.
428 /// [`Self::restore`] clears it. A platform without an accessibility API
429 /// for fullscreen fails surfaceably.
430 fn enter_fullscreen(&self, element: &ElementData) -> Result<()>;
431
432 /// Restore the window to its normal state (from minimized/maximized/fullscreen).
433 fn restore(&self, element: &ElementData) -> Result<()>;
434
435 /// Close the window.
436 fn close(&self, element: &ElementData) -> Result<()>;
437
438 /// Move the window in the coordinates of [`ElementData::bounds`]
439 /// (physical pixels on Windows, logical points elsewhere).
440 fn move_to(&self, element: &ElementData, x: i32, y: i32) -> Result<()>;
441
442 /// Resize the window in the units of [`ElementData::bounds`].
443 fn resize_to(&self, element: &ElementData, width: u32, height: u32) -> Result<()>;
444
445 // ── Events ──────────────────────────────────────────────────────
446
447 /// Subscribe to all accessibility events for an application.
448 ///
449 /// The element should be an application-level element (role=Application).
450 /// The provider extracts the PID from `element.pid`.
451 ///
452 /// Returns a [`Subscription`] that receives events until dropped.
453 fn subscribe(&self, element: &ElementData) -> Result<Subscription>;
454}
455
456// Blanket impl so shared references to a provider act as providers themselves.
457// Used by the umbrella crate's singleton (a `&'static dyn Provider` wrapped in
458// `Arc<_>`) and by any caller that wants to share a provider via `&T`. The
459// orphan rules keep this collision-free for downstream crates because `xa11y-core`
460// owns the `Provider` trait.
461impl<T: Provider + ?Sized> Provider for &T {
462 fn get_children(&self, element: Option<&ElementData>) -> Result<Vec<ElementData>> {
463 (**self).get_children(element)
464 }
465 fn get_parent(&self, element: &ElementData) -> Result<Option<ElementData>> {
466 (**self).get_parent(element)
467 }
468 fn list_apps(&self) -> Result<Vec<ElementData>> {
469 (**self).list_apps()
470 }
471 // Delegated explicitly (despite having a default impl) so a concrete
472 // provider's override isn't bypassed when it's used through a shared
473 // reference — the default body on `&T` would re-route and silently
474 // answer `false` for a Linux provider passed by reference.
475 fn splits_app_across_entries(&self) -> bool {
476 (**self).splits_app_across_entries()
477 }
478 fn app_roots(&self, app: &ElementData) -> Result<Vec<ElementData>> {
479 (**self).app_roots(app)
480 }
481 // Delegated explicitly (despite having a default impl) so a concrete
482 // provider's PID-direct override isn't bypassed when it's used through a
483 // shared reference — the default body on `&T` would re-route through
484 // `list_apps` and silently lose the override.
485 fn app_by_pid(&self, pid: u32) -> Result<ElementData> {
486 (**self).app_by_pid(pid)
487 }
488 fn focused_app(&self) -> Result<ElementData> {
489 (**self).focused_app()
490 }
491 fn list_shell_surfaces(&self) -> Result<Vec<(ShellSurfaceKind, ElementData)>> {
492 (**self).list_shell_surfaces()
493 }
494 fn find_elements(
495 &self,
496 root: &ElementData,
497 selector: &Selector,
498 limit: Option<usize>,
499 max_depth: Option<u32>,
500 ) -> Result<Vec<ElementData>> {
501 (**self).find_elements(root, selector, limit, max_depth)
502 }
503 fn find_elements_group(
504 &self,
505 root: &ElementData,
506 group: &SelectorGroup,
507 limit: Option<usize>,
508 max_depth: Option<u32>,
509 ) -> Result<Vec<ElementData>> {
510 (**self).find_elements_group(root, group, limit, max_depth)
511 }
512 fn narrow_multi_segment(
513 &self,
514 candidates: Vec<ElementData>,
515 segments: &[SelectorSegment],
516 max_depth: u32,
517 limit: Option<usize>,
518 ) -> Result<Vec<ElementData>> {
519 (**self).narrow_multi_segment(candidates, segments, max_depth, limit)
520 }
521 fn press(&self, element: &ElementData) -> Result<()> {
522 (**self).press(element)
523 }
524 fn focus(&self, element: &ElementData) -> Result<()> {
525 (**self).focus(element)
526 }
527 fn blur(&self, element: &ElementData) -> Result<()> {
528 (**self).blur(element)
529 }
530 fn toggle(&self, element: &ElementData) -> Result<()> {
531 (**self).toggle(element)
532 }
533 fn select(&self, element: &ElementData) -> Result<()> {
534 (**self).select(element)
535 }
536 fn expand(&self, element: &ElementData) -> Result<()> {
537 (**self).expand(element)
538 }
539 fn collapse(&self, element: &ElementData) -> Result<()> {
540 (**self).collapse(element)
541 }
542 fn show_menu(&self, element: &ElementData) -> Result<()> {
543 (**self).show_menu(element)
544 }
545 fn increment(&self, element: &ElementData) -> Result<()> {
546 (**self).increment(element)
547 }
548 fn decrement(&self, element: &ElementData) -> Result<()> {
549 (**self).decrement(element)
550 }
551 fn scroll_into_view(&self, element: &ElementData) -> Result<()> {
552 (**self).scroll_into_view(element)
553 }
554 fn set_value(&self, element: &ElementData, value: &str) -> Result<()> {
555 (**self).set_value(element, value)
556 }
557 fn set_numeric_value(&self, element: &ElementData, value: f64) -> Result<()> {
558 (**self).set_numeric_value(element, value)
559 }
560 fn type_text(&self, element: &ElementData, text: &str) -> Result<()> {
561 (**self).type_text(element, text)
562 }
563 fn set_text_selection(&self, element: &ElementData, start: u32, end: u32) -> Result<()> {
564 (**self).set_text_selection(element, start, end)
565 }
566 fn perform_action(&self, element: &ElementData, action: &str) -> Result<()> {
567 (**self).perform_action(element, action)
568 }
569 fn activate(&self, element: &ElementData) -> Result<()> {
570 (**self).activate(element)
571 }
572 fn minimize(&self, element: &ElementData) -> Result<()> {
573 (**self).minimize(element)
574 }
575 fn maximize(&self, element: &ElementData) -> Result<()> {
576 (**self).maximize(element)
577 }
578 fn enter_fullscreen(&self, element: &ElementData) -> Result<()> {
579 (**self).enter_fullscreen(element)
580 }
581 fn restore(&self, element: &ElementData) -> Result<()> {
582 (**self).restore(element)
583 }
584 fn close(&self, element: &ElementData) -> Result<()> {
585 (**self).close(element)
586 }
587 fn move_to(&self, element: &ElementData, x: i32, y: i32) -> Result<()> {
588 (**self).move_to(element, x, y)
589 }
590 fn resize_to(&self, element: &ElementData, width: u32, height: u32) -> Result<()> {
591 (**self).resize_to(element, width, height)
592 }
593 fn subscribe(&self, element: &ElementData) -> Result<Subscription> {
594 (**self).subscribe(element)
595 }
596}