1use accesskit::{ActionHandler, ActivationHandler, DeactivationHandler, NodeId, Rect, TreeUpdate};
7use accesskit_atspi_common::{
8 next_adapter_id, ActionHandlerNoMut, ActionHandlerWrapper, Adapter as AdapterImpl,
9 AdapterCallback, Event, PlatformNode, WindowBounds,
10};
11#[cfg(not(feature = "tokio"))]
12use async_channel::Sender;
13use atspi::InterfaceSet;
14use std::fmt::{Debug, Formatter};
15use std::sync::{Arc, Mutex};
16#[cfg(feature = "tokio")]
17use tokio::sync::mpsc::UnboundedSender as Sender;
18
19use crate::context::{get_or_init_app_context, get_or_init_messages};
20
21pub(crate) struct Callback {
22 messages: Sender<Message>,
23}
24
25impl Callback {
26 pub(crate) fn new() -> Self {
27 let messages = get_or_init_messages();
28 Self { messages }
29 }
30
31 fn send_message(&self, message: Message) {
32 #[cfg(not(feature = "tokio"))]
33 let _ = self.messages.try_send(message);
34 #[cfg(feature = "tokio")]
35 let _ = self.messages.send(message);
36 }
37}
38
39impl AdapterCallback for Callback {
40 fn register_interfaces(&self, adapter: &AdapterImpl, id: NodeId, interfaces: InterfaceSet) {
41 let node = adapter.platform_node(id);
42 self.send_message(Message::RegisterInterfaces { node, interfaces });
43 }
44
45 fn unregister_interfaces(&self, adapter: &AdapterImpl, id: NodeId, interfaces: InterfaceSet) {
46 self.send_message(Message::UnregisterInterfaces {
47 adapter_id: adapter.id(),
48 node_id: id,
49 interfaces,
50 })
51 }
52
53 fn emit_event(&self, adapter: &AdapterImpl, event: Event) {
54 self.send_message(Message::EmitEvent {
55 adapter_id: adapter.id(),
56 event,
57 });
58 }
59}
60
61pub(crate) enum AdapterState {
62 Inactive {
63 is_window_focused: bool,
64 root_window_bounds: WindowBounds,
65 action_handler: Arc<dyn ActionHandlerNoMut + Send + Sync>,
66 },
67 Pending {
68 is_window_focused: bool,
69 root_window_bounds: WindowBounds,
70 action_handler: Arc<dyn ActionHandlerNoMut + Send + Sync>,
71 },
72 Active(AdapterImpl),
73}
74
75impl Debug for AdapterState {
76 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
77 match self {
78 AdapterState::Inactive {
79 is_window_focused,
80 root_window_bounds,
81 action_handler: _,
82 } => f
83 .debug_struct("Inactive")
84 .field("is_window_focused", is_window_focused)
85 .field("root_window_bounds", root_window_bounds)
86 .field("action_handler", &"ActionHandler")
87 .finish(),
88 AdapterState::Pending {
89 is_window_focused,
90 root_window_bounds,
91 action_handler: _,
92 } => f
93 .debug_struct("Pending")
94 .field("is_window_focused", is_window_focused)
95 .field("root_window_bounds", root_window_bounds)
96 .field("action_handler", &"ActionHandler")
97 .finish(),
98 AdapterState::Active(r#impl) => f.debug_tuple("Active").field(r#impl).finish(),
99 }
100 }
101}
102
103#[derive(Debug)]
104pub struct Adapter {
105 messages: Sender<Message>,
106 id: usize,
107 state: Arc<Mutex<AdapterState>>,
108}
109
110impl Adapter {
111 pub fn new(
115 activation_handler: impl 'static + ActivationHandler + Send,
116 action_handler: impl 'static + ActionHandler + Send,
117 deactivation_handler: impl 'static + DeactivationHandler + Send,
118 ) -> Self {
119 let id = next_adapter_id();
120 let messages = get_or_init_messages();
121 let state = Arc::new(Mutex::new(AdapterState::Inactive {
122 is_window_focused: false,
123 root_window_bounds: Default::default(),
124 action_handler: Arc::new(ActionHandlerWrapper::new(action_handler)),
125 }));
126 let adapter = Self {
127 id,
128 messages,
129 state: Arc::clone(&state),
130 };
131 adapter.send_message(Message::AddAdapter {
132 id,
133 activation_handler: Box::new(activation_handler),
134 deactivation_handler: Box::new(deactivation_handler),
135 state,
136 });
137 adapter
138 }
139
140 pub(crate) fn send_message(&self, message: Message) {
141 #[cfg(not(feature = "tokio"))]
142 let _ = self.messages.try_send(message);
143 #[cfg(feature = "tokio")]
144 let _ = self.messages.send(message);
145 }
146
147 pub fn set_root_window_bounds(&mut self, outer: Rect, inner: Rect) {
155 let new_bounds = WindowBounds::new(outer, inner);
156 let mut state = self.state.lock().unwrap();
157 match &mut *state {
158 AdapterState::Inactive {
159 root_window_bounds, ..
160 } => {
161 *root_window_bounds = new_bounds;
162 }
163 AdapterState::Pending {
164 root_window_bounds, ..
165 } => {
166 *root_window_bounds = new_bounds;
167 }
168 AdapterState::Active(r#impl) => r#impl.set_root_window_bounds(new_bounds),
169 }
170 }
171
172 pub fn update_if_active(&mut self, update_factory: impl FnOnce() -> TreeUpdate) {
178 let mut state = self.state.lock().unwrap();
179 match &mut *state {
180 AdapterState::Inactive { .. } => (),
181 AdapterState::Pending {
182 is_window_focused,
183 root_window_bounds,
184 action_handler,
185 } => {
186 let initial_state = update_factory();
187 let r#impl = AdapterImpl::with_wrapped_action_handler(
188 self.id,
189 get_or_init_app_context(),
190 Callback::new(),
191 initial_state,
192 *is_window_focused,
193 *root_window_bounds,
194 Arc::clone(action_handler),
195 );
196 *state = AdapterState::Active(r#impl);
197 }
198 AdapterState::Active(r#impl) => r#impl.update(update_factory()),
199 }
200 }
201
202 pub fn update_window_focus_state(&mut self, is_focused: bool) {
204 let mut state = self.state.lock().unwrap();
205 match &mut *state {
206 AdapterState::Inactive {
207 is_window_focused, ..
208 } => {
209 *is_window_focused = is_focused;
210 }
211 AdapterState::Pending {
212 is_window_focused, ..
213 } => {
214 *is_window_focused = is_focused;
215 }
216 AdapterState::Active(r#impl) => r#impl.update_window_focus_state(is_focused),
217 }
218 }
219}
220
221impl Drop for Adapter {
222 fn drop(&mut self) {
223 self.send_message(Message::RemoveAdapter { id: self.id });
224 }
225}
226
227pub(crate) enum Message {
228 AddAdapter {
229 id: usize,
230 activation_handler: Box<dyn ActivationHandler + Send>,
231 deactivation_handler: Box<dyn DeactivationHandler + Send>,
232 state: Arc<Mutex<AdapterState>>,
233 },
234 RemoveAdapter {
235 id: usize,
236 },
237 RegisterInterfaces {
238 node: PlatformNode,
239 interfaces: InterfaceSet,
240 },
241 UnregisterInterfaces {
242 adapter_id: usize,
243 node_id: NodeId,
244 interfaces: InterfaceSet,
245 },
246 EmitEvent {
247 adapter_id: usize,
248 event: Event,
249 },
250}