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