accesskit_unix/
context.rs

1// Copyright 2023 The AccessKit Authors. All rights reserved.
2// Licensed under the Apache License, Version 2.0 (found in
3// the LICENSE-APACHE file) or the MIT license (found in
4// the LICENSE-MIT file), at your option.
5
6use 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}