1use accesskit::{ActivationHandler, DeactivationHandler};
7use accesskit_atspi_common::{Adapter as AdapterImpl, AppContext, Event};
8#[cfg(not(feature = "tokio"))]
9use async_channel::{Receiver, Sender};
10use atspi::proxy::bus::StatusProxy;
11#[cfg(not(feature = "tokio"))]
12use futures_util::{pin_mut as pin, select, StreamExt};
13use std::{
14 sync::{Arc, Mutex, OnceLock, RwLock},
15 thread,
16};
17#[cfg(feature = "tokio")]
18use tokio::{
19 pin, select,
20 sync::mpsc::{UnboundedReceiver as Receiver, UnboundedSender as Sender},
21};
22#[cfg(feature = "tokio")]
23use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};
24use zbus::{Connection, ConnectionBuilder};
25
26use crate::{
27 adapter::{AdapterState, Callback, Message},
28 atspi::{map_or_ignoring_broken_pipe, Bus},
29 executor::Executor,
30 util::block_on,
31};
32
33static APP_CONTEXT: OnceLock<Arc<RwLock<AppContext>>> = OnceLock::new();
34static MESSAGES: OnceLock<Sender<Message>> = OnceLock::new();
35
36pub(crate) fn get_or_init_app_context<'a>() -> &'a Arc<RwLock<AppContext>> {
37 APP_CONTEXT.get_or_init(AppContext::new)
38}
39
40pub(crate) fn get_or_init_messages() -> Sender<Message> {
41 MESSAGES
42 .get_or_init(|| {
43 #[cfg(not(feature = "tokio"))]
44 let (tx, rx) = async_channel::unbounded();
45 #[cfg(feature = "tokio")]
46 let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
47
48 thread::spawn(|| {
49 let executor = Executor::new();
50 block_on(executor.run(async {
51 if let Ok(session_bus) = ConnectionBuilder::session() {
52 if let Ok(session_bus) = session_bus.internal_executor(false).build().await
53 {
54 run_event_loop(&executor, session_bus, rx).await.unwrap();
55 }
56 }
57 }))
58 });
59
60 tx
61 })
62 .clone()
63}
64
65struct AdapterEntry {
66 id: usize,
67 activation_handler: Box<dyn ActivationHandler>,
68 deactivation_handler: Box<dyn DeactivationHandler>,
69 state: Arc<Mutex<AdapterState>>,
70}
71
72fn activate_adapter(entry: &mut AdapterEntry) {
73 let mut state = entry.state.lock().unwrap();
74 if let AdapterState::Inactive {
75 is_window_focused,
76 root_window_bounds,
77 action_handler,
78 } = &*state
79 {
80 *state = match entry.activation_handler.request_initial_tree() {
81 Some(initial_state) => {
82 let r#impl = AdapterImpl::with_wrapped_action_handler(
83 entry.id,
84 get_or_init_app_context(),
85 Callback::new(),
86 initial_state,
87 *is_window_focused,
88 *root_window_bounds,
89 Arc::clone(action_handler),
90 );
91 AdapterState::Active(r#impl)
92 }
93 None => AdapterState::Pending {
94 is_window_focused: *is_window_focused,
95 root_window_bounds: *root_window_bounds,
96 action_handler: Arc::clone(action_handler),
97 },
98 };
99 }
100}
101
102fn deactivate_adapter(entry: &mut AdapterEntry) {
103 let mut state = entry.state.lock().unwrap();
104 match &*state {
105 AdapterState::Inactive { .. } => (),
106 AdapterState::Pending {
107 is_window_focused,
108 root_window_bounds,
109 action_handler,
110 } => {
111 *state = AdapterState::Inactive {
112 is_window_focused: *is_window_focused,
113 root_window_bounds: *root_window_bounds,
114 action_handler: Arc::clone(action_handler),
115 };
116 drop(state);
117 entry.deactivation_handler.deactivate_accessibility();
118 }
119 AdapterState::Active(r#impl) => {
120 *state = AdapterState::Inactive {
121 is_window_focused: r#impl.is_window_focused(),
122 root_window_bounds: r#impl.root_window_bounds(),
123 action_handler: r#impl.wrapped_action_handler(),
124 };
125 drop(state);
126 entry.deactivation_handler.deactivate_accessibility();
127 }
128 }
129}
130
131async fn run_event_loop(
132 executor: &Executor<'_>,
133 session_bus: Connection,
134 rx: Receiver<Message>,
135) -> zbus::Result<()> {
136 let session_bus_copy = session_bus.clone();
137 let _session_bus_task = executor.spawn(
138 async move {
139 loop {
140 session_bus_copy.executor().tick().await;
141 }
142 },
143 "accesskit_session_bus_task",
144 );
145
146 let status = StatusProxy::new(&session_bus).await?;
147 let changes = status.receive_is_enabled_changed().await.fuse();
148 pin!(changes);
149
150 #[cfg(not(feature = "tokio"))]
151 let messages = rx.fuse();
152 #[cfg(feature = "tokio")]
153 let messages = UnboundedReceiverStream::new(rx).fuse();
154 pin!(messages);
155
156 let mut atspi_bus = None;
157 let mut adapters: Vec<AdapterEntry> = Vec::new();
158
159 loop {
160 select! {
161 change = changes.next() => {
162 atspi_bus = None;
163 if let Some(change) = change {
164 if change.get().await? {
165 atspi_bus = map_or_ignoring_broken_pipe(Bus::new(&session_bus, executor).await, None, Some)?;
166 }
167 }
168 for entry in &mut adapters {
169 if atspi_bus.is_some() {
170 activate_adapter(entry);
171 } else {
172 deactivate_adapter(entry);
173 }
174 }
175 }
176 message = messages.next() => {
177 if let Some(message) = message {
178 process_adapter_message(&atspi_bus, &mut adapters, message).await?;
179 }
180 }
181 }
182 }
183}
184
185async fn process_adapter_message(
186 atspi_bus: &Option<Bus>,
187 adapters: &mut Vec<AdapterEntry>,
188 message: Message,
189) -> zbus::Result<()> {
190 match message {
191 Message::AddAdapter {
192 id,
193 activation_handler,
194 deactivation_handler,
195 state,
196 } => {
197 adapters.push(AdapterEntry {
198 id,
199 activation_handler,
200 deactivation_handler,
201 state,
202 });
203 if atspi_bus.is_some() {
204 let entry = adapters.last_mut().unwrap();
205 activate_adapter(entry);
206 }
207 }
208 Message::RemoveAdapter { id } => {
209 if let Ok(index) = adapters.binary_search_by(|entry| entry.id.cmp(&id)) {
210 adapters.remove(index);
211 }
212 }
213 Message::RegisterInterfaces { node, interfaces } => {
214 if let Some(bus) = atspi_bus {
215 bus.register_interfaces(node, interfaces).await?
216 }
217 }
218 Message::UnregisterInterfaces {
219 adapter_id,
220 node_id,
221 interfaces,
222 } => {
223 if let Some(bus) = atspi_bus {
224 bus.unregister_interfaces(adapter_id, node_id, interfaces)
225 .await?
226 }
227 }
228 Message::EmitEvent {
229 adapter_id,
230 event: Event::Object { target, event },
231 } => {
232 if let Some(bus) = atspi_bus {
233 bus.emit_object_event(adapter_id, target, event).await?
234 }
235 }
236 Message::EmitEvent {
237 adapter_id,
238 event:
239 Event::Window {
240 target,
241 name,
242 event,
243 },
244 } => {
245 if let Some(bus) = atspi_bus {
246 bus.emit_window_event(adapter_id, target, name, event)
247 .await?;
248 }
249 }
250 }
251
252 Ok(())
253}