Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
accessibility_bridge.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <functional>
8#include <utility>
9
13
14namespace flutter { // namespace
15
16constexpr int kHasScrollingAction =
21
22// AccessibilityBridge
24 : tree_(std::make_unique<ui::AXTree>()) {
25 event_generator_.SetTree(tree_.get());
26 tree_->AddObserver(static_cast<ui::AXTreeObserver*>(this));
27 ui::AXTreeData data = tree_->data();
29 tree_->UpdateData(data);
31 this);
32}
33
35 event_generator_.ReleaseTree();
36 tree_->RemoveObserver(static_cast<ui::AXTreeObserver*>(this));
37}
38
40 const FlutterSemanticsNode2& node) {
41 pending_semantics_node_updates_[node.id] = FromFlutterSemanticsNode(node);
42}
43
46 pending_semantics_custom_action_updates_[action.id] =
47 FromFlutterSemanticsCustomAction(action);
48}
49
51 // AXTree cannot move a node in a single update.
52 // This must be split across two updates:
53 //
54 // * Update 1: remove nodes from their old parents.
55 // * Update 2: re-add nodes (including their children) to their new parents.
56 //
57 // First, start by removing nodes if necessary.
58 std::optional<ui::AXTreeUpdate> remove_reparented =
59 CreateRemoveReparentedNodesUpdate();
60 if (remove_reparented.has_value()) {
61 tree_->Unserialize(remove_reparented.value());
62
63 std::string error = tree_->error();
64 if (!error.empty()) {
65 FML_LOG(ERROR) << "Failed to update ui::AXTree, error: " << error;
66 assert(false);
67 return;
68 }
69 }
70
71 // Second, apply the pending node updates. This also moves reparented nodes to
72 // their new parents if needed.
73 ui::AXTreeUpdate update{.tree_data = tree_->data()};
74
75 // Figure out update order, ui::AXTree only accepts update in tree order,
76 // where parent node must come before the child node in
77 // ui::AXTreeUpdate.nodes. We start with picking a random node and turn the
78 // entire subtree into a list. We pick another node from the remaining update,
79 // and keep doing so until the update map is empty. We then concatenate the
80 // lists in the reversed order, this guarantees parent updates always come
81 // before child updates. If the root is in the update, it is guaranteed to
82 // be the first node of the last list.
83 std::vector<std::vector<SemanticsNode>> results;
84 while (!pending_semantics_node_updates_.empty()) {
85 auto begin = pending_semantics_node_updates_.begin();
86 SemanticsNode target = begin->second;
87 std::vector<SemanticsNode> sub_tree_list;
88 GetSubTreeList(target, sub_tree_list);
89 results.push_back(sub_tree_list);
90 pending_semantics_node_updates_.erase(begin);
91 }
92
93 for (size_t i = results.size(); i > 0; i--) {
94 for (const SemanticsNode& node : results[i - 1]) {
95 ConvertFlutterUpdate(node, update);
96 }
97 }
98
99 // The first update must set the tree's root, which is guaranteed to be the
100 // last list's first node. A tree's root node never changes, though it can be
101 // modified.
102 if (!results.empty() && GetRootAsAXNode()->id() == ui::AXNode::kInvalidAXID) {
103 FML_DCHECK(!results.back().empty());
104
105 update.root_id = results.back().front().id;
106 }
107
108 tree_->Unserialize(update);
109 pending_semantics_node_updates_.clear();
110 pending_semantics_custom_action_updates_.clear();
111
112 std::string error = tree_->error();
113 if (!error.empty()) {
114 FML_LOG(ERROR) << "Failed to update ui::AXTree, error: " << error;
115 return;
116 }
117 // Handles accessibility events as the result of the semantics update.
118 for (const auto& targeted_event : event_generator_) {
119 auto event_target =
120 GetFlutterPlatformNodeDelegateFromID(targeted_event.node->id());
121 if (event_target.expired()) {
122 continue;
123 }
124
125 OnAccessibilityEvent(targeted_event);
126 }
127 event_generator_.ClearEvents();
128}
129
130std::weak_ptr<FlutterPlatformNodeDelegate>
132 AccessibilityNodeId id) const {
133 const auto iter = id_wrapper_map_.find(id);
134 if (iter != id_wrapper_map_.end()) {
135 return iter->second;
136 }
137
138 return std::weak_ptr<FlutterPlatformNodeDelegate>();
139}
140
142 return tree_->data();
143}
144
145const std::vector<ui::AXEventGenerator::TargetedEvent>
147 std::vector<ui::AXEventGenerator::TargetedEvent> result(
148 event_generator_.begin(), event_generator_.end());
149 return result;
150}
151
152void AccessibilityBridge::OnNodeWillBeDeleted(ui::AXTree* tree,
153 ui::AXNode* node) {}
154
155void AccessibilityBridge::OnSubtreeWillBeDeleted(ui::AXTree* tree,
156 ui::AXNode* node) {}
157
158void AccessibilityBridge::OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) {
159}
160
161void AccessibilityBridge::OnRoleChanged(ui::AXTree* tree,
162 ui::AXNode* node,
163 ax::mojom::Role old_role,
164 ax::mojom::Role new_role) {}
165
166void AccessibilityBridge::OnNodeDataChanged(
167 ui::AXTree* tree,
168 const ui::AXNodeData& old_node_data,
169 const ui::AXNodeData& new_node_data) {
170 auto platform_view =
171 GetFlutterPlatformNodeDelegateFromID(new_node_data.id).lock();
172 if (platform_view) {
173 platform_view->NodeDataChanged(old_node_data, new_node_data);
174 }
175}
176
177void AccessibilityBridge::OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) {
178 BASE_DCHECK(node);
179 id_wrapper_map_[node->id()] = CreateFlutterPlatformNodeDelegate();
180 id_wrapper_map_[node->id()]->Init(
181 std::static_pointer_cast<FlutterPlatformNodeDelegate::OwnerBridge>(
182 shared_from_this()),
183 node);
184}
185
186void AccessibilityBridge::OnNodeDeleted(ui::AXTree* tree,
187 AccessibilityNodeId node_id) {
189 if (id_wrapper_map_.find(node_id) != id_wrapper_map_.end()) {
190 id_wrapper_map_.erase(node_id);
191 }
192}
193
194void AccessibilityBridge::OnAtomicUpdateFinished(
195 ui::AXTree* tree,
196 bool root_changed,
197 const std::vector<ui::AXTreeObserver::Change>& changes) {
198 // The Flutter semantics update does not include child->parent relationship
199 // We have to update the relative bound offset container id here in order
200 // to calculate the screen bound correctly.
201 for (const auto& change : changes) {
202 ui::AXNode* node = change.node;
203 const ui::AXNodeData& data = node->data();
204 AccessibilityNodeId offset_container_id = -1;
205 if (node->parent()) {
206 offset_container_id = node->parent()->id();
207 }
208 node->SetLocation(offset_container_id, data.relative_bounds.bounds,
209 data.relative_bounds.transform.get());
210 }
211}
212
213std::optional<ui::AXTreeUpdate>
214AccessibilityBridge::CreateRemoveReparentedNodesUpdate() {
215 std::unordered_map<int32_t, ui::AXNodeData> updates;
216
217 for (const auto& node_update : pending_semantics_node_updates_) {
218 for (int32_t child_id : node_update.second.children_in_traversal_order) {
219 // Skip nodes that don't exist or have a parent in the current tree.
220 ui::AXNode* child = tree_->GetFromId(child_id);
221 if (!child) {
222 continue;
223 }
224
225 // Flutter's root node should never be reparented.
226 assert(child->parent());
227
228 // Skip nodes whose parents are unchanged.
229 if (child->parent()->id() == node_update.second.id) {
230 continue;
231 }
232
233 // This pending update moves the current child node.
234 // That new child must have a corresponding pending update.
235 assert(pending_semantics_node_updates_.find(child_id) !=
236 pending_semantics_node_updates_.end());
237
238 // Create an update to remove the child from its previous parent.
239 int32_t parent_id = child->parent()->id();
240 if (updates.find(parent_id) == updates.end()) {
241 updates[parent_id] = tree_->GetFromId(parent_id)->data();
242 }
243
244 ui::AXNodeData* parent = &updates[parent_id];
245 auto iter = std::find(parent->child_ids.begin(), parent->child_ids.end(),
246 child_id);
247
248 assert(iter != parent->child_ids.end());
249 parent->child_ids.erase(iter);
250 }
251 }
252
253 if (updates.empty()) {
254 return std::nullopt;
255 }
256
257 ui::AXTreeUpdate update{
258 .tree_data = tree_->data(),
259 .nodes = std::vector<ui::AXNodeData>(),
260 };
261
262 for (std::pair<int32_t, ui::AXNodeData> data : updates) {
263 update.nodes.push_back(std::move(data.second));
264 }
265
266 return update;
267}
268
269// Private method.
270void AccessibilityBridge::GetSubTreeList(const SemanticsNode& target,
271 std::vector<SemanticsNode>& result) {
272 result.push_back(target);
273 for (int32_t child : target.children_in_traversal_order) {
274 auto iter = pending_semantics_node_updates_.find(child);
275 if (iter != pending_semantics_node_updates_.end()) {
276 SemanticsNode node = iter->second;
277 GetSubTreeList(node, result);
278 pending_semantics_node_updates_.erase(iter);
279 }
280 }
281}
282
283void AccessibilityBridge::ConvertFlutterUpdate(const SemanticsNode& node,
284 ui::AXTreeUpdate& tree_update) {
285 ui::AXNodeData node_data;
286 node_data.id = node.id;
287 SetRoleFromFlutterUpdate(node_data, node);
288 SetStateFromFlutterUpdate(node_data, node);
289 SetActionsFromFlutterUpdate(node_data, node);
290 SetBooleanAttributesFromFlutterUpdate(node_data, node);
291 SetIntAttributesFromFlutterUpdate(node_data, node);
292 SetIntListAttributesFromFlutterUpdate(node_data, node);
293 SetStringListAttributesFromFlutterUpdate(node_data, node);
294 SetIdentifierFromFlutterUpdate(node_data, node);
295 SetNameFromFlutterUpdate(node_data, node);
296 SetValueFromFlutterUpdate(node_data, node);
297 SetTooltipFromFlutterUpdate(node_data, node);
298 node_data.relative_bounds.bounds.SetRect(node.rect.left, node.rect.top,
299 node.rect.right - node.rect.left,
300 node.rect.bottom - node.rect.top);
301 node_data.relative_bounds.transform = std::make_unique<gfx::Transform>(
302 node.transform.scaleX, node.transform.skewX, node.transform.transX, 0,
303 node.transform.skewY, node.transform.scaleY, node.transform.transY, 0,
304 node.transform.pers0, node.transform.pers1, node.transform.pers2, 0, 0, 0,
305 0, 0);
306 for (auto child : node.children_in_traversal_order) {
307 node_data.child_ids.push_back(child);
308 }
309 SetTreeData(node, tree_update);
310 tree_update.nodes.push_back(node_data);
311}
312
313void AccessibilityBridge::SetRoleFromFlutterUpdate(ui::AXNodeData& node_data,
314 const SemanticsNode& node) {
315 const FlutterSemanticsFlags* flags = node.flags;
316 FML_DCHECK(flags) << "SemanticsNode::flags must not be null";
317 if (flags->is_button) {
318 node_data.role = ax::mojom::Role::kButton;
319 return;
320 }
321 if (flags->is_text_field && !flags->is_read_only) {
323 return;
324 }
325 if (flags->is_header) {
326 node_data.role = ax::mojom::Role::kHeader;
327 return;
328 }
329 if (flags->is_image) {
330 node_data.role = ax::mojom::Role::kImage;
331 return;
332 }
333 if (flags->is_link) {
334 node_data.role = ax::mojom::Role::kLink;
335 return;
336 }
337
341 return;
342 }
345 return;
346 }
348 node_data.role = ax::mojom::Role::kSwitch;
349 return;
350 }
351 if (flags->is_slider) {
352 node_data.role = ax::mojom::Role::kSlider;
353 return;
354 }
355 // If the state cannot be derived from the flutter flags, we fallback to group
356 // or static text.
357 if (node.children_in_traversal_order.empty()) {
359 } else {
360 node_data.role = ax::mojom::Role::kGroup;
361 }
362}
363
364void AccessibilityBridge::SetStateFromFlutterUpdate(ui::AXNodeData& node_data,
365 const SemanticsNode& node) {
366 const FlutterSemanticsFlags* flags = node.flags;
367 FlutterSemanticsAction actions = node.actions;
372 }
373 if (flags->is_text_field && !flags->is_read_only) {
375 }
376 if (node_data.role == ax::mojom::Role::kStaticText &&
377 (actions & kHasScrollingAction) == 0 && node.value.empty() &&
378 node.label.empty() && node.hint.empty()) {
380 } else {
381 // kFlutterSemanticsFlagIsFocusable means a keyboard focusable, it is
382 // different from semantics focusable.
383 // TODO(chunhtai): figure out whether something is not semantics focusable.
385 }
386}
387
388void AccessibilityBridge::SetActionsFromFlutterUpdate(
389 ui::AXNodeData& node_data,
390 const SemanticsNode& node) {
391 FlutterSemanticsAction actions = node.actions;
394 }
397 }
400 }
403 }
406 }
409 }
412 }
413 // Every node has show on screen action.
415
418 }
419 if (actions & FlutterSemanticsAction::
422 }
423 if (actions & FlutterSemanticsAction::
426 }
429 }
430}
431
432void AccessibilityBridge::SetBooleanAttributesFromFlutterUpdate(
433 ui::AXNodeData& node_data,
434 const SemanticsNode& node) {
435 FlutterSemanticsAction actions = node.actions;
436 const FlutterSemanticsFlags* flags = node.flags;
438 actions & kHasScrollingAction);
439 node_data.AddBoolAttribute(
442 // TODO(chunhtai): figure out if there is a node that does not clip overflow.
444 !node.children_in_traversal_order.empty());
445 node_data.AddBoolAttribute(
449 flags->is_text_field && !flags->is_read_only);
450 // Mark nodes as line breaking so that screen readers don't
451 // merge all consecutive objects into one.
452 // TODO(schectman): When should a node have this attribute set?
453 // https://github.com/flutter/flutter/issues/118184
455 true);
456}
457
458void AccessibilityBridge::SetIntAttributesFromFlutterUpdate(
459 ui::AXNodeData& node_data,
460 const SemanticsNode& node) {
461 const FlutterSemanticsFlags* flags = node.flags;
463 node.text_direction);
464
465 int sel_start = node.text_selection_base;
466 int sel_end = node.text_selection_extent;
467 if (flags->is_text_field && !flags->is_read_only && !node.value.empty()) {
468 // By default the text field selection should be at the end.
469 sel_start = sel_start == -1 ? node.value.length() : sel_start;
470 sel_end = sel_end == -1 ? node.value.length() : sel_end;
471 }
474
475 if (node_data.role == ax::mojom::Role::kRadioButton ||
476 node_data.role == ax::mojom::Role::kCheckBox) {
477 node_data.AddIntAttribute(
479 static_cast<int32_t>(
483 ? ax::mojom::CheckedState::kTrue
484 : ax::mojom::CheckedState::kFalse));
485 } else if (node_data.role == ax::mojom::Role::kSwitch) {
486 node_data.AddIntAttribute(
488 static_cast<int32_t>(
491 : ax::mojom::CheckedState::kFalse));
492 }
493}
494
495void AccessibilityBridge::SetIntListAttributesFromFlutterUpdate(
496 ui::AXNodeData& node_data,
497 const SemanticsNode& node) {
498 FlutterSemanticsAction actions = node.actions;
500 std::vector<int32_t> custom_action_ids;
501 custom_action_ids.reserve(node.custom_accessibility_actions.size());
502 for (size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
503 custom_action_ids.push_back(node.custom_accessibility_actions[i]);
504 }
506 custom_action_ids);
507 }
508}
509
510void AccessibilityBridge::SetStringListAttributesFromFlutterUpdate(
511 ui::AXNodeData& node_data,
512 const SemanticsNode& node) {
513 FlutterSemanticsAction actions = node.actions;
515 std::vector<std::string> custom_action_description;
516 for (size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
517 auto iter = pending_semantics_custom_action_updates_.find(
518 node.custom_accessibility_actions[i]);
519 BASE_DCHECK(iter != pending_semantics_custom_action_updates_.end());
520 custom_action_description.push_back(iter->second.label);
521 }
522 node_data.AddStringListAttribute(
524 custom_action_description);
525 }
526}
527
528void AccessibilityBridge::SetIdentifierFromFlutterUpdate(
529 ui::AXNodeData& node_data,
530 const SemanticsNode& node) {
532 node.identifier);
533}
534
535void AccessibilityBridge::SetNameFromFlutterUpdate(ui::AXNodeData& node_data,
536 const SemanticsNode& node) {
537 node_data.SetName(node.label);
538}
539
540void AccessibilityBridge::SetValueFromFlutterUpdate(ui::AXNodeData& node_data,
541 const SemanticsNode& node) {
542 node_data.SetValue(node.value);
543}
544
545void AccessibilityBridge::SetTooltipFromFlutterUpdate(
546 ui::AXNodeData& node_data,
547 const SemanticsNode& node) {
548 node_data.SetTooltip(node.tooltip);
549}
550
551void AccessibilityBridge::SetTreeData(const SemanticsNode& node,
552 ui::AXTreeUpdate& tree_update) {
553 const FlutterSemanticsFlags* flags = node.flags;
554 // Set selection of the focused node if:
555 // 1. this text field has a valid selection
556 // 2. this text field doesn't have a valid selection but had selection stored
557 // in the tree.
558 if (flags->is_text_field &&
560 if (node.text_selection_base != -1) {
561 tree_update.tree_data.sel_anchor_object_id = node.id;
562 tree_update.tree_data.sel_anchor_offset = node.text_selection_base;
563 tree_update.tree_data.sel_focus_object_id = node.id;
564 tree_update.tree_data.sel_focus_offset = node.text_selection_extent;
565 tree_update.has_tree_data = true;
566 } else if (tree_update.tree_data.sel_anchor_object_id == node.id) {
568 tree_update.tree_data.sel_anchor_offset = -1;
570 tree_update.tree_data.sel_focus_offset = -1;
571 tree_update.has_tree_data = true;
572 }
573 }
574
576 tree_update.tree_data.focus_id != node.id) {
577 tree_update.tree_data.focus_id = node.id;
578 tree_update.has_tree_data = true;
580 tree_update.tree_data.focus_id == node.id) {
582 tree_update.has_tree_data = true;
583 }
584}
585
586AccessibilityBridge::SemanticsNode
587AccessibilityBridge::FromFlutterSemanticsNode(
588 const FlutterSemanticsNode2& flutter_node) {
589 SemanticsNode result;
590 result.id = flutter_node.id;
591 FML_DCHECK(flutter_node.flags2)
592 << "FlutterSemanticsNode2::flags2 must not be null";
593
594 result.flags = flutter_node.flags2;
595 result.actions = flutter_node.actions;
596 result.heading_level = flutter_node.heading_level;
597 result.text_selection_base = flutter_node.text_selection_base;
598 result.text_selection_extent = flutter_node.text_selection_extent;
599 result.scroll_child_count = flutter_node.scroll_child_count;
600 result.scroll_index = flutter_node.scroll_index;
601 result.scroll_position = flutter_node.scroll_position;
602 result.scroll_extent_max = flutter_node.scroll_extent_max;
603 result.scroll_extent_min = flutter_node.scroll_extent_min;
604 if (flutter_node.label) {
605 result.label = std::string(flutter_node.label);
606 }
607 if (flutter_node.hint) {
608 result.hint = std::string(flutter_node.hint);
609 }
610 if (flutter_node.value) {
611 result.value = std::string(flutter_node.value);
612 }
613 if (flutter_node.increased_value) {
614 result.increased_value = std::string(flutter_node.increased_value);
615 }
616 if (flutter_node.decreased_value) {
617 result.decreased_value = std::string(flutter_node.decreased_value);
618 }
619 if (flutter_node.tooltip) {
620 result.tooltip = std::string(flutter_node.tooltip);
621 }
622 result.text_direction = flutter_node.text_direction;
623 result.rect = flutter_node.rect;
624 result.transform = flutter_node.transform;
625 if (flutter_node.child_count > 0) {
626 result.children_in_traversal_order = std::vector<int32_t>(
627 flutter_node.children_in_traversal_order,
628 flutter_node.children_in_traversal_order + flutter_node.child_count);
629 }
630 if (flutter_node.custom_accessibility_actions_count > 0) {
631 result.custom_accessibility_actions = std::vector<int32_t>(
632 flutter_node.custom_accessibility_actions,
633 flutter_node.custom_accessibility_actions +
635 }
636 if (flutter_node.identifier) {
637 result.identifier = std::string(flutter_node.identifier);
638 }
639 return result;
640}
641
642AccessibilityBridge::SemanticsCustomAction
643AccessibilityBridge::FromFlutterSemanticsCustomAction(
644 const FlutterSemanticsCustomAction2& flutter_custom_action) {
645 SemanticsCustomAction result;
646 result.id = flutter_custom_action.id;
647 result.override_action = flutter_custom_action.override_action;
648 if (flutter_custom_action.label) {
649 result.label = std::string(flutter_custom_action.label);
650 }
651 if (flutter_custom_action.hint) {
652 result.hint = std::string(flutter_custom_action.hint);
653 }
654 return result;
655}
656
657void AccessibilityBridge::SetLastFocusedId(AccessibilityNodeId node_id) {
658 if (last_focused_id_ != node_id) {
659 auto last_focused_child =
660 GetFlutterPlatformNodeDelegateFromID(last_focused_id_);
661 if (!last_focused_child.expired()) {
663 last_focused_id_,
666 {});
667 }
668 last_focused_id_ = node_id;
669 }
670}
671
672AccessibilityNodeId AccessibilityBridge::GetLastFocusedId() {
673 return last_focused_id_;
674}
675
676gfx::NativeViewAccessible AccessibilityBridge::GetNativeAccessibleFromId(
678 auto platform_node_delegate = GetFlutterPlatformNodeDelegateFromID(id).lock();
679 if (!platform_node_delegate) {
680 return nullptr;
681 }
682 return platform_node_delegate->GetNativeViewAccessible();
683}
684
685gfx::RectF AccessibilityBridge::RelativeToGlobalBounds(const ui::AXNode* node,
686 bool& offscreen,
687 bool clip_bounds) {
688 return tree_->RelativeToTreeBounds(node, gfx::RectF(), &offscreen,
689 clip_bounds);
690}
691
693 ui::AXTreeID tree_id,
694 ui::AXNode::AXID node_id) const {
695 return GetNodeFromTree(node_id);
696}
697
699 ui::AXNode::AXID node_id) const {
700 return tree_->GetFromId(node_id);
701}
702
704 return tree_->GetAXTreeID();
705}
706
710
712 return tree_->root();
713}
714
718
720 return tree_.get();
721}
722
724 const ui::AXNode::AXID node_id) const {
725 auto platform_delegate_weak = GetFlutterPlatformNodeDelegateFromID(node_id);
726 auto platform_delegate = platform_delegate_weak.lock();
727 if (!platform_delegate) {
728 return nullptr;
729 }
730 return platform_delegate->GetPlatformNode();
731}
732
737
743
744} // namespace flutter
std::unique_ptr< flutter::PlatformViewIOS > platform_view
ui::AXTree * GetTree() const override
ui::AXPlatformNodeDelegate * RootDelegate() const override
std::weak_ptr< FlutterPlatformNodeDelegate > GetFlutterPlatformNodeDelegateFromID(AccessibilityNodeId id) const
Get the flutter platform node delegate with the given id from this accessibility bridge....
void AddFlutterSemanticsNodeUpdate(const FlutterSemanticsNode2 &node)
Adds a semantics node update to the pending semantics update. Calling this method alone will NOT upda...
virtual std::shared_ptr< FlutterPlatformNodeDelegate > CreateFlutterPlatformNodeDelegate()=0
Creates a platform specific FlutterPlatformNodeDelegate. Ownership passes to the caller....
void AddFlutterSemanticsCustomActionUpdate(const FlutterSemanticsCustomAction2 &action)
Adds a custom semantics action update to the pending semantics update. Calling this method alone will...
ui::AXPlatformNode * GetPlatformNodeFromTree(const ui::AXNode::AXID node_id) const override
const ui::AXTreeData & GetAXTreeData() const
Get the ax tree data from this accessibility bridge. The tree data contains information such as the i...
ui::AXTreeID GetParentTreeID() const override
ui::AXNode * GetRootAsAXNode() const override
ui::AXNode * GetParentNodeFromParentTreeAsAXNode() const override
AccessibilityBridge()
Creates a new instance of a accessibility bridge.
virtual void OnAccessibilityEvent(ui::AXEventGenerator::TargetedEvent targeted_event)=0
Handle accessibility events generated due to accessibility tree changes. These events are needed to b...
ui::AXTreeID GetTreeID() const override
const std::vector< ui::AXEventGenerator::TargetedEvent > GetPendingEvents() const
Gets all pending accessibility events generated during semantics updates. This is useful when decidin...
void CommitUpdates()
Flushes the pending updates and applies them to this accessibility bridge. Calling this with no pendi...
ui::AXNode * GetNodeFromTree(const ui::AXTreeID tree_id, const ui::AXNode::AXID node_id) const override
virtual void DispatchAccessibilityAction(AccessibilityNodeId target, FlutterSemanticsAction action, fml::MallocMapping data)=0
Dispatch accessibility action back to the Flutter framework. These actions are generated in the nativ...
void SetRect(float x, float y, float width, float height)
Definition rect_f.h:79
void SetTree(AXTree *new_tree)
AXID id() const
Definition ax_node.h:110
int32_t AXID
Definition ax_node.h:36
static constexpr AXID kInvalidAXID
Definition ax_node.h:41
void SetLocation(int32_t offset_container_id, const gfx::RectF &location, gfx::Transform *transform)
Definition ax_node.cc:377
AXNode * parent() const
Definition ax_node.h:111
const AXNodeData & data() const
Definition ax_node.h:112
static AXTreeID CreateNewAXTreeID()
Definition ax_tree_id.cc:47
void AddTreeManager(AXTreeID tree_id, AXTreeManager *manager)
static AXTreeManagerMap & GetInstance()
FlutterCheckState
Definition embedder.h:287
@ kFlutterCheckStateNone
The semantics node does not have check state.
Definition embedder.h:289
@ kFlutterCheckStateTrue
The semantics node is checked.
Definition embedder.h:291
@ kFlutterCheckStateMixed
The semantics node represents a checkbox in mixed state.
Definition embedder.h:295
FlutterSemanticsAction
Definition embedder.h:122
@ kFlutterSemanticsActionDidLoseAccessibilityFocus
Indicate that the node has lost accessibility focus.
Definition embedder.h:163
@ kFlutterSemanticsActionDecrease
Decrease the value represented by the semantics node.
Definition embedder.h:145
@ kFlutterSemanticsActionScrollDown
Definition embedder.h:141
@ kFlutterSemanticsActionScrollRight
Definition embedder.h:135
@ kFlutterSemanticsActionSetSelection
Set the text selection to the given range.
Definition embedder.h:153
@ kFlutterSemanticsActionScrollUp
Definition embedder.h:138
@ kFlutterSemanticsActionCustomAction
Indicate that the user has invoked a custom accessibility action.
Definition embedder.h:165
@ kFlutterSemanticsActionIncrease
Increase the value represented by the semantics node.
Definition embedder.h:143
@ kFlutterSemanticsActionScrollLeft
Definition embedder.h:131
@ kFlutterSemanticsActionDidGainAccessibilityFocus
Indicate that the node has gained accessibility focus.
Definition embedder.h:161
@ kFlutterSemanticsActionTap
Definition embedder.h:125
@ kFlutterTristateTrue
The property is applicable and its state is "true" or "on".
Definition embedder.h:282
@ kFlutterTristateFalse
The property is applicable and its state is "false" or "off".
Definition embedder.h:284
@ kFlutterTristateNone
The property is not applicable to this semantics node.
Definition embedder.h:280
static gboolean is_checked(FlutterSemanticsFlags flags)
const uint8_t uint32_t uint32_t GError ** error
uint32_t * target
#define FML_LOG(severity)
Definition logging.h:101
#define FML_DCHECK(condition)
Definition logging.h:122
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
constexpr int kHasScrollingAction
ui::AXNode::AXID AccessibilityNodeId
UnimplementedNativeViewAccessible * NativeViewAccessible
Definition ref_ptr.h:261
const AXTreeID & AXTreeIDUnknown()
const char * hint
The hint description of this custom semantics action.
Definition embedder.h:1812
const char * label
The user-readable name of this custom semantics action.
Definition embedder.h:1810
FlutterSemanticsAction override_action
Definition embedder.h:1808
int32_t id
The unique custom action or action override ID.
Definition embedder.h:1805
bool is_link
Whether the semantics node represents a link.
Definition embedder.h:357
bool is_image
Whether the semantics node represents an image.
Definition embedder.h:335
bool is_slider
Whether the semantics node represents a slider.
Definition embedder.h:359
bool is_header
Whether a semantic node is a header that divides content into sections.
Definition embedder.h:324
FlutterTristate is_selected
Whether a semantics node is selected.
Definition embedder.h:304
bool is_in_mutually_exclusive_group
Whether a semantic node is in a mutually exclusive group.
Definition embedder.h:322
FlutterTristate is_toggled
Definition embedder.h:309
FlutterTristate is_focused
Whether the semantic node currently holds the user's focus.
Definition embedder.h:316
FlutterTristate is_expanded
Whether a semantic node that is currently expanded.
Definition embedder.h:311
bool is_text_field
Whether the semantic node represents a text field.
Definition embedder.h:320
FlutterCheckState is_checked
Whether a semantics node is checked.
Definition embedder.h:302
bool is_button
Whether the semantic node represents a button.
Definition embedder.h:318
const char * identifier
Definition embedder.h:1752
const char * increased_value
Definition embedder.h:1688
const char * tooltip
A textual tooltip attached to the node.
Definition embedder.h:1715
int32_t scroll_index
The index of the first visible semantic child of a scroll node.
Definition embedder.h:1667
size_t custom_accessibility_actions_count
The number of custom accessibility action associated with this node.
Definition embedder.h:1707
const int32_t * children_in_traversal_order
Array of child node IDs in traversal order. Has length child_count.
Definition embedder.h:1703
double scroll_extent_min
The minimum in-range value for scrollPosition if the node is scrollable.
Definition embedder.h:1674
int32_t text_selection_extent
The position at which the text selection terminates.
Definition embedder.h:1663
FlutterTextDirection text_direction
Definition embedder.h:1694
FlutterSemanticsAction actions
The set of semantics actions applicable to this node.
Definition embedder.h:1659
const int32_t * custom_accessibility_actions
Definition embedder.h:1710
int32_t id
The unique identifier for this node.
Definition embedder.h:1651
FlutterRect rect
The bounding box for this node in its coordinate system.
Definition embedder.h:1696
FlutterTransformation transform
Definition embedder.h:1699
size_t child_count
The number of children this node has.
Definition embedder.h:1701
double scroll_extent_max
The maximum in-range value for scrollPosition if the node is scrollable.
Definition embedder.h:1672
const char * decreased_value
Definition embedder.h:1691
const char * label
A textual description of the node.
Definition embedder.h:1681
int32_t text_selection_base
The position at which the text selection originates.
Definition embedder.h:1661
const char * hint
A brief description of the result of performing an action on the node.
Definition embedder.h:1683
FlutterSemanticsFlags * flags2
Definition embedder.h:1743
const char * value
A textual description of the current value of the node.
Definition embedder.h:1685
int32_t scroll_child_count
The total number of scrollable children that contribute to semantics.
Definition embedder.h:1665
AXRelativeBounds relative_bounds
void AddIntListAttribute(ax::mojom::IntListAttribute attribute, const std::vector< int32_t > &value)
void AddState(ax::mojom::State state)
void AddIntAttribute(ax::mojom::IntAttribute attribute, int32_t value)
std::vector< int32_t > child_ids
void SetValue(const std::string &value)
void AddStringListAttribute(ax::mojom::StringListAttribute attribute, const std::vector< std::string > &value)
void SetName(const std::string &name)
void AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string &value)
void SetTooltip(const std::string &value)
void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value)
ax::mojom::Role role
void AddAction(ax::mojom::Action action)
std::unique_ptr< gfx::Transform > transform
AXNode::AXID sel_anchor_object_id
AXNode::AXID sel_focus_object_id
AXNode::AXID focus_id
int32_t sel_focus_offset
int32_t sel_anchor_offset
std::vector< AXNodeData > nodes
#define BASE_DCHECK(condition)
Definition logging.h:63