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"
15
16constexpr int32_t kRootNodeId = 0;
17// This can be arbitrary number as long as it is bigger than 0.
18constexpr 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 */
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_
constexpr int32_t kRootNodeId
constexpr float kScrollExtentMaxForInf
SemanticsObject * parent
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