| Flutter iOS Embedder |

accessibility_bridge.h
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
5 #ifndef FLUTTER_SHELL_PLATFORM_COMMON_ACCESSIBILITY_BRIDGE_H_
6 #define FLUTTER_SHELL_PLATFORM_COMMON_ACCESSIBILITY_BRIDGE_H_
7
8 #include <unordered_map>
9
10 #include "flutter/fml/mapping.h"
11 #include "flutter/shell/platform/embedder/embedder.h"
12
13 #include "flutter/third_party/accessibility/ax/ax_event_generator.h"
14 #include "flutter/third_party/accessibility/ax/ax_tree.h"
15 #include "flutter/third_party/accessibility/ax/ax_tree_observer.h"
16 #include "flutter/third_party/accessibility/ax/platform/ax_platform_node_delegate.h"
17 #include "flutter/third_party/accessibility/ax/platform/ax_platform_tree_manager.h"
18
19 #include "flutter_platform_node_delegate.h"
20
21 namespace flutter {
22
23 //------------------------------------------------------------------------------
24 /// Use this class to maintain an accessibility tree. This class consumes
25 /// semantics updates from the embedder API and produces an accessibility tree
26 /// in the native format.
27 ///
28 /// The bridge creates an AXTree to hold the semantics data that comes from
29 /// Flutter semantics updates. The tree holds AXNode[s] which contain the
30 /// semantics information for semantics node. The AXTree resemble the Flutter
31 /// semantics tree in the Flutter framework. The bridge also uses
32 /// FlutterPlatformNodeDelegate to wrap each AXNode in order to provide
33 /// an accessibility tree in the native format.
34 ///
35 /// To use this class, one must subclass this class and provide their own
36 /// implementation of FlutterPlatformNodeDelegate.
37 ///
38 /// AccessibilityBridge must be created as a shared_ptr, since some methods
39 /// acquires its weak_ptr.
40 class AccessibilityBridge
41 : public std::enable_shared_from_this<AccessibilityBridge>,
42 public FlutterPlatformNodeDelegate::OwnerBridge,
43 public ui::AXPlatformTreeManager,
44 private ui::AXTreeObserver {
45 public:
46 //-----------------------------------------------------------------------------
47 /// @brief Creates a new instance of a accessibility bridge.
48 AccessibilityBridge();
49 virtual ~AccessibilityBridge();
50
51 //------------------------------------------------------------------------------
52 /// @brief Adds a semantics node update to the pending semantics update.
53 /// Calling this method alone will NOT update the semantics tree.
54 /// To flush the pending updates, call the CommitUpdates().
55 ///
56 /// @param[in] node A reference to the semantics node update.
57 void AddFlutterSemanticsNodeUpdate(const FlutterSemanticsNode2& node);
58
59 //------------------------------------------------------------------------------
60 /// @brief Adds a custom semantics action update to the pending semantics
61 /// update. Calling this method alone will NOT update the
62 /// semantics tree. To flush the pending updates, call the
63 /// CommitUpdates().
64 ///
65 /// @param[in] action A reference to the custom semantics action
66 /// update.
67 void AddFlutterSemanticsCustomActionUpdate(
68 const FlutterSemanticsCustomAction2& action);
69
70 //------------------------------------------------------------------------------
71 /// @brief Flushes the pending updates and applies them to this
72 /// accessibility bridge. Calling this with no pending updates
73 /// does nothing, and callers should call this method at the end
74 /// of an atomic batch to avoid leaving the tree in a unstable
75 /// state. For example if a node reparents from A to B, callers
76 /// should only call this method when both removal from A and
77 /// addition to B are in the pending updates.
78 void CommitUpdates();
79
80 //------------------------------------------------------------------------------
81 /// @brief Get the flutter platform node delegate with the given id from
82 /// this accessibility bridge. Returns expired weak_ptr if the
83 /// delegate associated with the id does not exist or has been
84 /// removed from the accessibility tree.
85 ///
86 /// @param[in] id The id of the flutter accessibility node you want
87 /// to retrieve.
88 std::weak_ptr<FlutterPlatformNodeDelegate>
89 GetFlutterPlatformNodeDelegateFromID(AccessibilityNodeId id) const;
90
91 //------------------------------------------------------------------------------
92 /// @brief Get the ax tree data from this accessibility bridge. The tree
93 /// data contains information such as the id of the node that
94 /// has the keyboard focus or the text selection range.
95 const ui::AXTreeData& GetAXTreeData() const;
96
97 //------------------------------------------------------------------------------
98 /// @brief Gets all pending accessibility events generated during
99 /// semantics updates. This is useful when deciding how to handle
100 /// events in AccessibilityBridgeDelegate::OnAccessibilityEvent in
101 /// case one may decide to handle an event differently based on
102 /// all pending events.
103 const std::vector<ui::AXEventGenerator::TargetedEvent> GetPendingEvents()
104 const;
105
106 // |AXTreeManager|
107 ui::AXNode* GetNodeFromTree(const ui::AXTreeID tree_id,
108 const ui::AXNode::AXID node_id) const override;
109
110 // |AXTreeManager|
111 ui::AXNode* GetNodeFromTree(const ui::AXNode::AXID node_id) const override;
112
113 // |AXTreeManager|
114 ui::AXTreeID GetTreeID() const override;
115
116 // |AXTreeManager|
117 ui::AXTreeID GetParentTreeID() const override;
118
119 // |AXTreeManager|
120 ui::AXNode* GetRootAsAXNode() const override;
121
122 // |AXTreeManager|
123 ui::AXNode* GetParentNodeFromParentTreeAsAXNode() const override;
124
125 // |AXTreeManager|
126 ui::AXTree* GetTree() const override;
127
128 // |AXPlatformTreeManager|
129 ui::AXPlatformNode* GetPlatformNodeFromTree(
130 const ui::AXNode::AXID node_id) const override;
131
132 // |AXPlatformTreeManager|
133 ui::AXPlatformNode* GetPlatformNodeFromTree(
134 const ui::AXNode& node) const override;
135
136 // |AXPlatformTreeManager|
137 ui::AXPlatformNodeDelegate* RootDelegate() const override;
138
139 protected:
140 //---------------------------------------------------------------------------
141 /// @brief Handle accessibility events generated due to accessibility
142 /// tree changes. These events are needed to be sent to native
143 /// accessibility system. See ui::AXEventGenerator::Event for
144 /// possible events.
145 ///
146 /// @param[in] targeted_event The object that contains both the
147 /// generated event and the event target.
148 virtual void OnAccessibilityEvent(
149 ui::AXEventGenerator::TargetedEvent targeted_event) = 0;
150
151 //---------------------------------------------------------------------------
152 /// @brief Creates a platform specific FlutterPlatformNodeDelegate.
153 /// Ownership passes to the caller. This method will be called
154 /// whenever a new AXNode is created in AXTree. Each platform
155 /// needs to implement this method in order to inject its
156 /// subclass into the accessibility bridge.
157 virtual std::shared_ptr<FlutterPlatformNodeDelegate>
158 CreateFlutterPlatformNodeDelegate() = 0;
159
160 private:
161 // See FlutterSemanticsNode in embedder.h
162 typedef struct {
163 int32_t id;
164 FlutterSemanticsFlags* flags;
165 FlutterSemanticsAction actions;
166 int32_t text_selection_base;
167 int32_t text_selection_extent;
168 int32_t scroll_child_count;
169 int32_t scroll_index;
170 double scroll_position;
171 double scroll_extent_max;
172 double scroll_extent_min;
173 std::string label;
174 std::string hint;
175 std::string value;
176 std::string increased_value;
177 std::string decreased_value;
178 std::string tooltip;
179 FlutterTextDirection text_direction;
180 FlutterRect rect;
181 FlutterTransformation transform;
182 std::vector<int32_t> children_in_traversal_order;
183 std::vector<int32_t> custom_accessibility_actions;
184 int32_t heading_level;
185 } SemanticsNode;
186
187 // See FlutterSemanticsCustomAction in embedder.h
188 typedef struct {
189 int32_t id;
190 FlutterSemanticsAction override_action;
191 std::string label;
192 std::string hint;
193 } SemanticsCustomAction;
194
195 std::unordered_map<AccessibilityNodeId,
196 std::shared_ptr<FlutterPlatformNodeDelegate>>
197 id_wrapper_map_;
198 std::unique_ptr<ui::AXTree> tree_;
199 ui::AXEventGenerator event_generator_;
200 std::unordered_map<int32_t, SemanticsNode> pending_semantics_node_updates_;
201 std::unordered_map<int32_t, SemanticsCustomAction>
202 pending_semantics_custom_action_updates_;
203 AccessibilityNodeId last_focused_id_ = ui::AXNode::kInvalidAXID;
204
205 void InitAXTree(const ui::AXTreeUpdate& initial_state);
206
207 // Create an update that removes any nodes that will be reparented by
208 // pending_semantics_updates_. Returns std::nullopt if none are reparented.
209 std::optional<ui::AXTreeUpdate> CreateRemoveReparentedNodesUpdate();
210
211 void GetSubTreeList(const SemanticsNode& target,
212 std::vector<SemanticsNode>& result);
213 void ConvertFlutterUpdate(const SemanticsNode& node,
214 ui::AXTreeUpdate& tree_update);
215 void SetRoleFromFlutterUpdate(ui::AXNodeData& node_data,
216 const SemanticsNode& node);
217 void SetStateFromFlutterUpdate(ui::AXNodeData& node_data,
218 const SemanticsNode& node);
219 void SetActionsFromFlutterUpdate(ui::AXNodeData& node_data,
220 const SemanticsNode& node);
221 void SetBooleanAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
222 const SemanticsNode& node);
223 void SetIntAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
224 const SemanticsNode& node);
225 void SetIntListAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
226 const SemanticsNode& node);
227 void SetStringListAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
228 const SemanticsNode& node);
229 void SetNameFromFlutterUpdate(ui::AXNodeData& node_data,
230 const SemanticsNode& node);
231 void SetValueFromFlutterUpdate(ui::AXNodeData& node_data,
232 const SemanticsNode& node);
233 void SetTooltipFromFlutterUpdate(ui::AXNodeData& node_data,
234 const SemanticsNode& node);
235 void SetTreeData(const SemanticsNode& node, ui::AXTreeUpdate& tree_update);
236 SemanticsNode FromFlutterSemanticsNode(
237 const FlutterSemanticsNode2& flutter_node);
238 SemanticsCustomAction FromFlutterSemanticsCustomAction(
239 const FlutterSemanticsCustomAction2& flutter_custom_action);
240
241 // |AXTreeObserver|
242 void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
243
244 // |AXTreeObserver|
245 void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
246
247 // |AXTreeObserver|
248 void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
249
250 // |AXTreeObserver|
251 void OnNodeDeleted(ui::AXTree* tree, AccessibilityNodeId node_id) override;
252
253 // |AXTreeObserver|
254 void OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) override;
255
256 // |AXTreeObserver|
257 void OnRoleChanged(ui::AXTree* tree,
258 ui::AXNode* node,
259 ax::mojom::Role old_role,
260 ax::mojom::Role new_role) override;
261
262 // |AXTreeObserver|
263 void OnNodeDataChanged(ui::AXTree* tree,
264 const ui::AXNodeData& old_node_data,
265 const ui::AXNodeData& new_node_data) override;
266
267 // |AXTreeObserver|
268 void OnAtomicUpdateFinished(
269 ui::AXTree* tree,
270 bool root_changed,
271 const std::vector<ui::AXTreeObserver::Change>& changes) override;
272
273 // |FlutterPlatformNodeDelegate::OwnerBridge|
274 void SetLastFocusedId(AccessibilityNodeId node_id) override;
275
276 // |FlutterPlatformNodeDelegate::OwnerBridge|
277 AccessibilityNodeId GetLastFocusedId() override;
278
279 // |FlutterPlatformNodeDelegate::OwnerBridge|
280 gfx::NativeViewAccessible GetNativeAccessibleFromId(
281 AccessibilityNodeId id) override;
282
283 // |FlutterPlatformNodeDelegate::OwnerBridge|
284 gfx::RectF RelativeToGlobalBounds(const ui::AXNode* node,
285 bool& offscreen,
286 bool clip_bounds) override;
287
288 BASE_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridge);
289 };
290
291 } // namespace flutter
292
293 #endif // FLUTTER_SHELL_PLATFORM_COMMON_ACCESSIBILITY_BRIDGE_H_
flutter::AccessibilityBridge::GetTree
ui::AXTree * GetTree() const override
Definition: accessibility_bridge.cc:707
flutter::AccessibilityBridge::RootDelegate
ui::AXPlatformNodeDelegate * RootDelegate() const override
Definition: accessibility_bridge.cc:726
flutter::AccessibilityBridge::GetFlutterPlatformNodeDelegateFromID
std::weak_ptr< FlutterPlatformNodeDelegate > GetFlutterPlatformNodeDelegateFromID(AccessibilityNodeId id) const
Get the flutter platform node delegate with the given id from this accessibility bridge....
Definition: accessibility_bridge.cc:131
flutter::AccessibilityBridge::CreateFlutterPlatformNodeDelegate
virtual std::shared_ptr< FlutterPlatformNodeDelegate > CreateFlutterPlatformNodeDelegate()=0
Creates a platform specific FlutterPlatformNodeDelegate. Ownership passes to the caller....
flutter::AccessibilityBridge::AddFlutterSemanticsNodeUpdate
void AddFlutterSemanticsNodeUpdate(const FlutterSemanticsNode2 &node)
Adds a semantics node update to the pending semantics update. Calling this method alone will NOT upda...
Definition: accessibility_bridge.cc:39
flutter::AccessibilityBridge::AddFlutterSemanticsCustomActionUpdate
void AddFlutterSemanticsCustomActionUpdate(const FlutterSemanticsCustomAction2 &action)
Adds a custom semantics action update to the pending semantics update. Calling this method alone will...
Definition: accessibility_bridge.cc:44
flutter::AccessibilityBridge::GetPlatformNodeFromTree
ui::AXPlatformNode * GetPlatformNodeFromTree(const ui::AXNode::AXID node_id) const override
Definition: accessibility_bridge.cc:711
flutter::AccessibilityBridge::GetAXTreeData
const ui::AXTreeData & GetAXTreeData() const
Get the ax tree data from this accessibility bridge. The tree data contains information such as the i...
Definition: accessibility_bridge.cc:141
flutter::AccessibilityBridge::GetParentTreeID
ui::AXTreeID GetParentTreeID() const override
Definition: accessibility_bridge.cc:695
flutter::AccessibilityBridge::~AccessibilityBridge
virtual ~AccessibilityBridge()
flutter::AccessibilityBridge::GetRootAsAXNode
ui::AXNode * GetRootAsAXNode() const override
Definition: accessibility_bridge.cc:699
flutter::AccessibilityBridge::GetParentNodeFromParentTreeAsAXNode
ui::AXNode * GetParentNodeFromParentTreeAsAXNode() const override
Definition: accessibility_bridge.cc:703
flutter::AccessibilityBridge::AccessibilityBridge
AccessibilityBridge()
Creates a new instance of a accessibility bridge.
Definition: accessibility_bridge.cc:23
flutter::AccessibilityBridge::OnAccessibilityEvent
virtual void OnAccessibilityEvent(ui::AXEventGenerator::TargetedEvent targeted_event)=0
Handle accessibility events generated due to accessibility tree changes. These events are needed to b...
flutter::AccessibilityBridge::GetTreeID
ui::AXTreeID GetTreeID() const override
Definition: accessibility_bridge.cc:691
flutter::AccessibilityBridge::GetPendingEvents
const std::vector< ui::AXEventGenerator::TargetedEvent > GetPendingEvents() const
Gets all pending accessibility events generated during semantics updates. This is useful when decidin...
Definition: accessibility_bridge.cc:146
flutter::AccessibilityBridge::CommitUpdates
void CommitUpdates()
Flushes the pending updates and applies them to this accessibility bridge. Calling this with no pendi...
Definition: accessibility_bridge.cc:50
flutter::AccessibilityBridge::GetNodeFromTree
ui::AXNode * GetNodeFromTree(const ui::AXTreeID tree_id, const ui::AXNode::AXID node_id) const override
Definition: accessibility_bridge.cc:680
flutter_platform_node_delegate.h
flutter
Definition: accessibility_bridge.h:26
flutter::AccessibilityNodeId
ui::AXNode::AXID AccessibilityNodeId
Definition: flutter_platform_node_delegate.h:15