| 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 | |