17bool IsActiveLiveRegion(
const AXTreeObserver::Change& change) {
18 return change.node->data().HasStringAttribute(
20 change.node->data().GetStringAttribute(
24bool IsContainedInLiveRegion(
const AXTreeObserver::Change& change) {
25 return change.node->data().HasStringAttribute(
27 change.node->data().HasStringAttribute(
31bool HasEvent(
const std::set<AXEventGenerator::EventParams>& node_events,
33 for (
auto& iter : node_events) {
34 if (iter.event ==
event)
40void RemoveEvent(std::set<AXEventGenerator::EventParams>* node_events,
42 for (
auto& iter : *node_events) {
43 if (iter.event ==
event) {
44 node_events->erase(iter);
56void RemoveEventsDueToIgnoredChanged(
57 std::set<AXEventGenerator::EventParams>* node_events) {
58 RemoveEvent(node_events,
66 RemoveEvent(node_events,
72void AddIgnoredChangedState(
75 ignored_changed_states.set(
static_cast<size_t>(
state));
80bool HasIgnoredChangedState(
83 return ignored_changed_states[
static_cast<size_t>(
state)];
91 const std::vector<AXEventIntent>& event_intents)
92 :
event(
event), event_from(event_from), event_intents(event_intents) {}
98 : node(node), event_params(event_params) {
107 return event < rhs.
event;
114 if (map_iter_ !=
map.end())
115 set_iter_ = map_iter_->second.begin();
125 return map_iter_ != rhs.map_iter_ ||
126 (map_iter_ != map_.end() && set_iter_ != rhs.set_iter_);
130 if (map_iter_ == map_.end())
134 while (map_iter_ != map_.end() && set_iter_ == map_iter_->second.end()) {
136 if (map_iter_ != map_.end())
137 set_iter_ = map_iter_->second.begin();
144 BASE_DCHECK(map_iter_ != map_.end() && set_iter_ != map_iter_->second.end());
171 tree_events_.clear();
180 std::set<EventParams>& node_events = tree_events_[node];
230 container = container->
parent();
237 if (unignored_parent)
261 const std::string& old_value,
262 const std::string& new_value) {
296 bool old_state = !old_value.empty() && old_value !=
"off";
297 bool new_state = !new_value.empty() && new_value !=
"off";
298 if (!old_state && new_state)
305 if (node != tree->
root())
310 FireLiveRegionEvents(node);
345 active_descendant_changed_.push_back(node);
372 &was_enabled, &was_readonly);
495 container = container->
parent();
510 const std::vector<int32_t>& old_value,
511 const std::vector<int32_t>& new_value) {
525 for (int32_t
id : ComputeIntListDifference(old_value, new_value)) {
526 if (
auto* target_node = tree->
GetFromId(
id))
557 ShouldFireLoadEvents(tree->
root())) {
571 if (new_tree_data.
title != old_tree_data.
title)
583 tree_events_.erase(node);
592 tree_events_.erase(node);
602 const std::vector<Change>& changes) {
605 if (root_changed && ShouldFireLoadEvents(tree->
root())) {
612 for (
const auto& change : changes) {
616 FireRelationSourceEvents(tree, change.node);
620 if (
IsAlert(change.node->data().role))
622 else if (IsActiveLiveRegion(change))
624 else if (IsContainedInLiveRegion(change))
625 FireLiveRegionEvents(change.node);
628 FireActiveDescendantEvents();
633void AXEventGenerator::FireLiveRegionEvents(
AXNode* node) {
637 live_root = live_root->
parent();
653void AXEventGenerator::FireActiveDescendantEvents() {
654 for (AXNode* node : active_descendant_changed_) {
659 switch (descendant->data().role) {
670 active_descendant_changed_.clear();
673void AXEventGenerator::FireRelationSourceEvents(AXTree* tree,
674 AXNode* target_node) {
675 int32_t target_id = target_node->id();
676 std::set<AXNode*> source_nodes;
677 auto callback = [&](
const auto& entry) {
678 const auto& target_to_sources = entry.second;
679 auto sources_it = target_to_sources.find(target_id);
680 if (sources_it == target_to_sources.end())
683 auto sources = sources_it->second;
684 std::for_each(
sources.begin(),
sources.end(), [&](int32_t source_id) {
685 AXNode* source_node = tree->GetFromId(source_id);
687 if (!source_node || source_nodes.count(source_node) > 0)
690 source_nodes.insert(source_node);
694 this->AddEvent(source_node, Event::RELATED_NODE_CHANGED);
698 std::for_each(tree->int_reverse_relations().begin(),
699 tree->int_reverse_relations().end(),
callback);
701 tree->intlist_reverse_relations().begin(),
702 tree->intlist_reverse_relations().end(), [&](
auto& entry) {
707 if (entry.first != ax::mojom::IntListAttribute::kRadioGroupIds)
714bool AXEventGenerator::ShouldFireLoadEvents(AXNode* node) {
715 if (always_fire_load_complete_)
718 const AXNodeData&
data = node->data();
719 return data.relative_bounds.bounds.width() ||
720 data.relative_bounds.bounds.height();
723void AXEventGenerator::TrimEventsDueToAncestorIgnoredChanged(
725 std::map<AXNode*, IgnoredChangedStatesBitset>&
726 ancestor_ignored_changed_map) {
732 if (node->parent() &&
734 TrimEventsDueToAncestorIgnoredChanged(node->parent(),
735 ancestor_ignored_changed_map);
744 const auto& parent_map_iter =
745 ancestor_ignored_changed_map.find(node->parent());
746 const auto& curr_events_iter = tree_events_.find(node);
751 ancestor_ignored_changed_map[node];
758 if (parent_map_iter != ancestor_ignored_changed_map.end()) {
760 if (HasIgnoredChangedState(parent_map_iter->second,
762 AddIgnoredChangedState(ancestor_ignored_changed_states,
765 if (HasIgnoredChangedState(parent_map_iter->second,
767 AddIgnoredChangedState(ancestor_ignored_changed_states,
774 if (curr_events_iter != tree_events_.end() &&
776 if ((HasIgnoredChangedState(parent_map_iter->second,
778 node->IsIgnored()) ||
779 (HasIgnoredChangedState(parent_map_iter->second,
781 !node->IsIgnored())) {
783 RemoveEventsDueToIgnoredChanged(&(curr_events_iter->second));
786 if (node->IsIgnored()) {
787 AddIgnoredChangedState(ancestor_ignored_changed_states,
790 AddIgnoredChangedState(ancestor_ignored_changed_states,
801 if (curr_events_iter != tree_events_.end() &&
803 if (node->IsIgnored()) {
804 AddIgnoredChangedState(ancestor_ignored_changed_states,
807 AddIgnoredChangedState(ancestor_ignored_changed_states,
815void AXEventGenerator::PostprocessEvents() {
816 std::map<AXNode*, IgnoredChangedStatesBitset> ancestor_ignored_changed_map;
817 std::set<AXNode*> removed_subtree_created_nodes;
818 auto iter = tree_events_.begin();
819 while (iter != tree_events_.end()) {
820 AXNode* node = iter->first;
821 std::set<EventParams>& node_events = iter->second;
835 TrimEventsDueToAncestorIgnoredChanged(node, ancestor_ignored_changed_map);
836 RemoveEventsDueToIgnoredChanged(&node_events);
848 AXNode* parent = node->GetUnignoredParent();
853 tree_events_.find(parent) != tree_events_.end() &&
862 (tree_events_.find(parent) != tree_events_.end() ||
867 removed_subtree_created_nodes.insert(node);
870 parent = parent->GetUnignoredParent();
876 if (node_events.empty())
877 iter = tree_events_.erase(iter);
887 switch (restriction) {
904std::vector<int32_t> AXEventGenerator::ComputeIntListDifference(
905 const std::vector<int32_t>& lhs,
906 const std::vector<int32_t>& rhs) {
907 std::set<int32_t> sorted_lhs(lhs.cbegin(), lhs.cend());
908 std::set<int32_t> sorted_rhs(rhs.cbegin(), rhs.cend());
910 std::vector<int32_t>
result;
911 std::set_symmetric_difference(sorted_lhs.cbegin(), sorted_lhs.cend(),
912 sorted_rhs.cbegin(), sorted_rhs.cend(),
913 std::back_inserter(
result));
924 return "ACCESS_KEY_CHANGED";
926 return "ATOMIC_CHANGED";
928 return "ACTIVE_DESCENDANT_CHANGED";
932 return "ATK_TEXT_OBJECT_ATTRIBUTE_CHANGED";
934 return "BUSY_CHANGED";
936 return "CHECKED_STATE_CHANGED";
938 return "CHILDREN_CHANGED";
940 return "CLASS_NAME_CHANGED";
944 return "CONTROLS_CHANGED";
946 return "DESCRIBED_BY_CHANGED";
948 return "DESCRIPTION_CHANGED";
950 return "DOCUMENT_SELECTION_CHANGED";
952 return "DOCUMENT_TITLE_CHANGED";
954 return "DROPEFFECT_CHANGED";
956 return "ENABLED_CHANGED";
960 return "FLOW_FROM_CHANGED";
962 return "FLOW_TO_CHANGED";
964 return "GRABBED_CHANGED";
966 return "HASPOPUP_CHANGED";
968 return "HIERARCHICAL_LEVEL_CHANGED";
970 return "IGNORED_CHANGED";
972 return "IMAGE_ANNOTATION_CHANGED";
974 return "INVALID_STATUS_CHANGED";
976 return "KEY_SHORTCUTS_CHANGED";
978 return "LABELED_BY_CHANGED";
980 return "LANGUAGE_CHANGED";
982 return "LAYOUT_INVALIDATED";
984 return "LIVE_REGION_CHANGED";
986 return "LIVE_REGION_CREATED";
988 return "LIVE_REGION_NODE_CHANGED";
990 return "LIVE_RELEVANT_CHANGED";
992 return "LIVE_STATUS_CHANGED";
994 return "LOAD_COMPLETE";
998 return "MENU_ITEM_SELECTED";
1000 return "MULTILINE_STATE_CHANGED";
1002 return "MULTISELECTABLE_STATE_CHANGED";
1004 return "NAME_CHANGED";
1006 return "OBJECT_ATTRIBUTE_CHANGED";
1008 return "OTHER_ATTRIBUTE_CHANGED";
1010 return "PLACEHOLDER_CHANGED";
1012 return "PORTAL_ACTIVATED";
1014 return "POSITION_IN_SET_CHANGED";
1016 return "READONLY_CHANGED";
1018 return "RELATED_NODE_CHANGED";
1020 return "REQUIRED_STATE_CHANGED";
1022 return "ROLE_CHANGED";
1024 return "ROW_COUNT_CHANGED";
1026 return "SCROLL_HORIZONTAL_POSITION_CHANGED";
1028 return "SCROLL_VERTICAL_POSITION_CHANGED";
1030 return "SELECTED_CHANGED";
1032 return "SELECTED_CHILDREN_CHANGED";
1034 return "SET_SIZE_CHANGED";
1036 return "STATE_CHANGED";
1038 return "SUBTREE_CREATED";
1040 return "TEXT_ATTRIBUTE_CHANGED";
1042 return "VALUE_CHANGED";
1044 return "VALUE_MAX_CHANGED";
1046 return "VALUE_MIN_CHANGED";
1048 return "VALUE_STEP_CHANGED";
1050 return "AUTO_COMPLETE_CHANGED";
1052 return "FOCUS_CHANGED";
1054 return "SORT_CHANGED";
1056 return "WIN_IACCESSIBLE_STATE_CHANGED";
TargetedEvent operator*() const
Iterator(const std::map< AXNode *, std::set< EventParams > > &map, const std::map< AXNode *, std::set< EventParams > >::const_iterator &head)
bool operator!=(const Iterator &rhs) const
@ LIVE_REGION_NODE_CHANGED
@ ATK_TEXT_OBJECT_ATTRIBUTE_CHANGED
@ DOCUMENT_SELECTION_CHANGED
@ OBJECT_ATTRIBUTE_CHANGED
@ SCROLL_HORIZONTAL_POSITION_CHANGED
@ POSITION_IN_SET_CHANGED
@ IMAGE_ANNOTATION_CHANGED
@ WIN_IACCESSIBLE_STATE_CHANGED
@ MULTILINE_STATE_CHANGED
@ OTHER_ATTRIBUTE_CHANGED
@ MULTISELECTABLE_STATE_CHANGED
@ SCROLL_VERTICAL_POSITION_CHANGED
@ HIERARCHICAL_LEVEL_CHANGED
@ ACTIVE_DESCENDANT_CHANGED
@ SELECTED_CHILDREN_CHANGED
void AddEvent(ui::AXNode *node, Event event)
void OnIntAttributeChanged(AXTree *tree, AXNode *node, ax::mojom::IntAttribute attr, int32_t old_value, int32_t new_value) override
void OnRoleChanged(AXTree *tree, AXNode *node, ax::mojom::Role old_role, ax::mojom::Role new_role) override
~AXEventGenerator() override
void OnNodeWillBeDeleted(AXTree *tree, AXNode *node) override
std::bitset< static_cast< size_t >(IgnoredChangedState::kCount)> IgnoredChangedStatesBitset
void OnStateChanged(AXTree *tree, AXNode *node, ax::mojom::State state, bool new_value) override
void OnBoolAttributeChanged(AXTree *tree, AXNode *node, ax::mojom::BoolAttribute attr, bool new_value) override
void OnTreeDataChanged(AXTree *tree, const ui::AXTreeData &old_data, const ui::AXTreeData &new_data) override
void OnNodeWillBeReparented(AXTree *tree, AXNode *node) override
void OnIntListAttributeChanged(AXTree *tree, AXNode *node, ax::mojom::IntListAttribute attr, const std::vector< int32_t > &old_value, const std::vector< int32_t > &new_value) override
void OnSubtreeWillBeDeleted(AXTree *tree, AXNode *node) override
void OnNodeDataChanged(AXTree *tree, const AXNodeData &old_node_data, const AXNodeData &new_node_data) override
void SetTree(AXTree *new_tree)
void OnAtomicUpdateFinished(AXTree *tree, bool root_changed, const std::vector< Change > &changes) override
void OnFloatAttributeChanged(AXTree *tree, AXNode *node, ax::mojom::FloatAttribute attr, float old_value, float new_value) override
void OnSubtreeWillBeReparented(AXTree *tree, AXNode *node) override
void OnStringAttributeChanged(AXTree *tree, AXNode *node, ax::mojom::StringAttribute attr, const std::string &old_value, const std::string &new_value) override
AXNode * GetUnignoredParent() const
AXNode * GetTextFieldAncestor() const
const AXNodeData & data() const
const AXTreeData & data() const
AXNode * GetFromId(int32_t id) const override
void AddObserver(AXTreeObserver *observer)
void RemoveObserver(AXTreeObserver *observer)
const std::vector< AXEventIntent > & event_intents() const
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static bool is_readonly(const InterfaceBlock &block)
@ kTextStrikethroughStyle
bool Contains(const Container &container, const Value &value)
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
bool IsContainerWithSelectableChildren(const ax::mojom::Role role)
const char * ToString(ax::mojom::Event event)
bool IsRowContainer(const ax::mojom::Role role)
std::ostream & operator<<(std::ostream &os, AXEventGenerator::Event event)
bool IsTableHeader(ax::mojom::Role role)
bool IsText(ax::mojom::Role role)
bool IsAlert(const ax::mojom::Role role)
static Target * is_enabled(Benchmark *bench, const Config &config)
bool operator<(const EventParams &rhs) const
bool operator==(const EventParams &rhs)
EventParams(Event event, ax::mojom::EventFrom event_from, const std::vector< AXEventIntent > &event_intents)
TargetedEvent(ui::AXNode *node, const EventParams &event_params)
bool HasState(ax::mojom::State state) const
std::vector< int32_t > child_ids
bool HasStringAttribute(ax::mojom::StringAttribute attribute) const
bool GetBoolAttribute(ax::mojom::BoolAttribute attribute) const
int GetIntAttribute(ax::mojom::IntAttribute attribute) const
const std::string & GetStringAttribute(ax::mojom::StringAttribute attribute) const
AXNode::AXID sel_anchor_object_id
ax::mojom::TextAffinity sel_focus_affinity
AXNode::AXID sel_focus_object_id
ax::mojom::TextAffinity sel_anchor_affinity
int32_t sel_anchor_offset
std::shared_ptr< const fml::Mapping > data
#define BASE_DCHECK(condition)
#define BASE_UNREACHABLE()