• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_ACCESSIBILITY_BRIDGE_H_
6 #define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_ACCESSIBILITY_BRIDGE_H_
7 
8 #include <memory>
9 #include <unordered_map>
10 #include <unordered_set>
11 #include <vector>
12 
13 #import <UIKit/UIKit.h>
14 
15 #include "flutter/fml/macros.h"
16 #include "flutter/fml/memory/weak_ptr.h"
17 #include "flutter/fml/platform/darwin/scoped_nsobject.h"
18 #include "flutter/lib/ui/semantics/custom_accessibility_action.h"
19 #include "flutter/lib/ui/semantics/semantics_node.h"
20 #include "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
21 #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
22 #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
23 #include "third_party/skia/include/core/SkMatrix44.h"
24 #include "third_party/skia/include/core/SkRect.h"
25 
26 namespace flutter {
27 class AccessibilityBridge;
28 }  // namespace flutter
29 
30 @class FlutterPlatformViewSemanticsContainer;
31 
32 /**
33  * A node in the iOS semantics tree.
34  */
35 @interface SemanticsObject : NSObject
36 
37 /**
38  * The globally unique identifier for this node.
39  */
40 @property(nonatomic, readonly) int32_t uid;
41 
42 /**
43  * The parent of this node in the node tree. Will be nil for the root node and
44  * during transient state changes.
45  */
46 @property(nonatomic, assign) SemanticsObject* parent;
47 
48 /**
49  * The accessibility bridge that this semantics object is attached to. This
50  * object may use the bridge to access contextual application information. A weak pointer is used
51  * because the platform view owns the accessibility bridge.
52  */
53 @property(nonatomic, readonly) fml::WeakPtr<flutter::AccessibilityBridge> bridge;
54 
55 /**
56  * The semantics node used to produce this semantics object.
57  */
58 @property(nonatomic, readonly) flutter::SemanticsNode node;
59 
60 /**
61  * Updates this semantics object using data from the `node` argument.
62  */
63 - (void)setSemanticsNode:(const flutter::SemanticsNode*)node NS_REQUIRES_SUPER;
64 
65 /**
66  * Whether this semantics object has child semantics objects.
67  */
68 @property(nonatomic, readonly) BOOL hasChildren;
69 
70 /**
71  * Direct children of this semantics object. Each child's `parent` property must
72  * be equal to this object.
73  */
74 @property(nonatomic, strong) NSMutableArray<SemanticsObject*>* children;
75 
76 /**
77  * Used if this SemanticsObject is for a platform view.
78  */
79 @property(strong, nonatomic) FlutterPlatformViewSemanticsContainer* platformViewSemanticsContainer;
80 
81 - (BOOL)nodeWillCauseLayoutChange:(const flutter::SemanticsNode*)node;
82 
83 #pragma mark - Designated initializers
84 
85 - (instancetype)init __attribute__((unavailable("Use initWithBridge instead")));
86 - (instancetype)initWithBridge:(fml::WeakPtr<flutter::AccessibilityBridge>)bridge
87                            uid:(int32_t)uid NS_DESIGNATED_INITIALIZER;
88 
89 @end
90 
91 /**
92  * An implementation of UIAccessibilityCustomAction which also contains the
93  * Flutter uid.
94  */
95 @interface FlutterCustomAccessibilityAction : UIAccessibilityCustomAction
96 
97 /**
98  * The uid of the action defined by the flutter application.
99  */
100 @property(nonatomic) int32_t uid;
101 
102 @end
103 
104 /**
105  * The default implementation of `SemanticsObject` for most accessibility elements
106  * in the iOS accessibility tree.
107  *
108  * Use this implementation for nodes that do not need to be expressed via UIKit-specific
109  * protocols (it only implements NSObject).
110  *
111  * See also:
112  *  * TextInputSemanticsObject, which implements `UITextInput` protocol to expose
113  *    editable text widgets to a11y.
114  */
115 @interface FlutterSemanticsObject : SemanticsObject
116 @end
117 
118 /**
119  * Designated to act as an accessibility container of a platform view.
120  *
121  * This object does not take any accessibility actions on its own, nor has any accessibility
122  * label/value/trait/hint... on its own. The accessibility data will be handled by the platform
123  * view.
124  *
125  * See also:
126  * * `SemanticsObject` for the other type of semantics objects.
127  * * `FlutterSemanticsObject` for default implementation of `SemanticsObject`.
128  */
129 @interface FlutterPlatformViewSemanticsContainer : NSObject
130 
131 /**
132  * The position inside an accessibility container.
133  */
134 @property(nonatomic) NSInteger index;
135 
136 - (instancetype)init __attribute__((unavailable("Use initWithAccessibilityContainer: instead")));
137 
138 - (instancetype)initWithSemanticsObject:(SemanticsObject*)object;
139 
140 @end
141 
142 namespace flutter {
143 class PlatformViewIOS;
144 
145 class AccessibilityBridge final {
146  public:
147   AccessibilityBridge(UIView* view,
148                       PlatformViewIOS* platform_view,
149                       FlutterPlatformViewsController* platform_views_controller);
150   ~AccessibilityBridge();
151 
152   void UpdateSemantics(flutter::SemanticsNodeUpdates nodes,
153                        flutter::CustomAccessibilityActionUpdates actions);
154   void DispatchSemanticsAction(int32_t id, flutter::SemanticsAction action);
155   void DispatchSemanticsAction(int32_t id,
156                                flutter::SemanticsAction action,
157                                std::vector<uint8_t> args);
158 
159   UIView<UITextInput>* textInputView();
160 
view()161   UIView* view() const { return view_; }
162 
163   fml::WeakPtr<AccessibilityBridge> GetWeakPtr();
164 
GetPlatformViewsController()165   FlutterPlatformViewsController* GetPlatformViewsController() const {
166     return platform_views_controller_;
167   };
168 
169   void clearState();
170 
171  private:
172   SemanticsObject* GetOrCreateObject(int32_t id, flutter::SemanticsNodeUpdates& updates);
173   void VisitObjectsRecursivelyAndRemove(SemanticsObject* object,
174                                         NSMutableArray<NSNumber*>* doomed_uids);
175   void HandleEvent(NSDictionary<NSString*, id>* annotatedEvent);
176 
177   UIView* view_;
178   PlatformViewIOS* platform_view_;
179   FlutterPlatformViewsController* platform_views_controller_;
180   fml::scoped_nsobject<NSMutableDictionary<NSNumber*, SemanticsObject*>> objects_;
181   fml::scoped_nsprotocol<FlutterBasicMessageChannel*> accessibility_channel_;
182   fml::WeakPtrFactory<AccessibilityBridge> weak_factory_;
183   int32_t previous_route_id_;
184   std::unordered_map<int32_t, flutter::CustomAccessibilityAction> actions_;
185   std::vector<int32_t> previous_routes_;
186 
187   FML_DISALLOW_COPY_AND_ASSIGN(AccessibilityBridge);
188 };
189 
190 }  // namespace flutter
191 
192 #endif  // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_ACCESSIBILITY_BRIDGE_H_
193