Flutter Engine
SemanticsObject.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 SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_SEMANTICS_OBJECT_H_
6 #define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_SEMANTICS_OBJECT_H_
7 
8 #import <UIKit/UIKit.h>
9 
10 #include "flutter/fml/macros.h"
11 #include "flutter/fml/memory/weak_ptr.h"
12 #include "flutter/lib/ui/semantics/semantics_node.h"
13 #import "flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge_ios.h"
14 
15 constexpr int32_t kRootNodeId = 0;
16 // This can be arbitrary number as long as it is bigger than 0.
17 constexpr float kScrollExtentMaxForInf = 1000;
18 
21 
22 /**
23  * A node in the iOS semantics tree.
24  */
25 @interface SemanticsObject : UIAccessibilityElement
26 
27 /**
28  * The globally unique identifier for this node.
29  */
30 @property(nonatomic, readonly) int32_t uid;
31 
32 /**
33  * The parent of this node in the node tree. Will be nil for the root node and
34  * during transient state changes.
35  */
36 @property(nonatomic, assign) SemanticsObject* parent;
37 
38 /**
39  * The accessibility bridge that this semantics object is attached to. This
40  * object may use the bridge to access contextual application information. A weak
41  * pointer is used because the platform view owns the accessibility bridge.
42  * If you are referencing this property from an iOS callback, be sure to
43  * use `isAccessibilityBridgeActive` to protect against the case where this
44  * node may be orphaned.
45  */
47 
48 /**
49  * The semantics node used to produce this semantics object.
50  */
51 @property(nonatomic, readonly) flutter::SemanticsNode node;
52 
53 /**
54  * Whether this semantics object has child semantics objects.
55  */
56 @property(nonatomic, readonly) BOOL hasChildren;
57 
58 /**
59  * Direct children of this semantics object. Each child's `parent` property must
60  * be equal to this object.
61  */
62 @property(nonatomic, strong) NSArray<SemanticsObject*>* children;
63 
64 /**
65  * Used if this SemanticsObject is for a platform view.
66  */
68 
69 /**
70  * The UIAccessibility that represents this object.
71  *
72  * By default, this return self. Subclasses can override to return different
73  * objects to represent them. For example, FlutterScrollableSemanticsObject[s]
74  * maintain UIScrollView[s] to represent their UIAccessibility[s].
75  */
76 @property(nonatomic, readonly) id nativeAccessibility;
77 
78 /**
79  * Due to the fact that VoiceOver may hold onto SemanticObjects even after it shuts down,
80  * there can be situations where the AccessibilityBridge is shutdown, but the SemanticObject
81  * will still be alive. If VoiceOver is turned on again, it may try to access this orphaned
82  * SemanticObject. Methods that are called from the accessiblity framework should use
83  * this to guard against this case by just returning early if its bridge has been shutdown.
84  *
85  * See https://github.com/flutter/flutter/issues/43795 for more information.
86  */
88 
89 /**
90  * Updates this semantics object using data from the `node` argument.
91  */
92 - (void)setSemanticsNode:(const flutter::SemanticsNode*)node NS_REQUIRES_SUPER;
93 
94 - (void)replaceChildAtIndex:(NSInteger)index withChild:(SemanticsObject*)child;
95 
96 - (BOOL)nodeWillCauseLayoutChange:(const flutter::SemanticsNode*)node;
97 
98 - (BOOL)nodeWillCauseScroll:(const flutter::SemanticsNode*)node;
99 
100 - (BOOL)nodeShouldTriggerAnnouncement:(const flutter::SemanticsNode*)node;
101 
102 - (void)collectRoutes:(NSMutableArray<SemanticsObject*>*)edges;
103 
104 - (NSString*)routeName;
105 
106 - (BOOL)onCustomAccessibilityAction:(FlutterCustomAccessibilityAction*)action;
107 
108 /**
109  * Called after accessibility bridge finishes a semantics update.
110  *
111  * Subclasses can override this method if they contain states that can only be
112  * updated once every node in the accessibility tree has finished updating.
113  */
115 
116 #pragma mark - Designated initializers
117 
118 - (instancetype)init __attribute__((unavailable("Use initWithBridge instead")));
119 - (instancetype)initWithBridge:(fml::WeakPtr<flutter::AccessibilityBridgeIos>)bridge
120  uid:(int32_t)uid NS_DESIGNATED_INITIALIZER;
121 
122 @end
123 
124 /**
125  * An implementation of UIAccessibilityCustomAction which also contains the
126  * Flutter uid.
127  */
128 @interface FlutterCustomAccessibilityAction : UIAccessibilityCustomAction
129 
130 /**
131  * The uid of the action defined by the flutter application.
132  */
133 @property(nonatomic) int32_t uid;
134 
135 @end
136 
137 /**
138  * The default implementation of `SemanticsObject` for most accessibility elements
139  * in the iOS accessibility tree.
140  *
141  * Use this implementation for nodes that do not need to be expressed via UIKit-specific
142  * protocols (it only implements NSObject).
143  *
144  * See also:
145  * * TextInputSemanticsObject, which implements `UITextInput` protocol to expose
146  * editable text widgets to a11y.
147  */
149 @end
150 
151 /**
152  * Designated to act as an accessibility container of a platform view.
153  *
154  * This object does not take any accessibility actions on its own, nor has any accessibility
155  * label/value/trait/hint... on its own. The accessibility data will be handled by the platform
156  * view.
157  *
158  * See also:
159  * * `SemanticsObject` for the other type of semantics objects.
160  * * `FlutterSemanticsObject` for default implementation of `SemanticsObject`.
161  */
162 @interface FlutterPlatformViewSemanticsContainer : UIAccessibilityElement
163 
164 /**
165  * The position inside an accessibility container.
166  */
167 @property(nonatomic) NSInteger index;
168 
169 - (instancetype)init __attribute__((unavailable("Use initWithAccessibilityContainer: instead")));
170 
171 - (instancetype)initWithSemanticsObject:(SemanticsObject*)object;
172 
173 @end
174 
175 /// The semantics object for switch buttons. This class creates an UISwitch to interact with the
176 /// iOS.
178 
179 @end
180 
181 /// The semantics object for scrollable. This class creates an UIScrollView to interact with the
182 /// iOS.
184 
185 @end
186 
187 /**
188  * Represents a semantics object that has children and hence has to be presented to the OS as a
189  * UIAccessibilityContainer.
190  *
191  * The SemanticsObject class cannot implement the UIAccessibilityContainer protocol because an
192  * object that returns YES for isAccessibilityElement cannot also implement
193  * UIAccessibilityContainer.
194  *
195  * With the help of SemanticsObjectContainer, the hierarchy of semantic objects received from
196  * the framework, such as:
197  *
198  * SemanticsObject1
199  * SemanticsObject2
200  * SemanticsObject3
201  * SemanticsObject4
202  *
203  * is translated into the following hierarchy, which is understood by iOS:
204  *
205  * SemanticsObjectContainer1
206  * SemanticsObject1
207  * SemanticsObjectContainer2
208  * SemanticsObject2
209  * SemanticsObject3
210  * SemanticsObject4
211  *
212  * From Flutter's view of the world (the first tree seen above), we construct iOS's view of the
213  * world (second tree) as follows: We replace each SemanticsObjects that has children with a
214  * SemanticsObjectContainer, which has the original SemanticsObject and its children as children.
215  *
216  * SemanticsObjects have semantic information attached to them which is interpreted by
217  * VoiceOver (they return YES for isAccessibilityElement). The SemanticsObjectContainers are just
218  * there for structure and they don't provide any semantic information to VoiceOver (they return
219  * NO for isAccessibilityElement).
220  */
221 @interface SemanticsObjectContainer : UIAccessibilityElement
222 - (instancetype)init NS_UNAVAILABLE;
223 + (instancetype)new NS_UNAVAILABLE;
224 - (instancetype)initWithAccessibilityContainer:(id)container NS_UNAVAILABLE;
225 - (instancetype)initWithSemanticsObject:(SemanticsObject*)semanticsObject
226  bridge:(fml::WeakPtr<flutter::AccessibilityBridgeIos>)bridge
227  NS_DESIGNATED_INITIALIZER;
228 
229 @property(nonatomic, weak) SemanticsObject* semanticsObject;
230 
231 @end
232 
233 #endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_SEMANTICS_OBJECT_H_
constexpr float kScrollExtentMaxForInf
instancetype NS_UNAVAILABLE()
FlutterPlatformViewSemanticsContainer * platformViewSemanticsContainer
auto WeakPtr(std::shared_ptr< T > pointer)
(unavailable("Use initWithBridge instead" __attribute__()
NSArray< SemanticsObject * > * children
Definition: ascii_trie.cc:9
fml::WeakPtr< flutter::AccessibilityBridgeIos > bridge
SemanticsObject * parent
void accessibilityBridgeDidFinishUpdate()
int BOOL
Definition: windows_types.h:37
constexpr int32_t kRootNodeId
flutter::SemanticsNode node
NSString * routeName()
BOOL isAccessibilityBridgeAlive()