accesskit_atspi_common/
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::{ActionHandler, ActionRequest};
7use accesskit_consumer::Tree;
8use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
9
10use crate::WindowBounds;
11
12/// This is an implementation detail of `accesskit_unix`, required for robust
13/// state transitions with minimal overhead.
14pub 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.
20pub struct ActionHandlerWrapper<H: ActionHandler + Send>(Mutex<H>);
21
22impl<H: 'static + ActionHandler + Send> ActionHandlerWrapper<H> {
23    pub fn new(inner: H) -> Self {
24        Self(Mutex::new(inner))
25    }
26}
27
28impl<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
34pub(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
41impl 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
77pub 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
85impl 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}