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 | |
6 | use accesskit::{ActionHandler, ActionRequest}; |
7 | use accesskit_consumer::Tree; |
8 | use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard}; |
9 | |
10 | use crate::WindowBounds; |
11 | |
12 | /// This is an implementation detail of `accesskit_unix`, required for robust |
13 | /// state transitions with minimal overhead. |
14 | pub trait ActionHandlerNoMut { |
15 | fn do_action(&self, request: ActionRequest); |
16 | } |
17 | |
18 | /// This is an implementation detail of `accesskit_unix`, required for robust |
19 | /// state transitions with minimal overhead. |
20 | pub struct ActionHandlerWrapper<H: ActionHandler + Send>(Mutex<H>); |
21 | |
22 | impl<H: 'static + ActionHandler + Send> ActionHandlerWrapper<H> { |
23 | pub fn new(inner: H) -> Self { |
24 | Self(Mutex::new(inner)) |
25 | } |
26 | } |
27 | |
28 | impl<H: ActionHandler + Send> ActionHandlerNoMut for ActionHandlerWrapper<H> { |
29 | fn do_action(&self, request: ActionRequest) { |
30 | self.0.lock().unwrap().do_action(request) |
31 | } |
32 | } |
33 | |
34 | pub(crate) struct Context { |
35 | pub(crate) app_context: Arc<RwLock<AppContext>>, |
36 | pub(crate) tree: RwLock<Tree>, |
37 | pub(crate) action_handler: Arc<dyn ActionHandlerNoMut + Send + Sync>, |
38 | pub(crate) root_window_bounds: RwLock<WindowBounds>, |
39 | } |
40 | |
41 | impl Context { |
42 | pub(crate) fn new( |
43 | app_context: &Arc<RwLock<AppContext>>, |
44 | tree: Tree, |
45 | action_handler: Arc<dyn ActionHandlerNoMut + Send + Sync>, |
46 | root_window_bounds: WindowBounds, |
47 | ) -> Arc<Self> { |
48 | Arc::new(Self { |
49 | app_context: Arc::clone(app_context), |
50 | tree: RwLock::new(tree), |
51 | action_handler, |
52 | root_window_bounds: RwLock::new(root_window_bounds), |
53 | }) |
54 | } |
55 | |
56 | pub(crate) fn read_tree(&self) -> RwLockReadGuard<'_, Tree> { |
57 | self.tree.read().unwrap() |
58 | } |
59 | |
60 | pub(crate) fn read_root_window_bounds(&self) -> RwLockReadGuard<'_, WindowBounds> { |
61 | self.root_window_bounds.read().unwrap() |
62 | } |
63 | |
64 | pub fn do_action(&self, request: ActionRequest) { |
65 | self.action_handler.do_action(request); |
66 | } |
67 | |
68 | pub(crate) fn read_app_context(&self) -> RwLockReadGuard<'_, AppContext> { |
69 | self.app_context.read().unwrap() |
70 | } |
71 | |
72 | pub(crate) fn write_app_context(&self) -> RwLockWriteGuard<'_, AppContext> { |
73 | self.app_context.write().unwrap() |
74 | } |
75 | } |
76 | |
77 | pub struct AppContext { |
78 | pub(crate) name: Option<String>, |
79 | pub(crate) toolkit_name: Option<String>, |
80 | pub(crate) toolkit_version: Option<String>, |
81 | pub(crate) id: Option<i32>, |
82 | pub(crate) adapters: Vec<(usize, Arc<Context>)>, |
83 | } |
84 | |
85 | impl AppContext { |
86 | pub fn new() -> Arc<RwLock<Self>> { |
87 | Arc::new(RwLock::new(Self { |
88 | name: None, |
89 | toolkit_name: None, |
90 | toolkit_version: None, |
91 | id: None, |
92 | adapters: Vec::new(), |
93 | })) |
94 | } |
95 | |
96 | pub(crate) fn adapter_index(&self, id: usize) -> Result<usize, usize> { |
97 | self.adapters.binary_search_by(|adapter| adapter.0.cmp(&id)) |
98 | } |
99 | |
100 | pub(crate) fn push_adapter(&mut self, id: usize, context: &Arc<Context>) { |
101 | self.adapters.push((id, Arc::clone(context))); |
102 | } |
103 | |
104 | pub(crate) fn remove_adapter(&mut self, id: usize) { |
105 | if let Ok(index) = self.adapter_index(id) { |
106 | self.adapters.remove(index); |
107 | } |
108 | } |
109 | } |
110 | |