Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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"
15
17
18constexpr int32_t kRootNodeId = 0;
19// This can be arbitrary number as long as it is bigger than 0.
20constexpr float kScrollExtentMaxForInf = 1000;
21
25
26/**
27 * A node in the iOS semantics tree. This object is a wrapper over a native accessibiliy
28 * object, which is stored in the property `nativeAccessibility`. In the most case, the
29 * `nativeAccessibility` directly returns this object. Some subclasses such as the
30 * `FlutterScrollableSemanticsObject` creates a native `UIScrollView` as its `nativeAccessibility`
31 * so that it can interact with iOS.
32 */
33@interface SemanticsObject : UIAccessibilityElement
34
35/**
36 * The globally unique identifier for this node.
37 */
38@property(nonatomic, readonly) int32_t uid;
39
40/**
41 * The parent of this node in the node tree. Will be nil for the root node and
42 * during transient state changes.
43 */
44@property(nonatomic, weak, readonly, nullable) SemanticsObject* parent;
45
46/**
47 * The semantics node used to produce this semantics object.
48 */
49@property(nonatomic, readonly) flutter::SemanticsNode node;
50
51/**
52 * Whether this semantics object has child semantics objects.
53 */
54@property(nonatomic, readonly) BOOL hasChildren;
55
56/**
57 * Direct children of this semantics object. Each child's `parent` property must
58 * be equal to this object.
59 */
60@property(nonatomic, copy) NSArray<SemanticsObject*>* children;
61
62/**
63 * Direct children of this semantics object in hit test order. Each child's `parent` property
64 * must be equal to this object.
65 */
66@property(nonatomic, copy, nullable) NSArray<SemanticsObject*>* childrenInHitTestOrder;
67
68/**
69 * The UIAccessibility that represents this object.
70 *
71 * By default, this return self. Subclasses can override to return different
72 * objects to represent them. For example, FlutterScrollableSemanticsObject[s]
73 * maintain UIScrollView[s] to represent their UIAccessibility[s].
74 */
75@property(nonatomic, readonly) id nativeAccessibility;
76
77/**
78 * Due to the fact that VoiceOver may hold onto SemanticObjects even after it shuts down,
79 * there can be situations where the AccessibilityBridge is shutdown, but the SemanticObject
80 * will still be alive. If VoiceOver is turned on again, it may try to access this orphaned
81 * SemanticObject. Methods that are called from the accessibility framework should use
82 * `bridge` (or `bridgeView`) to guard against this case by just returning early if its bridge
83 * has been shutdown.
84 *
85 * See https://github.com/flutter/flutter/issues/43795 for more information.
86 *
87 * Returns a raw pointer to the AccessibilityBridge if it is still alive, or nullptr if destroyed.
88 */
89- (nullable flutter::AccessibilityBridgeIos*)bridge;
90
91/**
92 * Returns the underlying UIView from the bridge if alive, or nil if destroyed.
93 */
94- (nullable UIView*)bridgeView;
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:(nullable const flutter::SemanticsNode*)node;
108
109- (void)collectRoutes:(NSMutableArray<SemanticsObject*>*)edges;
110
111- (nullable 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 NS_DESIGNATED_INITIALIZER;
232
233@property(nonatomic, weak, nullable) SemanticsObject* semanticsObject;
234
235@end
236
238
239#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_SEMANTICSOBJECT_H_
#define NS_ASSUME_NONNULL_BEGIN
#define NS_ASSUME_NONNULL_END
NS_ASSUME_NONNULL_BEGIN constexpr int32_t kRootNodeId
constexpr float kScrollExtentMaxForInf
NSArray< SemanticsObject * > * children
SemanticsObject * parent
nullable UIView * bridgeView()
NSArray< SemanticsObject * > * childrenInHitTestOrder
(unavailable("Use initWithBridge instead" __attribute__()
void accessibilityBridgeDidFinishUpdate()
nullable NSString * routeName()
flutter::SemanticsNode node
instancetype init NS_UNAVAILABLE
int BOOL