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