Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Unified Diff: ui/accessibility/ax_tree.cc

Issue 2737043003: Add support for attribute change callbacks in AXNodeData. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/accessibility/ax_tree.h ('k') | ui/accessibility/ax_tree_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/accessibility/ax_tree.cc
diff --git a/ui/accessibility/ax_tree.cc b/ui/accessibility/ax_tree.cc
index 2d2a535f7e985a8ec5c0814b2628a2a05818cd77..e67ca5975feae1c9482702605fa6f7a74a604896 100644
--- a/ui/accessibility/ax_tree.cc
+++ b/ui/accessibility/ax_tree.cc
@@ -24,6 +24,26 @@ std::string TreeToStringHelper(AXNode* node, int indent) {
return result;
}
+template <typename K, typename V>
+bool KeyValuePairsKeysMatch(std::vector<std::pair<K, V>> pairs1,
+ std::vector<std::pair<K, V>> pairs2) {
+ if (pairs1.size() != pairs2.size())
+ return false;
+ for (size_t i = 0; i < pairs1.size(); ++i) {
+ if (pairs1[i].first != pairs2[i].first)
+ return false;
+ }
+ return true;
+}
+
+template <typename K, typename V>
+std::map<K, V> MapFromKeyValuePairs(std::vector<std::pair<K, V>> pairs) {
+ std::map<K, V> result;
+ for (size_t i = 0; i < pairs.size(); ++i)
+ result[pairs[i].first] = pairs[i].second;
+ return result;
+}
+
} // namespace
// Intermediate state to keep track of during a tree update.
@@ -228,9 +248,8 @@ bool AXTree::UpdateNode(const AXNodeData& src,
AXNode* node = GetFromId(src.id);
if (node) {
update_state->pending_nodes.erase(node);
- if (delegate_ &&
- update_state->new_nodes.find(node) == update_state->new_nodes.end())
- delegate_->OnNodeDataWillChange(this, node->data(), src);
+ if (update_state->new_nodes.find(node) == update_state->new_nodes.end())
+ CallNodeChangeCallbacks(node, src);
node->SetData(src);
} else {
if (!is_new_root) {
@@ -291,6 +310,193 @@ bool AXTree::UpdateNode(const AXNodeData& src,
return success;
}
+void AXTree::CallNodeChangeCallbacks(AXNode* node, const AXNodeData& new_data) {
+ if (!delegate_)
+ return;
+
+ const AXNodeData& old_data = node->data();
+ delegate_->OnNodeDataWillChange(this, old_data, new_data);
+
+ if (old_data.role != new_data.role)
+ delegate_->OnRoleChanged(this, node, old_data.role, new_data.role);
+
+ if (old_data.state != new_data.state) {
+ for (int i = AX_STATE_NONE + 1; i <= AX_STATE_LAST; ++i) {
+ AXState state = static_cast<AXState>(i);
+ if (old_data.HasStateFlag(state) != new_data.HasStateFlag(state)) {
+ delegate_->OnStateChanged(this, node, state,
+ new_data.HasStateFlag(state));
+ }
+ }
+ }
+
+ const auto& old_strings = old_data.string_attributes;
+ const auto& new_strings = new_data.string_attributes;
+ if (KeyValuePairsKeysMatch(old_strings, new_strings)) {
+ for (size_t i = 0; i < old_strings.size(); ++i) {
+ if (old_strings[i].second != new_strings[i].second) {
+ delegate_->OnStringAttributeChanged(this, node, old_strings[i].first,
aboxhall 2017/03/09 00:46:06 Can we fix this duplication somehow? Something som
dmazzoni 2017/03/10 23:40:25 Figured it out! What do you think? It's about 90%
+ old_strings[i].second,
+ new_strings[i].second);
+ }
+ }
+ } else {
+ auto old_string_map = MapFromKeyValuePairs(old_strings);
+ auto new_string_map = MapFromKeyValuePairs(new_strings);
+ for (size_t i = 0; i < old_strings.size(); ++i) {
+ const auto& new_iter = new_string_map.find(old_strings[i].first);
+ if (new_iter == new_string_map.end()) {
+ delegate_->OnStringAttributeChanged(this, node, old_strings[i].first,
+ old_strings[i].second, "");
+ }
+ }
+ for (size_t i = 0; i < new_strings.size(); ++i) {
+ const auto& old_iter = old_string_map.find(new_strings[i].first);
+ if (old_iter == old_string_map.end()) {
+ delegate_->OnStringAttributeChanged(this, node, new_strings[i].first,
+ "", new_strings[i].second);
+ } else if (old_iter->second != new_strings[i].second) {
+ delegate_->OnStringAttributeChanged(this, node, new_strings[i].first,
+ old_iter->second,
+ new_strings[i].second);
+ }
+ }
+ }
+
+ const auto& old_bools = old_data.bool_attributes;
+ const auto& new_bools = new_data.bool_attributes;
+ if (KeyValuePairsKeysMatch(old_bools, new_bools)) {
+ for (size_t i = 0; i < old_bools.size(); ++i) {
+ if (old_bools[i].second != new_bools[i].second) {
+ delegate_->OnBoolAttributeChanged(this, node, old_bools[i].first,
+ new_bools[i].second);
+ }
+ }
+ } else {
+ auto old_bool_map = MapFromKeyValuePairs(old_bools);
+ auto new_bool_map = MapFromKeyValuePairs(new_bools);
+ for (size_t i = 0; i < old_bools.size(); ++i) {
+ const auto& new_iter = new_bool_map.find(old_bools[i].first);
+ if (old_bools[i].second && new_iter == new_bool_map.end()) {
+ delegate_->OnBoolAttributeChanged(this, node, old_bools[i].first,
+ false);
+ }
+ }
+ for (size_t i = 0; i < new_bools.size(); ++i) {
+ const auto& old_iter = old_bool_map.find(new_bools[i].first);
+ if (old_iter == old_bool_map.end()) {
+ if (new_bools[i].second) {
+ delegate_->OnBoolAttributeChanged(this, node, new_bools[i].first,
+ new_bools[i].second);
+ }
+ } else if (old_iter->second != new_bools[i].second) {
+ delegate_->OnBoolAttributeChanged(this, node, new_bools[i].first,
+ new_bools[i].second);
+ }
+ }
+ }
+
+ const auto& old_floats = old_data.float_attributes;
+ const auto& new_floats = new_data.float_attributes;
+ if (KeyValuePairsKeysMatch(old_floats, new_floats)) {
+ for (size_t i = 0; i < old_floats.size(); ++i) {
+ if (old_floats[i].second != new_floats[i].second) {
+ delegate_->OnFloatAttributeChanged(this, node, old_floats[i].first,
+ old_floats[i].second,
+ new_floats[i].second);
+ }
+ }
+ } else {
+ auto old_float_map = MapFromKeyValuePairs(old_floats);
+ auto new_float_map = MapFromKeyValuePairs(new_floats);
+ for (size_t i = 0; i < old_floats.size(); ++i) {
+ const auto& new_iter = new_float_map.find(old_floats[i].first);
+ if (new_iter == new_float_map.end()) {
+ delegate_->OnFloatAttributeChanged(this, node, old_floats[i].first,
+ old_floats[i].second, 0.0);
+ }
+ }
+ for (size_t i = 0; i < new_floats.size(); ++i) {
+ const auto& old_iter = old_float_map.find(new_floats[i].first);
+ if (old_iter == old_float_map.end()) {
+ delegate_->OnFloatAttributeChanged(this, node, new_floats[i].first, 0.0,
+ new_floats[i].second);
+ } else if (old_iter->second != new_floats[i].second) {
+ delegate_->OnFloatAttributeChanged(this, node, new_floats[i].first,
+ old_iter->second,
+ new_floats[i].second);
+ }
+ }
+ }
+
+ const auto& old_ints = old_data.int_attributes;
+ const auto& new_ints = new_data.int_attributes;
+ if (KeyValuePairsKeysMatch(old_ints, new_ints)) {
+ for (size_t i = 0; i < old_ints.size(); ++i) {
+ if (old_ints[i].second != new_ints[i].second) {
+ delegate_->OnIntAttributeChanged(this, node, old_ints[i].first,
+ old_ints[i].second,
+ new_ints[i].second);
+ }
+ }
+ } else {
+ auto old_int_map = MapFromKeyValuePairs(old_ints);
+ auto new_int_map = MapFromKeyValuePairs(new_ints);
+ for (size_t i = 0; i < old_ints.size(); ++i) {
+ const auto& new_iter = new_int_map.find(old_ints[i].first);
+ if (new_iter == new_int_map.end()) {
+ delegate_->OnIntAttributeChanged(this, node, old_ints[i].first,
+ old_ints[i].second, 0);
+ }
+ }
+ for (size_t i = 0; i < new_ints.size(); ++i) {
+ const auto& old_iter = old_int_map.find(new_ints[i].first);
+ if (old_iter == old_int_map.end()) {
+ delegate_->OnIntAttributeChanged(this, node, new_ints[i].first, 0,
+ new_ints[i].second);
+ } else if (old_iter->second != new_ints[i].second) {
+ delegate_->OnIntAttributeChanged(this, node, new_ints[i].first,
+ old_iter->second, new_ints[i].second);
+ }
+ }
+ }
+
+ const auto& old_intlists = old_data.intlist_attributes;
+ const auto& new_intlists = new_data.intlist_attributes;
+ if (KeyValuePairsKeysMatch(old_intlists, new_intlists)) {
+ for (size_t i = 0; i < old_intlists.size(); ++i) {
+ if (old_intlists[i].second != new_intlists[i].second) {
+ delegate_->OnIntListAttributeChanged(this, node, old_intlists[i].first,
+ old_intlists[i].second,
+ new_intlists[i].second);
+ }
+ }
+ } else {
+ auto old_intlist_map = MapFromKeyValuePairs(old_intlists);
+ auto new_intlist_map = MapFromKeyValuePairs(new_intlists);
+ for (size_t i = 0; i < old_intlists.size(); ++i) {
+ const auto& new_iter = new_intlist_map.find(old_intlists[i].first);
+ if (new_iter == new_intlist_map.end()) {
+ delegate_->OnIntListAttributeChanged(this, node, old_intlists[i].first,
+ old_intlists[i].second,
+ std::vector<int32_t>());
+ }
+ }
+ for (size_t i = 0; i < new_intlists.size(); ++i) {
+ const auto& old_iter = old_intlist_map.find(new_intlists[i].first);
+ if (old_iter == old_intlist_map.end()) {
+ delegate_->OnIntListAttributeChanged(this, node, new_intlists[i].first,
+ std::vector<int32_t>(),
+ new_intlists[i].second);
+ } else if (old_iter->second != new_intlists[i].second) {
+ delegate_->OnIntListAttributeChanged(this, node, new_intlists[i].first,
+ old_iter->second,
+ new_intlists[i].second);
+ }
+ }
+ }
+}
+
void AXTree::DestroySubtree(AXNode* node,
AXTreeUpdateState* update_state) {
DCHECK(update_state);
« no previous file with comments | « ui/accessibility/ax_tree.h ('k') | ui/accessibility/ax_tree_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698