| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" | 5 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" |
| 6 | 6 |
| 7 #import "base/mac/mac_util.h" | 7 #import "base/mac/mac_util.h" |
| 8 #import "base/mac/sdk_forward_declarations.h" | 8 #import "base/mac/sdk_forward_declarations.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 }; | 58 }; |
| 59 | 59 |
| 60 NSString* const NSAccessibilityAutocorrectionOccurredNotification = | 60 NSString* const NSAccessibilityAutocorrectionOccurredNotification = |
| 61 @"AXAutocorrectionOccurred"; | 61 @"AXAutocorrectionOccurred"; |
| 62 NSString* const NSAccessibilityLayoutCompleteNotification = | 62 NSString* const NSAccessibilityLayoutCompleteNotification = |
| 63 @"AXLayoutComplete"; | 63 @"AXLayoutComplete"; |
| 64 NSString* const NSAccessibilityLoadCompleteNotification = | 64 NSString* const NSAccessibilityLoadCompleteNotification = |
| 65 @"AXLoadComplete"; | 65 @"AXLoadComplete"; |
| 66 NSString* const NSAccessibilityInvalidStatusChangedNotification = | 66 NSString* const NSAccessibilityInvalidStatusChangedNotification = |
| 67 @"AXInvalidStatusChanged"; | 67 @"AXInvalidStatusChanged"; |
| 68 NSString* const NSAccessibilityLiveRegionCreatedNotification = |
| 69 @"AXLiveRegionCreated"; |
| 68 NSString* const NSAccessibilityLiveRegionChangedNotification = | 70 NSString* const NSAccessibilityLiveRegionChangedNotification = |
| 69 @"AXLiveRegionChanged"; | 71 @"AXLiveRegionChanged"; |
| 70 NSString* const NSAccessibilityExpandedChanged = | 72 NSString* const NSAccessibilityExpandedChanged = |
| 71 @"AXExpandedChanged"; | 73 @"AXExpandedChanged"; |
| 72 NSString* const NSAccessibilityMenuItemSelectedNotification = | 74 NSString* const NSAccessibilityMenuItemSelectedNotification = |
| 73 @"AXMenuItemSelected"; | 75 @"AXMenuItemSelected"; |
| 74 | 76 |
| 75 // Attributes used for NSAccessibilitySelectedTextChangedNotification and | 77 // Attributes used for NSAccessibilitySelectedTextChangedNotification and |
| 76 // NSAccessibilityValueChangedNotification. | 78 // NSAccessibilityValueChangedNotification. |
| 77 NSString* const NSAccessibilityTextStateChangeTypeKey = | 79 NSString* const NSAccessibilityTextStateChangeTypeKey = |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 if (!root) | 256 if (!root) |
| 255 return; | 257 return; |
| 256 | 258 |
| 257 NSAccessibilityPostNotificationWithUserInfo( | 259 NSAccessibilityPostNotificationWithUserInfo( |
| 258 native_node, mac_notification, user_info); | 260 native_node, mac_notification, user_info); |
| 259 NSAccessibilityPostNotificationWithUserInfo( | 261 NSAccessibilityPostNotificationWithUserInfo( |
| 260 ToBrowserAccessibilityCocoa(root), mac_notification, user_info); | 262 ToBrowserAccessibilityCocoa(root), mac_notification, user_info); |
| 261 return; | 263 return; |
| 262 } | 264 } |
| 263 break; | 265 break; |
| 264 // TODO(nektar): Need to add an event for live region created. | 266 case ui::AX_EVENT_ALERT: |
| 267 mac_notification = NSAccessibilityLiveRegionCreatedNotification; |
| 268 break; |
| 265 case ui::AX_EVENT_LIVE_REGION_CHANGED: | 269 case ui::AX_EVENT_LIVE_REGION_CHANGED: |
| 266 mac_notification = NSAccessibilityLiveRegionChangedNotification; | 270 mac_notification = NSAccessibilityLiveRegionChangedNotification; |
| 267 break; | 271 break; |
| 268 case ui::AX_EVENT_ROW_COUNT_CHANGED: | 272 case ui::AX_EVENT_ROW_COUNT_CHANGED: |
| 269 mac_notification = NSAccessibilityRowCountChangedNotification; | 273 mac_notification = NSAccessibilityRowCountChangedNotification; |
| 270 break; | 274 break; |
| 271 case ui::AX_EVENT_ROW_EXPANDED: | 275 case ui::AX_EVENT_ROW_EXPANDED: |
| 272 mac_notification = NSAccessibilityRowExpandedNotification; | 276 mac_notification = NSAccessibilityRowExpandedNotification; |
| 273 break; | 277 break; |
| 274 case ui::AX_EVENT_ROW_COLLAPSED: | 278 case ui::AX_EVENT_ROW_COLLAPSED: |
| 275 mac_notification = NSAccessibilityRowCollapsedNotification; | 279 mac_notification = NSAccessibilityRowCollapsedNotification; |
| 276 break; | 280 break; |
| 277 // TODO(nektar): Add events for busy. | 281 // TODO(nektar): Add events for busy. |
| 278 case ui::AX_EVENT_EXPANDED_CHANGED: | 282 case ui::AX_EVENT_EXPANDED_CHANGED: |
| 279 mac_notification = NSAccessibilityExpandedChanged; | 283 mac_notification = NSAccessibilityExpandedChanged; |
| 280 break; | 284 break; |
| 281 // TODO(nektar): Support menu open/close notifications. | 285 // TODO(nektar): Support menu open/close notifications. |
| 282 case ui::AX_EVENT_MENU_LIST_ITEM_SELECTED: | 286 case ui::AX_EVENT_MENU_LIST_ITEM_SELECTED: |
| 283 mac_notification = NSAccessibilityMenuItemSelectedNotification; | 287 mac_notification = NSAccessibilityMenuItemSelectedNotification; |
| 284 break; | 288 break; |
| 285 | 289 |
| 286 // These events are not used on Mac for now. | 290 // These events are not used on Mac for now. |
| 287 case ui::AX_EVENT_ALERT: | |
| 288 case ui::AX_EVENT_TEXT_CHANGED: | 291 case ui::AX_EVENT_TEXT_CHANGED: |
| 289 case ui::AX_EVENT_CHILDREN_CHANGED: | 292 case ui::AX_EVENT_CHILDREN_CHANGED: |
| 290 case ui::AX_EVENT_MENU_LIST_VALUE_CHANGED: | 293 case ui::AX_EVENT_MENU_LIST_VALUE_CHANGED: |
| 291 case ui::AX_EVENT_SCROLL_POSITION_CHANGED: | 294 case ui::AX_EVENT_SCROLL_POSITION_CHANGED: |
| 292 case ui::AX_EVENT_SCROLLED_TO_ANCHOR: | 295 case ui::AX_EVENT_SCROLLED_TO_ANCHOR: |
| 293 case ui::AX_EVENT_ARIA_ATTRIBUTE_CHANGED: | 296 case ui::AX_EVENT_ARIA_ATTRIBUTE_CHANGED: |
| 294 case ui::AX_EVENT_LOCATION_CHANGED: | 297 case ui::AX_EVENT_LOCATION_CHANGED: |
| 295 return; | 298 return; |
| 296 | 299 |
| 297 // Deprecated events. | 300 // Deprecated events. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 } | 369 } |
| 367 } | 370 } |
| 368 | 371 |
| 369 void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished( | 372 void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished( |
| 370 ui::AXTree* tree, | 373 ui::AXTree* tree, |
| 371 bool root_changed, | 374 bool root_changed, |
| 372 const std::vector<ui::AXTreeDelegate::Change>& changes) { | 375 const std::vector<ui::AXTreeDelegate::Change>& changes) { |
| 373 BrowserAccessibilityManager::OnAtomicUpdateFinished( | 376 BrowserAccessibilityManager::OnAtomicUpdateFinished( |
| 374 tree, root_changed, changes); | 377 tree, root_changed, changes); |
| 375 | 378 |
| 376 bool created_live_region = false; | |
| 377 for (size_t i = 0; i < changes.size(); ++i) { | 379 for (size_t i = 0; i < changes.size(); ++i) { |
| 378 if (changes[i].type != NODE_CREATED && changes[i].type != SUBTREE_CREATED) | 380 if (changes[i].type != NODE_CREATED && changes[i].type != SUBTREE_CREATED) |
| 379 continue; | 381 continue; |
| 380 | 382 |
| 381 const ui::AXNode* changed_node = changes[i].node; | 383 const ui::AXNode* changed_node = changes[i].node; |
| 382 DCHECK(changed_node); | 384 DCHECK(changed_node); |
| 383 BrowserAccessibility* obj = GetFromAXNode(changed_node); | 385 BrowserAccessibility* obj = GetFromAXNode(changed_node); |
| 384 if (obj && obj->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) { | 386 if (obj && obj->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) { |
| 385 created_live_region = true; | 387 NotifyAccessibilityEvent(BrowserAccessibilityEvent::FromTreeChange, |
| 386 break; | 388 ui::AX_EVENT_ALERT, obj); |
| 387 } | 389 } |
| 388 } | 390 } |
| 389 | |
| 390 if (!created_live_region) | |
| 391 return; | |
| 392 | |
| 393 // This code is to work around a bug in VoiceOver, where a new live | |
| 394 // region that gets added is ignored. VoiceOver seems to only scan the | |
| 395 // page for live regions once. By recreating the NSAccessibility | |
| 396 // object for the root of the tree, we force VoiceOver to clear out its | |
| 397 // internal state and find newly-added live regions this time. | |
| 398 BrowserAccessibilityMac* root = | |
| 399 static_cast<BrowserAccessibilityMac*>(GetRoot()); | |
| 400 if (root) { | |
| 401 root->RecreateNativeObject(); | |
| 402 NotifyAccessibilityEvent( | |
| 403 BrowserAccessibilityEvent::FromTreeChange, | |
| 404 ui::AX_EVENT_CHILDREN_CHANGED, | |
| 405 root); | |
| 406 } | |
| 407 } | 391 } |
| 408 | 392 |
| 409 NSDictionary* BrowserAccessibilityManagerMac:: | 393 NSDictionary* BrowserAccessibilityManagerMac:: |
| 410 GetUserInfoForSelectedTextChangedNotification() { | 394 GetUserInfoForSelectedTextChangedNotification() { |
| 411 NSMutableDictionary* user_info = [[[NSMutableDictionary alloc] init] | 395 NSMutableDictionary* user_info = [[[NSMutableDictionary alloc] init] |
| 412 autorelease]; | 396 autorelease]; |
| 413 [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey]; | 397 [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey]; |
| 414 [user_info setObject:@(AXTextStateChangeTypeUnknown) | 398 [user_info setObject:@(AXTextStateChangeTypeUnknown) |
| 415 forKey:NSAccessibilityTextStateChangeTypeKey]; | 399 forKey:NSAccessibilityTextStateChangeTypeKey]; |
| 416 [user_info setObject:@(AXTextSelectionDirectionUnknown) | 400 [user_info setObject:@(AXTextSelectionDirectionUnknown) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 } | 449 } |
| 466 | 450 |
| 467 return @{ | 451 return @{ |
| 468 NSAccessibilityTextStateChangeTypeKey : @(AXTextStateChangeTypeEdit), | 452 NSAccessibilityTextStateChangeTypeKey : @(AXTextStateChangeTypeEdit), |
| 469 NSAccessibilityTextChangeValues : changes, | 453 NSAccessibilityTextChangeValues : changes, |
| 470 NSAccessibilityTextChangeElement : native_node | 454 NSAccessibilityTextChangeElement : native_node |
| 471 }; | 455 }; |
| 472 } | 456 } |
| 473 | 457 |
| 474 } // namespace content | 458 } // namespace content |
| OLD | NEW |