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
//! Accessibility bridge for the **self-drawn** Linux popups (X11 override-redirect
//! + Wayland layer-shell), wired to `accesskit_unix` behind the `a11y` feature.
//!
//! ## Why this exists
//!
//! The native dbusmenu presenter ([`super::sni`]) is accessible over AT-SPI **for
//! free**: the SNI host draws a real native menu, so Orca walks it with no work
//! from muri. The moment muri draws its *own* styled popup (the X11 or Wayland
//! custom presenter), that free accessibility is gone — the compositor sees only
//! an opaque surface of pixels. To stay accessible, muri publishes a semantic tree
//! itself, exactly as it already does on macOS/Windows via `accesskit`.
//!
//! ## How it works (research doc §13)
//!
//! `accesskit_unix` implements the AT-SPI2 D-Bus interfaces via `zbus`. Crucially
//! **AT-SPI2 rides D-Bus, not the display protocol**, so the adapter is identical
//! under X11 and Wayland and never touches the compositor — it only needs a logical
//! `Window`/`Menu`-role node plus the menu items as `Role::MenuItem` /
//! `Role::MenuItemCheckBox`, and the app reporting focus. muri already builds this
//! exact tree for the macOS/Windows self-drawn menus behind the `a11y` feature
//! ([`crate::a11y`]); the Unix adapter reuses [`crate::a11y::accesskit::tree_update`].
//!
//! **Known Wayland caveat:** `Adapter::set_root_window_bounds()` is X11-only (a
//! Wayland client can't read its window position), so absolute-screen AT
//! hit-testing won't be exact on Wayland — roles, text, focus, and actions all
//! still work. muri never calls it (the popup carries no reliable screen rect on
//! either backend), which is the documented, bounded cost of the styled path.
//!
//! ## Status
//!
//! Fully wired: [`PopupA11y::attach`] creates an `accesskit_unix::Adapter` seeded
//! with the popup's menu tree, and [`PopupA11y::focus_row`] /
//! [`PopupA11y::set_focused`] push focus/activation updates. The adapter lazily
//! no-ops until a real AT-SPI bus + assistive technology (Orca) is listening —
//! `DEVICE-VERIFY(0.11.1)`: the live bus handshake + Orca announcement can only be
//! confirmed on a real Linux session. When the `a11y` feature is off the whole type
//! degrades to inert no-ops so the popups run without accessibility rather than not
//! at all.
use crateMenu;
/// The AT-SPI action handler for a popup. AccessKit action requests (e.g. a screen
/// reader's "click"/"focus") arrive here on the adapter's own thread.
///
/// DEVICE-VERIFY(0.11.1): AT-driven *activation* would need to hop the request back
/// onto the popup's event-loop thread to fire the row (the self-drawn loops are
/// single-threaded and own the dispatch closure). Focus/label/state announcement —
/// the bulk of screen-reader value — works through the pushed `TreeUpdate`s without
/// it, so the handler is a no-op for now.
;
/// Serves the initial AccessKit tree the moment an assistive technology attaches
/// (AccessKit is lazy — nothing is built until an AT asks).
/// Notified when the last AT detaches; nothing to tear down here.
;
/// A handle to the AT-SPI adapter driving one self-drawn popup session. Owns the
/// `accesskit_unix::Adapter` (behind `a11y`); created when a styled popup opens and
/// dropped when it dismisses, mirroring the macOS/Windows adapters' lifetimes. When
/// the `a11y` feature is off this is a ZST whose methods are no-ops.
pub