fltk_accesskit/
lib.rs

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}