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 } |
392 | 393 |
393 bool is_menu_list_option = | 394 // We already handled all focus events above. |
394 node->data().role == ui::AX_ROLE_MENU_LIST_OPTION; | 395 continue; |
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; | |
402 } | 396 } |
403 | 397 |
404 // Fire the native event. | 398 // Fire the native event. |
405 BrowserAccessibility* event_target = GetFromAXNode(node); | 399 BrowserAccessibility* event_target = GetFromAXNode(node); |
406 if (event_target) { | 400 if (event_target) { |
407 NotifyAccessibilityEvent( | 401 NotifyAccessibilityEvent( |
408 BrowserAccessibilityEvent::FromBlink, | 402 BrowserAccessibilityEvent::FromBlink, |
409 event_type, | 403 event_type, |
410 event_target); | 404 event_target); |
411 } | 405 } |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 } | 476 } |
483 | 477 |
484 // The "scrolled to anchor" notification is a great way to get a | 478 // The "scrolled to anchor" notification is a great way to get a |
485 // screen reader to jump directly to a specific location in a document. | 479 // screen reader to jump directly to a specific location in a document. |
486 NotifyAccessibilityEvent( | 480 NotifyAccessibilityEvent( |
487 BrowserAccessibilityEvent::FromFindInPageResult, | 481 BrowserAccessibilityEvent::FromFindInPageResult, |
488 ui::AX_EVENT_SCROLLED_TO_ANCHOR, | 482 ui::AX_EVENT_SCROLLED_TO_ANCHOR, |
489 node); | 483 node); |
490 } | 484 } |
491 | 485 |
492 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus( | 486 BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendant( |
493 BrowserAccessibility* focus) { | 487 BrowserAccessibility* focus) { |
494 if (!focus) | 488 if (!focus) |
495 return NULL; | 489 return nullptr; |
496 | 490 |
497 int active_descendant_id; | 491 int32_t active_descendant_id; |
| 492 BrowserAccessibility* active_descendant = nullptr; |
498 if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, | 493 if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, |
499 &active_descendant_id)) { | 494 &active_descendant_id)) { |
500 BrowserAccessibility* active_descendant = | 495 active_descendant = focus->manager()->GetFromID(active_descendant_id); |
501 focus->manager()->GetFromID(active_descendant_id); | |
502 if (active_descendant) | |
503 return active_descendant; | |
504 } | 496 } |
| 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 |
505 return focus; | 515 return focus; |
506 } | 516 } |
507 | 517 |
508 bool BrowserAccessibilityManager::NativeViewHasFocus() { | 518 bool BrowserAccessibilityManager::NativeViewHasFocus() { |
509 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); | 519 BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager(); |
510 if (delegate) | 520 if (delegate) |
511 return delegate->AccessibilityViewHasFocus(); | 521 return delegate->AccessibilityViewHasFocus(); |
512 return false; | 522 return false; |
513 } | 523 } |
514 | 524 |
515 BrowserAccessibility* BrowserAccessibilityManager::GetFocus() { | 525 BrowserAccessibility* BrowserAccessibilityManager::GetFocus() { |
516 BrowserAccessibilityManager* root_manager = GetRootManager(); | 526 BrowserAccessibilityManager* root_manager = GetRootManager(); |
517 if (!root_manager) | 527 if (!root_manager) |
518 root_manager = this; | 528 root_manager = this; |
519 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id; | 529 int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id; |
520 | 530 |
521 BrowserAccessibilityManager* focused_manager = nullptr; | 531 BrowserAccessibilityManager* focused_manager = nullptr; |
522 if (focused_tree_id) | 532 if (focused_tree_id) |
523 focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id); | 533 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. |
524 if (!focused_manager) | 537 if (!focused_manager) |
525 focused_manager = root_manager; | 538 focused_manager = root_manager; |
526 | 539 |
527 return focused_manager->GetFocusFromThisOrDescendantFrame(); | 540 return focused_manager->GetFocusFromThisOrDescendantFrame(); |
528 } | 541 } |
529 | 542 |
530 BrowserAccessibility* | 543 BrowserAccessibility* |
531 BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() { | 544 BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() { |
532 int32_t focus_id = GetTreeData().focus_id; | 545 int32_t focus_id = GetTreeData().focus_id; |
533 BrowserAccessibility* obj = GetFromID(focus_id); | 546 BrowserAccessibility* obj = GetFromID(focus_id); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
889 tree_source(tree_->CreateTreeSource()); | 902 tree_source(tree_->CreateTreeSource()); |
890 ui::AXTreeSerializer<const ui::AXNode*, | 903 ui::AXTreeSerializer<const ui::AXNode*, |
891 ui::AXNodeData, | 904 ui::AXNodeData, |
892 ui::AXTreeData> serializer(tree_source.get()); | 905 ui::AXTreeData> serializer(tree_source.get()); |
893 ui::AXTreeUpdate update; | 906 ui::AXTreeUpdate update; |
894 serializer.SerializeChanges(tree_->root(), &update); | 907 serializer.SerializeChanges(tree_->root(), &update); |
895 return update; | 908 return update; |
896 } | 909 } |
897 | 910 |
898 } // namespace content | 911 } // namespace content |
OLD | NEW |