Flutter Engine
The Flutter Engine
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
10#include "flutter/third_party/accessibility/ax/ax_tree_manager_map.h"
11#include "flutter/third_party/accessibility/ax/ax_tree_update.h"
12#include "flutter/third_party/accessibility/base/logging.h"
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::OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) {
167 BASE_DCHECK(node);
168 id_wrapper_map_[node->id()] = CreateFlutterPlatformNodeDelegate();
169 id_wrapper_map_[node->id()]->Init(
170 std::static_pointer_cast<FlutterPlatformNodeDelegate::OwnerBridge>(
171 shared_from_this()),
172 node);
173}
174
175void AccessibilityBridge::OnNodeDeleted(ui::AXTree* tree,
176 AccessibilityNodeId node_id) {
178 if (id_wrapper_map_.find(node_id) != id_wrapper_map_.end()) {
179 id_wrapper_map_.erase(node_id);
180 }
181}
182
183void AccessibilityBridge::OnAtomicUpdateFinished(
184 ui::AXTree* tree,
185 bool root_changed,
186 const std::vector<ui::AXTreeObserver::Change>& changes) {
187 // The Flutter semantics update does not include child->parent relationship
188 // We have to update the relative bound offset container id here in order
189 // to calculate the screen bound correctly.
190 for (const auto& change : changes) {
191 ui::AXNode* node = change.node;
192 const ui::AXNodeData& data = node->data();
193 AccessibilityNodeId offset_container_id = -1;
194 if (node->parent()) {
195 offset_container_id = node->parent()->id();
196 }
197 node->SetLocation(offset_container_id, data.relative_bounds.bounds,
198 data.relative_bounds.transform.get());
199 }
200}
201
202std::optional<ui::AXTreeUpdate>
203AccessibilityBridge::CreateRemoveReparentedNodesUpdate() {
204 std::unordered_map<int32_t, ui::AXNodeData> updates;
205
206 for (const auto& node_update : pending_semantics_node_updates_) {
207 for (int32_t child_id : node_update.second.children_in_traversal_order) {
208 // Skip nodes that don't exist or have a parent in the current tree.
209 ui::AXNode* child = tree_->GetFromId(child_id);
210 if (!child) {
211 continue;
212 }
213
214 // Flutter's root node should never be reparented.
215 assert(child->parent());
216
217 // Skip nodes whose parents are unchanged.
218 if (child->parent()->id() == node_update.second.id) {
219 continue;
220 }
221
222 // This pending update moves the current child node.
223 // That new child must have a corresponding pending update.
224 assert(pending_semantics_node_updates_.find(child_id) !=
225 pending_semantics_node_updates_.end());
226
227 // Create an update to remove the child from its previous parent.
228 int32_t parent_id = child->parent()->id();
229 if (updates.find(parent_id) == updates.end()) {
230 updates[parent_id] = tree_->GetFromId(parent_id)->data();
231 }
232
233 ui::AXNodeData* parent = &updates[parent_id];
234 auto iter = std::find(parent->child_ids.begin(), parent->child_ids.end(),
235 child_id);
236
237 assert(iter != parent->child_ids.end());
238 parent->child_ids.erase(iter);
239 }
240 }
241
242 if (updates.empty()) {
243 return std::nullopt;
244 }
245
247 .tree_data = tree_->data(),
248 .nodes = std::vector<ui::AXNodeData>(),
249 };
250
251 for (std::pair<int32_t, ui::AXNodeData> data : updates) {
252 update.nodes.push_back(std::move(data.second));
253 }
254
255 return update;
256}
257
258// Private method.
259void AccessibilityBridge::GetSubTreeList(const SemanticsNode& target,
260 std::vector<SemanticsNode>& result) {
261 result.push_back(target);
262 for (int32_t child : target.children_in_traversal_order) {
263 auto iter = pending_semantics_node_updates_.find(child);
264 if (iter != pending_semantics_node_updates_.end()) {
265 SemanticsNode node = iter->second;
266 GetSubTreeList(node, result);
267 pending_semantics_node_updates_.erase(iter);
268 }
269 }
270}
271
272void AccessibilityBridge::ConvertFlutterUpdate(const SemanticsNode& node,
273 ui::AXTreeUpdate& tree_update) {
274 ui::AXNodeData node_data;
275 node_data.id = node.id;
276 SetRoleFromFlutterUpdate(node_data, node);
277 SetStateFromFlutterUpdate(node_data, node);
278 SetActionsFromFlutterUpdate(node_data, node);
279 SetBooleanAttributesFromFlutterUpdate(node_data, node);
280 SetIntAttributesFromFlutterUpdate(node_data, node);
281 SetIntListAttributesFromFlutterUpdate(node_data, node);
282 SetStringListAttributesFromFlutterUpdate(node_data, node);
283 SetNameFromFlutterUpdate(node_data, node);
284 SetValueFromFlutterUpdate(node_data, node);
285 SetTooltipFromFlutterUpdate(node_data, node);
286 node_data.relative_bounds.bounds.SetRect(node.rect.left, node.rect.top,
287 node.rect.right - node.rect.left,
288 node.rect.bottom - node.rect.top);
289 node_data.relative_bounds.transform = std::make_unique<gfx::Transform>(
290 node.transform.scaleX, node.transform.skewX, node.transform.transX, 0,
291 node.transform.skewY, node.transform.scaleY, node.transform.transY, 0,
292 node.transform.pers0, node.transform.pers1, node.transform.pers2, 0, 0, 0,
293 0, 0);
294 for (auto child : node.children_in_traversal_order) {
295 node_data.child_ids.push_back(child);
296 }
297 SetTreeData(node, tree_update);
298 tree_update.nodes.push_back(node_data);
299}
300
301void AccessibilityBridge::SetRoleFromFlutterUpdate(ui::AXNodeData& node_data,
302 const SemanticsNode& node) {
303 FlutterSemanticsFlag flags = node.flags;
305 node_data.role = ax::mojom::Role::kButton;
306 return;
307 }
311 return;
312 }
314 node_data.role = ax::mojom::Role::kHeader;
315 return;
316 }
318 node_data.role = ax::mojom::Role::kImage;
319 return;
320 }
322 node_data.role = ax::mojom::Role::kLink;
323 return;
324 }
325
329 return;
330 }
333 return;
334 }
336 node_data.role = ax::mojom::Role::kSwitch;
337 return;
338 }
340 node_data.role = ax::mojom::Role::kSlider;
341 return;
342 }
343 // If the state cannot be derived from the flutter flags, we fallback to group
344 // or static text.
345 if (node.children_in_traversal_order.empty()) {
347 } else {
348 node_data.role = ax::mojom::Role::kGroup;
349 }
350}
351
352void AccessibilityBridge::SetStateFromFlutterUpdate(ui::AXNodeData& node_data,
353 const SemanticsNode& node) {
354 FlutterSemanticsFlag flags = node.flags;
355 FlutterSemanticsAction actions = node.actions;
359 } else if (flags &
362 }
366 }
367 if (node_data.role == ax::mojom::Role::kStaticText &&
368 (actions & kHasScrollingAction) == 0 && node.value.empty() &&
369 node.label.empty() && node.hint.empty()) {
371 } else {
372 // kFlutterSemanticsFlagIsFocusable means a keyboard focusable, it is
373 // different from semantics focusable.
374 // TODO(chunhtai): figure out whether something is not semantics focusable.
376 }
377}
378
379void AccessibilityBridge::SetActionsFromFlutterUpdate(
380 ui::AXNodeData& node_data,
381 const SemanticsNode& node) {
382 FlutterSemanticsAction actions = node.actions;
385 }
388 }
391 }
394 }
397 }
400 }
403 }
404 // Every node has show on screen action.
406
409 }
410 if (actions & FlutterSemanticsAction::
413 }
414 if (actions & FlutterSemanticsAction::
417 }
420 }
421}
422
423void AccessibilityBridge::SetBooleanAttributesFromFlutterUpdate(
424 ui::AXNodeData& node_data,
425 const SemanticsNode& node) {
426 FlutterSemanticsAction actions = node.actions;
427 FlutterSemanticsFlag flags = node.flags;
429 actions & kHasScrollingAction);
430 node_data.AddBoolAttribute(
433 // TODO(chunhtai): figure out if there is a node that does not clip overflow.
435 !node.children_in_traversal_order.empty());
436 node_data.AddBoolAttribute(
439 node_data.AddBoolAttribute(
443 // Mark nodes as line breaking so that screen readers don't
444 // merge all consecutive objects into one.
445 // TODO(schectman): When should a node have this attribute set?
446 // https://github.com/flutter/flutter/issues/118184
448 true);
449}
450
451void AccessibilityBridge::SetIntAttributesFromFlutterUpdate(
452 ui::AXNodeData& node_data,
453 const SemanticsNode& node) {
454 FlutterSemanticsFlag flags = node.flags;
456 node.text_direction);
457
458 int sel_start = node.text_selection_base;
459 int sel_end = node.text_selection_extent;
462 !node.value.empty()) {
463 // By default the text field selection should be at the end.
464 sel_start = sel_start == -1 ? node.value.length() : sel_start;
465 sel_end = sel_end == -1 ? node.value.length() : sel_end;
466 }
469
470 if (node_data.role == ax::mojom::Role::kRadioButton ||
471 node_data.role == ax::mojom::Role::kCheckBox) {
472 node_data.AddIntAttribute(
474 static_cast<int32_t>(
480 } else if (node_data.role == ax::mojom::Role::kSwitch) {
481 node_data.AddIntAttribute(
483 static_cast<int32_t>(
487 }
488}
489
490void AccessibilityBridge::SetIntListAttributesFromFlutterUpdate(
491 ui::AXNodeData& node_data,
492 const SemanticsNode& node) {
493 FlutterSemanticsAction actions = node.actions;
495 std::vector<int32_t> custom_action_ids;
496 for (size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
497 custom_action_ids.push_back(node.custom_accessibility_actions[i]);
498 }
500 custom_action_ids);
501 }
502}
503
504void AccessibilityBridge::SetStringListAttributesFromFlutterUpdate(
505 ui::AXNodeData& node_data,
506 const SemanticsNode& node) {
507 FlutterSemanticsAction actions = node.actions;
509 std::vector<std::string> custom_action_description;
510 for (size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
511 auto iter = pending_semantics_custom_action_updates_.find(
512 node.custom_accessibility_actions[i]);
513 BASE_DCHECK(iter != pending_semantics_custom_action_updates_.end());
514 custom_action_description.push_back(iter->second.label);
515 }
516 node_data.AddStringListAttribute(
518 custom_action_description);
519 }
520}
521
522void AccessibilityBridge::SetNameFromFlutterUpdate(ui::AXNodeData& node_data,
523 const SemanticsNode& node) {
524 node_data.SetName(node.label);
525}
526
527void AccessibilityBridge::SetValueFromFlutterUpdate(ui::AXNodeData& node_data,
528 const SemanticsNode& node) {
529 node_data.SetValue(node.value);
530}
531
532void AccessibilityBridge::SetTooltipFromFlutterUpdate(
533 ui::AXNodeData& node_data,
534 const SemanticsNode& node) {
535 node_data.SetTooltip(node.tooltip);
536}
537
538void AccessibilityBridge::SetTreeData(const SemanticsNode& node,
539 ui::AXTreeUpdate& tree_update) {
540 FlutterSemanticsFlag flags = node.flags;
541 // Set selection of the focused node if:
542 // 1. this text field has a valid selection
543 // 2. this text field doesn't have a valid selection but had selection stored
544 // in the tree.
547 if (node.text_selection_base != -1) {
548 tree_update.tree_data.sel_anchor_object_id = node.id;
549 tree_update.tree_data.sel_anchor_offset = node.text_selection_base;
550 tree_update.tree_data.sel_focus_object_id = node.id;
551 tree_update.tree_data.sel_focus_offset = node.text_selection_extent;
552 tree_update.has_tree_data = true;
553 } else if (tree_update.tree_data.sel_anchor_object_id == node.id) {
555 tree_update.tree_data.sel_anchor_offset = -1;
557 tree_update.tree_data.sel_focus_offset = -1;
558 tree_update.has_tree_data = true;
559 }
560 }
561
563 tree_update.tree_data.focus_id != node.id) {
564 tree_update.tree_data.focus_id = node.id;
565 tree_update.has_tree_data = true;
567 0 &&
568 tree_update.tree_data.focus_id == node.id) {
570 tree_update.has_tree_data = true;
571 }
572}
573
574AccessibilityBridge::SemanticsNode
575AccessibilityBridge::FromFlutterSemanticsNode(
576 const FlutterSemanticsNode2& flutter_node) {
577 SemanticsNode result;
578 result.id = flutter_node.id;
579 result.flags = flutter_node.flags;
580 result.actions = flutter_node.actions;
581 result.text_selection_base = flutter_node.text_selection_base;
582 result.text_selection_extent = flutter_node.text_selection_extent;
583 result.scroll_child_count = flutter_node.scroll_child_count;
584 result.scroll_index = flutter_node.scroll_index;
585 result.scroll_position = flutter_node.scroll_position;
586 result.scroll_extent_max = flutter_node.scroll_extent_max;
587 result.scroll_extent_min = flutter_node.scroll_extent_min;
588 result.elevation = flutter_node.elevation;
589 result.thickness = flutter_node.thickness;
590 if (flutter_node.label) {
591 result.label = std::string(flutter_node.label);
592 }
593 if (flutter_node.hint) {
594 result.hint = std::string(flutter_node.hint);
595 }
596 if (flutter_node.value) {
597 result.value = std::string(flutter_node.value);
598 }
599 if (flutter_node.increased_value) {
600 result.increased_value = std::string(flutter_node.increased_value);
601 }
602 if (flutter_node.decreased_value) {
603 result.decreased_value = std::string(flutter_node.decreased_value);
604 }
605 if (flutter_node.tooltip) {
606 result.tooltip = std::string(flutter_node.tooltip);
607 }
608 result.text_direction = flutter_node.text_direction;
609 result.rect = flutter_node.rect;
610 result.transform = flutter_node.transform;
611 if (flutter_node.child_count > 0) {
612 result.children_in_traversal_order = std::vector<int32_t>(
613 flutter_node.children_in_traversal_order,
614 flutter_node.children_in_traversal_order + flutter_node.child_count);
615 }
616 if (flutter_node.custom_accessibility_actions_count > 0) {
617 result.custom_accessibility_actions = std::vector<int32_t>(
618 flutter_node.custom_accessibility_actions,
619 flutter_node.custom_accessibility_actions +
621 }
622 return result;
623}
624
625AccessibilityBridge::SemanticsCustomAction
626AccessibilityBridge::FromFlutterSemanticsCustomAction(
627 const FlutterSemanticsCustomAction2& flutter_custom_action) {
628 SemanticsCustomAction result;
629 result.id = flutter_custom_action.id;
630 result.override_action = flutter_custom_action.override_action;
631 if (flutter_custom_action.label) {
632 result.label = std::string(flutter_custom_action.label);
633 }
634 if (flutter_custom_action.hint) {
635 result.hint = std::string(flutter_custom_action.hint);
636 }
637 return result;
638}
639
640void AccessibilityBridge::SetLastFocusedId(AccessibilityNodeId node_id) {
641 if (last_focused_id_ != node_id) {
642 auto last_focused_child =
643 GetFlutterPlatformNodeDelegateFromID(last_focused_id_);
644 if (!last_focused_child.expired()) {
646 last_focused_id_,
649 {});
650 }
651 last_focused_id_ = node_id;
652 }
653}
654
655AccessibilityNodeId AccessibilityBridge::GetLastFocusedId() {
656 return last_focused_id_;
657}
658
659gfx::NativeViewAccessible AccessibilityBridge::GetNativeAccessibleFromId(
661 auto platform_node_delegate = GetFlutterPlatformNodeDelegateFromID(id).lock();
662 if (!platform_node_delegate) {
663 return nullptr;
664 }
665 return platform_node_delegate->GetNativeViewAccessible();
666}
667
668gfx::RectF AccessibilityBridge::RelativeToGlobalBounds(const ui::AXNode* node,
669 bool& offscreen,
670 bool clip_bounds) {
671 return tree_->RelativeToTreeBounds(node, gfx::RectF(), &offscreen,
672 clip_bounds);
673}
674
676 ui::AXTreeID tree_id,
677 ui::AXNode::AXID node_id) const {
678 return GetNodeFromTree(node_id);
679}
680
682 ui::AXNode::AXID node_id) const {
683 return tree_->GetFromId(node_id);
684}
685
687 return tree_->GetAXTreeID();
688}
689
691 return ui::AXTreeIDUnknown();
692}
693
695 return tree_->root();
696}
697
699 return nullptr;
700}
701
703 return tree_.get();
704}
705
707 const ui::AXNode::AXID node_id) const {
708 auto platform_delegate_weak = GetFlutterPlatformNodeDelegateFromID(node_id);
709 auto platform_delegate = platform_delegate_weak.lock();
710 if (!platform_delegate) {
711 return nullptr;
712 }
713 return platform_delegate->GetPlatformNode();
714}
715
717 const ui::AXNode& node) const {
718 return GetPlatformNodeFromTree(node.id());
719}
720
723 .lock()
724 .get();
725}
726
727} // namespace flutter
int find(T *array, int N, T item)
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
Iterator begin() const
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()
static const char * begin(const StringSlice &s)
Definition: editor.cpp:252
FlutterSemanticsAction
Definition: embedder.h:113
@ kFlutterSemanticsActionDidLoseAccessibilityFocus
Indicate that the node has lost accessibility focus.
Definition: embedder.h:154
@ kFlutterSemanticsActionDecrease
Decrease the value represented by the semantics node.
Definition: embedder.h:136
@ kFlutterSemanticsActionScrollDown
Definition: embedder.h:132
@ kFlutterSemanticsActionScrollRight
Definition: embedder.h:126
@ kFlutterSemanticsActionSetSelection
Set the text selection to the given range.
Definition: embedder.h:144
@ kFlutterSemanticsActionScrollUp
Definition: embedder.h:129
@ kFlutterSemanticsActionCustomAction
Indicate that the user has invoked a custom accessibility action.
Definition: embedder.h:156
@ kFlutterSemanticsActionIncrease
Increase the value represented by the semantics node.
Definition: embedder.h:134
@ kFlutterSemanticsActionScrollLeft
Definition: embedder.h:122
@ kFlutterSemanticsActionDidGainAccessibilityFocus
Indicate that the node has gained accessibility focus.
Definition: embedder.h:152
@ kFlutterSemanticsActionTap
Definition: embedder.h:116
FlutterSemanticsFlag
Definition: embedder.h:172
@ kFlutterSemanticsFlagIsHeader
Whether a semantic node is a header that divides content into sections.
Definition: embedder.h:194
@ kFlutterSemanticsFlagIsSlider
Whether the semantics node represents a slider.
Definition: embedder.h:236
@ kFlutterSemanticsFlagHasToggledState
The semantics node has the quality of either being "on" or "off".
Definition: embedder.h:209
@ kFlutterSemanticsFlagIsSelected
Whether a semantics node is selected.
Definition: embedder.h:179
@ kFlutterSemanticsFlagIsInMutuallyExclusiveGroup
Whether a semantic node is in a mutually exclusive group.
Definition: embedder.h:192
@ kFlutterSemanticsFlagIsChecked
Whether a semantics node is checked.
Definition: embedder.h:177
@ kFlutterSemanticsFlagHasExpandedState
Definition: embedder.h:243
@ kFlutterSemanticsFlagIsCheckStateMixed
Whether the semantics node represents a tristate checkbox in mixed state.
Definition: embedder.h:240
@ kFlutterSemanticsFlagIsToggled
Definition: embedder.h:212
@ kFlutterSemanticsFlagIsButton
Whether the semantic node represents a button.
Definition: embedder.h:181
@ kFlutterSemanticsFlagIsReadOnly
Definition: embedder.h:230
@ kFlutterSemanticsFlagIsLink
Whether the semantics node represents a link.
Definition: embedder.h:234
@ kFlutterSemanticsFlagIsFocused
Whether the semantic node currently holds the user's focus.
Definition: embedder.h:185
@ kFlutterSemanticsFlagIsImage
Whether the semantics node represents an image.
Definition: embedder.h:205
@ kFlutterSemanticsFlagIsTextField
Whether the semantic node represents a text field.
Definition: embedder.h:183
@ kFlutterSemanticsFlagHasCheckedState
Definition: embedder.h:175
@ kFlutterSemanticsFlagIsExpanded
Whether a semantic node that hasExpandedState is currently expanded.
Definition: embedder.h:245
FlutterSemanticsFlag flags
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
uint32_t * target
#define FML_LOG(severity)
Definition: logging.h:82
#define FML_DCHECK(condition)
Definition: logging.h:103
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: switches.h:41
constexpr int kHasScrollingAction
ui::AXNode::AXID AccessibilityNodeId
UnimplementedNativeViewAccessible * NativeViewAccessible
Definition: ref_ptr.h:256
const AXTreeID & AXTreeIDUnknown()
Definition: ax_tree_id.cc:103
Definition: update.py:1
const char * hint
The hint description of this custom semantics action.
Definition: embedder.h:1482
const char * label
The user-readable name of this custom semantics action.
Definition: embedder.h:1480
FlutterSemanticsAction override_action
Definition: embedder.h:1478
int32_t id
The unique custom action or action override ID.
Definition: embedder.h:1475
const char * increased_value
Definition: embedder.h:1370
const char * tooltip
A textual tooltip attached to the node.
Definition: embedder.h:1397
int32_t scroll_index
The index of the first visible semantic child of a scroll node.
Definition: embedder.h:1349
size_t custom_accessibility_actions_count
The number of custom accessibility action associated with this node.
Definition: embedder.h:1389
const int32_t * children_in_traversal_order
Array of child node IDs in traversal order. Has length child_count.
Definition: embedder.h:1385
double scroll_extent_min
The minimum in-range value for scrollPosition if the node is scrollable.
Definition: embedder.h:1356
double thickness
Describes how much space the semantics node takes up along the z-axis.
Definition: embedder.h:1361
int32_t text_selection_extent
The position at which the text selection terminates.
Definition: embedder.h:1345
FlutterTextDirection text_direction
Definition: embedder.h:1376
FlutterSemanticsAction actions
The set of semantics actions applicable to this node.
Definition: embedder.h:1341
const int32_t * custom_accessibility_actions
Definition: embedder.h:1392
int32_t id
The unique identifier for this node.
Definition: embedder.h:1337
FlutterRect rect
The bounding box for this node in its coordinate system.
Definition: embedder.h:1378
FlutterTransformation transform
Definition: embedder.h:1381
size_t child_count
The number of children this node has.
Definition: embedder.h:1383
double scroll_extent_max
The maximum in-range value for scrollPosition if the node is scrollable.
Definition: embedder.h:1354
const char * decreased_value
Definition: embedder.h:1373
const char * label
A textual description of the node.
Definition: embedder.h:1363
int32_t text_selection_base
The position at which the text selection originates.
Definition: embedder.h:1343
const char * hint
A brief description of the result of performing an action on the node.
Definition: embedder.h:1365
const char * value
A textual description of the current value of the node.
Definition: embedder.h:1367
int32_t scroll_child_count
The total number of scrollable children that contribute to semantics.
Definition: embedder.h:1347
FlutterSemanticsFlag flags
The set of semantics flags associated with this node.
Definition: embedder.h:1339
AXRelativeBounds relative_bounds
Definition: ax_node_data.h:293
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
Definition: ax_node_data.h:291
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 SetTooltip(const std::string &value)
void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value)
ax::mojom::Role role
Definition: ax_node_data.h:277
void AddAction(ax::mojom::Action action)
std::unique_ptr< gfx::Transform > transform
AXNode::AXID sel_anchor_object_id
Definition: ax_tree_data.h:62
AXNode::AXID sel_focus_object_id
Definition: ax_tree_data.h:65
AXNode::AXID focus_id
Definition: ax_tree_data.h:53
int32_t sel_focus_offset
Definition: ax_tree_data.h:66
int32_t sel_anchor_offset
Definition: ax_tree_data.h:63
std::vector< AXNodeData > nodes
#define BASE_DCHECK(condition)
Definition: logging.h:63
#define ERROR(message)
Definition: elf_loader.cc:260