xa11y-core 0.15.4

Core types, traits, and selector engine for xa11y cross-platform accessibility
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
use crate::element::ElementData;
use crate::error::{Error, Result};
use crate::event_provider::Subscription;
use crate::selector::{matches_simple, Combinator, Selector, SelectorGroup, SelectorSegment};
use crate::shell::ShellSurfaceKind;

/// Platform backend trait for accessibility tree access.
///
/// Providers implement lazy, on-demand tree navigation. Elements are identified
/// by their [`ElementData`] (which contains a provider-specific `handle` for
/// looking up the underlying platform object).
///
/// # Action model
///
/// Common actions are first-class methods with proper typed signatures.
/// Platform-specific or custom actions use [`perform_action`](Self::perform_action)
/// as an escape hatch — it takes a `snake_case` action name string.
///
/// Providers should check platform permissions in their constructor (`new()`)
/// and return [`Error::PermissionDenied`](crate::Error::PermissionDenied) if
/// required permissions are not granted.
pub trait Provider: Send + Sync {
    // ── Tree navigation ─────────────────────────────────────────────

    /// Get direct children of an element.
    ///
    /// If `element` is `None`, returns top-level application elements.
    fn get_children(&self, element: Option<&ElementData>) -> Result<Vec<ElementData>>;

    /// List an application's windows. Backends whose native window list is
    /// wider than their accessibility tree roots can override this.
    fn app_windows(&self, app: &ElementData) -> Result<Vec<ElementData>> {
        self.get_children(Some(app))
    }

    /// Get the parent of an element.
    ///
    /// Returns `None` for top-level (application) elements.
    fn get_parent(&self, element: &ElementData) -> Result<Option<ElementData>>;

    /// Enumerate top-level applications visible to this provider.
    ///
    /// Backends return one `ElementData` per application, always with
    /// `role=Application` as the **enumeration** contract. The direct-attach
    /// path ([`app_by_pid`](Self::app_by_pid)) is the one exception: macOS
    /// deliberately preserves `Role::Unknown` for a process that exposes no
    /// AX application (Window Server), so that `windows()` fails honestly
    /// instead of pretending the process has no windows. Windows synthesizes
    /// one Application node per
    /// process (UIA exposes applications as their top-level windows; the
    /// provider groups them by pid — and calls the process's first window the
    /// node's representative — see `xa11y-windows`). AT-SPI can return several
    /// native registrations sharing a pid; the core collapses those into one
    /// public `App` and uses [`app_roots`](Self::app_roots) for process-wide
    /// traversal. The application's top-level
    /// windows are its `app_windows` results, filtered to `Window|Dialog`.
    /// This is the dedicated discovery primitive: it replaces the previous
    /// `find_elements(None, application_selector, .., depth=0)` idiom and
    /// lets each backend batch the platform-specific enumeration (CGWindowList
    /// on macOS, the AT-SPI registry on Linux, UIA's desktop root on Windows)
    /// in one place.
    ///
    /// Required: every `Provider` implements this explicitly. There's no
    /// default impl — discovery and subtree search have different cost
    /// profiles, and silently routing app discovery through `get_children`
    /// would hide the difference from implementors.
    fn list_apps(&self) -> Result<Vec<ElementData>>;

    /// Whether [`list_apps`](Self::list_apps) can expose more than one
    /// `Application` entry for a single process id.
    ///
    /// Only the AT-SPI backend can (a per-process entry plus per-event-loop
    /// pieces such as a tray or a tooltip context); macOS and Windows
    /// guarantee one entry per pid. When `false`, [`App::windows_with`]
    /// skips the same-pid merge — and the full `list_apps` re-enumeration it
    /// requires — because the calling entry's descendants already cover the
    /// process, so no cross-entry merge can add anything.
    ///
    /// Defaults to `false`. A provider that overrides this with `true` must
    /// answer `get_children` per same-pid entry and give each entry (and its
    /// windows) a stable identity durable across `list_apps` calls, since
    /// the merge deduplicates by that identity.
    fn splits_app_across_entries(&self) -> bool {
        false
    }

    /// Return every native application root that belongs to the same process
    /// as `app`.
    ///
    /// Most accessibility APIs expose exactly one root per process, so the
    /// default is the supplied root. AT-SPI providers override this because a
    /// process may register several independent roots.
    fn app_roots(&self, app: &ElementData) -> Result<Vec<ElementData>> {
        Ok(vec![app.clone()])
    }

    /// Find the application owning process `pid` — one attempt, no polling.
    ///
    /// This is the single-shot discovery primitive behind `App::by_pid`; the
    /// core's lookup loop owns the retry/timeout policy. Returns
    /// [`Error::SelectorNotMatched`] when no accessible application for `pid`
    /// exists *yet* — the signal the poll loop retries on — and any other
    /// error when the lookup itself failed (permissions, platform API
    /// failure), which short-circuits the poll.
    ///
    /// The default implementation filters [`list_apps`](Self::list_apps) by
    /// `pid`, and its not-matched error carries enumeration diagnostics (how
    /// many apps were visible and how many had no resolvable pid) so a
    /// timeout on an opaque CI runner says *why* the app was invisible.
    /// Backends override this where the platform supports reaching a process
    /// directly (`AXUIElementCreateApplication` on macOS, a UIA `ProcessId`
    /// property search on Windows): direct attach is immune to enumeration
    /// blind spots such as top-level windows that are still unnamed while the
    /// app starts up.
    fn app_by_pid(&self, pid: u32) -> Result<ElementData> {
        let apps = self.list_apps()?;
        let total = apps.len();
        let unresolved = apps.iter().filter(|a| a.pid.is_none()).count();
        if let Some(data) = apps.into_iter().find(|a| a.pid == Some(pid)) {
            return Ok(data);
        }
        // The enumeration counts are structured diagnosis fields (tenet 6),
        // not prose baked into the selector — bindings expose them as
        // attributes, and `App::by_pid_with` merges in the full candidate
        // list at its terminal failure site. Cheap to build (two counters),
        // so attaching it per poll tick is fine.
        Err(
            Error::selector_not_matched(format!("application[pid={pid}]")).diagnose(
                crate::error::Diagnosis {
                    last_observed: Some(format!(
                        "enumerated {total} running apps, {unresolved} without a resolvable pid"
                    )),
                    ..Default::default()
                },
            ),
        )
    }

    /// Identify the application that currently holds the system foreground /
    /// input focus — one attempt, no polling.
    ///
    /// Each backend uses its platform's canonical foreground mechanism: the
    /// system-wide `AXUIElement`'s focused-application attribute (macOS),
    /// `GetForegroundWindow` + `ElementFromHandle` (Windows), and the focused
    /// element's `Application` ancestor in the AT-SPI registry (Linux). The
    /// returned `ElementData` has the same shape [`list_apps`](Self::list_apps)
    /// produces for that app — in particular its `pid` lines up — so the core
    /// can tag the foreground entry within an enumeration by pid.
    ///
    /// Returns [`Error::SelectorNotMatched`] when no application currently
    /// holds focus (e.g. focus rests on the desktop / shell, or the screen is
    /// locked). That is a legitimate state, not a failure: the core treats it
    /// as "nothing is foreground" — every listed app stays untagged — rather
    /// than surfacing an error. Any other error (permission, platform API
    /// failure) is a real failure and propagates.
    ///
    /// Required: every `Provider` implements this explicitly. Like
    /// [`list_apps`](Self::list_apps) there is no default impl — there is no
    /// portable way to derive the foreground app, so a silent no-op default
    /// would hide an unimplemented backend (tenet 1).
    fn focused_app(&self) -> Result<ElementData>;

    /// Enumerate OS shell surfaces — taskbars, panels, docks, menu bars,
    /// status items, the desktop, and any transient shell flyout currently
    /// open. One entry per surface, each a real platform element usable as a
    /// search root.
    ///
    /// The listing is live: transient surfaces
    /// ([`ShellSurfaceKind::Flyout`]) appear only while they are on screen,
    /// and enumerating NEVER opens, closes, or presses anything. Required —
    /// no default impl, for the same reason [`list_apps`](Self::list_apps)
    /// has none: enumeration is platform-specific, and a silent empty default
    /// would hide an unimplemented backend (tenet 1).
    ///
    /// The kind is part of the primitive's contract, so it travels in the
    /// signature where the compiler sees it rather than being smuggled
    /// through `raw`. Backends return the platform root untouched;
    /// `ShellSurface::list_with` additionally stamps `raw["shell_kind"]` on
    /// the surface root, in one place, so a consumer holding only an
    /// [`Element`](crate::Element) can read the kind back. That stamp is a
    /// readback, not a selector: it is on the root alone, a rooted locator
    /// only emits descendants of its root, and `TreeNode` carries no `raw`.
    fn list_shell_surfaces(&self) -> Result<Vec<(ShellSurfaceKind, ElementData)>>;

    /// Search for elements matching a selector.
    ///
    /// The selector is already parsed by the core — providers match against it
    /// during traversal and can prune subtrees that can't match.
    ///
    /// `root` is the subtree root to search under (always present; use
    /// [`list_apps`](Self::list_apps) to discover application roots first).
    /// If `limit` is `Some(n)`, stops after finding `n` matches.
    /// If `max_depth` is `Some(d)`, does not descend deeper than `d` levels.
    ///
    /// This is a thin convenience wrapper that re-uses
    /// [`find_elements_group`](Self::find_elements_group) with a single-clause
    /// group. Backends do **not** override this method — they override
    /// `find_elements_group`, and the single-clause case runs through the
    /// same native code path as multi-clause queries.
    fn find_elements(
        &self,
        root: &ElementData,
        selector: &Selector,
        limit: Option<usize>,
        max_depth: Option<u32>,
    ) -> Result<Vec<ElementData>> {
        let group = SelectorGroup {
            clauses: vec![selector.clone()],
        };
        self.find_elements_group(root, &group, limit, max_depth)
    }

    /// Search for elements matching any clause of a comma-separated selector
    /// group, scoped to `root`'s subtree.
    ///
    /// This is the **primary search primitive** each backend should override.
    /// A native implementation performs ONE platform-level subtree query/walk
    /// (e.g. `FindAllBuildCache(TreeScope_Subtree)` on Windows, one DFS over
    /// AT-SPI children on Linux, one AX walk on macOS) and evaluates every
    /// clause inline against each visited element. This avoids the
    /// per-clause-walk perf cliff and also keeps the cross-clause dedup
    /// correct: because everything happens inside one call, each platform
    /// node is visited once and platform identity is stable.
    ///
    /// `root` is non-optional: app discovery now goes through
    /// [`list_apps`](Self::list_apps) and any rootless multi-app search is
    /// performed by the caller (e.g. `Locator`) by enumerating apps and
    /// invoking this method per app.
    ///
    /// The default implementation traverses via [`get_children`](Self::get_children)
    /// and uses tree-path identity for cross-clause merging. It's the
    /// fallback for backends that haven't shipped a native override yet —
    /// the same path the test/mock provider exercises.
    fn find_elements_group(
        &self,
        root: &ElementData,
        group: &SelectorGroup,
        limit: Option<usize>,
        max_depth: Option<u32>,
    ) -> Result<Vec<ElementData>> {
        crate::selector::find_elements_in_tree_group(
            |el| self.get_children(el),
            Some(root),
            group,
            limit,
            max_depth,
        )
    }

    /// Narrow candidates through remaining selector segments (Child/Descendant
    /// combinators), deduplicate, apply final :nth and limit.
    fn narrow_multi_segment(
        &self,
        mut candidates: Vec<ElementData>,
        segments: &[SelectorSegment],
        max_depth: u32,
        limit: Option<usize>,
    ) -> Result<Vec<ElementData>> {
        for segment in segments {
            let mut next_candidates = Vec::new();
            for candidate in &candidates {
                match segment.combinator {
                    Combinator::Child => {
                        let children = self.get_children(Some(candidate))?;
                        for child in children {
                            if matches_simple(&child, &segment.simple) {
                                next_candidates.push(child);
                            }
                        }
                    }
                    Combinator::Descendant => {
                        let sub_selector = Selector {
                            segments: vec![SelectorSegment {
                                combinator: Combinator::Root,
                                simple: segment.simple.clone(),
                            }],
                        };
                        let mut sub_results =
                            self.find_elements(candidate, &sub_selector, None, Some(max_depth))?;
                        next_candidates.append(&mut sub_results);
                    }
                    Combinator::Root => unreachable!(),
                }
            }
            let mut seen = std::collections::HashSet::new();
            next_candidates.retain(|e| seen.insert(e.handle));
            candidates = next_candidates;
        }

        // Apply :nth on last segment
        if let Some(nth) = segments.last().and_then(|s| s.simple.nth) {
            if nth <= candidates.len() {
                candidates = vec![candidates.remove(nth - 1)];
            } else {
                candidates.clear();
            }
        }

        if let Some(limit) = limit {
            candidates.truncate(limit);
        }

        Ok(candidates)
    }

    // ── Common actions ──────────────────────────────────────────────

    /// Click / tap / invoke the element.
    fn press(&self, element: &ElementData) -> Result<()>;

    /// Set keyboard focus to the element.
    fn focus(&self, element: &ElementData) -> Result<()>;

    /// Remove keyboard focus from the element.
    fn blur(&self, element: &ElementData) -> Result<()>;

    /// Toggle a checkbox or switch.
    fn toggle(&self, element: &ElementData) -> Result<()>;

    /// Select an item in a list, tab group, or menu.
    fn select(&self, element: &ElementData) -> Result<()>;

    /// Expand a collapsible element (combo box, tree item, disclosure).
    fn expand(&self, element: &ElementData) -> Result<()>;

    /// Collapse an expanded element.
    fn collapse(&self, element: &ElementData) -> Result<()>;

    /// Show the element's context menu or dropdown.
    fn show_menu(&self, element: &ElementData) -> Result<()>;

    /// Increment a slider or spinner by one step.
    fn increment(&self, element: &ElementData) -> Result<()>;

    /// Decrement a slider or spinner by one step.
    fn decrement(&self, element: &ElementData) -> Result<()>;

    /// Scroll the element into the visible area.
    fn scroll_into_view(&self, element: &ElementData) -> Result<()>;

    // ── Typed operations ────────────────────────────────────────────

    /// Set the text value of the element.
    fn set_value(&self, element: &ElementData, value: &str) -> Result<()>;

    /// Set the numeric value of the element (slider, spinner).
    fn set_numeric_value(&self, element: &ElementData, value: f64) -> Result<()>;

    /// Insert text at the current cursor position.
    fn type_text(&self, element: &ElementData, text: &str) -> Result<()>;

    /// Select a text range (0-based character offsets).
    fn set_text_selection(&self, element: &ElementData, start: u32, end: u32) -> Result<()>;

    // ── Generic action escape hatch ─────────────────────────────────

    /// Perform an action by `snake_case` name.
    ///
    /// This is the escape hatch for platform-specific actions not covered by
    /// the first-class methods above. The provider converts the name to the
    /// platform's convention (e.g. `"custom_thing"` → `"AXCustomThing"` on
    /// macOS) and invokes it.
    ///
    /// Well-known action names (`"press"`, `"focus"`, etc.) should also work
    /// here — providers should delegate to the corresponding method.
    fn perform_action(&self, element: &ElementData, action: &str) -> Result<()>;

    // ── Window management ──────────────────────────────────────────

    /// `App::windows` filters `app_windows` to `Role::Window | Role::Dialog`.
    /// By default `app_windows` returns the Application node's children.
    /// Windows overrides it because native dialogs can be UIA descendants
    /// of another window; listing them does not make them separate roots
    /// for an app-wide tree walk.
    ///
    /// Linux refines the contract: an app may register several AT-SPI
    /// Application entries (per-process instance plus per-event-loop pieces
    /// such as a tray or the GTK IM context), so `App::windows_with` starts
    /// from this entry's filtered children, then merges the filtered children
    /// of every same-pid Application entry and deduplicates by stable id (see
    /// `same_window_identity`). The result is process-complete rather than a
    /// strict direct-children filter, and merged windows are not this node's
    /// children, so no single z-order spans them. Providers that split an app
    /// across entries must answer `app_windows` per entry; the merge is
    /// core's job.
    ///
    /// The filter lives in `App::windows_with`; backends only override
    /// `app_windows` when native window listing differs from tree navigation.
    ///
    /// Activate the window: bring it to the foreground and give it focus.
    ///
    /// Window verbs may use the platform accessibility API or a native
    /// window-manager protocol. A native provider must establish a durable
    /// association from this accessibility element to exactly one native
    /// window before it mutates state; process lifetime, destroyed/reused
    /// identifiers, and same-process ambiguity are errors rather than guesses.
    /// Titles are never sufficient identity by themselves.
    ///
    /// Unless a backend documents a stronger postcondition, success means the
    /// semantic platform request was accepted for delivery. Window managers
    /// commonly apply it asynchronously; consumers can re-read the element's
    /// tri-state window flags or bounds to observe completion. Unsupported
    /// capabilities and refused requests must remain distinct errors, and a
    /// backend must never substitute simulated input.
    ///
    /// Required: every `Provider` implements this explicitly. There is no
    /// portable default — each platform's activation mechanism is unique
    /// (AXRaise on macOS, `SetForegroundWindow` on Windows, GrabFocus on
    /// Linux), and a silent no-op default would hide an unimplemented
    /// backend (tenet 1).
    fn activate(&self, element: &ElementData) -> Result<()>;

    /// Minimize the window.
    fn minimize(&self, element: &ElementData) -> Result<()>;

    /// Maximize the window.
    ///
    /// Distinct from [`Self::enter_fullscreen`]: maximizing leaves the window
    /// in its platform's maximized state (the macOS zoom equivalent, Windows
    /// `WindowVisualState_Maximized`) while fullscreen is the native
    /// fullscreen state. A platform without the operation fails surfaceably
    /// rather than substituting the other.
    fn maximize(&self, element: &ElementData) -> Result<()>;

    /// Put the window in native fullscreen.
    ///
    /// Distinct from [`Self::maximize`]: fullscreen is the platform's native
    /// fullscreen state (macOS `AXFullScreen`), not a maximized window.
    /// [`Self::restore`] clears it. A platform without an accessibility API
    /// for fullscreen fails surfaceably.
    fn enter_fullscreen(&self, element: &ElementData) -> Result<()>;

    /// Restore the window to its normal state (from minimized/maximized/fullscreen).
    fn restore(&self, element: &ElementData) -> Result<()>;

    /// Close the window.
    fn close(&self, element: &ElementData) -> Result<()>;

    /// Move the window in the coordinates of [`ElementData::bounds`]
    /// (physical pixels on Windows, logical points elsewhere).
    fn move_to(&self, element: &ElementData, x: i32, y: i32) -> Result<()>;

    /// Resize the window in the units of [`ElementData::bounds`].
    fn resize_to(&self, element: &ElementData, width: u32, height: u32) -> Result<()>;

    // ── Events ──────────────────────────────────────────────────────

    /// Subscribe to all accessibility events for an application.
    ///
    /// The element should be an application-level element (role=Application).
    /// The provider extracts the PID from `element.pid`.
    ///
    /// Returns a [`Subscription`] that receives events until dropped.
    fn subscribe(&self, element: &ElementData) -> Result<Subscription>;
}

// Blanket impl so shared references to a provider act as providers themselves.
// Used by the umbrella crate's singleton (a `&'static dyn Provider` wrapped in
// `Arc<_>`) and by any caller that wants to share a provider via `&T`. The
// orphan rules keep this collision-free for downstream crates because `xa11y-core`
// owns the `Provider` trait.
impl<T: Provider + ?Sized> Provider for &T {
    fn get_children(&self, element: Option<&ElementData>) -> Result<Vec<ElementData>> {
        (**self).get_children(element)
    }
    fn app_windows(&self, app: &ElementData) -> Result<Vec<ElementData>> {
        (**self).app_windows(app)
    }
    fn get_parent(&self, element: &ElementData) -> Result<Option<ElementData>> {
        (**self).get_parent(element)
    }
    fn list_apps(&self) -> Result<Vec<ElementData>> {
        (**self).list_apps()
    }
    // Delegated explicitly (despite having a default impl) so a concrete
    // provider's override isn't bypassed when it's used through a shared
    // reference — the default body on `&T` would re-route and silently
    // answer `false` for a Linux provider passed by reference.
    fn splits_app_across_entries(&self) -> bool {
        (**self).splits_app_across_entries()
    }
    fn app_roots(&self, app: &ElementData) -> Result<Vec<ElementData>> {
        (**self).app_roots(app)
    }
    // Delegated explicitly (despite having a default impl) so a concrete
    // provider's PID-direct override isn't bypassed when it's used through a
    // shared reference — the default body on `&T` would re-route through
    // `list_apps` and silently lose the override.
    fn app_by_pid(&self, pid: u32) -> Result<ElementData> {
        (**self).app_by_pid(pid)
    }
    fn focused_app(&self) -> Result<ElementData> {
        (**self).focused_app()
    }
    fn list_shell_surfaces(&self) -> Result<Vec<(ShellSurfaceKind, ElementData)>> {
        (**self).list_shell_surfaces()
    }
    fn find_elements(
        &self,
        root: &ElementData,
        selector: &Selector,
        limit: Option<usize>,
        max_depth: Option<u32>,
    ) -> Result<Vec<ElementData>> {
        (**self).find_elements(root, selector, limit, max_depth)
    }
    fn find_elements_group(
        &self,
        root: &ElementData,
        group: &SelectorGroup,
        limit: Option<usize>,
        max_depth: Option<u32>,
    ) -> Result<Vec<ElementData>> {
        (**self).find_elements_group(root, group, limit, max_depth)
    }
    fn narrow_multi_segment(
        &self,
        candidates: Vec<ElementData>,
        segments: &[SelectorSegment],
        max_depth: u32,
        limit: Option<usize>,
    ) -> Result<Vec<ElementData>> {
        (**self).narrow_multi_segment(candidates, segments, max_depth, limit)
    }
    fn press(&self, element: &ElementData) -> Result<()> {
        (**self).press(element)
    }
    fn focus(&self, element: &ElementData) -> Result<()> {
        (**self).focus(element)
    }
    fn blur(&self, element: &ElementData) -> Result<()> {
        (**self).blur(element)
    }
    fn toggle(&self, element: &ElementData) -> Result<()> {
        (**self).toggle(element)
    }
    fn select(&self, element: &ElementData) -> Result<()> {
        (**self).select(element)
    }
    fn expand(&self, element: &ElementData) -> Result<()> {
        (**self).expand(element)
    }
    fn collapse(&self, element: &ElementData) -> Result<()> {
        (**self).collapse(element)
    }
    fn show_menu(&self, element: &ElementData) -> Result<()> {
        (**self).show_menu(element)
    }
    fn increment(&self, element: &ElementData) -> Result<()> {
        (**self).increment(element)
    }
    fn decrement(&self, element: &ElementData) -> Result<()> {
        (**self).decrement(element)
    }
    fn scroll_into_view(&self, element: &ElementData) -> Result<()> {
        (**self).scroll_into_view(element)
    }
    fn set_value(&self, element: &ElementData, value: &str) -> Result<()> {
        (**self).set_value(element, value)
    }
    fn set_numeric_value(&self, element: &ElementData, value: f64) -> Result<()> {
        (**self).set_numeric_value(element, value)
    }
    fn type_text(&self, element: &ElementData, text: &str) -> Result<()> {
        (**self).type_text(element, text)
    }
    fn set_text_selection(&self, element: &ElementData, start: u32, end: u32) -> Result<()> {
        (**self).set_text_selection(element, start, end)
    }
    fn perform_action(&self, element: &ElementData, action: &str) -> Result<()> {
        (**self).perform_action(element, action)
    }
    fn activate(&self, element: &ElementData) -> Result<()> {
        (**self).activate(element)
    }
    fn minimize(&self, element: &ElementData) -> Result<()> {
        (**self).minimize(element)
    }
    fn maximize(&self, element: &ElementData) -> Result<()> {
        (**self).maximize(element)
    }
    fn enter_fullscreen(&self, element: &ElementData) -> Result<()> {
        (**self).enter_fullscreen(element)
    }
    fn restore(&self, element: &ElementData) -> Result<()> {
        (**self).restore(element)
    }
    fn close(&self, element: &ElementData) -> Result<()> {
        (**self).close(element)
    }
    fn move_to(&self, element: &ElementData, x: i32, y: i32) -> Result<()> {
        (**self).move_to(element, x, y)
    }
    fn resize_to(&self, element: &ElementData, width: u32, height: u32) -> Result<()> {
        (**self).resize_to(element, width, height)
    }
    fn subscribe(&self, element: &ElementData) -> Result<Subscription> {
        (**self).subscribe(element)
    }
}