Flutter Engine
The Flutter Engine
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
20
21namespace 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.
41 : public std::enable_shared_from_this<AccessibilityBridge>,
44 private ui::AXTreeObserver {
45 public:
46 //-----------------------------------------------------------------------------
47 /// @brief Creates a new instance of a accessibility bridge.
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.
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.
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>
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|
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|
124
125 // |AXTreeManager|
126 ui::AXTree* GetTree() const override;
127
128 // |AXPlatformTreeManager|
130 const ui::AXNode::AXID node_id) const override;
131
132 // |AXPlatformTreeManager|
134 const ui::AXNode& node) const override;
135
136 // |AXPlatformTreeManager|
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.
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>
159
160 private:
161 // See FlutterSemanticsNode in embedder.h
162 typedef struct {
163 int32_t id;
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 double elevation;
174 double thickness;
175 std::string label;
176 std::string hint;
177 std::string value;
178 std::string increased_value;
179 std::string decreased_value;
180 std::string tooltip;
181 FlutterTextDirection text_direction;
184 std::vector<int32_t> children_in_traversal_order;
185 std::vector<int32_t> custom_accessibility_actions;
187
188 // See FlutterSemanticsCustomAction in embedder.h
189 typedef struct {
190 int32_t id;
191 FlutterSemanticsAction override_action;
192 std::string label;
193 std::string hint;
194 } SemanticsCustomAction;
195
196 std::unordered_map<AccessibilityNodeId,
197 std::shared_ptr<FlutterPlatformNodeDelegate>>
198 id_wrapper_map_;
199 std::unique_ptr<ui::AXTree> tree_;
200 ui::AXEventGenerator event_generator_;
201 std::unordered_map<int32_t, SemanticsNode> pending_semantics_node_updates_;
202 std::unordered_map<int32_t, SemanticsCustomAction>
203 pending_semantics_custom_action_updates_;
205
206 void InitAXTree(const ui::AXTreeUpdate& initial_state);
207
208 // Create an update that removes any nodes that will be reparented by
209 // pending_semantics_updates_. Returns std::nullopt if none are reparented.
210 std::optional<ui::AXTreeUpdate> CreateRemoveReparentedNodesUpdate();
211
212 void GetSubTreeList(const SemanticsNode& target,
213 std::vector<SemanticsNode>& result);
214 void ConvertFlutterUpdate(const SemanticsNode& node,
215 ui::AXTreeUpdate& tree_update);
216 void SetRoleFromFlutterUpdate(ui::AXNodeData& node_data,
217 const SemanticsNode& node);
218 void SetStateFromFlutterUpdate(ui::AXNodeData& node_data,
219 const SemanticsNode& node);
220 void SetActionsFromFlutterUpdate(ui::AXNodeData& node_data,
221 const SemanticsNode& node);
222 void SetBooleanAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
223 const SemanticsNode& node);
224 void SetIntAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
225 const SemanticsNode& node);
226 void SetIntListAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
227 const SemanticsNode& node);
228 void SetStringListAttributesFromFlutterUpdate(ui::AXNodeData& node_data,
229 const SemanticsNode& node);
230 void SetNameFromFlutterUpdate(ui::AXNodeData& node_data,
231 const SemanticsNode& node);
232 void SetValueFromFlutterUpdate(ui::AXNodeData& node_data,
233 const SemanticsNode& node);
234 void SetTooltipFromFlutterUpdate(ui::AXNodeData& node_data,
235 const SemanticsNode& node);
236 void SetTreeData(const SemanticsNode& node, ui::AXTreeUpdate& tree_update);
237 SemanticsNode FromFlutterSemanticsNode(
238 const FlutterSemanticsNode2& flutter_node);
239 SemanticsCustomAction FromFlutterSemanticsCustomAction(
240 const FlutterSemanticsCustomAction2& flutter_custom_action);
241
242 // |AXTreeObserver|
243 void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
244
245 // |AXTreeObserver|
246 void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
247
248 // |AXTreeObserver|
249 void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
250
251 // |AXTreeObserver|
252 void OnNodeDeleted(ui::AXTree* tree, AccessibilityNodeId node_id) override;
253
254 // |AXTreeObserver|
255 void OnNodeReparented(ui::AXTree* tree, ui::AXNode* node) override;
256
257 // |AXTreeObserver|
258 void OnRoleChanged(ui::AXTree* tree,
259 ui::AXNode* node,
260 ax::mojom::Role old_role,
261 ax::mojom::Role new_role) override;
262
263 // |AXTreeObserver|
264 void OnAtomicUpdateFinished(
265 ui::AXTree* tree,
266 bool root_changed,
267 const std::vector<ui::AXTreeObserver::Change>& changes) override;
268
269 // |FlutterPlatformNodeDelegate::OwnerBridge|
270 void SetLastFocusedId(AccessibilityNodeId node_id) override;
271
272 // |FlutterPlatformNodeDelegate::OwnerBridge|
273 AccessibilityNodeId GetLastFocusedId() override;
274
275 // |FlutterPlatformNodeDelegate::OwnerBridge|
276 gfx::NativeViewAccessible GetNativeAccessibleFromId(
277 AccessibilityNodeId id) override;
278
279 // |FlutterPlatformNodeDelegate::OwnerBridge|
280 gfx::RectF RelativeToGlobalBounds(const ui::AXNode* node,
281 bool& offscreen,
282 bool clip_bounds) override;
283
284 BASE_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridge);
285};
286
287} // namespace flutter
288
289#endif // FLUTTER_SHELL_PLATFORM_COMMON_ACCESSIBILITY_BRIDGE_H_
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
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
int32_t AXID
Definition: ax_node.h:36
static constexpr AXID kInvalidAXID
Definition: ax_node.h:41
FlutterSemanticsAction
Definition: embedder.h:113
FlutterTextDirection
Definition: embedder.h:248
FlutterSemanticsFlag
Definition: embedder.h:172
FlutterSemanticsFlag flags
uint8_t value
GAsyncResult * result
uint32_t * target
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
ui::AXNode::AXID AccessibilityNodeId
UnimplementedNativeViewAccessible * NativeViewAccessible
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
A structure to represent a rectangle.
Definition: embedder.h:437
const uintptr_t id