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 |