From dda214bbfe7c64478a7b16421411b00de0526bd0 Mon Sep 17 00:00:00 2001 From: Arnold Loubriat Date: Fri, 6 Jun 2025 00:06:20 +0200 Subject: [PATCH] fix: Raise events when adding or removing nodes due to filtering on Unix --- platforms/atspi-common/src/adapter.rs | 67 +++++++++++++++++++++------ platforms/atspi-common/src/node.rs | 29 ++++++------ platforms/unix/src/atspi/bus.rs | 8 +++- 3 files changed, 73 insertions(+), 31 deletions(-) diff --git a/platforms/atspi-common/src/adapter.rs b/platforms/atspi-common/src/adapter.rs index ae5e8d087..ca53c4c8c 100644 --- a/platforms/atspi-common/src/adapter.rs +++ b/platforms/atspi-common/src/adapter.rs @@ -116,6 +116,59 @@ impl<'a> AdapterChangeHandler<'a> { self.remove_node(node); } + fn apply_filters( + &mut self, + old_node: &Node, + old_filter_result: FilterResult, + new_node: &Node, + new_filter_result: FilterResult, + ) { + let parent = new_node.filtered_parent(&filter); + if new_filter_result == FilterResult::Include { + if old_filter_result == FilterResult::ExcludeSubtree { + self.add_subtree(new_node); + } else { + self.add_node(new_node); + if let Some(parent) = parent { + for child in old_node.filtered_children(&filter) { + self.adapter + .emit_object_event(parent.id(), ObjectEvent::ChildRemoved(child.id())); + } + } + } + + if let Some(parent) = parent { + let position = parent + .filtered_children(&filter) + .position(|c| c.id() == new_node.id()) + .unwrap(); + self.adapter.emit_object_event( + parent.id(), + ObjectEvent::ChildAdded(position, new_node.id()), + ); + } + } else if old_filter_result == FilterResult::Include { + if new_filter_result == FilterResult::ExcludeSubtree { + self.remove_subtree(old_node); + } else { + self.remove_node(old_node); + if let Some(parent) = parent { + for (position, child) in new_node.filtered_children(&filter).enumerate() { + self.adapter.emit_object_event( + parent.id(), + ObjectEvent::ChildAdded(position, child.id()), + ); + } + } + } + + if let Some(parent) = parent { + self.adapter + .emit_object_event(parent.id(), ObjectEvent::ChildRemoved(old_node.id())); + } + } + } + fn emit_text_change_if_needed_parent(&mut self, old_node: &Node, new_node: &Node) { if !new_node.supports_text_ranges() || !old_node.supports_text_ranges() { return; @@ -287,19 +340,7 @@ impl TreeChangeHandler for AdapterChangeHandler<'_> { let filter_old = filter(old_node); let filter_new = filter(new_node); if filter_new != filter_old { - if filter_new == FilterResult::Include { - if filter_old == FilterResult::ExcludeSubtree { - self.add_subtree(new_node); - } else { - self.add_node(new_node); - } - } else if filter_old == FilterResult::Include { - if filter_new == FilterResult::ExcludeSubtree { - self.remove_subtree(old_node); - } else { - self.remove_node(old_node); - } - } + self.apply_filters(old_node, filter_old, new_node, filter_new); } else if filter_new == FilterResult::Include { let old_wrapper = NodeWrapper(old_node); let new_wrapper = NodeWrapper(new_node); diff --git a/platforms/atspi-common/src/node.rs b/platforms/atspi-common/src/node.rs index 2e47aa23e..40ddfa239 100644 --- a/platforms/atspi-common/src/node.rs +++ b/platforms/atspi-common/src/node.rs @@ -47,10 +47,6 @@ impl NodeWrapper<'_> { self.0.description() } - pub(crate) fn parent_id(&self) -> Option { - self.0.parent_id() - } - pub(crate) fn id(&self) -> NodeId { self.0.id() } @@ -540,17 +536,7 @@ impl NodeWrapper<'_> { )), ); } - let parent_id = self.parent_id(); - if parent_id != old.parent_id() { - let parent = self - .0 - .filtered_parent(&filter) - .map_or(NodeIdOrRoot::Root, |node| NodeIdOrRoot::Node(node.id())); - adapter.emit_object_event( - self.id(), - ObjectEvent::PropertyChanged(Property::Parent(parent)), - ); - } + self.notify_parent_change(adapter, old); let role = self.role(); if role != old.role() { adapter.emit_object_event( @@ -568,6 +554,17 @@ impl NodeWrapper<'_> { } } + pub(crate) fn notify_parent_change(&self, adapter: &Adapter, old: &NodeWrapper) { + let parent = self.0.filtered_parent(&filter); + if parent.map(|p| p.id()) != old.0.filtered_parent(&filter).map(|p| p.id()) { + let parent = parent.map_or(NodeIdOrRoot::Root, |node| NodeIdOrRoot::Node(node.id())); + adapter.emit_object_event( + self.id(), + ObjectEvent::PropertyChanged(Property::Parent(parent)), + ); + } + } + fn notify_bounds_changes( &self, window_bounds: &WindowBounds, @@ -581,7 +578,7 @@ impl NodeWrapper<'_> { } } - fn notify_children_changes(&self, adapter: &Adapter, old: &NodeWrapper<'_>) { + pub(crate) fn notify_children_changes(&self, adapter: &Adapter, old: &NodeWrapper<'_>) { let old_filtered_children = old.filtered_child_ids().collect::>(); let new_filtered_children = self.filtered_child_ids().collect::>(); for (index, child) in new_filtered_children.iter().enumerate() { diff --git a/platforms/unix/src/atspi/bus.rs b/platforms/unix/src/atspi/bus.rs index afeb9d098..30a4cceca 100644 --- a/platforms/unix/src/atspi/bus.rs +++ b/platforms/unix/src/atspi/bus.rs @@ -189,11 +189,15 @@ impl Bus { where T: zbus::object_server::Interface, { - map_or_ignoring_broken_pipe( + let result = map_or_ignoring_broken_pipe( self.conn.object_server().remove::(path).await, false, |result| result, - ) + ); + match result { + Err(zbus::Error::InterfaceNotFound) => Ok(false), + _ => result, + } } pub(crate) async fn emit_object_event(