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 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #import "base/mac/mac_util.h" | 8 #import "base/mac/mac_util.h" |
9 #import "base/mac/scoped_nsobject.h" | 9 #import "base/mac/scoped_nsobject.h" |
10 #import "base/mac/sdk_forward_declarations.h" | 10 #import "base/mac/sdk_forward_declarations.h" |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 } | 355 } |
356 | 356 |
357 void BrowserAccessibilityManagerMac::OnAccessibilityEvents( | 357 void BrowserAccessibilityManagerMac::OnAccessibilityEvents( |
358 const std::vector<AXEventNotificationDetails>& details) { | 358 const std::vector<AXEventNotificationDetails>& details) { |
359 text_edits_.clear(); | 359 text_edits_.clear(); |
360 // Call the base method last as it might delete the tree if it receives an | 360 // Call the base method last as it might delete the tree if it receives an |
361 // invalid message. | 361 // invalid message. |
362 BrowserAccessibilityManager::OnAccessibilityEvents(details); | 362 BrowserAccessibilityManager::OnAccessibilityEvents(details); |
363 } | 363 } |
364 | 364 |
| 365 void BrowserAccessibilityManagerMac::OnTreeDataChanged( |
| 366 ui::AXTree* tree, |
| 367 const ui::AXTreeData& old_tree_data, |
| 368 const ui::AXTreeData& new_tree_data) { |
| 369 BrowserAccessibilityManager::OnTreeDataChanged(tree, old_tree_data, |
| 370 new_tree_data); |
| 371 if (new_tree_data.loaded && !old_tree_data.loaded) |
| 372 tree_events_[tree->root()->id()].insert(ui::AX_EVENT_LOAD_COMPLETE); |
| 373 if (new_tree_data.sel_anchor_object_id != |
| 374 old_tree_data.sel_anchor_object_id || |
| 375 new_tree_data.sel_anchor_offset != old_tree_data.sel_anchor_offset || |
| 376 new_tree_data.sel_anchor_affinity != old_tree_data.sel_anchor_affinity || |
| 377 new_tree_data.sel_focus_object_id != old_tree_data.sel_focus_object_id || |
| 378 new_tree_data.sel_focus_offset != old_tree_data.sel_focus_offset || |
| 379 new_tree_data.sel_focus_affinity != old_tree_data.sel_focus_affinity) { |
| 380 tree_events_[tree->root()->id()].insert( |
| 381 ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED); |
| 382 } |
| 383 } |
| 384 |
365 void BrowserAccessibilityManagerMac::OnNodeDataWillChange( | 385 void BrowserAccessibilityManagerMac::OnNodeDataWillChange( |
366 ui::AXTree* tree, | 386 ui::AXTree* tree, |
367 const ui::AXNodeData& old_node_data, | 387 const ui::AXNodeData& old_node_data, |
368 const ui::AXNodeData& new_node_data) { | 388 const ui::AXNodeData& new_node_data) { |
369 BrowserAccessibilityManager::OnNodeDataWillChange(tree, old_node_data, | 389 BrowserAccessibilityManager::OnNodeDataWillChange(tree, old_node_data, |
370 new_node_data); | 390 new_node_data); |
371 | 391 |
372 // Starting from OS X 10.11, if the user has edited some text we need to | 392 // Starting from OS X 10.11, if the user has edited some text we need to |
373 // dispatch the actual text that changed on the value changed notification. | 393 // dispatch the actual text that changed on the value changed notification. |
374 // We run this code on all OS X versions to get the highest test coverage. | 394 // We run this code on all OS X versions to get the highest test coverage. |
(...skipping 29 matching lines...) Expand all Loading... |
404 while (i < old_text.length() && i < new_text.length() && | 424 while (i < old_text.length() && i < new_text.length() && |
405 old_text[i] == new_text[i]) { | 425 old_text[i] == new_text[i]) { |
406 ++i; | 426 ++i; |
407 } | 427 } |
408 size_t length = (old_text.length() - i) - (new_text.length() - i); | 428 size_t length = (old_text.length() - i) - (new_text.length() - i); |
409 base::string16 deleted_text = old_text.substr(i, length); | 429 base::string16 deleted_text = old_text.substr(i, length); |
410 text_edits_[new_node_data.id] = deleted_text; | 430 text_edits_[new_node_data.id] = deleted_text; |
411 } | 431 } |
412 } | 432 } |
413 | 433 |
| 434 bool IsContainerWithSelectableChildrenRole(ui::AXRole role) { |
| 435 switch (role) { |
| 436 case ui::AX_ROLE_COMBO_BOX: |
| 437 case ui::AX_ROLE_GRID: |
| 438 case ui::AX_ROLE_LIST_BOX: |
| 439 case ui::AX_ROLE_MENU: |
| 440 case ui::AX_ROLE_MENU_BAR: |
| 441 case ui::AX_ROLE_RADIO_GROUP: |
| 442 case ui::AX_ROLE_TAB_LIST: |
| 443 case ui::AX_ROLE_TOOLBAR: |
| 444 case ui::AX_ROLE_TREE: |
| 445 case ui::AX_ROLE_TREE_GRID: |
| 446 return true; |
| 447 default: |
| 448 return false; |
| 449 } |
| 450 } |
| 451 |
| 452 bool IsRowContainer(ui::AXRole role) { |
| 453 switch (role) { |
| 454 case ui::AX_ROLE_TREE: |
| 455 case ui::AX_ROLE_TREE_GRID: |
| 456 case ui::AX_ROLE_GRID: |
| 457 case ui::AX_ROLE_TABLE: |
| 458 return true; |
| 459 default: |
| 460 return false; |
| 461 } |
| 462 } |
| 463 |
| 464 void BrowserAccessibilityManagerMac::OnStateChanged(ui::AXTree* tree, |
| 465 ui::AXNode* node, |
| 466 ui::AXState state, |
| 467 bool new_value) { |
| 468 BrowserAccessibilityManager::OnStateChanged(tree, node, state, new_value); |
| 469 if (state == ui::AX_STATE_EXPANDED) { |
| 470 if (node->data().role == ui::AX_ROLE_ROW || |
| 471 node->data().role == ui::AX_ROLE_TREE_ITEM) { |
| 472 if (new_value) |
| 473 tree_events_[node->id()].insert(ui::AX_EVENT_ROW_EXPANDED); |
| 474 else |
| 475 tree_events_[node->id()].insert(ui::AX_EVENT_ROW_COLLAPSED); |
| 476 ui::AXNode* container = node; |
| 477 while (container && !IsRowContainer(container->data().role)) |
| 478 container = container->parent(); |
| 479 if (container) |
| 480 tree_events_[container->id()].insert(ui::AX_EVENT_ROW_COUNT_CHANGED); |
| 481 } else { |
| 482 tree_events_[node->id()].insert(ui::AX_EVENT_EXPANDED_CHANGED); |
| 483 } |
| 484 } |
| 485 if (state == ui::AX_STATE_SELECTED) { |
| 486 ui::AXNode* container = node; |
| 487 while (container && |
| 488 !IsContainerWithSelectableChildrenRole(container->data().role)) |
| 489 container = container->parent(); |
| 490 if (container) |
| 491 tree_events_[container->id()].insert( |
| 492 ui::AX_EVENT_SELECTED_CHILDREN_CHANGED); |
| 493 } |
| 494 } |
| 495 |
| 496 void BrowserAccessibilityManagerMac::OnStringAttributeChanged( |
| 497 ui::AXTree* tree, |
| 498 ui::AXNode* node, |
| 499 ui::AXStringAttribute attr, |
| 500 const std::string& old_value, |
| 501 const std::string& new_value) { |
| 502 BrowserAccessibilityManager::OnStringAttributeChanged(tree, node, attr, |
| 503 old_value, new_value); |
| 504 switch (attr) { |
| 505 case ui::AX_ATTR_VALUE: |
| 506 tree_events_[node->id()].insert(ui::AX_EVENT_VALUE_CHANGED); |
| 507 break; |
| 508 case ui::AX_ATTR_ARIA_INVALID_VALUE: |
| 509 tree_events_[node->id()].insert(ui::AX_EVENT_INVALID_STATUS_CHANGED); |
| 510 break; |
| 511 case ui::AX_ATTR_LIVE_STATUS: |
| 512 tree_events_[node->id()].insert(ui::AX_EVENT_LIVE_REGION_CREATED); |
| 513 break; |
| 514 default: |
| 515 break; |
| 516 } |
| 517 } |
| 518 |
| 519 void BrowserAccessibilityManagerMac::OnIntAttributeChanged( |
| 520 ui::AXTree* tree, |
| 521 ui::AXNode* node, |
| 522 ui::AXIntAttribute attr, |
| 523 int32_t old_value, |
| 524 int32_t new_value) { |
| 525 BrowserAccessibilityManager::OnIntAttributeChanged(tree, node, attr, |
| 526 old_value, new_value); |
| 527 switch (attr) { |
| 528 case ui::AX_ATTR_CHECKED_STATE: |
| 529 tree_events_[node->id()].insert(ui::AX_EVENT_VALUE_CHANGED); |
| 530 break; |
| 531 case ui::AX_ATTR_ACTIVEDESCENDANT_ID: |
| 532 tree_events_[node->id()].insert(ui::AX_EVENT_ACTIVEDESCENDANTCHANGED); |
| 533 break; |
| 534 case ui::AX_ATTR_INVALID_STATE: |
| 535 tree_events_[node->id()].insert(ui::AX_EVENT_INVALID_STATUS_CHANGED); |
| 536 break; |
| 537 default: |
| 538 break; |
| 539 } |
| 540 } |
| 541 |
| 542 void BrowserAccessibilityManagerMac::OnFloatAttributeChanged( |
| 543 ui::AXTree* tree, |
| 544 ui::AXNode* node, |
| 545 ui::AXFloatAttribute attr, |
| 546 float old_value, |
| 547 float new_value) { |
| 548 BrowserAccessibilityManager::OnFloatAttributeChanged(tree, node, attr, |
| 549 old_value, new_value); |
| 550 if (attr == ui::AX_ATTR_VALUE_FOR_RANGE) |
| 551 tree_events_[node->id()].insert(ui::AX_EVENT_VALUE_CHANGED); |
| 552 } |
| 553 |
| 554 void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished( |
| 555 ui::AXTree* tree, |
| 556 bool root_changed, |
| 557 const std::vector<Change>& changes) { |
| 558 BrowserAccessibilityManager::OnAtomicUpdateFinished(tree, root_changed, |
| 559 changes); |
| 560 for (const auto& change : changes) { |
| 561 if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED) && |
| 562 change.node->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) { |
| 563 if (change.node->data().role == ui::AX_ROLE_ALERT) |
| 564 tree_events_[change.node->id()].insert(ui::AX_EVENT_ALERT); |
| 565 else |
| 566 tree_events_[change.node->id()].insert( |
| 567 ui::AX_EVENT_LIVE_REGION_CREATED); |
| 568 continue; |
| 569 } |
| 570 if (change.node->data().HasStringAttribute( |
| 571 ui::AX_ATTR_CONTAINER_LIVE_STATUS)) { |
| 572 ui::AXNode* live_root = change.node; |
| 573 while (live_root && |
| 574 !live_root->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) |
| 575 live_root = live_root->parent(); |
| 576 if (live_root) |
| 577 tree_events_[live_root->id()].insert(ui::AX_EVENT_LIVE_REGION_CHANGED); |
| 578 } |
| 579 } |
| 580 } |
| 581 |
414 NSDictionary* BrowserAccessibilityManagerMac:: | 582 NSDictionary* BrowserAccessibilityManagerMac:: |
415 GetUserInfoForSelectedTextChangedNotification() { | 583 GetUserInfoForSelectedTextChangedNotification() { |
416 NSMutableDictionary* user_info = [[[NSMutableDictionary alloc] init] | 584 NSMutableDictionary* user_info = [[[NSMutableDictionary alloc] init] |
417 autorelease]; | 585 autorelease]; |
418 [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey]; | 586 [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey]; |
419 [user_info setObject:@(AXTextStateChangeTypeUnknown) | 587 [user_info setObject:@(AXTextStateChangeTypeUnknown) |
420 forKey:NSAccessibilityTextStateChangeTypeKey]; | 588 forKey:NSAccessibilityTextStateChangeTypeKey]; |
421 [user_info setObject:@(AXTextSelectionDirectionUnknown) | 589 [user_info setObject:@(AXTextSelectionDirectionUnknown) |
422 forKey:NSAccessibilityTextSelectionDirection]; | 590 forKey:NSAccessibilityTextSelectionDirection]; |
423 [user_info setObject:@(AXTextSelectionGranularityUnknown) | 591 [user_info setObject:@(AXTextSelectionGranularityUnknown) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 NSAccessibilityTextChangeValues : changes, | 642 NSAccessibilityTextChangeValues : changes, |
475 NSAccessibilityTextChangeElement : native_node | 643 NSAccessibilityTextChangeElement : native_node |
476 }; | 644 }; |
477 } | 645 } |
478 | 646 |
479 NSView* BrowserAccessibilityManagerMac::GetParentView() { | 647 NSView* BrowserAccessibilityManagerMac::GetParentView() { |
480 return delegate() ? delegate()->AccessibilityGetAcceleratedWidget() : nullptr; | 648 return delegate() ? delegate()->AccessibilityGetAcceleratedWidget() : nullptr; |
481 } | 649 } |
482 | 650 |
483 } // namespace content | 651 } // namespace content |
OLD | NEW |