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) {
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(
446 ax::mojom::BoolAttribute::kSelected,
447 flags->is_selected == FlutterTristate::kFlutterTristateTrue);
448 node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kEditableRoot,
449 flags->is_text_field && !flags->is_read_only);
454 node_data.AddBoolAttribute(ax::mojom::BoolAttribute::kIsLineBreakingObject,
458 void AccessibilityBridge::SetIntAttributesFromFlutterUpdate(
459 ui::AXNodeData& node_data,
460 const SemanticsNode& node) {
461 const FlutterSemanticsFlags* flags = node.flags;
462 node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextDirection,
463 node.text_direction);
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()) {
469 sel_start = sel_start == -1 ? node.value.length() : sel_start;
470 sel_end = sel_end == -1 ? node.value.length() : sel_end;
472 node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart, sel_start);
473 node_data.AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, sel_end);
475 if (node_data.role == ax::mojom::Role::kRadioButton ||
476 node_data.role == ax::mojom::Role::kCheckBox) {
477 node_data.AddIntAttribute(
478 ax::mojom::IntAttribute::kCheckedState,
479 static_cast<int32_t
>(
480 (flags->is_checked == FlutterCheckState::kFlutterCheckStateMixed)
481 ? ax::mojom::CheckedState::kMixed
482 : (flags->is_checked == FlutterCheckState::kFlutterCheckStateTrue)
483 ? ax::mojom::CheckedState::kTrue
484 : ax::mojom::CheckedState::kFalse));
485 }
else if (node_data.role == ax::mojom::Role::kSwitch) {
486 node_data.AddIntAttribute(
487 ax::mojom::IntAttribute::kCheckedState,
488 static_cast<int32_t
>(
489 (flags->is_toggled == FlutterTristate::kFlutterTristateTrue)
490 ? ax::mojom::CheckedState::kTrue
491 : ax::mojom::CheckedState::kFalse));
495 void AccessibilityBridge::SetIntListAttributesFromFlutterUpdate(
496 ui::AXNodeData& node_data,
497 const SemanticsNode& node) {
498 FlutterSemanticsAction actions = node.actions;
499 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
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]);
505 node_data.AddIntListAttribute(ax::mojom::IntListAttribute::kCustomActionIds,
510 void AccessibilityBridge::SetStringListAttributesFromFlutterUpdate(
511 ui::AXNodeData& node_data,
512 const SemanticsNode& node) {
513 FlutterSemanticsAction actions = node.actions;
514 if (actions & FlutterSemanticsAction::kFlutterSemanticsActionCustomAction) {
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);
522 node_data.AddStringListAttribute(
523 ax::mojom::StringListAttribute::kCustomActionDescriptions,
524 custom_action_description);
528 void AccessibilityBridge::SetIdentifierFromFlutterUpdate(
529 ui::AXNodeData& node_data,
530 const SemanticsNode& node) {
531 node_data.AddStringAttribute(ax::mojom::StringAttribute::kIdentifier,
535 void AccessibilityBridge::SetNameFromFlutterUpdate(ui::AXNodeData& node_data,
536 const SemanticsNode& node) {
537 node_data.SetName(node.label);
540 void AccessibilityBridge::SetValueFromFlutterUpdate(ui::AXNodeData& node_data,
541 const SemanticsNode& node) {
542 node_data.SetValue(node.value);
545 void AccessibilityBridge::SetTooltipFromFlutterUpdate(
546 ui::AXNodeData& node_data,
547 const SemanticsNode& node) {
548 node_data.SetTooltip(node.tooltip);
551 void AccessibilityBridge::SetTreeData(
const SemanticsNode& node,
552 ui::AXTreeUpdate& tree_update) {
553 const FlutterSemanticsFlags* flags = node.flags;
558 if (flags->is_text_field &&
559 flags->is_focused == FlutterTristate::kFlutterTristateTrue) {
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) {
567 tree_update.tree_data.sel_anchor_object_id = ui::AXNode::kInvalidAXID;
568 tree_update.tree_data.sel_anchor_offset = -1;
569 tree_update.tree_data.sel_focus_object_id = ui::AXNode::kInvalidAXID;
570 tree_update.tree_data.sel_focus_offset = -1;
571 tree_update.has_tree_data =
true;
575 if (flags->is_focused == FlutterTristate::kFlutterTristateTrue &&
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;
579 }
else if (flags->is_focused != FlutterTristate::kFlutterTristateTrue &&
580 tree_update.tree_data.focus_id == node.id) {
581 tree_update.tree_data.focus_id = ui::AXNode::kInvalidAXID;
582 tree_update.has_tree_data =
true;
586 AccessibilityBridge::SemanticsNode
587 AccessibilityBridge::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";
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);
607 if (flutter_node.hint) {
608 result.hint = std::string(flutter_node.hint);
610 if (flutter_node.value) {
611 result.value = std::string(flutter_node.value);
613 if (flutter_node.increased_value) {
614 result.increased_value = std::string(flutter_node.increased_value);
616 if (flutter_node.decreased_value) {
617 result.decreased_value = std::string(flutter_node.decreased_value);
619 if (flutter_node.tooltip) {
620 result.tooltip = std::string(flutter_node.tooltip);
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);
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 +
634 flutter_node.custom_accessibility_actions_count);
636 if (flutter_node.identifier) {
637 result.identifier = std::string(flutter_node.identifier);
642 AccessibilityBridge::SemanticsCustomAction
643 AccessibilityBridge::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);
651 if (flutter_custom_action.hint) {
652 result.hint = std::string(flutter_custom_action.hint);
658 if (last_focused_id_ != node_id) {
659 auto last_focused_child =
661 if (!last_focused_child.expired()) {
664 FlutterSemanticsAction::
665 kFlutterSemanticsActionDidLoseAccessibilityFocus,
668 last_focused_id_ = node_id;
673 return last_focused_id_;
676 gfx::NativeViewAccessible AccessibilityBridge::GetNativeAccessibleFromId(
679 if (!platform_node_delegate) {
682 return platform_node_delegate->GetNativeViewAccessible();
685 gfx::RectF AccessibilityBridge::RelativeToGlobalBounds(
const ui::AXNode* node,
688 return tree_->RelativeToTreeBounds(node, gfx::RectF(), &offscreen,
693 ui::AXTreeID tree_id,
694 ui::AXNode::AXID node_id)
const {
699 ui::AXNode::AXID node_id)
const {
700 return tree_->GetFromId(node_id);
704 return tree_->GetAXTreeID();
708 return ui::AXTreeIDUnknown();
712 return tree_->root();
724 const ui::AXNode::AXID node_id)
const {
726 auto platform_delegate = platform_delegate_weak.lock();
727 if (!platform_delegate) {
730 return platform_delegate->GetPlatformNode();
734 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
virtual ~AccessibilityBridge()
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
const uint8_t uint32_t uint32_t GError ** error
constexpr int kHasScrollingAction
ui::AXNode::AXID AccessibilityNodeId