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