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::sync::{Arc, Mutex};
15#[cfg(feature = "tokio")]
16use tokio::sync::mpsc::UnboundedSender as Sender;
17
18use crate::context::{get_or_init_app_context, get_or_init_messages};
19
20pub(crate) struct Callback {
21 messages: Sender<Message>,
22}
23
24impl Callback {
25 pub(crate) fn new() -> Self {
26 let messages = get_or_init_messages();
27 Self { messages }
28 }
29
30 fn send_message(&self, message: Message) {
31 #[cfg(not(feature = "tokio"))]
32 let _ = self.messages.try_send(message);
33 #[cfg(feature = "tokio")]
34 let _ = self.messages.send(message);
35 }
36}
37
38impl AdapterCallback for Callback {
39 fn register_interfaces(&self, adapter: &AdapterImpl, id: NodeId, interfaces: InterfaceSet) {
40 let node = adapter.platform_node(id);
41 self.send_message(Message::RegisterInterfaces { node, interfaces });
42 }
43
44 fn unregister_interfaces(&self, adapter: &AdapterImpl, id: NodeId, interfaces: InterfaceSet) {
45 self.send_message(Message::UnregisterInterfaces {
46 adapter_id: adapter.id(),
47 node_id: id,
48 interfaces,
49 })
50 }
51
52 fn emit_event(&self, adapter: &AdapterImpl, event: Event) {
53 self.send_message(Message::EmitEvent {
54 adapter_id: adapter.id(),
55 event,
56 });
57 }
58}
59
60pub(crate) enum AdapterState {
61 Inactive {
62 is_window_focused: bool,
63 root_window_bounds: WindowBounds,
64 action_handler: Arc<dyn ActionHandlerNoMut + Send + Sync>,
65 },
66 Pending {
67 is_window_focused: bool,
68 root_window_bounds: WindowBounds,
69 action_handler: Arc<dyn ActionHandlerNoMut + Send + Sync>,
70 },
71 Active(AdapterImpl),
72}
73
74pub struct Adapter {
75 messages: Sender<Message>,
76 id: usize,
77 state: Arc<Mutex<AdapterState>>,
78}
79
80impl Adapter {
81 pub fn new(
85 activation_handler: impl 'static + ActivationHandler + Send,
86 action_handler: impl 'static + ActionHandler + Send,
87 deactivation_handler: impl 'static + DeactivationHandler + Send,
88 ) -> Self {
89 let id = next_adapter_id();
90 let messages = get_or_init_messages();
91 let state = Arc::new(Mutex::new(AdapterState::Inactive {
92 is_window_focused: false,
93 root_window_bounds: Default::default(),
94 action_handler: Arc::new(ActionHandlerWrapper::new(action_handler)),
95 }));
96 let adapter = Self {
97 id,
98 messages,
99 state: Arc::clone(&state),
100 };
101 adapter.send_message(Message::AddAdapter {
102 id,
103 activation_handler: Box::new(activation_handler),
104 deactivation_handler: Box::new(deactivation_handler),
105 state,
106 });
107 adapter
108 }
109
110 pub(crate) fn send_message(&self, message: Message) {
111 #[cfg(not(feature = "tokio"))]
112 let _ = self.messages.try_send(message);
113 #[cfg(feature = "tokio")]
114 let _ = self.messages.send(message);
115 }
116
117 pub fn set_root_window_bounds(&mut self, outer: Rect, inner: Rect) {
118 let new_bounds = WindowBounds::new(outer, inner);
119 let mut state = self.state.lock().unwrap();
120 match &mut *state {
121 AdapterState::Inactive {
122 root_window_bounds, ..
123 } => {
124 *root_window_bounds = new_bounds;
125 }
126 AdapterState::Pending {
127 root_window_bounds, ..
128 } => {
129 *root_window_bounds = new_bounds;
130 }
131 AdapterState::Active(r#impl) => r#impl.set_root_window_bounds(new_bounds),
132 }
133 }
134
135 pub fn update_if_active(&mut self, update_factory: impl FnOnce() -> TreeUpdate) {
141 let mut state = self.state.lock().unwrap();
142 match &mut *state {
143 AdapterState::Inactive { .. } => (),
144 AdapterState::Pending {
145 is_window_focused,
146 root_window_bounds,
147 action_handler,
148 } => {
149 let initial_state = update_factory();
150 let r#impl = AdapterImpl::with_wrapped_action_handler(
151 self.id,
152 get_or_init_app_context(),
153 Callback::new(),
154 initial_state,
155 *is_window_focused,
156 *root_window_bounds,
157 Arc::clone(action_handler),
158 );
159 *state = AdapterState::Active(r#impl);
160 }
161 AdapterState::Active(r#impl) => r#impl.update(update_factory()),
162 }
163 }
164
165 pub fn update_window_focus_state(&mut self, is_focused: bool) {
167 let mut state = self.state.lock().unwrap();
168 match &mut *state {
169 AdapterState::Inactive {
170 is_window_focused, ..
171 } => {
172 *is_window_focused = is_focused;
173 }
174 AdapterState::Pending {
175 is_window_focused, ..
176 } => {
177 *is_window_focused = is_focused;
178 }
179 AdapterState::Active(r#impl) => r#impl.update_window_focus_state(is_focused),
180 }
181 }
182}
183
184impl Drop for Adapter {
185 fn drop(&mut self) {
186 self.send_message(Message::RemoveAdapter { id: self.id });
187 }
188}
189
190pub(crate) enum Message {
191 AddAdapter {
192 id: usize,
193 activation_handler: Box<dyn ActivationHandler + Send>,
194 deactivation_handler: Box<dyn DeactivationHandler + Send>,
195 state: Arc<Mutex<AdapterState>>,
196 },
197 RemoveAdapter {
198 id: usize,
199 },
200 RegisterInterfaces {
201 node: PlatformNode,
202 interfaces: InterfaceSet,
203 },
204 UnregisterInterfaces {
205 adapter_id: usize,
206 node_id: NodeId,
207 interfaces: InterfaceSet,
208 },
209 EmitEvent {
210 adapter_id: usize,
211 event: Event,
212 },
213}