5#import "flutter/shell/platform/darwin/macos/framework/Source/AccessibilityBridgeMac.h"
7#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
8#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformNodeDelegateMac.h"
9#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterTextInputSemanticsObject.h"
10#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
11#include "flutter/shell/platform/embedder/embedder.h"
25 : flutter_engine_(flutter_engine), view_controller_(view_controller) {}
29 if (!view_controller_.viewLoaded || !view_controller_.
view.window) {
34 std::vector<AccessibilityBridgeMac::NSAccessibilityEvent> events =
36 for (
const AccessibilityBridgeMac::NSAccessibilityEvent&
event : events) {
37 if (
event.user_info != nil) {
38 DispatchMacOSNotificationWithUserInfo(
event.target,
event.name,
event.user_info);
45std::vector<AccessibilityBridgeMac::NSAccessibilityEvent>
49 NSCAssert(flutter_engine_,
@"Flutter engine should not be deallocated");
51 NSCAssert(platform_node_delegate,
@"Event target must exist in accessibility bridge.");
52 auto mac_platform_node_delegate =
53 std::static_pointer_cast<FlutterPlatformNodeDelegateMac>(platform_node_delegate);
56 std::vector<AccessibilityBridgeMac::NSAccessibilityEvent> events;
58 case ui::AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED:
61 .name = NSAccessibilitySelectedRowsChangedNotification,
62 .target = native_node,
70 .name = NSAccessibilitySelectedChildrenChangedNotification,
71 .target = native_node,
79 case ui::AXEventGenerator::Event::LOAD_COMPLETE:
82 .target = native_node,
86 case ui::AXEventGenerator::Event::INVALID_STATUS_CHANGED:
89 .target = native_node,
93 case ui::AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
96 .name = NSAccessibilitySelectedRowsChangedNotification,
97 .target = native_node,
104 NSAccessibilityElement* native_accessibility_node = (NSAccessibilityElement*)native_node;
105 if (native_accessibility_node.accessibilityFocusedUIElement &&
107 !HasPendingEvent(ui::AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED) &&
108 !HasPendingEvent(ui::AXEventGenerator::Event::FOCUS_CHANGED)) {
114 .name = NSAccessibilitySelectedChildrenChangedNotification,
115 .target = native_node,
120 case ui::AXEventGenerator::Event::DOCUMENT_SELECTION_CHANGED: {
121 id focused = mac_platform_node_delegate->GetFocus();
127 if (native_text_field == mac_platform_node_delegate->GetFocus()) {
128 [native_text_field startEditing];
134 .name = NSAccessibilitySelectedTextChangedNotification,
135 .target = native_node,
150 .name = NSAccessibilitySelectedTextChangedNotification,
151 .target = focus_node->GetNativeViewAccessible(),
156 case ui::AXEventGenerator::Event::CHECKED_STATE_CHANGED:
158 .name = NSAccessibilityValueChangedNotification,
159 .target = native_node,
163 case ui::AXEventGenerator::Event::VALUE_CHANGED: {
170 id focused = mac_platform_node_delegate->GetFocus();
171 if (!focused || native_text_field == focused) {
172 [native_text_field startEditing];
177 .name = NSAccessibilityValueChangedNotification,
178 .target = native_node,
183 .name = NSAccessibilityValueChangedNotification,
190 case ui::AXEventGenerator::Event::LIVE_REGION_CREATED:
193 .target = native_node,
197 case ui::AXEventGenerator::Event::ALERT: {
200 .target = native_node,
205 auto live_region_events =
206 MacOSEventsFromAXEvent(ui::AXEventGenerator::Event::LIVE_REGION_CHANGED, ax_node);
207 events.insert(events.end(), live_region_events.begin(), live_region_events.end());
210 case ui::AXEventGenerator::Event::LIVE_REGION_CHANGED: {
214 .target = native_node,
219 case ui::AXEventGenerator::Event::ROW_COUNT_CHANGED:
221 .name = NSAccessibilityRowCountChangedNotification,
222 .target = native_node,
226 case ui::AXEventGenerator::Event::EXPANDED: {
227 NSAccessibilityNotificationName mac_notification;
230 mac_notification = NSAccessibilityRowExpandedNotification;
235 .name = mac_notification,
236 .target = native_node,
241 case ui::AXEventGenerator::Event::COLLAPSED: {
242 NSAccessibilityNotificationName mac_notification;
245 mac_notification = NSAccessibilityRowCollapsedNotification;
250 .name = mac_notification,
251 .target = native_node,
256 case ui::AXEventGenerator::Event::MENU_ITEM_SELECTED:
259 .target = native_node,
263 case ui::AXEventGenerator::Event::CHILDREN_CHANGED: {
267 .name = NSAccessibilityCreatedNotification,
268 .target = view_controller_.
view.window,
273 case ui::AXEventGenerator::Event::SUBTREE_CREATED:
274 case ui::AXEventGenerator::Event::ACCESS_KEY_CHANGED:
275 case ui::AXEventGenerator::Event::ATK_TEXT_OBJECT_ATTRIBUTE_CHANGED:
276 case ui::AXEventGenerator::Event::ATOMIC_CHANGED:
277 case ui::AXEventGenerator::Event::AUTO_COMPLETE_CHANGED:
278 case ui::AXEventGenerator::Event::BUSY_CHANGED:
279 case ui::AXEventGenerator::Event::CONTROLS_CHANGED:
280 case ui::AXEventGenerator::Event::CLASS_NAME_CHANGED:
281 case ui::AXEventGenerator::Event::DESCRIBED_BY_CHANGED:
282 case ui::AXEventGenerator::Event::DESCRIPTION_CHANGED:
283 case ui::AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
284 case ui::AXEventGenerator::Event::DROPEFFECT_CHANGED:
285 case ui::AXEventGenerator::Event::ENABLED_CHANGED:
286 case ui::AXEventGenerator::Event::FOCUS_CHANGED:
287 case ui::AXEventGenerator::Event::FLOW_FROM_CHANGED:
288 case ui::AXEventGenerator::Event::FLOW_TO_CHANGED:
289 case ui::AXEventGenerator::Event::GRABBED_CHANGED:
290 case ui::AXEventGenerator::Event::HASPOPUP_CHANGED:
291 case ui::AXEventGenerator::Event::HIERARCHICAL_LEVEL_CHANGED:
292 case ui::AXEventGenerator::Event::IGNORED_CHANGED:
293 case ui::AXEventGenerator::Event::IMAGE_ANNOTATION_CHANGED:
294 case ui::AXEventGenerator::Event::KEY_SHORTCUTS_CHANGED:
295 case ui::AXEventGenerator::Event::LABELED_BY_CHANGED:
296 case ui::AXEventGenerator::Event::LANGUAGE_CHANGED:
297 case ui::AXEventGenerator::Event::LAYOUT_INVALIDATED:
298 case ui::AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
299 case ui::AXEventGenerator::Event::LIVE_RELEVANT_CHANGED:
300 case ui::AXEventGenerator::Event::LIVE_STATUS_CHANGED:
301 case ui::AXEventGenerator::Event::LOAD_START:
302 case ui::AXEventGenerator::Event::MULTILINE_STATE_CHANGED:
303 case ui::AXEventGenerator::Event::MULTISELECTABLE_STATE_CHANGED:
304 case ui::AXEventGenerator::Event::NAME_CHANGED:
305 case ui::AXEventGenerator::Event::OBJECT_ATTRIBUTE_CHANGED:
306 case ui::AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
307 case ui::AXEventGenerator::Event::PLACEHOLDER_CHANGED:
308 case ui::AXEventGenerator::Event::PORTAL_ACTIVATED:
309 case ui::AXEventGenerator::Event::POSITION_IN_SET_CHANGED:
310 case ui::AXEventGenerator::Event::READONLY_CHANGED:
311 case ui::AXEventGenerator::Event::RELATED_NODE_CHANGED:
312 case ui::AXEventGenerator::Event::REQUIRED_STATE_CHANGED:
313 case ui::AXEventGenerator::Event::ROLE_CHANGED:
314 case ui::AXEventGenerator::Event::SCROLL_HORIZONTAL_POSITION_CHANGED:
315 case ui::AXEventGenerator::Event::SCROLL_VERTICAL_POSITION_CHANGED:
316 case ui::AXEventGenerator::Event::SELECTED_CHANGED:
317 case ui::AXEventGenerator::Event::SET_SIZE_CHANGED:
318 case ui::AXEventGenerator::Event::SORT_CHANGED:
319 case ui::AXEventGenerator::Event::STATE_CHANGED:
320 case ui::AXEventGenerator::Event::TEXT_ATTRIBUTE_CHANGED:
321 case ui::AXEventGenerator::Event::VALUE_MAX_CHANGED:
322 case ui::AXEventGenerator::Event::VALUE_MIN_CHANGED:
323 case ui::AXEventGenerator::Event::VALUE_STEP_CHANGED:
324 case ui::AXEventGenerator::Event::WIN_IACCESSIBLE_STATE_CHANGED:
335 NSCAssert(flutter_engine_,
@"Flutter engine should not be deallocated");
336 NSCAssert(view_controller_.viewLoaded && view_controller_.
view.window,
337 @"The accessibility bridge should not receive accessibility actions if the flutter view"
338 @"is not loaded or attached to a NSWindow.");
339 [flutter_engine_ dispatchSemanticsAction:
action toTarget:
target withData:std::move(
data)];
342std::shared_ptr<FlutterPlatformNodeDelegate>
344 return std::make_shared<FlutterPlatformNodeDelegateMac>(weak_from_this(), view_controller_);
350 NSAccessibilityNotificationName mac_notification) {
351 NSCAssert(mac_notification,
@"The notification must not be null.");
352 NSCAssert(native_node,
@"The notification target must not be null.");
353 NSAccessibilityPostNotification(native_node, mac_notification);
356void AccessibilityBridgeMac::DispatchMacOSNotificationWithUserInfo(
358 NSAccessibilityNotificationName mac_notification,
359 NSDictionary* user_info) {
360 NSCAssert(mac_notification,
@"The notification must not be null.");
361 NSCAssert(native_node,
@"The notification target must not be null.");
362 NSCAssert(user_info,
@"The notification data must not be null.");
363 NSAccessibilityPostNotificationWithUserInfo(native_node, mac_notification, user_info);
367 NSCAssert(flutter_engine_,
@"Flutter engine should not be deallocated");
368 std::vector<ui::AXEventGenerator::TargetedEvent> pending_events =
GetPendingEvents();
370 if (pending_event.event_params.event ==
event) {
ax::mojom::Event event_type
AccessibilityBridgeMac(__weak FlutterEngine *flutter_engine, __weak FlutterViewController *view_controller)
Creates an AccessibilityBridgeMacDelegate.
void OnAccessibilityEvent(ui::AXEventGenerator::TargetedEvent targeted_event) override
Handle accessibility events generated due to accessibility tree changes. These events are needed to b...
std::shared_ptr< FlutterPlatformNodeDelegate > CreateFlutterPlatformNodeDelegate() override
Creates a platform specific FlutterPlatformNodeDelegate. Ownership passes to the caller....
virtual void DispatchMacOSNotification(gfx::NativeViewAccessible native_node, NSAccessibilityNotificationName mac_notification)
Posts the given event against the given node to the macOS accessibility notification system.
void DispatchAccessibilityAction(AccessibilityNodeId target, FlutterSemanticsAction action, fml::MallocMapping data) override
Dispatch accessibility action back to the Flutter framework. These actions are generated in the nativ...
ui::AXPlatformNodeDelegate * RootDelegate() const override
std::weak_ptr< FlutterPlatformNodeDelegate > GetFlutterPlatformNodeDelegateFromID(AccessibilityNodeId id) const
Get the flutter platform node delegate with the given id from this accessibility bridge....
const ui::AXTreeData & GetAXTreeData() const
Get the ax tree data from this accessibility bridge. The tree data contains information such as the i...
const std::vector< ui::AXEventGenerator::TargetedEvent > GetPendingEvents() const
Gets all pending accessibility events generated during semantics updates. This is useful when decidin...
FlutterView * view() const
A Mapping like NonOwnedMapping, but uses Free as its release proc.
static constexpr AXID kInvalidAXID
const AXNodeData & data() const
static NSString *const kAccessibilityLoadCompleteNotification
static NSString *const kAccessibilityExpandedChanged
static NSString *const kAccessibilityMenuItemSelectedNotification
static NSString *const kAccessibilityLiveRegionChangedNotification
static NSString *const kAccessibilityInvalidStatusChangedNotification
static NSString *const kAccessibilityLiveRegionCreatedNotification
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
UnimplementedNativeViewAccessible * NativeViewAccessible
bool IsTableLike(const ax::mojom::Role role)
const EventParams & event_params
bool HasState(ax::mojom::State state) const
AXNode::AXID sel_anchor_object_id