diff --git a/Cargo.lock b/Cargo.lock index f787c3a41..73d928863 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,6 +56,7 @@ name = "accesskit_consumer" version = "0.19.1" dependencies = [ "accesskit", + "immutable-chunkmap", ] [[package]] @@ -430,6 +431,18 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -666,7 +679,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.7.4", + "libloading", ] [[package]] @@ -829,6 +842,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-core" version = "0.3.27" @@ -957,6 +976,17 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "immutable-chunkmap" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374b75d1b5a9df2c4d9392f21a9e821113543ffc49571b3428d8e161802f8cc7" +dependencies = [ + "arrayvec", + "packed_struct", + "packed_struct_codegen", +] + [[package]] name = "indexmap" version = "1.9.2" @@ -1051,16 +1081,6 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - [[package]] name = "libloading" version = "0.8.3" @@ -1352,6 +1372,27 @@ dependencies = [ "ttf-parser", ] +[[package]] +name = "packed_struct" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36b29691432cc9eff8b282278473b63df73bea49bc3ec5e67f31a3ae9c3ec190" +dependencies = [ + "bitvec", + "packed_struct_codegen", +] + +[[package]] +name = "packed_struct_codegen" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd6706dfe50d53e0f6aa09e12c034c44faacd23e966ae5a209e8bdb8f179f98" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "parking" version = "2.0.0" @@ -1566,6 +1607,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.5" @@ -1949,6 +1996,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.12.11" @@ -2721,6 +2774,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11-dl" version = "2.21.0" @@ -2741,7 +2803,7 @@ dependencies = [ "as-raw-xcb-connection", "gethostname", "libc", - "libloading 0.8.3", + "libloading", "once_cell", "rustix 0.38.21", "x11rb-protocol", diff --git a/consumer/Cargo.toml b/consumer/Cargo.toml index f32a387be..5c9b58dbd 100644 --- a/consumer/Cargo.toml +++ b/consumer/Cargo.toml @@ -13,3 +13,4 @@ rust-version.workspace = true [dependencies] accesskit = { version = "0.14.0", path = "../common" } +immutable-chunkmap = "2.0.4" diff --git a/consumer/src/filters.rs b/consumer/src/filters.rs index 41e0ecc83..f13b2cc4f 100644 --- a/consumer/src/filters.rs +++ b/consumer/src/filters.rs @@ -5,7 +5,7 @@ use accesskit::Role; -use crate::node::{DetachedNode, Node, NodeState}; +use crate::node::Node; #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] pub enum FilterResult { @@ -14,7 +14,11 @@ pub enum FilterResult { ExcludeSubtree, } -fn common_filter_base(node: &NodeState) -> FilterResult { +pub fn common_filter(node: &Node) -> FilterResult { + if node.is_focused() { + return FilterResult::Include; + } + if node.is_hidden() { return FilterResult::ExcludeSubtree; } @@ -27,20 +31,6 @@ fn common_filter_base(node: &NodeState) -> FilterResult { FilterResult::Include } -pub fn common_filter(node: &Node) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - common_filter_base(node.state()) -} - -pub fn common_filter_detached(node: &DetachedNode) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - common_filter_base(node.state()) -} - pub fn common_filter_with_root_exception(node: &Node) -> FilterResult { if node.is_root() { return FilterResult::Include; diff --git a/consumer/src/lib.rs b/consumer/src/lib.rs index ce294ddee..c809f7a31 100644 --- a/consumer/src/lib.rs +++ b/consumer/src/lib.rs @@ -7,12 +7,10 @@ pub(crate) mod tree; pub use tree::{ChangeHandler as TreeChangeHandler, State as TreeState, Tree}; pub(crate) mod node; -pub use node::{DetachedNode, Node, NodeState}; +pub use node::Node; pub(crate) mod filters; -pub use filters::{ - common_filter, common_filter_detached, common_filter_with_root_exception, FilterResult, -}; +pub use filters::{common_filter, common_filter_with_root_exception, FilterResult}; pub(crate) mod iterators; diff --git a/consumer/src/node.rs b/consumer/src/node.rs index b471dc382..9941f3a50 100644 --- a/consumer/src/node.rs +++ b/consumer/src/node.rs @@ -8,7 +8,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE.chromium file. -use std::{iter::FusedIterator, ops::Deref, sync::Arc}; +use std::{iter::FusedIterator, sync::Arc}; use accesskit::{ Action, Affine, DefaultActionVerb, Live, Node as NodeData, NodeId, Point, Rect, Role, @@ -26,8 +26,7 @@ use crate::tree::State as TreeState; pub(crate) struct ParentAndIndex(pub(crate) NodeId, pub(crate) usize); #[derive(Clone)] -pub struct NodeState { - pub(crate) id: NodeId, +pub(crate) struct NodeState { pub(crate) parent_and_index: Option, pub(crate) data: Arc, } @@ -35,57 +34,36 @@ pub struct NodeState { #[derive(Copy, Clone)] pub struct Node<'a> { pub tree_state: &'a TreeState, + pub(crate) id: NodeId, pub(crate) state: &'a NodeState, } -impl NodeState { - pub(crate) fn data(&self) -> &NodeData { - &self.data - } -} - impl<'a> Node<'a> { - pub fn detached(&self) -> DetachedNode { - DetachedNode { - state: self.state.clone(), - is_focused: self.is_focused(), - is_root: self.is_root(), - name: self.name(), - description: self.description(), - value: self.value(), - live: self.live(), - supports_text_ranges: self.supports_text_ranges(), - } + pub(crate) fn data(&self) -> &NodeData { + &self.state.data } pub fn is_focused(&self) -> bool { self.tree_state.focus_id() == Some(self.id()) } -} -impl NodeState { pub fn is_focusable(&self) -> bool { self.supports_action(Action::Focus) } -} -impl<'a> Node<'a> { pub fn is_root(&self) -> bool { // Don't check for absence of a parent node, in case a non-root node // somehow gets detached from the tree. self.id() == self.tree_state.root_id() } -} -impl NodeState { pub fn parent_id(&self) -> Option { - self.parent_and_index + self.state + .parent_and_index .as_ref() .map(|ParentAndIndex(id, _)| *id) } -} -impl<'a> Node<'a> { pub fn parent(&self) -> Option> { self.parent_id() .map(|id| self.tree_state.node_by_id(id).unwrap()) @@ -109,21 +87,17 @@ impl<'a> Node<'a> { (self.tree_state.node_by_id(*parent).unwrap(), *index) }) } -} -impl NodeState { pub fn child_ids( &self, ) -> impl DoubleEndedIterator + ExactSizeIterator + FusedIterator + '_ { - let data = &self.data; + let data = &self.state.data; data.children().iter().copied() } -} -impl<'a> Node<'a> { pub fn children( &self, ) -> impl DoubleEndedIterator> @@ -131,9 +105,10 @@ impl<'a> Node<'a> { + FusedIterator> + 'a { let state = self.tree_state; - self.state - .child_ids() - .map(move |id| state.node_by_id(id).unwrap()) + let data = &self.state.data; + data.children() + .iter() + .map(move |id| state.node_by_id(*id).unwrap()) } pub fn filtered_children( @@ -244,9 +219,7 @@ impl<'a> Node<'a> { } false } -} -impl NodeState { /// Returns the transform defined directly on this node, or the identity /// transform, without taking into account transforms on ancestors. pub fn direct_transform(&self) -> Affine { @@ -254,9 +227,7 @@ impl NodeState { .transform() .map_or(Affine::IDENTITY, |value| *value) } -} -impl<'a> Node<'a> { /// Returns the combined affine transform of this node and its ancestors, /// up to and including the root of this node's tree. pub fn transform(&self) -> Affine { @@ -277,31 +248,25 @@ impl<'a> Node<'a> { }; parent_transform * self.direct_transform() } -} -impl NodeState { pub fn raw_bounds(&self) -> Option { self.data().bounds() } -} -impl<'a> Node<'a> { pub fn has_bounds(&self) -> bool { - self.state.raw_bounds().is_some() + self.raw_bounds().is_some() } /// Returns the node's transformed bounding box relative to the tree's /// container (e.g. window). pub fn bounding_box(&self) -> Option { - self.state - .raw_bounds() + self.raw_bounds() .as_ref() .map(|rect| self.transform().transform_rect_bbox(*rect)) } pub(crate) fn bounding_box_in_coordinate_space(&self, other: &Node) -> Option { - self.state - .raw_bounds() + self.raw_bounds() .as_ref() .map(|rect| self.relative_transform(other).transform_rect_bbox(*rect)) } @@ -325,7 +290,7 @@ impl<'a> Node<'a> { } if filter_result == FilterResult::Include { - if let Some(rect) = &self.state.raw_bounds() { + if let Some(rect) = &self.raw_bounds() { if rect.contains(point) { return Some((*self, point)); } @@ -344,9 +309,7 @@ impl<'a> Node<'a> { ) -> Option> { self.hit_test(point, filter).map(|(node, _)| node) } -} -impl NodeState { pub fn id(&self) -> NodeId { self.id } @@ -561,9 +524,7 @@ impl<'a> Node<'a> { pub fn has_value(&self) -> bool { self.data().value().is_some() || (self.supports_text_ranges() && !self.is_multiline()) } -} -impl NodeState { pub fn is_read_only_supported(&self) -> bool { self.is_text_input() || matches!( @@ -606,17 +567,13 @@ impl NodeState { | Role::Tooltip ) } -} -impl<'a> Node<'a> { pub fn live(&self) -> Live { self.data() .live() .unwrap_or_else(|| self.parent().map_or(Live::Off, |parent| parent.live())) } -} -impl NodeState { pub fn is_selected(&self) -> Option { self.data().is_selected() } @@ -632,9 +589,7 @@ impl NodeState { pub fn class_name(&self) -> Option<&str> { self.data().class_name() } -} -impl<'a> Node<'a> { pub fn index_path(&self) -> Vec { self.relative_index_path(self.tree_state.root_id()) } @@ -686,76 +641,6 @@ impl<'a> Node<'a> { } None } - - pub fn state(&self) -> &'a NodeState { - self.state - } -} - -impl<'a> Deref for Node<'a> { - type Target = NodeState; - - fn deref(&self) -> &NodeState { - self.state - } -} - -#[derive(Clone)] -pub struct DetachedNode { - pub(crate) state: NodeState, - pub(crate) is_focused: bool, - pub(crate) is_root: bool, - pub(crate) name: Option, - pub(crate) description: Option, - pub(crate) value: Option, - pub(crate) live: Live, - pub(crate) supports_text_ranges: bool, -} - -impl DetachedNode { - pub fn is_focused(&self) -> bool { - self.is_focused - } - - pub fn is_root(&self) -> bool { - self.is_root - } - - pub fn name(&self) -> Option { - self.name.clone() - } - - pub fn description(&self) -> Option { - self.description.clone() - } - - pub fn value(&self) -> Option { - self.value.clone() - } - - pub fn has_value(&self) -> bool { - self.value.is_some() - } - - pub fn live(&self) -> Live { - self.live - } - - pub fn supports_text_ranges(&self) -> bool { - self.supports_text_ranges - } - - pub fn state(&self) -> &NodeState { - &self.state - } -} - -impl Deref for DetachedNode { - type Target = NodeState; - - fn deref(&self) -> &NodeState { - &self.state - } } #[cfg(test)] diff --git a/consumer/src/tree.rs b/consumer/src/tree.rs index ae95ac895..d3638fced 100644 --- a/consumer/src/tree.rs +++ b/consumer/src/tree.rs @@ -3,41 +3,36 @@ // the LICENSE-APACHE file) or the MIT license (found in // the LICENSE-MIT file), at your option. -use accesskit::{Live, Node as NodeData, NodeId, Tree as TreeData, TreeUpdate}; +use accesskit::{Node as NodeData, NodeId, Tree as TreeData, TreeUpdate}; +use immutable_chunkmap::map::MapM as ChunkMap; use std::{ collections::{HashMap, HashSet}, sync::Arc, }; -use crate::node::{DetachedNode, Node, NodeState, ParentAndIndex}; +use crate::node::{Node, NodeState, ParentAndIndex}; #[derive(Clone)] pub struct State { - pub(crate) nodes: HashMap, + pub(crate) nodes: ChunkMap, pub(crate) data: TreeData, focus: NodeId, is_host_focused: bool, } -struct InternalFocusChange { - old_focus: Option, - new_focus_old_node: Option, -} - #[derive(Default)] struct InternalChanges { added_node_ids: HashSet, - updated_nodes: HashMap, - focus_change: Option, - removed_nodes: HashMap, + updated_node_ids: HashSet, + removed_node_ids: HashSet, } impl State { fn validate_global(&self) { - if !self.nodes.contains_key(&self.data.root) { + if self.nodes.get_key(&self.data.root).is_none() { panic!("Root id #{} is not in the node list", self.data.root.0); } - if !self.nodes.contains_key(&self.focus) { + if self.nodes.get_key(&self.focus).is_none() { panic!("Focused id #{} is not in the node list", self.focus.0); } } @@ -48,20 +43,17 @@ impl State { is_host_focused: bool, mut changes: Option<&mut InternalChanges>, ) { - // First, if we're collecting changes, get the accurate state - // of any updated nodes. + // First, if we're collecting changes, collect the IDS of any nodes + // in the update that were in the previous state. if let Some(changes) = &mut changes { for (node_id, _) in &update.nodes { - if let Some(old_node) = self.node_by_id(*node_id) { - let old_node = old_node.detached(); - changes.updated_nodes.insert(*node_id, old_node); + if self.nodes.get(node_id).is_some() { + changes.updated_node_ids.insert(*node_id); } } } let mut orphans = HashSet::new(); - let old_focus_id = self.is_host_focused.then_some(self.focus); - let old_root_id = self.data.root; if let Some(tree) = update.tree { if tree.root != self.data.root { @@ -75,18 +67,17 @@ impl State { let mut pending_children = HashMap::new(); fn add_node( - nodes: &mut HashMap, + nodes: &mut ChunkMap, changes: &mut Option<&mut InternalChanges>, parent_and_index: Option, id: NodeId, data: NodeData, ) { let state = NodeState { - id, parent_and_index, data: Arc::new(data), }; - nodes.insert(id, state); + nodes.insert_cow(id, state); if let Some(changes) = changes { changes.added_node_ids.insert(id); } @@ -105,7 +96,7 @@ impl State { } orphans.remove(child_id); let parent_and_index = ParentAndIndex(node_id, child_index); - if let Some(child_state) = self.nodes.get_mut(child_id) { + if let Some(child_state) = self.nodes.get_mut_cow(child_id) { if child_state.parent_and_index != Some(parent_and_index) { child_state.parent_and_index = Some(parent_and_index); } @@ -123,7 +114,7 @@ impl State { seen_child_ids.insert(child_id); } - if let Some(node_state) = self.nodes.get_mut(&node_id) { + if let Some(node_state) = self.nodes.get_mut_cow(&node_id) { if node_id == root { node_state.parent_and_index = None; } @@ -155,29 +146,14 @@ impl State { panic!("TreeUpdate's nodes include {} children ids which are neither in the current tree nor the id of another node from the update: {}", pending_children.len(), short_node_list(pending_children.keys())); } - if update.focus != self.focus || is_host_focused != self.is_host_focused { - let old_focus = old_focus_id.map(|id| self.node_by_id(id).unwrap().detached()); - let new_focus = is_host_focused.then_some(update.focus); - if let Some(changes) = &mut changes { - changes.focus_change = Some(InternalFocusChange { - old_focus, - new_focus_old_node: new_focus - .and_then(|id| { - (!changes.updated_nodes.contains_key(&id)) - .then(|| self.node_by_id(id).map(|node| node.detached())) - }) - .flatten(), - }); - } - self.focus = update.focus; - self.is_host_focused = is_host_focused; - } + self.focus = update.focus; + self.is_host_focused = is_host_focused; if !orphans.is_empty() { let mut to_remove = HashSet::new(); fn traverse_orphan( - nodes: &HashMap, + nodes: &ChunkMap, to_remove: &mut HashSet, id: NodeId, ) { @@ -193,19 +169,9 @@ impl State { } for id in to_remove { - if let Some(old_node_state) = self.nodes.remove(&id) { + if self.nodes.remove_cow(&id).is_some() { if let Some(changes) = &mut changes { - let old_node = DetachedNode { - state: old_node_state, - is_focused: old_focus_id == Some(id), - is_root: old_root_id == id, - name: None, - description: None, - value: None, - live: Live::Off, - supports_text_ranges: false, - }; - changes.removed_nodes.insert(id, old_node); + changes.removed_node_ids.insert(id); } } } @@ -250,12 +216,13 @@ impl State { } pub fn has_node(&self, id: NodeId) -> bool { - self.nodes.contains_key(&id) + self.nodes.get(&id).is_some() } pub fn node_by_id(&self, id: NodeId) -> Option> { self.nodes.get(&id).map(|node_state| Node { tree_state: self, + id, state: node_state, }) } @@ -295,21 +262,9 @@ impl State { pub trait ChangeHandler { fn node_added(&mut self, node: &Node); - fn node_updated(&mut self, old_node: &DetachedNode, new_node: &Node); - fn focus_moved( - &mut self, - old_node: Option<&DetachedNode>, - new_node: Option<&Node>, - current_state: &State, - ); - /// The tree update process doesn't currently collect all possible information - /// about removed nodes. The following methods don't accurately reflect - /// the full state of the old node: - /// - /// * [`DetachedNode::name`] - /// * [`DetachedNode::live`] - /// * [`DetachedNode::supports_text_ranges`] - fn node_removed(&mut self, node: &DetachedNode, current_state: &State); + fn node_updated(&mut self, old_node: &Node, new_node: &Node); + fn focus_moved(&mut self, old_node: Option<&Node>, new_node: Option<&Node>); + fn node_removed(&mut self, node: &Node); } pub struct Tree { @@ -322,7 +277,7 @@ impl Tree { panic!("Tried to initialize the accessibility tree without a root tree. TreeUpdate::tree must be Some."); }; let mut state = State { - nodes: HashMap::new(), + nodes: ChunkMap::new(), data: tree, focus: initial_state.focus, is_host_focused, @@ -341,9 +296,10 @@ impl Tree { handler: &mut impl ChangeHandler, ) { let mut changes = InternalChanges::default(); + let old_state = self.state.clone(); self.state .update(update, self.state.is_host_focused, Some(&mut changes)); - self.process_changes(changes, handler); + self.process_changes(old_state, changes, handler); } pub fn update_host_focus_state(&mut self, is_host_focused: bool) { @@ -356,25 +312,33 @@ impl Tree { handler: &mut impl ChangeHandler, ) { let mut changes = InternalChanges::default(); + let old_state = self.state.clone(); self.state .update_host_focus_state(is_host_focused, Some(&mut changes)); - self.process_changes(changes, handler); + self.process_changes(old_state, changes, handler); } - fn process_changes(&self, changes: InternalChanges, handler: &mut impl ChangeHandler) { + fn process_changes( + &self, + old_state: State, + changes: InternalChanges, + handler: &mut impl ChangeHandler, + ) { for id in &changes.added_node_ids { let node = self.state.node_by_id(*id).unwrap(); handler.node_added(&node); } - for (id, old_node) in &changes.updated_nodes { + for id in &changes.updated_node_ids { + let old_node = old_state.node_by_id(*id).unwrap(); let new_node = self.state.node_by_id(*id).unwrap(); - handler.node_updated(old_node, &new_node); + handler.node_updated(&old_node, &new_node); } - if let Some(focus_change) = changes.focus_change { - if let Some(old_node) = &focus_change.old_focus { + if old_state.focus_id() != self.state.focus_id() { + let old_node = old_state.focus(); + if let Some(old_node) = &old_node { let id = old_node.id(); - if !changes.updated_nodes.contains_key(&id) - && !changes.removed_nodes.contains_key(&id) + if !changes.updated_node_ids.contains(&id) + && !changes.removed_node_ids.contains(&id) { if let Some(old_node_new_version) = self.state.node_by_id(id) { handler.node_updated(old_node, &old_node_new_version); @@ -382,23 +346,20 @@ impl Tree { } } let new_node = self.state.focus(); - if let Some(new_node) = new_node { + if let Some(new_node) = &new_node { let id = new_node.id(); - if !changes.added_node_ids.contains(&id) && !changes.updated_nodes.contains_key(&id) + if !changes.added_node_ids.contains(&id) && !changes.updated_node_ids.contains(&id) { - if let Some(new_node_old_version) = focus_change.new_focus_old_node { - handler.node_updated(&new_node_old_version, &new_node); + if let Some(new_node_old_version) = old_state.node_by_id(id) { + handler.node_updated(&new_node_old_version, new_node); } } } - handler.focus_moved( - focus_change.old_focus.as_ref(), - new_node.as_ref(), - &self.state, - ); + handler.focus_moved(old_node.as_ref(), new_node.as_ref()); } - for node in changes.removed_nodes.values() { - handler.node_removed(node, &self.state); + for id in &changes.removed_node_ids { + let node = old_state.node_by_id(*id).unwrap(); + handler.node_removed(&node); } } @@ -510,7 +471,7 @@ mod tests { } unexpected_change(); } - fn node_updated(&mut self, old_node: &crate::DetachedNode, new_node: &crate::Node) { + fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) { if new_node.id() == NodeId(0) && old_node.data().children().is_empty() && new_node.data().children() == [NodeId(1)] @@ -522,17 +483,12 @@ mod tests { } fn focus_moved( &mut self, - _old_node: Option<&crate::DetachedNode>, + _old_node: Option<&crate::Node>, _new_node: Option<&crate::Node>, - _current_state: &crate::TreeState, ) { unexpected_change(); } - fn node_removed( - &mut self, - _node: &crate::DetachedNode, - _current_state: &crate::TreeState, - ) { + fn node_removed(&mut self, _node: &crate::Node) { unexpected_change(); } } @@ -585,7 +541,7 @@ mod tests { fn node_added(&mut self, _node: &crate::Node) { unexpected_change(); } - fn node_updated(&mut self, old_node: &crate::DetachedNode, new_node: &crate::Node) { + fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) { if new_node.id() == NodeId(0) && old_node.data().children() == [NodeId(1)] && new_node.data().children().is_empty() @@ -597,17 +553,12 @@ mod tests { } fn focus_moved( &mut self, - _old_node: Option<&crate::DetachedNode>, + _old_node: Option<&crate::Node>, _new_node: Option<&crate::Node>, - _current_state: &crate::TreeState, ) { unexpected_change(); } - fn node_removed( - &mut self, - node: &crate::DetachedNode, - _current_state: &crate::TreeState, - ) { + fn node_removed(&mut self, node: &crate::Node) { if node.id() == NodeId(1) { self.got_removed_child_node = true; return; @@ -660,7 +611,7 @@ mod tests { fn node_added(&mut self, _node: &crate::Node) { unexpected_change(); } - fn node_updated(&mut self, old_node: &crate::DetachedNode, new_node: &crate::Node) { + fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) { if old_node.id() == NodeId(1) && new_node.id() == NodeId(1) && old_node.is_focused() @@ -681,9 +632,8 @@ mod tests { } fn focus_moved( &mut self, - old_node: Option<&crate::DetachedNode>, + old_node: Option<&crate::Node>, new_node: Option<&crate::Node>, - _current_state: &crate::TreeState, ) { if let (Some(old_node), Some(new_node)) = (old_node, new_node) { if old_node.id() == NodeId(1) && new_node.id() == NodeId(2) { @@ -693,11 +643,7 @@ mod tests { } unexpected_change(); } - fn node_removed( - &mut self, - _node: &crate::DetachedNode, - _current_state: &crate::TreeState, - ) { + fn node_removed(&mut self, _node: &crate::Node) { unexpected_change(); } } @@ -757,7 +703,7 @@ mod tests { fn node_added(&mut self, _node: &crate::Node) { unexpected_change(); } - fn node_updated(&mut self, old_node: &crate::DetachedNode, new_node: &crate::Node) { + fn node_updated(&mut self, old_node: &crate::Node, new_node: &crate::Node) { if new_node.id() == NodeId(1) && old_node.name() == Some("foo".into()) && new_node.name() == Some("bar".into()) @@ -769,17 +715,12 @@ mod tests { } fn focus_moved( &mut self, - _old_node: Option<&crate::DetachedNode>, + _old_node: Option<&crate::Node>, _new_node: Option<&crate::Node>, - _current_state: &crate::TreeState, ) { unexpected_change(); } - fn node_removed( - &mut self, - _node: &crate::DetachedNode, - _current_state: &crate::TreeState, - ) { + fn node_removed(&mut self, _node: &crate::Node) { unexpected_change(); } }