Flutter Engine
The Flutter Engine
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
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
154
157
160
162 ui::AXNode* node,
163 ax::mojom::Role old_role,
164 ax::mojom::Role new_role) {}
165
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
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
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>(
478 ? ax::mojom::CheckedState::kTrue
479 : ax::mojom::CheckedState::kFalse));
480 } else if (node_data.role == ax::mojom::Role::kSwitch) {
481 node_data.AddIntAttribute(
483 static_cast<int32_t>(
486 : ax::mojom::CheckedState::kFalse));
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
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
656 return last_focused_id_;
657}
658
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
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
693
695 return tree_->root();
696}
697
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
720
726
727} // namespace flutter
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 OnNodeCreated(ui::AXTree *tree, ui::AXNode *node) override
AccessibilityNodeId GetLastFocusedId() override
Get the last id of the node that received accessibility focus.
void AddFlutterSemanticsNodeUpdate(const FlutterSemanticsNode2 &node)
Adds a semantics node update to the pending semantics update. Calling this method alone will NOT upda...
void OnSubtreeWillBeDeleted(ui::AXTree *tree, ui::AXNode *node) override
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
gfx::RectF RelativeToGlobalBounds(const ui::AXNode *node, bool &offscreen, bool clip_bounds) override
Gets the rectangular bounds of the ax node relative to global coordinate.
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
void SetLastFocusedId(AccessibilityNodeId node_id) override
Update the id of the node that is currently foucsed by the native accessibility system.
gfx::NativeViewAccessible GetNativeAccessibleFromId(AccessibilityNodeId id) override
Get the native accessibility node with the given id.
ui::AXNode * GetParentNodeFromParentTreeAsAXNode() const override
void OnAtomicUpdateFinished(ui::AXTree *tree, bool root_changed, const std::vector< ui::AXTreeObserver::Change > &changes) 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
void OnNodeWillBeDeleted(ui::AXTree *tree, ui::AXNode *node) override
void OnNodeDeleted(ui::AXTree *tree, AccessibilityNodeId node_id) override
const std::vector< ui::AXEventGenerator::TargetedEvent > GetPendingEvents() const
Gets all pending accessibility events generated during semantics updates. This is useful when decidin...
void OnRoleChanged(ui::AXTree *tree, ui::AXNode *node, ax::mojom::Role old_role, ax::mojom::Role new_role) override
void CommitUpdates()
Flushes the pending updates and applies them to this accessibility bridge. Calling this with no pendi...
void OnNodeReparented(ui::AXTree *tree, ui::AXNode *node) override
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()
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:170
@ kFlutterSemanticsFlagIsHeader
Whether a semantic node is a header that divides content into sections.
Definition embedder.h:192
@ kFlutterSemanticsFlagIsSlider
Whether the semantics node represents a slider.
Definition embedder.h:234
@ kFlutterSemanticsFlagHasToggledState
The semantics node has the quality of either being "on" or "off".
Definition embedder.h:207
@ kFlutterSemanticsFlagIsSelected
Whether a semantics node is selected.
Definition embedder.h:177
@ kFlutterSemanticsFlagIsInMutuallyExclusiveGroup
Whether a semantic node is in a mutually exclusive group.
Definition embedder.h:190
@ kFlutterSemanticsFlagIsChecked
Whether a semantics node is checked.
Definition embedder.h:175
@ kFlutterSemanticsFlagHasExpandedState
Definition embedder.h:241
@ kFlutterSemanticsFlagIsCheckStateMixed
Whether the semantics node represents a tristate checkbox in mixed state.
Definition embedder.h:238
@ kFlutterSemanticsFlagIsToggled
Definition embedder.h:210
@ kFlutterSemanticsFlagIsButton
Whether the semantic node represents a button.
Definition embedder.h:179
@ kFlutterSemanticsFlagIsReadOnly
Definition embedder.h:228
@ kFlutterSemanticsFlagIsLink
Whether the semantics node represents a link.
Definition embedder.h:232
@ kFlutterSemanticsFlagIsFocused
Whether the semantic node currently holds the user's focus.
Definition embedder.h:183
@ kFlutterSemanticsFlagIsImage
Whether the semantics node represents an image.
Definition embedder.h:203
@ kFlutterSemanticsFlagIsTextField
Whether the semantic node represents a text field.
Definition embedder.h:181
@ kFlutterSemanticsFlagHasCheckedState
Definition embedder.h:173
@ kFlutterSemanticsFlagIsExpanded
Whether a semantic node that hasExpandedState is currently expanded.
Definition embedder.h:243
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()
const char * hint
The hint description of this custom semantics action.
Definition embedder.h:1480
const char * label
The user-readable name of this custom semantics action.
Definition embedder.h:1478
FlutterSemanticsAction override_action
Definition embedder.h:1476
int32_t id
The unique custom action or action override ID.
Definition embedder.h:1473
const char * increased_value
Definition embedder.h:1368
const char * tooltip
A textual tooltip attached to the node.
Definition embedder.h:1395
int32_t scroll_index
The index of the first visible semantic child of a scroll node.
Definition embedder.h:1347
size_t custom_accessibility_actions_count
The number of custom accessibility action associated with this node.
Definition embedder.h:1387
const int32_t * children_in_traversal_order
Array of child node IDs in traversal order. Has length child_count.
Definition embedder.h:1383
double scroll_extent_min
The minimum in-range value for scrollPosition if the node is scrollable.
Definition embedder.h:1354
double thickness
Describes how much space the semantics node takes up along the z-axis.
Definition embedder.h:1359
int32_t text_selection_extent
The position at which the text selection terminates.
Definition embedder.h:1343
FlutterTextDirection text_direction
Definition embedder.h:1374
FlutterSemanticsAction actions
The set of semantics actions applicable to this node.
Definition embedder.h:1339
const int32_t * custom_accessibility_actions
Definition embedder.h:1390
int32_t id
The unique identifier for this node.
Definition embedder.h:1335
FlutterRect rect
The bounding box for this node in its coordinate system.
Definition embedder.h:1376
FlutterTransformation transform
Definition embedder.h:1379
size_t child_count
The number of children this node has.
Definition embedder.h:1381
double scroll_extent_max
The maximum in-range value for scrollPosition if the node is scrollable.
Definition embedder.h:1352
const char * decreased_value
Definition embedder.h:1371
const char * label
A textual description of the node.
Definition embedder.h:1361
int32_t text_selection_base
The position at which the text selection originates.
Definition embedder.h:1341
const char * hint
A brief description of the result of performing an action on the node.
Definition embedder.h:1363
const char * value
A textual description of the current value of the node.
Definition embedder.h:1365
int32_t scroll_child_count
The total number of scrollable children that contribute to semantics.
Definition embedder.h:1345
FlutterSemanticsFlag flags
The set of semantics flags associated with this node.
Definition embedder.h:1337
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 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
#define ERROR(message)