24 : tree_(
std::make_unique<
ui::AXTree>()) {
25 event_generator_.
SetTree(tree_.get());
29 tree_->UpdateData(
data);
41 pending_semantics_node_updates_[node.
id] = FromFlutterSemanticsNode(node);
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;
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);
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()) {
130std::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();
145const std::vector<ui::AXEventGenerator::TargetedEvent>
147 std::vector<ui::AXEventGenerator::TargetedEvent> result(
148 event_generator_.
begin(), event_generator_.
end());
152void AccessibilityBridge::OnNodeWillBeDeleted(
ui::AXTree* tree,
155void AccessibilityBridge::OnSubtreeWillBeDeleted(
ui::AXTree* tree,
161void AccessibilityBridge::OnRoleChanged(
ui::AXTree* tree,
166void AccessibilityBridge::OnNodeDataChanged(
173 platform_view->NodeDataChanged(old_node_data, new_node_data);
180 id_wrapper_map_[node->
id()]->Init(
181 std::static_pointer_cast<FlutterPlatformNodeDelegate::OwnerBridge>(
186void AccessibilityBridge::OnNodeDeleted(
ui::AXTree* tree,
189 if (id_wrapper_map_.find(node_id) != id_wrapper_map_.end()) {
190 id_wrapper_map_.erase(node_id);
194void AccessibilityBridge::OnAtomicUpdateFinished(
197 const std::vector<ui::AXTreeObserver::Change>& changes) {
201 for (
const auto& change : changes) {
206 offset_container_id = node->
parent()->
id();
209 data.relative_bounds.transform.get());
213std::optional<ui::AXTreeUpdate>
214AccessibilityBridge::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);
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();
253 if (updates.empty()) {
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));
270void 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);
283void AccessibilityBridge::ConvertFlutterUpdate(
const SemanticsNode& node,
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);
299 node.rect.right - node.rect.left,
300 node.rect.bottom - node.rect.top);
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) {
309 SetTreeData(node, tree_update);
310 tree_update.
nodes.push_back(node_data);
313void AccessibilityBridge::SetRoleFromFlutterUpdate(
ui::AXNodeData& node_data,
314 const SemanticsNode& node) {
316 FML_DCHECK(flags) <<
"SemanticsNode::flags must not be null";
357 if (node.children_in_traversal_order.empty()) {
364void AccessibilityBridge::SetStateFromFlutterUpdate(
ui::AXNodeData& node_data,
365 const SemanticsNode& node) {
378 node.label.empty() && node.hint.empty()) {
388void AccessibilityBridge::SetActionsFromFlutterUpdate(
390 const SemanticsNode& node) {
432void AccessibilityBridge::SetBooleanAttributesFromFlutterUpdate(
434 const SemanticsNode& node) {
444 !node.children_in_traversal_order.empty());
458void AccessibilityBridge::SetIntAttributesFromFlutterUpdate(
460 const SemanticsNode& node) {
463 node.text_direction);
465 int sel_start = node.text_selection_base;
466 int sel_end = node.text_selection_extent;
469 sel_start = sel_start == -1 ? node.value.length() : sel_start;
470 sel_end = sel_end == -1 ? node.value.length() : sel_end;
479 static_cast<int32_t
>(
488 static_cast<int32_t
>(
495void AccessibilityBridge::SetIntListAttributesFromFlutterUpdate(
497 const SemanticsNode& node) {
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]);
510void AccessibilityBridge::SetStringListAttributesFromFlutterUpdate(
512 const SemanticsNode& node) {
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);
524 custom_action_description);
528void AccessibilityBridge::SetIdentifierFromFlutterUpdate(
530 const SemanticsNode& node) {
535void AccessibilityBridge::SetNameFromFlutterUpdate(
ui::AXNodeData& node_data,
536 const SemanticsNode& node) {
540void AccessibilityBridge::SetValueFromFlutterUpdate(
ui::AXNodeData& node_data,
541 const SemanticsNode& node) {
545void AccessibilityBridge::SetTooltipFromFlutterUpdate(
547 const SemanticsNode& node) {
551void AccessibilityBridge::SetTreeData(
const SemanticsNode& node,
560 if (node.text_selection_base != -1) {
586AccessibilityBridge::SemanticsNode
587AccessibilityBridge::FromFlutterSemanticsNode(
589 SemanticsNode result;
590 result.id = flutter_node.
id;
592 <<
"FlutterSemanticsNode2::flags2 must not be null";
594 result.flags = flutter_node.
flags2;
595 result.actions = flutter_node.
actions;
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);
620 result.tooltip = std::string(flutter_node.
tooltip);
623 result.rect = flutter_node.
rect;
624 result.transform = flutter_node.
transform;
626 result.children_in_traversal_order = std::vector<int32_t>(
631 result.custom_accessibility_actions = std::vector<int32_t>(
637 result.identifier = std::string(flutter_node.
identifier);
642AccessibilityBridge::SemanticsCustomAction
643AccessibilityBridge::FromFlutterSemanticsCustomAction(
645 SemanticsCustomAction result;
646 result.id = flutter_custom_action.
id;
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()) {
668 last_focused_id_ = node_id;
673 return last_focused_id_;
679 if (!platform_node_delegate) {
682 return platform_node_delegate->GetNativeViewAccessible();
688 return tree_->RelativeToTreeBounds(node,
gfx::RectF(), &offscreen,
700 return tree_->GetFromId(node_id);
704 return tree_->GetAXTreeID();
712 return tree_->root();
726 auto platform_delegate = platform_delegate_weak.lock();
727 if (!platform_delegate) {
730 return platform_delegate->GetPlatformNode();
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
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
void SetRect(float x, float y, float width, float height)
void SetTree(AXTree *new_tree)
static constexpr AXID kInvalidAXID
void SetLocation(int32_t offset_container_id, const gfx::RectF &location, gfx::Transform *transform)
const AXNodeData & data() const
static AXTreeID CreateNewAXTreeID()
void AddTreeManager(AXTreeID tree_id, AXTreeManager *manager)
static AXTreeManagerMap & GetInstance()
@ kFlutterCheckStateNone
The semantics node does not have check state.
@ kFlutterCheckStateTrue
The semantics node is checked.
@ kFlutterCheckStateMixed
The semantics node represents a checkbox in mixed state.
@ kFlutterSemanticsActionDidLoseAccessibilityFocus
Indicate that the node has lost accessibility focus.
@ kFlutterSemanticsActionDecrease
Decrease the value represented by the semantics node.
@ kFlutterSemanticsActionScrollDown
@ kFlutterSemanticsActionScrollRight
@ kFlutterSemanticsActionSetSelection
Set the text selection to the given range.
@ kFlutterSemanticsActionScrollUp
@ kFlutterSemanticsActionCustomAction
Indicate that the user has invoked a custom accessibility action.
@ kFlutterSemanticsActionIncrease
Increase the value represented by the semantics node.
@ kFlutterSemanticsActionScrollLeft
@ kFlutterSemanticsActionDidGainAccessibilityFocus
Indicate that the node has gained accessibility focus.
@ kFlutterSemanticsActionTap
@ kFlutterTristateTrue
The property is applicable and its state is "true" or "on".
@ kFlutterTristateFalse
The property is applicable and its state is "false" or "off".
@ kFlutterTristateNone
The property is not applicable to this semantics node.
static gboolean is_checked(FlutterSemanticsFlags flags)
const uint8_t uint32_t uint32_t GError ** error
#define FML_LOG(severity)
#define FML_DCHECK(condition)
@ kCustomActionDescriptions
@ kClearAccessibilityFocus
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
constexpr int kHasScrollingAction
ui::AXNode::AXID AccessibilityNodeId
UnimplementedNativeViewAccessible * NativeViewAccessible
const AXTreeID & AXTreeIDUnknown()
const char * hint
The hint description of this custom semantics action.
const char * label
The user-readable name of this custom semantics action.
FlutterSemanticsAction override_action
int32_t id
The unique custom action or action override ID.
bool is_link
Whether the semantics node represents a link.
bool is_image
Whether the semantics node represents an image.
bool is_slider
Whether the semantics node represents a slider.
bool is_header
Whether a semantic node is a header that divides content into sections.
FlutterTristate is_selected
Whether a semantics node is selected.
bool is_in_mutually_exclusive_group
Whether a semantic node is in a mutually exclusive group.
FlutterTristate is_toggled
FlutterTristate is_focused
Whether the semantic node currently holds the user's focus.
FlutterTristate is_expanded
Whether a semantic node that is currently expanded.
bool is_text_field
Whether the semantic node represents a text field.
FlutterCheckState is_checked
Whether a semantics node is checked.
bool is_button
Whether the semantic node represents a button.
const char * increased_value
const char * tooltip
A textual tooltip attached to the node.
int32_t scroll_index
The index of the first visible semantic child of a scroll node.
size_t custom_accessibility_actions_count
The number of custom accessibility action associated with this node.
const int32_t * children_in_traversal_order
Array of child node IDs in traversal order. Has length child_count.
double scroll_extent_min
The minimum in-range value for scrollPosition if the node is scrollable.
int32_t text_selection_extent
The position at which the text selection terminates.
FlutterTextDirection text_direction
FlutterSemanticsAction actions
The set of semantics actions applicable to this node.
const int32_t * custom_accessibility_actions
int32_t id
The unique identifier for this node.
FlutterRect rect
The bounding box for this node in its coordinate system.
FlutterTransformation transform
size_t child_count
The number of children this node has.
double scroll_extent_max
The maximum in-range value for scrollPosition if the node is scrollable.
const char * decreased_value
const char * label
A textual description of the node.
int32_t text_selection_base
The position at which the text selection originates.
const char * hint
A brief description of the result of performing an action on the node.
FlutterSemanticsFlags * flags2
const char * value
A textual description of the current value of the node.
int32_t scroll_child_count
The total number of scrollable children that contribute to semantics.
AXRelativeBounds relative_bounds
void AddIntListAttribute(ax::mojom::IntListAttribute attribute, const std::vector< int32_t > &value)
void AddState(ax::mojom::State state)
void AddIntAttribute(ax::mojom::IntAttribute attribute, int32_t value)
std::vector< int32_t > child_ids
void SetValue(const std::string &value)
void AddStringListAttribute(ax::mojom::StringListAttribute attribute, const std::vector< std::string > &value)
void SetName(const std::string &name)
void AddStringAttribute(ax::mojom::StringAttribute attribute, const std::string &value)
void SetTooltip(const std::string &value)
void AddBoolAttribute(ax::mojom::BoolAttribute attribute, bool value)
void AddAction(ax::mojom::Action action)
std::unique_ptr< gfx::Transform > transform
AXNode::AXID sel_anchor_object_id
AXNode::AXID sel_focus_object_id
int32_t sel_anchor_offset
std::vector< AXNodeData > nodes
#define BASE_DCHECK(condition)