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