diff --git a/common/Cargo.toml b/common/Cargo.toml index 55c61bd88..8448357af 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -17,7 +17,7 @@ features = ["schemars", "serde"] enumset = "1.0.8" kurbo = "0.8.3" schemars_lib = { package = "schemars", version = "0.8.7", features = ["enumset"], optional = true } -serde_lib = { package = "serde", version = "1.0", features = ["derive"], optional = true } +serde_lib = { package = "serde", version = "1.0", features = ["derive", "rc"], optional = true } [features] schemars = ["serde", "schemars_lib", "kurbo/schemars"] diff --git a/common/src/lib.rs b/common/src/lib.rs index 15000e4d7..6455579bf 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -22,6 +22,7 @@ use serde_lib::{Deserialize, Serialize}; use std::{ num::{NonZeroU128, NonZeroU64}, ops::Range, + sync::Arc, }; /// The type of an accessibility node. @@ -1221,7 +1222,7 @@ pub struct TreeUpdate { /// placeholder must be updated within the same `TreeUpdate`, otherwise /// it's a fatal error. This guarantees the tree is always complete /// before or after a `TreeUpdate`. - pub nodes: Vec<(NodeId, Node)>, + pub nodes: Vec<(NodeId, Arc)>, /// Rarely updated information about the tree as a whole. This may be omitted /// if it has not changed since the previous update, but providing the same diff --git a/consumer/src/lib.rs b/consumer/src/lib.rs index cf27893df..6d9ada709 100644 --- a/consumer/src/lib.rs +++ b/consumer/src/lib.rs @@ -47,7 +47,7 @@ mod tests { } pub fn test_tree() -> Arc { - let root = Node { + let root = Arc::new(Node { role: Role::RootWebArea, children: vec![ PARAGRAPH_0_ID, @@ -56,19 +56,19 @@ mod tests { PARAGRAPH_3_IGNORED_ID, ], ..Default::default() - }; - let paragraph_0 = Node { + }); + let paragraph_0 = Arc::new(Node { role: Role::Paragraph, children: vec![STATIC_TEXT_0_0_IGNORED_ID], ..Default::default() - }; - let static_text_0_0_ignored = Node { + }); + let static_text_0_0_ignored = Arc::new(Node { role: Role::StaticText, ignored: true, name: Some("static_text_0_0_ignored".into()), ..Default::default() - }; - let paragraph_1_ignored = Node { + }); + let paragraph_1_ignored = Arc::new(Node { role: Role::Paragraph, transform: Some(Box::new(Affine::translate(Vec2::new(10.0, 40.0)))), bounds: Some(Rect { @@ -80,8 +80,8 @@ mod tests { children: vec![STATIC_TEXT_1_0_ID], ignored: true, ..Default::default() - }; - let static_text_1_0 = Node { + }); + let static_text_1_0 = Arc::new(Node { role: Role::StaticText, bounds: Some(Rect { x0: 10.0, @@ -91,18 +91,18 @@ mod tests { }), name: Some("static_text_1_0".into()), ..Default::default() - }; - let paragraph_2 = Node { + }); + let paragraph_2 = Arc::new(Node { role: Role::Paragraph, children: vec![STATIC_TEXT_2_0_ID], ..Default::default() - }; - let static_text_2_0 = Node { + }); + let static_text_2_0 = Arc::new(Node { role: Role::StaticText, name: Some("static_text_2_0".into()), ..Default::default() - }; - let paragraph_3_ignored = Node { + }); + let paragraph_3_ignored = Arc::new(Node { role: Role::Paragraph, children: vec![ EMPTY_CONTAINER_3_0_IGNORED_ID, @@ -112,34 +112,34 @@ mod tests { ], ignored: true, ..Default::default() - }; - let empty_container_3_0_ignored = Node { + }); + let empty_container_3_0_ignored = Arc::new(Node { role: Role::GenericContainer, ignored: true, ..Default::default() - }; - let link_3_1_ignored = Node { + }); + let link_3_1_ignored = Arc::new(Node { role: Role::Link, children: vec![STATIC_TEXT_3_1_0_ID], ignored: true, linked: true, ..Default::default() - }; - let static_text_3_1_0 = Node { + }); + let static_text_3_1_0 = Arc::new(Node { role: Role::StaticText, name: Some("static_text_3_1_0".into()), ..Default::default() - }; - let button_3_2 = Node { + }); + let button_3_2 = Arc::new(Node { role: Role::Button, name: Some("button_3_2".into()), ..Default::default() - }; - let empty_container_3_3_ignored = Node { + }); + let empty_container_3_3_ignored = Arc::new(Node { role: Role::GenericContainer, ignored: true, ..Default::default() - }; + }); let initial_update = TreeUpdate { nodes: vec![ (ROOT_ID, root), diff --git a/consumer/src/node.rs b/consumer/src/node.rs index 26cb66759..4fe6996e8 100644 --- a/consumer/src/node.rs +++ b/consumer/src/node.rs @@ -542,7 +542,7 @@ impl Node<'_> { mod tests { use accesskit::kurbo::{Point, Rect}; use accesskit::{Node, NodeId, Role, Tree, TreeUpdate}; - use std::num::NonZeroU128; + use std::{num::NonZeroU128, sync::Arc}; use crate::tests::*; @@ -796,18 +796,18 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { role: Role::Window, children: vec![NODE_ID_2], ..Default::default() - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { role: Role::Button, ..Default::default() - }, + }), ), ], tree: Some(Tree::new(NODE_ID_1)), @@ -828,43 +828,43 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { role: Role::Window, children: vec![NODE_ID_2, NODE_ID_3, NODE_ID_4, NODE_ID_5], ..Default::default() - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { role: Role::CheckBox, labelled_by: vec![NODE_ID_3, NODE_ID_5], ..Default::default() - }, + }), ), ( NODE_ID_3, - Node { + Arc::new(Node { role: Role::StaticText, name: Some(LABEL_1.into()), ..Default::default() - }, + }), ), ( NODE_ID_4, - Node { + Arc::new(Node { role: Role::CheckBox, labelled_by: vec![NODE_ID_5], ..Default::default() - }, + }), ), ( NODE_ID_5, - Node { + Arc::new(Node { role: Role::StaticText, name: Some(LABEL_2.into()), ..Default::default() - }, + }), ), ], tree: Some(Tree::new(NODE_ID_1)), diff --git a/consumer/src/tree.rs b/consumer/src/tree.rs index e6b0f9a99..5fea6e3ac 100644 --- a/consumer/src/tree.rs +++ b/consumer/src/tree.rs @@ -17,7 +17,7 @@ pub(crate) struct ParentAndIndex(pub(crate) NodeId, pub(crate) usize); pub(crate) struct NodeState { pub(crate) id: NodeId, pub(crate) parent_and_index: Option, - pub(crate) data: Box, + pub(crate) data: Arc, } #[derive(Clone)] @@ -65,12 +65,12 @@ impl State { changes: &mut Option<&mut InternalChanges>, parent_and_index: Option, id: NodeId, - data: NodeData, + data: Arc, ) { let state = NodeState { id, parent_and_index, - data: Box::new(data), + data, }; nodes.insert(id, state); if let Some(changes) = changes { @@ -113,8 +113,8 @@ impl State { orphans.insert(*child_id); } } - if *node_state.data != node_data { - node_state.data = Box::new(node_data); + if *node_state.data != *node_data { + node_state.data = node_data; if let Some(changes) = &mut changes { changes.updated_node_ids.insert(node_id); } @@ -184,9 +184,9 @@ impl State { fn serialize(&self) -> TreeUpdate { let mut nodes = Vec::new(); - fn traverse(state: &State, nodes: &mut Vec<(NodeId, NodeData)>, id: NodeId) { + fn traverse(state: &State, nodes: &mut Vec<(NodeId, Arc)>, id: NodeId) { let node = state.nodes.get(&id).unwrap(); - nodes.push((id, (*node.data).clone())); + nodes.push((id, Arc::clone(&node.data))); for child_id in node.data.children.iter() { traverse(state, nodes, *child_id); @@ -349,7 +349,7 @@ impl Tree { #[cfg(test)] mod tests { use accesskit::{Node, NodeId, Role, Tree, TreeUpdate}; - use std::num::NonZeroU128; + use std::{num::NonZeroU128, sync::Arc}; use crate::tests::NullActionHandler; @@ -362,10 +362,10 @@ mod tests { let update = TreeUpdate { nodes: vec![( NODE_ID_1, - Node { + Arc::new(Node { role: Role::Window, ..Node::default() - }, + }), )], tree: Some(Tree::new(NODE_ID_1)), focus: None, @@ -382,25 +382,25 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { role: Role::Window, children: vec![NODE_ID_2, NODE_ID_3], ..Default::default() - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { role: Role::Button, ..Default::default() - }, + }), ), ( NODE_ID_3, - Node { + Arc::new(Node { role: Role::Button, ..Default::default() - }, + }), ), ], tree: Some(Tree::new(NODE_ID_1)), @@ -426,7 +426,7 @@ mod tests { ..Default::default() }; let first_update = TreeUpdate { - nodes: vec![(NODE_ID_1, root_node.clone())], + nodes: vec![(NODE_ID_1, Arc::new(root_node.clone()))], tree: Some(Tree::new(NODE_ID_1)), focus: None, }; @@ -436,17 +436,17 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { children: vec![NODE_ID_2], ..root_node - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { role: Role::RootWebArea, ..Default::default() - }, + }), ), ], tree: None, @@ -493,17 +493,17 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { children: vec![NODE_ID_2], ..root_node.clone() - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { role: Role::RootWebArea, ..Default::default() - }, + }), ), ], tree: Some(Tree::new(NODE_ID_1)), @@ -512,7 +512,7 @@ mod tests { let tree = super::Tree::new(first_update, Box::new(NullActionHandler {})); assert_eq!(1, tree.read().root().children().count()); let second_update = TreeUpdate { - nodes: vec![(NODE_ID_1, root_node)], + nodes: vec![(NODE_ID_1, Arc::new(root_node))], tree: None, focus: None, }; @@ -548,25 +548,25 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { role: Role::Window, children: vec![NODE_ID_2, NODE_ID_3], ..Default::default() - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { role: Role::Button, ..Default::default() - }, + }), ), ( NODE_ID_3, - Node { + Arc::new(Node { role: Role::Button, ..Default::default() - }, + }), ), ], tree: Some(Tree::new(NODE_ID_1)), @@ -630,18 +630,18 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { role: Role::Window, children: vec![NODE_ID_2], ..Default::default() - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { name: Some("foo".into()), ..child_node.clone() - }, + }), ), ], tree: Some(Tree::new(NODE_ID_1)), @@ -655,10 +655,10 @@ mod tests { let second_update = TreeUpdate { nodes: vec![( NODE_ID_2, - Node { + Arc::new(Node { name: Some("bar".into()), ..child_node - }, + }), )], tree: None, focus: None, @@ -693,25 +693,25 @@ mod tests { nodes: vec![ ( NODE_ID_1, - Node { + Arc::new(Node { role: Role::Window, children: vec![NODE_ID_2, NODE_ID_3], ..Default::default() - }, + }), ), ( NODE_ID_2, - Node { + Arc::new(Node { role: Role::Button, ..Default::default() - }, + }), ), ( NODE_ID_3, - Node { + Arc::new(Node { role: Role::Button, ..Default::default() - }, + }), ), ], tree: Some(Tree::new(NODE_ID_1)), diff --git a/platforms/windows/examples/hello_world.rs b/platforms/windows/examples/hello_world.rs index e82aefc43..bbbad67f0 100644 --- a/platforms/windows/examples/hello_world.rs +++ b/platforms/windows/examples/hello_world.rs @@ -1,6 +1,6 @@ // Based on the create_window sample in windows-samples-rs. -use std::{cell::RefCell, convert::TryInto, mem::drop, num::NonZeroU128, rc::Rc}; +use std::{cell::RefCell, convert::TryInto, mem::drop, num::NonZeroU128, rc::Rc, sync::Arc}; use accesskit::kurbo::Rect; use accesskit::{ @@ -73,30 +73,30 @@ const BUTTON_2_RECT: Rect = Rect { const SET_FOCUS_MSG: u32 = WM_USER; const DO_DEFAULT_ACTION_MSG: u32 = WM_USER + 1; -fn make_button(id: NodeId, name: &str) -> Node { +fn make_button(id: NodeId, name: &str) -> Arc { let rect = match id { BUTTON_1_ID => BUTTON_1_RECT, BUTTON_2_ID => BUTTON_2_RECT, _ => unreachable!(), }; - Node { + Arc::new(Node { role: Role::Button, bounds: Some(rect), name: Some(name.into()), focusable: true, default_action_verb: Some(DefaultActionVerb::Click), ..Default::default() - } + }) } fn get_initial_state() -> TreeUpdate { - let root = Node { + let root = Arc::new(Node { role: Role::Window, children: vec![BUTTON_1_ID, BUTTON_2_ID], name: Some(WINDOW_TITLE.into()), ..Default::default() - }; + }); let button_1 = make_button(BUTTON_1_ID, "Button 1"); let button_2 = make_button(BUTTON_2_ID, "Button 2"); TreeUpdate { @@ -141,18 +141,18 @@ impl WindowState { } else { "You pressed button 2" }; - let node = Node { + let node = Arc::new(Node { role: Role::StaticText, name: Some(name.into()), live: Some(Live::Polite), ..Default::default() - }; - let root = Node { + }); + let root = Arc::new(Node { role: Role::Window, children: vec![BUTTON_1_ID, BUTTON_2_ID, PRESSED_TEXT_ID], name: Some(WINDOW_TITLE.into()), ..Node::default() - }; + }); let update = TreeUpdate { nodes: vec![(PRESSED_TEXT_ID, node), (WINDOW_ID, root)], tree: None, diff --git a/platforms/windows/src/tests/simple.rs b/platforms/windows/src/tests/simple.rs index b8ba50157..0c7a4438c 100644 --- a/platforms/windows/src/tests/simple.rs +++ b/platforms/windows/src/tests/simple.rs @@ -3,7 +3,7 @@ // the LICENSE-APACHE file) or the MIT license (found in // the LICENSE-MIT file), at your option. -use std::{convert::TryInto, num::NonZeroU128}; +use std::{convert::TryInto, num::NonZeroU128, sync::Arc}; use accesskit::{ActionHandler, ActionRequest, Node, NodeId, Role, Tree, TreeUpdate}; use windows::{core::*, Win32::UI::Accessibility::*}; @@ -16,22 +16,22 @@ const WINDOW_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(1) }); const BUTTON_1_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(2) }); const BUTTON_2_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(3) }); -fn make_button(name: &str) -> Node { - Node { +fn make_button(name: &str) -> Arc { + Arc::new(Node { role: Role::Button, name: Some(name.into()), focusable: true, ..Default::default() - } + }) } fn get_initial_state() -> TreeUpdate { - let root = Node { + let root = Arc::new(Node { role: Role::Window, children: vec![BUTTON_1_ID, BUTTON_2_ID], name: Some(WINDOW_TITLE.into()), ..Default::default() - }; + }); let button_1 = make_button("Button 1"); let button_2 = make_button("Button 2"); TreeUpdate { diff --git a/platforms/windows/src/tests/subclassed.rs b/platforms/windows/src/tests/subclassed.rs index 67dc741c6..2efbbb9d2 100644 --- a/platforms/windows/src/tests/subclassed.rs +++ b/platforms/windows/src/tests/subclassed.rs @@ -3,7 +3,7 @@ // the LICENSE-APACHE file) or the MIT license (found in // the LICENSE-MIT file), at your option. -use std::num::NonZeroU128; +use std::{num::NonZeroU128, sync::Arc}; use accesskit::{ActionHandler, ActionRequest, Node, NodeId, Role, Tree, TreeUpdate}; use windows::Win32::{Foundation::*, UI::Accessibility::*}; @@ -21,22 +21,22 @@ const WINDOW_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(1) }); const BUTTON_1_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(2) }); const BUTTON_2_ID: NodeId = NodeId(unsafe { NonZeroU128::new_unchecked(3) }); -fn make_button(name: &str) -> Node { - Node { +fn make_button(name: &str) -> Arc { + Arc::new(Node { role: Role::Button, name: Some(name.into()), focusable: true, ..Default::default() - } + }) } fn get_initial_state() -> TreeUpdate { - let root = Node { + let root = Arc::new(Node { role: Role::Window, children: vec![BUTTON_1_ID, BUTTON_2_ID], name: Some(WINDOW_TITLE.into()), ..Default::default() - }; + }); let button_1 = make_button("Button 1"); let button_2 = make_button("Button 2"); TreeUpdate { diff --git a/platforms/winit/examples/simple.rs b/platforms/winit/examples/simple.rs index a8b122893..26f2a8e76 100644 --- a/platforms/winit/examples/simple.rs +++ b/platforms/winit/examples/simple.rs @@ -35,21 +35,21 @@ const BUTTON_2_RECT: Rect = Rect { y1: 100.0, }; -fn make_button(id: NodeId, name: &str) -> Node { +fn make_button(id: NodeId, name: &str) -> Arc { let rect = match id { BUTTON_1_ID => BUTTON_1_RECT, BUTTON_2_ID => BUTTON_2_RECT, _ => unreachable!(), }; - Node { + Arc::new(Node { role: Role::Button, bounds: Some(rect), name: Some(name.into()), focusable: true, default_action_verb: Some(DefaultActionVerb::Click), ..Default::default() - } + }) } #[derive(Debug)] @@ -90,18 +90,18 @@ impl State { } else { "You pressed button 2" }; - let node = Node { + let node = Arc::new(Node { role: Role::StaticText, name: Some(name.into()), live: Some(Live::Polite), ..Default::default() - }; - let root = Node { + }); + let root = Arc::new(Node { role: Role::Window, children: vec![BUTTON_1_ID, BUTTON_2_ID, PRESSED_TEXT_ID], name: Some(WINDOW_TITLE.into()), ..Default::default() - }; + }); let update = TreeUpdate { nodes: vec![(PRESSED_TEXT_ID, node), (WINDOW_ID, root)], tree: None, @@ -112,12 +112,12 @@ impl State { } fn initial_tree_update(state: &State) -> TreeUpdate { - let root = Node { + let root = Arc::new(Node { role: Role::Window, children: vec![BUTTON_1_ID, BUTTON_2_ID], name: Some(WINDOW_TITLE.into()), ..Default::default() - }; + }); let button_1 = make_button(BUTTON_1_ID, "Button 1"); let button_2 = make_button(BUTTON_2_ID, "Button 2"); TreeUpdate {