1#![doc = include_str!("../README.md")]
2
3use accesskit::{NodeId, TreeUpdate};
4use fltk::{enums::*, prelude::*, *};
5
6pub mod accessible;
7mod fltk_adapter;
8mod platform_adapter;
9
10pub use accessible::Accessible;
11pub use fltk_adapter::{ActionRequestEvent, Adapter};
12
13pub struct AccessibilityContext {
14 adapter: Adapter,
15 root: window::Window,
16 widgets: Vec<Box<dyn Accessible>>,
17}
18
19impl AccessibilityContext {
20 pub fn new(root: window::Window, widgets: Vec<Box<dyn Accessible>>) -> Self {
21 let mut wids = vec![];
22 for w in &widgets {
23 let n = w.make_node(&[]);
24 wids.push(n);
25 }
26 let (win_id, win_node) = root.make_node(&wids.iter().map(|x| x.0).collect::<Vec<_>>());
27 wids.push((win_id, win_node));
28 let activation_handler = crate::fltk_adapter::FltkActivationHandler { wids, win_id };
29 let adapter = { Adapter::new(&root, activation_handler) };
30 Self {
31 adapter,
32 root,
33 widgets,
34 }
35 }
36}
37
38pub trait AccessibleApp {
39 fn run_with_accessibility(&self, ac: AccessibilityContext) -> Result<(), FltkError>;
40}
41
42impl AccessibleApp for app::App {
43 fn run_with_accessibility(&self, mut ac: AccessibilityContext) -> Result<(), FltkError> {
44 ac.root.handle({
45 let mut adapter = ac.adapter.clone();
46 move |root_window, ev| {
47 match ev {
48 Event::KeyUp => {
49 let mut wids = vec![];
50 for w in &ac.widgets {
51 let n = w.make_node(&[]);
52 wids.push(n);
53 }
54
55 let (win_id, win_node) =
56 root_window.make_node(&wids.iter().map(|x| x.0).collect::<Vec<_>>());
57 wids.push((win_id, win_node));
58
59 if let Some(focused) = fltk::app::focus() {
60 let node_id = NodeId(focused.as_widget_ptr() as _);
61 adapter.update_if_active(|| TreeUpdate {
62 nodes: wids,
63 tree: None,
64 focus: node_id,
65 });
66 }
67 false
68 }
69 _ => false,
70 }
71 }
72 });
73 self.run()
74 }
75}