| 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.h" | 5 #include "content/browser/accessibility/browser_accessibility_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 // Find the node corresponding to the id that's the target of the | 380 // Find the node corresponding to the id that's the target of the |
| 381 // event (which may not be the root of the update tree). | 381 // event (which may not be the root of the update tree). |
| 382 ui::AXNode* node = tree_->GetFromId(detail.id); | 382 ui::AXNode* node = tree_->GetFromId(detail.id); |
| 383 if (!node) | 383 if (!node) |
| 384 continue; | 384 continue; |
| 385 | 385 |
| 386 ui::AXEvent event_type = detail.event_type; | 386 ui::AXEvent event_type = detail.event_type; |
| 387 if (event_type == ui::AX_EVENT_FOCUS || | 387 if (event_type == ui::AX_EVENT_FOCUS || |
| 388 event_type == ui::AX_EVENT_BLUR) { | 388 event_type == ui::AX_EVENT_BLUR) { |
| 389 if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN && | 389 if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN && |
| 390 osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) { | 390 osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED) |
| 391 osk_state_ = OSK_ALLOWED; | 391 osk_state_ = OSK_ALLOWED; |
| 392 } | |
| 393 | 392 |
| 394 // We already handled all focus events above. | 393 bool is_menu_list_option = |
| 395 continue; | 394 node->data().role == ui::AX_ROLE_MENU_LIST_OPTION; |
| 395 |
| 396 // Skip all focus events other than ones on menu list options; |
| 397 // we've already handled them, above. Menu list options are a weird |
| 398 // exception because the menu list itself has focus but we need to fire |
| 399 // focus events on the individual options. |
| 400 if (!is_menu_list_option) |
| 401 continue; |
| 396 } | 402 } |
| 397 | 403 |
| 398 // Fire the native event. | 404 // Fire the native event. |
| 399 BrowserAccessibility* event_target = GetFromAXNode(node); | 405 BrowserAccessibility* event_target = GetFromAXNode(node); |
| 400 if (event_target) { | 406 if (event_target) { |
| 401 NotifyAccessibilityEvent( | 407 NotifyAccessibilityEvent( |
| 402 BrowserAccessibilityEvent::FromBlink, | 408 BrowserAccessibilityEvent::FromBlink, |
| 403 event_type, | 409 event_type, |
| 404 event_target); | 410 event_target); |
| 405 } | 411 } |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 } | 482 } |
| 477 | 483 |
| 478 // The "scrolled to anchor" notification is a great way to get a | 484 // The "scrolled to anchor" notification is a great way to get a |
| 479 // screen reader to jump directly to a specific location in a document. | 485 // screen reader to jump directly to a specific location in a document. |
| 480 NotifyAccessibilityEvent( | 486 NotifyAccessibilityEvent( |
| 481 BrowserAccessibilityEvent::FromFindInPageResult, | 487 BrowserAccessibilityEvent::FromFindInPageResult, |
| 482 ui::AX_EVENT_SCROLLED_TO_ANCHOR, | 488 ui::AX_EVENT_SCROLLED_TO_ANCHOR, |
| 483 node); | 489 node); |
| 484 } | 490 } |
| 485 | 491 |
| 486 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendant( | 492 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus( |
| 487 BrowserAccessibility* focus) { | 493 BrowserAccessibility* focus) { |
| 488 if (!focus) | 494 if (!focus) |
| 489 return nullptr; | 495 return NULL; |
| 490 | 496 |
| 491 int32_t active_descendant_id; | 497 int active_descendant_id; |
| 492 BrowserAccessibility* active_descendant = nullptr; | |
| 493 if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, | 498 if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, |
| 494 &active_descendant_id)) { | 499 &active_descendant_id)) { |
| 495 active_descendant = focus->manager()->GetFromID(active_descendant_id); | 500 BrowserAccessibility* active_descendant = |
| 501 focus->manager()->GetFromID(active_descendant_id); |
| 502 if (active_descendant) |
| 503 return active_descendant; |
| 496 } | 504 } |
| 497 | |
| 498 if (focus->GetRole() == ui::AX_ROLE_POP_UP_BUTTON) { | |
| 499 BrowserAccessibility* child = focus->InternalGetChild(0); | |
| 500 if (child && child->GetRole() == ui::AX_ROLE_MENU_LIST_POPUP) { | |
| 501 // The active descendant is found on the menu list popup, i.e. on the | |
| 502 // actual list and not on the button that opens it. | |
| 503 // If there is no active descendant, focus should stay on the button so | |
| 504 // that Windows screen readers would enable their virtual cursor. | |
| 505 if (child->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, | |
| 506 &active_descendant_id)) { | |
| 507 active_descendant = child->manager()->GetFromID(active_descendant_id); | |
| 508 } | |
| 509 } | |
| 510 } | |
| 511 | |
| 512 if (active_descendant) | |
| 513 return active_descendant; | |
| 514 | |
| 515 return focus; | 505 return focus; |
| 516 } | 506 } |
| 517 | 507 |
| 518 bool BrowserAccessibilityManager::NativeViewHasFocus() { | 508 bool BrowserAccessibilityManager::NativeViewHasFocus() { |
| 519 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); | 509 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); |
| 520 if (delegate) | 510 if (delegate) |
| 521 return delegate->AccessibilityViewHasFocus(); | 511 return delegate->AccessibilityViewHasFocus(); |
| 522 return false; | 512 return false; |
| 523 } | 513 } |
| 524 | 514 |
| 525 BrowserAccessibility* BrowserAccessibilityManager::GetFocus() { | 515 BrowserAccessibility* BrowserAccessibilityManager::GetFocus() { |
| 526 BrowserAccessibilityManager* root_manager = GetRootManager(); | 516 BrowserAccessibilityManager* root_manager = GetRootManager(); |
| 527 if (!root_manager) | 517 if (!root_manager) |
| 528 root_manager = this; | 518 root_manager = this; |
| 529 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id; | 519 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id; |
| 530 | 520 |
| 531 BrowserAccessibilityManager* focused_manager = nullptr; | 521 BrowserAccessibilityManager* focused_manager = nullptr; |
| 532 if (focused_tree_id) | 522 if (focused_tree_id) |
| 533 focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id); | 523 focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id); |
| 534 | |
| 535 // BrowserAccessibilityManager::FromID(focused_tree_id) may return nullptr | |
| 536 // if the tree is not created or has been destroyed. | |
| 537 if (!focused_manager) | 524 if (!focused_manager) |
| 538 focused_manager = root_manager; | 525 focused_manager = root_manager; |
| 539 | 526 |
| 540 return focused_manager->GetFocusFromThisOrDescendantFrame(); | 527 return focused_manager->GetFocusFromThisOrDescendantFrame(); |
| 541 } | 528 } |
| 542 | 529 |
| 543 BrowserAccessibility* | 530 BrowserAccessibility* |
| 544 BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() { | 531 BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() { |
| 545 int32_t focus_id = GetTreeData().focus_id; | 532 int32_t focus_id = GetTreeData().focus_id; |
| 546 BrowserAccessibility* obj = GetFromID(focus_id); | 533 BrowserAccessibility* obj = GetFromID(focus_id); |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 tree_source(tree_->CreateTreeSource()); | 889 tree_source(tree_->CreateTreeSource()); |
| 903 ui::AXTreeSerializer<const ui::AXNode*, | 890 ui::AXTreeSerializer<const ui::AXNode*, |
| 904 ui::AXNodeData, | 891 ui::AXNodeData, |
| 905 ui::AXTreeData> serializer(tree_source.get()); | 892 ui::AXTreeData> serializer(tree_source.get()); |
| 906 ui::AXTreeUpdate update; | 893 ui::AXTreeUpdate update; |
| 907 serializer.SerializeChanges(tree_->root(), &update); | 894 serializer.SerializeChanges(tree_->root(), &update); |
| 908 return update; | 895 return update; |
| 909 } | 896 } |
| 910 | 897 |
| 911 } // namespace content | 898 } // namespace content |
| OLD | NEW |