accesskit_unix/
adapter.rs

1// Copyright 2022 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::{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    /// Create a new Unix adapter.
82    ///
83    /// All of the handlers will always be called from another thread.
84    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    /// If and only if the tree has been initialized, call the provided function
136    /// and apply the resulting update. Note: If the caller's implementation of
137    /// [`ActivationHandler::request_initial_tree`] initially returned `None`,
138    /// the [`TreeUpdate`] returned by the provided function must contain
139    /// a full tree.
140    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    /// Update the tree state based on whether the window is focused.
166    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}