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"
17 FlutterSemanticsAction::kFlutterSemanticsActionScrollLeft |
18 FlutterSemanticsAction::kFlutterSemanticsActionScrollRight |
19 FlutterSemanticsAction::kFlutterSemanticsActionScrollUp |
20 FlutterSemanticsAction::kFlutterSemanticsActionScrollDown;
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();
28 data.tree_id = ui::AXTreeID::CreateNewAXTreeID();
29 tree_->UpdateData(data);
30 ui::AXTreeManagerMap::GetInstance().AddTreeManager(tree_->GetAXTreeID(),
35 event_generator_.ReleaseTree();
36 tree_->RemoveObserver(
static_cast<ui::AXTreeObserver*
>(
this));
40 const FlutterSemanticsNode2& node) {
41 pending_semantics_node_updates_[node.id] = FromFlutterSemanticsNode(node);
45 const FlutterSemanticsCustomAction2& action) {
46 pending_semantics_custom_action_updates_[action.id] =
47 FromFlutterSemanticsCustomAction(action);
58 std::optional<ui::AXTreeUpdate> remove_reparented =
59 CreateRemoveReparentedNodesUpdate();
60 if (remove_reparented.has_value()) {
61 tree_->Unserialize(remove_reparented.value());
63 std::string error = tree_->error();
65 FML_LOG(ERROR) <<
"Failed to update ui::AXTree, error: " << error;
73 ui::AXTreeUpdate update{.tree_data = tree_->data()};
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);
93 for (
size_t i = results.size(); i > 0; i--) {
94 for (
const SemanticsNode& node : results[i - 1]) {
95 ConvertFlutterUpdate(node, update);
102 if (!results.empty() &&
GetRootAsAXNode()->
id() == ui::AXNode::kInvalidAXID) {
103 FML_DCHECK(!results.back().empty());
105 update.root_id = results.back().front().id;
108 tree_->Unserialize(update);
109 pending_semantics_node_updates_.clear();
110 pending_semantics_custom_action_updates_.clear();
112 std::string error = tree_->error();
113 if (!error.empty()) {
114 FML_LOG(ERROR) <<
"Failed to update ui::AXTree, error: " << error;
118 for (
const auto& targeted_event : event_generator_) {
121 if (event_target.expired()) {
127 event_generator_.ClearEvents();
130 std::weak_ptr<FlutterPlatformNodeDelegate>
133 const auto iter = id_wrapper_map_.find(
id);
134 if (iter != id_wrapper_map_.end()) {
138 return std::weak_ptr<FlutterPlatformNodeDelegate>();
142 return tree_->data();
145 const std::vector<ui::AXEventGenerator::TargetedEvent>
147 std::vector<ui::AXEventGenerator::TargetedEvent> result(
148 event_generator_.begin(), event_generator_.end());
152 void AccessibilityBridge::OnNodeWillBeDeleted(ui::AXTree* tree,
155 void AccessibilityBridge::OnSubtreeWillBeDeleted(ui::AXTree* tree,
158 void AccessibilityBridge::OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) {
161 void AccessibilityBridge::OnRoleChanged(ui::AXTree* tree,
163 ax::mojom::Role old_role,
164 ax::mojom::Role new_role) {}
166 void AccessibilityBridge::OnNodeDataChanged(
168 const ui::AXNodeData& old_node_data,
169 const ui::AXNodeData& new_node_data) {
173 platform_view->NodeDataChanged(old_node_data, new_node_data);
177 void AccessibilityBridge::OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) {
180 id_wrapper_map_[node->id()]->Init(
181 std::static_pointer_cast<FlutterPlatformNodeDelegate::OwnerBridge>(
186 void AccessibilityBridge::OnNodeDeleted(ui::AXTree* tree,
188 BASE_DCHECK(node_id != ui::AXNode::kInvalidAXID);
189 if (id_wrapper_map_.find(node_id) != id_wrapper_map_.end()) {
190 id_wrapper_map_.erase(node_id);
194 void AccessibilityBridge::OnAtomicUpdateFinished(
197 const std::vector<ui::AXTreeObserver::Change>& changes) {
201 for (
const auto& change : changes) {
202 ui::AXNode* node = change.node;
203 const ui::AXNodeData& data = node->data();
205 if (node->parent()) {
206 offset_container_id = node->parent()->id();
208 node->SetLocation(offset_container_id, data.relative_bounds.bounds,
209 data.relative_bounds.transform.get());
213 std::optional<ui::AXTreeUpdate>
214 AccessibilityBridge::CreateRemoveReparentedNodesUpdate() {
215 std::unordered_map<int32_t, ui::AXNodeData> updates;
217 for (
const auto& node_update : pending_semantics_node_updates_) {
218 for (int32_t child_id : node_update.second.children_in_traversal_order) {
220 ui::AXNode* child = tree_->GetFromId(child_id);
226 assert(child->parent());
229 if (child->parent()->id() == node_update.second.id) {
235 assert(pending_semantics_node_updates_.find(child_id) !=
236 pending_semantics_node_updates_.end());
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();
244 ui::AXNodeData* parent = &updates[parent_id];
245 auto iter = std::find(parent->child_ids.begin(), parent->child_ids.end(),
248 assert(iter != parent->child_ids.end());
249 parent->child_ids.erase(iter);
253 if (updates.empty()) {
257 ui::AXTreeUpdate update{
258 .tree_data = tree_->data(),
259 .nodes = std::vector<ui::AXNodeData>(),
262 for (std::pair<int32_t, ui::AXNodeData> data : updates) {
263 update.nodes.push_back(std::move(data.second));
270 void 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);
283 void 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,
306 for (
auto child : node.children_in_traversal_order) {
307 node_data.child_ids.push_back(child);
309 SetTreeData(node, tree_update);
310 tree_update.nodes.push_back(node_data);
313 void 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;
321 if (flags->is_text_field && !flags->is_read_only) {
322 node_data.role = ax::mojom::Role::kTextField;
325 if (flags->is_header) {
326 node_data.role = ax::mojom::Role::kHeader;
329 if (flags->is_image) {
330 node_data.role = ax::mojom::Role::kImage;
333 if (flags->is_link) {
334 node_data.role = ax::mojom::Role::kLink;
338 if (flags->is_in_mutually_exclusive_group &&
339 flags->is_checked != FlutterCheckState::kFlutterCheckStateNone) {
340 node_data.role = ax::mojom::Role::kRadioButton;
343 if (flags->is_checked != FlutterCheckState::kFlutterCheckStateNone) {
344 node_data.role = ax::mojom::Role::kCheckBox;
347 if (flags->is_toggled != FlutterTristate::kFlutterTristateNone) {
348 node_data.role = ax::mojom::Role::kSwitch;
351 if (flags->is_slider) {
352 node_data.role = ax::mojom::Role::kSlider;
357 if (node.children_in_traversal_order.empty()) {
358 node_data.role = ax::mojom::Role::kStaticText;
360 node_data.role = ax::mojom::Role::kGroup;
364 void AccessibilityBridge::SetStateFromFlutterUpdate(ui::AXNodeData& node_data,
365 const SemanticsNode& node) {
366 const FlutterSemanticsFlags* flags = node.flags;
367 FlutterSemanticsAction actions = node.actions;
368 if (flags->is_expanded == FlutterTristate::kFlutterTristateTrue) {
369 node_data.AddState(ax::mojom::State::kExpanded);
370 }
else if (flags->is_expanded == FlutterTristate::kFlutterTristateFalse) {
371 node_data.AddState(ax::mojom::State::kCollapsed);
373 if (flags->is_text_field && !flags->is_read_only) {
374 node_data.AddState(ax::mojom::State::kEditable);
376 if (node_data.role == ax::mojom::Role::kStaticText &&
378 node.label.empty() && node.hint.empty()) {
379 node_data.AddState(ax::mojom::State::kIgnored);
384 node_data.AddState(ax::mojom::State::kFocusable);
388 void AccessibilityBridge::SetActionsFromFlutterUpdate(
389 ui::AXNodeData& node_data,
390 const SemanticsNode& node) {
391 FlutterSemanticsAction actions = node.actions;
392 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionTap) {
393 node_data.AddAction(ax::mojom::Action::kDoDefault);
395 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollLeft) {
396 node_data.AddAction(ax::mojom::Action::kScrollLeft);
398 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollRight) {
399 node_data.AddAction(ax::mojom::Action::kScrollRight);
401 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollUp) {
402 node_data.AddAction(ax::mojom::Action::kScrollUp);
404 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionScrollDown) {
405 node_data.AddAction(ax::mojom::Action::kScrollDown);
407 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionIncrease) {
408 node_data.AddAction(ax::mojom::Action::kIncrement);
410 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionDecrease) {
411 node_data.AddAction(ax::mojom::Action::kDecrement);
414 node_data.AddAction(ax::mojom::Action::kScrollToMakeVisible);
416 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionSetSelection) {
417 node_data.AddAction(ax::mojom::Action::kSetSelection);
419 if (actions & FlutterSemanticsAction::
420 kFlutterSemanticsActionDidGainAccessibilityFocus) {
421 node_data.AddAction(ax::mojom::Action::kSetAccessibilityFocus);
423 if (actions & FlutterSemanticsAction::
424 kFlutterSemanticsActionDidLoseAccessibilityFocus) {
425 node_data.AddAction(ax::mojom::Action::kClearAccessibilityFocus);
427 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
428 node_data.AddAction(ax::mojom::Action::kCustomAction);
432 void AccessibilityBridge::SetBooleanAttributesFromFlutterUpdate(
433 ui::AXNodeData& node_data,
434 const SemanticsNode& node) {
435 FlutterSemanticsAction actions = node.actions;
436 const FlutterSemanticsFlags* flags = node.flags;
437 node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable,
439 node_data.AddBoolAttribute(
440 ax::mojom::BoolAttribute::kClickable,
441 actions & FlutterSemanticsAction::kFlutterSemanticsActionTap);
443 node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kClipsChildren,
444 !node.children_in_traversal_order.empty());
445 node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kSelected,
447 node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
448 flags->is_text_field && !flags->is_read_only);
453 node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
457 void AccessibilityBridge::SetIntAttributesFromFlutterUpdate(
458 ui::AXNodeData& node_data,
459 const SemanticsNode& node) {
460 const FlutterSemanticsFlags* flags = node.flags;
461 node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextDirection,
462 node.text_direction);
464 int sel_start = node.text_selection_base;
465 int sel_end = node.text_selection_extent;
466 if (flags->is_text_field && !flags->is_read_only && !node.value.empty()) {
468 sel_start = sel_start == -1 ? node.value.length() : sel_start;
469 sel_end = sel_end == -1 ? node.value.length() : sel_end;
471 node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart, sel_start);
472 node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, sel_end);
474 if (node_data.role == ax::mojom::Role::kRadioButton ||
475 node_data.role == ax::mojom::Role::kCheckBox) {
476 node_data.AddIntAttribute(
477 ax::mojom::IntAttribute::kCheckedState,
478 static_cast<int32_t
>(
479 (flags->is_checked == FlutterCheckState::kFlutterCheckStateMixed)
480 ? ax::mojom::CheckedState::kMixed
481 : (flags->is_checked == FlutterCheckState::kFlutterCheckStateTrue)
482 ? ax::mojom::CheckedState::kTrue
483 : ax::mojom::CheckedState::kFalse));
484 }
else if (node_data.role == ax::mojom::Role::kSwitch) {
485 node_data.AddIntAttribute(
486 ax::mojom::IntAttribute::kCheckedState,
487 static_cast<int32_t
>(
488 (flags->is_toggled == FlutterTristate::kFlutterTristateTrue)
489 ? ax::mojom::CheckedState::kTrue
490 : ax::mojom::CheckedState::kFalse));
494 void AccessibilityBridge::SetIntListAttributesFromFlutterUpdate(
495 ui::AXNodeData& node_data,
496 const SemanticsNode& node) {
497 FlutterSemanticsAction actions = node.actions;
498 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
499 std::vector<int32_t> custom_action_ids;
500 custom_action_ids.reserve(node.custom_accessibility_actions.size());
501 for (
size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
502 custom_action_ids.push_back(node.custom_accessibility_actions[i]);
504 node_data.AddIntListAttribute(ax::mojom::IntListAttribute::kCustomActionIds,
509 void AccessibilityBridge::SetStringListAttributesFromFlutterUpdate(
510 ui::AXNodeData& node_data,
511 const SemanticsNode& node) {
512 FlutterSemanticsAction actions = node.actions;
513 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
514 std::vector<std::string> custom_action_description;
515 for (
size_t i = 0; i < node.custom_accessibility_actions.size(); i++) {
516 auto iter = pending_semantics_custom_action_updates_.find(
517 node.custom_accessibility_actions[i]);
518 BASE_DCHECK(iter != pending_semantics_custom_action_updates_.end());
519 custom_action_description.push_back(iter->second.label);
521 node_data.AddStringListAttribute(
522 ax::mojom::StringListAttribute::kCustomActionDescriptions,
523 custom_action_description);
527 void AccessibilityBridge::SetIdentifierFromFlutterUpdate(
528 ui::AXNodeData& node_data,
529 const SemanticsNode& node) {
530 node_data.AddStringAttribute(ax::mojom::StringAttribute::kIdentifier,
534 void AccessibilityBridge::SetNameFromFlutterUpdate(ui::AXNodeData& node_data,
535 const SemanticsNode& node) {
536 node_data.SetName(node.label);
539 void AccessibilityBridge::SetValueFromFlutterUpdate(ui::AXNodeData& node_data,
540 const SemanticsNode& node) {
541 node_data.SetValue(node.value);
544 void AccessibilityBridge::SetTooltipFromFlutterUpdate(
545 ui::AXNodeData& node_data,
546 const SemanticsNode& node) {
547 node_data.SetTooltip(node.tooltip);
550 void AccessibilityBridge::SetTreeData(
const SemanticsNode& node,
551 ui::AXTreeUpdate& tree_update) {
552 const FlutterSemanticsFlags* flags = node.flags;
557 if (flags->is_text_field &&
558 flags->is_focused == FlutterTristate::kFlutterTristateTrue) {
559 if (node.text_selection_base != -1) {
560 tree_update.tree_data.sel_anchor_object_id = node.id;
561 tree_update.tree_data.sel_anchor_offset = node.text_selection_base;
562 tree_update.tree_data.sel_focus_object_id = node.id;
563 tree_update.tree_data.sel_focus_offset = node.text_selection_extent;
564 tree_update.has_tree_data =
true;
565 }
else if (tree_update.tree_data.sel_anchor_object_id == node.id) {
566 tree_update.tree_data.sel_anchor_object_id = ui::AXNode::kInvalidAXID;
567 tree_update.tree_data.sel_anchor_offset = -1;
568 tree_update.tree_data.sel_focus_object_id = ui::AXNode::kInvalidAXID;
569 tree_update.tree_data.sel_focus_offset = -1;
570 tree_update.has_tree_data =
true;
574 if (flags->is_focused == FlutterTristate::kFlutterTristateTrue &&
575 tree_update.tree_data.focus_id != node.id) {
576 tree_update.tree_data.focus_id = node.id;
577 tree_update.has_tree_data =
true;
578 }
else if (flags->is_focused != FlutterTristate::kFlutterTristateTrue &&
579 tree_update.tree_data.focus_id == node.id) {
580 tree_update.tree_data.focus_id = ui::AXNode::kInvalidAXID;
581 tree_update.has_tree_data =
true;
585 AccessibilityBridge::SemanticsNode
586 AccessibilityBridge::FromFlutterSemanticsNode(
587 const FlutterSemanticsNode2& flutter_node) {
588 SemanticsNode result;
589 result.id = flutter_node.id;
590 FML_DCHECK(flutter_node.flags2)
591 <<
"FlutterSemanticsNode2::flags2 must not be null";
593 result.flags = flutter_node.flags2;
594 result.actions = flutter_node.actions;
595 result.heading_level = flutter_node.heading_level;
596 result.text_selection_base = flutter_node.text_selection_base;
597 result.text_selection_extent = flutter_node.text_selection_extent;
598 result.scroll_child_count = flutter_node.scroll_child_count;
599 result.scroll_index = flutter_node.scroll_index;
600 result.scroll_position = flutter_node.scroll_position;
601 result.scroll_extent_max = flutter_node.scroll_extent_max;
602 result.scroll_extent_min = flutter_node.scroll_extent_min;
603 if (flutter_node.label) {
604 result.label = std::string(flutter_node.label);
606 if (flutter_node.hint) {
607 result.hint = std::string(flutter_node.hint);
609 if (flutter_node.value) {
610 result.value = std::string(flutter_node.value);
612 if (flutter_node.increased_value) {
613 result.increased_value = std::string(flutter_node.increased_value);
615 if (flutter_node.decreased_value) {
616 result.decreased_value = std::string(flutter_node.decreased_value);
618 if (flutter_node.tooltip) {
619 result.tooltip = std::string(flutter_node.tooltip);
621 result.text_direction = flutter_node.text_direction;
622 result.rect = flutter_node.rect;
623 result.transform = flutter_node.transform;
624 if (flutter_node.child_count > 0) {
625 result.children_in_traversal_order = std::vector<int32_t>(
626 flutter_node.children_in_traversal_order,
627 flutter_node.children_in_traversal_order + flutter_node.child_count);
629 if (flutter_node.custom_accessibility_actions_count > 0) {
630 result.custom_accessibility_actions = std::vector<int32_t>(
631 flutter_node.custom_accessibility_actions,
632 flutter_node.custom_accessibility_actions +
633 flutter_node.custom_accessibility_actions_count);
635 if (flutter_node.identifier) {
636 result.identifier = std::string(flutter_node.identifier);
641 AccessibilityBridge::SemanticsCustomAction
642 AccessibilityBridge::FromFlutterSemanticsCustomAction(
643 const FlutterSemanticsCustomAction2& flutter_custom_action) {
644 SemanticsCustomAction result;
645 result.id = flutter_custom_action.id;
646 result.override_action = flutter_custom_action.override_action;
647 if (flutter_custom_action.label) {
648 result.label = std::string(flutter_custom_action.label);
650 if (flutter_custom_action.hint) {
651 result.hint = std::string(flutter_custom_action.hint);
657 if (last_focused_id_ != node_id) {
658 auto last_focused_child =
660 if (!last_focused_child.expired()) {
663 FlutterSemanticsAction::
664 kFlutterSemanticsActionDidLoseAccessibilityFocus,
667 last_focused_id_ = node_id;
672 return last_focused_id_;
675 gfx::NativeViewAccessible AccessibilityBridge::GetNativeAccessibleFromId(
678 if (!platform_node_delegate) {
681 return platform_node_delegate->GetNativeViewAccessible();
684 gfx::RectF AccessibilityBridge::RelativeToGlobalBounds(
const ui::AXNode* node,
687 return tree_->RelativeToTreeBounds(node, gfx::RectF(), &offscreen,
692 ui::AXTreeID tree_id,
693 ui::AXNode::AXID node_id)
const {
698 ui::AXNode::AXID node_id)
const {
699 return tree_->GetFromId(node_id);
703 return tree_->GetAXTreeID();
707 return ui::AXTreeIDUnknown();
711 return tree_->root();
723 const ui::AXNode::AXID node_id)
const {
725 auto platform_delegate = platform_delegate_weak.lock();
726 if (!platform_delegate) {
729 return platform_delegate->GetPlatformNode();
733 const ui::AXNode& node)
const {
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....
virtual std::shared_ptr< FlutterPlatformNodeDelegate > CreateFlutterPlatformNodeDelegate()=0
Creates a platform specific FlutterPlatformNodeDelegate. Ownership passes to the caller....
void AddFlutterSemanticsNodeUpdate(const FlutterSemanticsNode2 &node)
Adds a semantics node update to the pending semantics update. Calling this method alone will NOT upda...
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
constexpr int kHasScrollingAction
ui::AXNode::AXID AccessibilityNodeId