From b3a1093315c69b0e1642a79c702707ed56d7fa8f Mon Sep 17 00:00:00 2001 From: Matt Campbell Date: Tue, 29 Aug 2023 11:58:34 -0500 Subject: [PATCH] fix: Use common filters across platform adapters (#287) --- consumer/src/filters.rs | 49 ++++++++++++++++++++++++++++++++ consumer/src/iterators.rs | 9 +----- consumer/src/lib.rs | 6 +++- consumer/src/node.rs | 3 +- platforms/macos/src/adapter.rs | 3 +- platforms/macos/src/event.rs | 3 +- platforms/macos/src/filters.rs | 8 ++++++ platforms/macos/src/lib.rs | 1 + platforms/macos/src/node.rs | 31 +------------------- platforms/unix/src/adapter.rs | 3 +- platforms/unix/src/filters.rs | 8 ++++++ platforms/unix/src/lib.rs | 1 + platforms/unix/src/node.rs | 30 +------------------ platforms/windows/src/adapter.rs | 3 +- platforms/windows/src/filters.rs | 9 ++++++ platforms/windows/src/lib.rs | 1 + platforms/windows/src/node.rs | 43 ++++------------------------ 17 files changed, 101 insertions(+), 110 deletions(-) create mode 100644 consumer/src/filters.rs create mode 100644 platforms/macos/src/filters.rs create mode 100644 platforms/unix/src/filters.rs create mode 100644 platforms/windows/src/filters.rs diff --git a/consumer/src/filters.rs b/consumer/src/filters.rs new file mode 100644 index 000000000..b7bdfe8da --- /dev/null +++ b/consumer/src/filters.rs @@ -0,0 +1,49 @@ +// Copyright 2023 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file) or the MIT license (found in +// the LICENSE-MIT file), at your option. + +use accesskit::Role; + +use crate::node::{DetachedNode, Node, NodeState}; + +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub enum FilterResult { + Include, + ExcludeNode, + ExcludeSubtree, +} + +fn common_filter_base(node: &NodeState) -> FilterResult { + if node.is_hidden() { + return FilterResult::ExcludeSubtree; + } + + let role = node.role(); + if role == Role::Presentation || role == Role::GenericContainer || role == Role::InlineTextBox { + return FilterResult::ExcludeNode; + } + + 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; + } + common_filter(node) +} diff --git a/consumer/src/iterators.rs b/consumer/src/iterators.rs index 41a40c5e2..0920c6259 100644 --- a/consumer/src/iterators.rs +++ b/consumer/src/iterators.rs @@ -12,7 +12,7 @@ use std::iter::FusedIterator; use accesskit::NodeId; -use crate::{node::Node, tree::State as TreeState}; +use crate::{filters::FilterResult, node::Node, tree::State as TreeState}; /// An iterator that yields following siblings of a node. /// @@ -178,13 +178,6 @@ impl<'a> ExactSizeIterator for PrecedingSiblings<'a> {} impl<'a> FusedIterator for PrecedingSiblings<'a> {} -#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -pub enum FilterResult { - Include, - ExcludeNode, - ExcludeSubtree, -} - fn next_filtered_sibling<'a>( node: Option>, filter: &impl Fn(&Node) -> FilterResult, diff --git a/consumer/src/lib.rs b/consumer/src/lib.rs index eeae46712..0e7d57e47 100644 --- a/consumer/src/lib.rs +++ b/consumer/src/lib.rs @@ -9,8 +9,12 @@ pub use tree::{ChangeHandler as TreeChangeHandler, State as TreeState, Tree}; pub(crate) mod node; pub use node::{DetachedNode, Node, NodeState}; +pub(crate) mod filters; +pub use filters::{ + common_filter, common_filter_detached, common_filter_with_root_exception, FilterResult, +}; + pub(crate) mod iterators; -pub use iterators::FilterResult; pub(crate) mod text; pub use text::{ diff --git a/consumer/src/node.rs b/consumer/src/node.rs index 0a2983695..96be5a1cf 100644 --- a/consumer/src/node.rs +++ b/consumer/src/node.rs @@ -15,8 +15,9 @@ use accesskit::{ Role, TextSelection, }; +use crate::filters::FilterResult; use crate::iterators::{ - FilterResult, FilteredChildren, FollowingFilteredSiblings, FollowingSiblings, LabelledBy, + FilteredChildren, FollowingFilteredSiblings, FollowingSiblings, LabelledBy, PrecedingFilteredSiblings, PrecedingSiblings, }; use crate::tree::State as TreeState; diff --git a/platforms/macos/src/adapter.rs b/platforms/macos/src/adapter.rs index e4da04c59..e51cdd5c3 100644 --- a/platforms/macos/src/adapter.rs +++ b/platforms/macos/src/adapter.rs @@ -15,7 +15,8 @@ use crate::{ appkit::NSView, context::Context, event::{EventGenerator, QueuedEvents}, - node::{can_be_focused, filter}, + filters::filter, + node::can_be_focused, util::*, }; diff --git a/platforms/macos/src/event.rs b/platforms/macos/src/event.rs index 64995dd1b..3bbfaa60b 100644 --- a/platforms/macos/src/event.rs +++ b/platforms/macos/src/event.rs @@ -14,7 +14,8 @@ use std::{collections::HashSet, rc::Rc}; use crate::{ appkit::*, context::Context, - node::{filter, filter_detached, NodeWrapper}, + filters::{filter, filter_detached}, + node::NodeWrapper, }; // Workaround for https://github.com/madsmtm/objc2/issues/306 diff --git a/platforms/macos/src/filters.rs b/platforms/macos/src/filters.rs new file mode 100644 index 000000000..f062ee72c --- /dev/null +++ b/platforms/macos/src/filters.rs @@ -0,0 +1,8 @@ +// Copyright 2023 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file) or the MIT license (found in +// the LICENSE-MIT file), at your option. + +pub(crate) use accesskit_consumer::{ + common_filter as filter, common_filter_detached as filter_detached, +}; diff --git a/platforms/macos/src/lib.rs b/platforms/macos/src/lib.rs index 0debbc7ed..5eab267ca 100644 --- a/platforms/macos/src/lib.rs +++ b/platforms/macos/src/lib.rs @@ -7,6 +7,7 @@ mod appkit; mod context; +mod filters; mod node; mod util; diff --git a/platforms/macos/src/node.rs b/platforms/macos/src/node.rs index b408fb78e..7ef053ac5 100644 --- a/platforms/macos/src/node.rs +++ b/platforms/macos/src/node.rs @@ -28,7 +28,7 @@ use std::{ rc::{Rc, Weak}, }; -use crate::{appkit::*, context::Context, util::*}; +use crate::{appkit::*, context::Context, filters::filter, util::*}; fn ns_role(node_state: &NodeState) -> &'static NSString { let role = node_state.role(); @@ -232,35 +232,6 @@ fn ns_role(node_state: &NodeState) -> &'static NSString { } } -fn filter_common(node_state: &NodeState) -> FilterResult { - let ns_role = ns_role(node_state); - if ns_role == unsafe { NSAccessibilityUnknownRole } { - return FilterResult::ExcludeNode; - } - - if node_state.is_hidden() { - return FilterResult::ExcludeSubtree; - } - - FilterResult::Include -} - -pub(crate) fn filter(node: &Node) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - - filter_common(node.state()) -} - -pub(crate) fn filter_detached(node: &DetachedNode) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - - filter_common(node.state()) -} - pub(crate) fn can_be_focused(node: &Node) -> bool { filter(node) == FilterResult::Include && node.role() != Role::Window } diff --git a/platforms/unix/src/adapter.rs b/platforms/unix/src/adapter.rs index 62407f6f3..d8f1f17ff 100644 --- a/platforms/unix/src/adapter.rs +++ b/platforms/unix/src/adapter.rs @@ -12,7 +12,8 @@ use crate::{ Bus, ObjectId, ACCESSIBLE_PATH_PREFIX, }, context::Context, - node::{filter, filter_detached, NodeWrapper, PlatformNode}, + filters::{filter, filter_detached}, + node::{NodeWrapper, PlatformNode}, util::{block_on, AppContext}, }; use accesskit::{ActionHandler, NodeId, Rect, Role, TreeUpdate}; diff --git a/platforms/unix/src/filters.rs b/platforms/unix/src/filters.rs new file mode 100644 index 000000000..f062ee72c --- /dev/null +++ b/platforms/unix/src/filters.rs @@ -0,0 +1,8 @@ +// Copyright 2023 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file) or the MIT license (found in +// the LICENSE-MIT file), at your option. + +pub(crate) use accesskit_consumer::{ + common_filter as filter, common_filter_detached as filter_detached, +}; diff --git a/platforms/unix/src/lib.rs b/platforms/unix/src/lib.rs index 65235ccff..5f6d0ab1d 100644 --- a/platforms/unix/src/lib.rs +++ b/platforms/unix/src/lib.rs @@ -9,6 +9,7 @@ extern crate zbus; mod adapter; mod atspi; mod context; +mod filters; mod node; mod util; diff --git a/platforms/unix/src/node.rs b/platforms/unix/src/node.rs index f2369f51f..190a58b1d 100644 --- a/platforms/unix/src/node.rs +++ b/platforms/unix/src/node.rs @@ -14,6 +14,7 @@ use crate::{ ObjectId, ObjectRef, Rect as AtspiRect, ACCESSIBLE_PATH_PREFIX, }, context::Context, + filters::{filter, filter_detached}, util::WindowBounds, }; use accesskit::{ @@ -32,35 +33,6 @@ use std::{ }; use zbus::fdo; -fn filter_common(node: &NodeState) -> FilterResult { - if node.is_hidden() { - return FilterResult::ExcludeSubtree; - } - - let role = node.role(); - if role == Role::Presentation || role == Role::GenericContainer || role == Role::InlineTextBox { - return FilterResult::ExcludeNode; - } - - FilterResult::Include -} - -pub(crate) fn filter(node: &Node) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - - filter_common(node.state()) -} - -pub(crate) fn filter_detached(node: &DetachedNode) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - - filter_common(node.state()) -} - pub(crate) enum NodeWrapper<'a> { Node(&'a Node<'a>), DetachedNode(&'a DetachedNode), diff --git a/platforms/windows/src/adapter.rs b/platforms/windows/src/adapter.rs index fb3601f90..b8bc9dae6 100644 --- a/platforms/windows/src/adapter.rs +++ b/platforms/windows/src/adapter.rs @@ -13,8 +13,9 @@ use windows::Win32::{ use crate::{ context::Context, + filters::{filter, filter_detached}, init::UiaInitMarker, - node::{filter, filter_detached, NodeWrapper, PlatformNode}, + node::{NodeWrapper, PlatformNode}, util::QueuedEvent, }; diff --git a/platforms/windows/src/filters.rs b/platforms/windows/src/filters.rs new file mode 100644 index 000000000..e5d21d7ae --- /dev/null +++ b/platforms/windows/src/filters.rs @@ -0,0 +1,9 @@ +// Copyright 2023 The AccessKit Authors. All rights reserved. +// Licensed under the Apache License, Version 2.0 (found in +// the LICENSE-APACHE file) or the MIT license (found in +// the LICENSE-MIT file), at your option. + +pub(crate) use accesskit_consumer::{ + common_filter as filter, common_filter_detached as filter_detached, + common_filter_with_root_exception as filter_with_root_exception, +}; diff --git a/platforms/windows/src/lib.rs b/platforms/windows/src/lib.rs index 1a51575d3..38276037f 100644 --- a/platforms/windows/src/lib.rs +++ b/platforms/windows/src/lib.rs @@ -4,6 +4,7 @@ // the LICENSE-MIT file), at your option. mod context; +mod filters; mod node; mod text; mod util; diff --git a/platforms/windows/src/node.rs b/platforms/windows/src/node.rs index 03533f64e..6909bbee6 100644 --- a/platforms/windows/src/node.rs +++ b/platforms/windows/src/node.rs @@ -21,7 +21,12 @@ use windows::{ Win32::{Foundation::*, System::Com::*, UI::Accessibility::*}, }; -use crate::{context::Context, text::PlatformRange as PlatformTextRange, util::*}; +use crate::{ + context::Context, + filters::{filter, filter_detached, filter_with_root_exception}, + text::PlatformRange as PlatformTextRange, + util::*, +}; const RUNTIME_ID_SIZE: usize = 3; @@ -35,42 +40,6 @@ fn runtime_id_from_node_id(id: NodeId) -> [i32; RUNTIME_ID_SIZE] { ] } -fn filter_common(node: &NodeState) -> FilterResult { - if node.is_hidden() { - return FilterResult::ExcludeSubtree; - } - - let role = node.role(); - if role == Role::Presentation || role == Role::GenericContainer || role == Role::InlineTextBox { - return FilterResult::ExcludeNode; - } - - FilterResult::Include -} - -pub(crate) fn filter(node: &Node) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - - filter_common(node.state()) -} - -pub(crate) fn filter_detached(node: &DetachedNode) -> FilterResult { - if node.is_focused() { - return FilterResult::Include; - } - - filter_common(node.state()) -} - -fn filter_with_root_exception(node: &Node) -> FilterResult { - if node.is_root() { - return FilterResult::Include; - } - filter(node) -} - pub(crate) enum NodeWrapper<'a> { Node(&'a Node<'a>), DetachedNode(&'a DetachedNode),