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 "ui/views/focus/focus_manager.h" | |
6 | |
7 #include <stddef.h> | 5 #include <stddef.h> |
8 | 6 |
9 #include "base/macros.h" | 7 #include "base/macros.h" |
10 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
11 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
13 #include "ui/base/models/combobox_model.h" | 11 #include "ui/base/models/combobox_model.h" |
14 #include "ui/views/background.h" | 12 #include "ui/views/background.h" |
15 #include "ui/views/border.h" | 13 #include "ui/views/border.h" |
16 #include "ui/views/controls/button/checkbox.h" | 14 #include "ui/views/controls/button/checkbox.h" |
17 #include "ui/views/controls/button/label_button.h" | 15 #include "ui/views/controls/button/label_button.h" |
18 #include "ui/views/controls/button/radio_button.h" | 16 #include "ui/views/controls/button/radio_button.h" |
19 #include "ui/views/controls/combobox/combobox.h" | 17 #include "ui/views/controls/combobox/combobox.h" |
20 #include "ui/views/controls/label.h" | 18 #include "ui/views/controls/label.h" |
21 #include "ui/views/controls/link.h" | 19 #include "ui/views/controls/link.h" |
22 #include "ui/views/controls/native/native_view_host.h" | 20 #include "ui/views/controls/native/native_view_host.h" |
23 #include "ui/views/controls/scroll_view.h" | 21 #include "ui/views/controls/scroll_view.h" |
24 #include "ui/views/controls/tabbed_pane/tabbed_pane.h" | 22 #include "ui/views/controls/tabbed_pane/tabbed_pane.h" |
25 #include "ui/views/controls/textfield/textfield.h" | 23 #include "ui/views/controls/textfield/textfield.h" |
| 24 #include "ui/views/focus/focus_manager.h" |
26 #include "ui/views/test/focus_manager_test.h" | 25 #include "ui/views/test/focus_manager_test.h" |
27 #include "ui/views/widget/root_view.h" | 26 #include "ui/views/widget/root_view.h" |
28 #include "ui/views/widget/widget.h" | 27 #include "ui/views/widget/widget.h" |
29 | 28 |
30 using base::ASCIIToUTF16; | 29 using base::ASCIIToUTF16; |
31 | 30 |
32 namespace views { | 31 namespace views { |
33 | 32 |
34 namespace { | 33 namespace { |
35 | 34 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 view = style_tab_->GetSelectedTab()->GetViewByID(id); | 194 view = style_tab_->GetSelectedTab()->GetViewByID(id); |
196 if (view) | 195 if (view) |
197 return view; | 196 return view; |
198 view = search_border_view_->GetContentsRootView()->GetViewByID(id); | 197 view = search_border_view_->GetContentsRootView()->GetViewByID(id); |
199 if (view) | 198 if (view) |
200 return view; | 199 return view; |
201 return NULL; | 200 return NULL; |
202 } | 201 } |
203 | 202 |
204 protected: | 203 protected: |
| 204 // Helper function to advance focus multiple times in a loop. |traversal_ids| |
| 205 // is an array of view ids of length |N|. |reverse| denotes the direction in |
| 206 // which focus should be advanced. |
| 207 template <size_t N> |
| 208 void AdvanceEntireFocusLoop(const int (&traversal_ids)[N], bool reverse) { |
| 209 for (size_t i = 0; i < 3; ++i) { |
| 210 for (size_t j = 0; j < N; j++) { |
| 211 SCOPED_TRACE(testing::Message() << "reverse:" << reverse << " i:" << i |
| 212 << " j:" << j); |
| 213 GetFocusManager()->AdvanceFocus(reverse); |
| 214 View* focused_view = GetFocusManager()->GetFocusedView(); |
| 215 EXPECT_NE(nullptr, focused_view); |
| 216 if (focused_view) |
| 217 EXPECT_EQ(traversal_ids[reverse ? N - j - 1 : j], focused_view->id()); |
| 218 } |
| 219 } |
| 220 } |
| 221 |
205 TabbedPane* style_tab_; | 222 TabbedPane* style_tab_; |
206 BorderView* search_border_view_; | 223 BorderView* search_border_view_; |
207 DummyComboboxModel combobox_model_; | 224 DummyComboboxModel combobox_model_; |
208 PaneView* left_container_; | 225 PaneView* left_container_; |
209 PaneView* right_container_; | 226 PaneView* right_container_; |
210 | 227 |
211 DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest); | 228 DISALLOW_COPY_AND_ASSIGN(FocusTraversalTest); |
212 }; | 229 }; |
213 | 230 |
214 FocusTraversalTest::FocusTraversalTest() | 231 FocusTraversalTest::FocusTraversalTest() |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID, | 587 kFruitButtonID, kFruitCheckBoxID, kComboboxID, kBroccoliButtonID, |
571 kRosettaLinkID, kStupeurEtTremblementLinkID, | 588 kRosettaLinkID, kStupeurEtTremblementLinkID, |
572 kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, | 589 kDinerGameLinkID, kRidiculeLinkID, kClosetLinkID, kVisitingLinkID, |
573 kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID, | 590 kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, kBriceDeNiceLinkID, |
574 kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID, | 591 kTaxiLinkID, kAsterixLinkID, kOKButtonID, kCancelButtonID, kHelpButtonID, |
575 kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID, | 592 kStyleContainerID, kBoldCheckBoxID, kItalicCheckBoxID, |
576 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID, | 593 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID, |
577 kSearchTextfieldID, kSearchButtonID, kHelpLinkID, | 594 kSearchTextfieldID, kSearchButtonID, kHelpLinkID, |
578 kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID }; | 595 kThumbnailContainerID, kThumbnailStarID, kThumbnailSuperStarID }; |
579 | 596 |
| 597 SCOPED_TRACE("NormalTraversal"); |
| 598 |
580 // Let's traverse the whole focus hierarchy (several times, to make sure it | 599 // Let's traverse the whole focus hierarchy (several times, to make sure it |
581 // loops OK). | 600 // loops OK). |
582 GetFocusManager()->ClearFocus(); | 601 GetFocusManager()->ClearFocus(); |
583 for (int i = 0; i < 3; ++i) { | 602 AdvanceEntireFocusLoop(kTraversalIDs, false); |
584 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { | |
585 GetFocusManager()->AdvanceFocus(false); | |
586 View* focused_view = GetFocusManager()->GetFocusedView(); | |
587 EXPECT_TRUE(focused_view != NULL); | |
588 if (focused_view) | |
589 EXPECT_EQ(kTraversalIDs[j], focused_view->id()); | |
590 } | |
591 } | |
592 | 603 |
593 // Let's traverse in reverse order. | 604 // Let's traverse in reverse order. |
594 GetFocusManager()->ClearFocus(); | 605 GetFocusManager()->ClearFocus(); |
595 for (int i = 0; i < 3; ++i) { | 606 AdvanceEntireFocusLoop(kTraversalIDs, true); |
596 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) { | |
597 GetFocusManager()->AdvanceFocus(true); | |
598 View* focused_view = GetFocusManager()->GetFocusedView(); | |
599 EXPECT_TRUE(focused_view != NULL); | |
600 if (focused_view) | |
601 EXPECT_EQ(kTraversalIDs[j], focused_view->id()); | |
602 } | |
603 } | |
604 } | 607 } |
605 | 608 |
| 609 #if defined(OS_MACOSX) |
| 610 // Test focus traversal with full keyboard access off on Mac. |
| 611 TEST_F(FocusTraversalTest, NormalTraversalMac) { |
| 612 GetFocusManager()->SetKeyboardAccessible(false); |
| 613 |
| 614 // Now only views with FocusBehavior of ALWAYS will be focusable. |
| 615 const int kTraversalIDs[] = {kAppleTextfieldID, kOrangeTextfieldID, |
| 616 kBananaTextfieldID, kKiwiTextfieldID, |
| 617 kStyleTextEditID, kSearchTextfieldID, |
| 618 kThumbnailContainerID}; |
| 619 |
| 620 SCOPED_TRACE("NormalTraversalMac"); |
| 621 |
| 622 // Let's traverse the whole focus hierarchy (several times, to make sure it |
| 623 // loops OK). |
| 624 GetFocusManager()->ClearFocus(); |
| 625 AdvanceEntireFocusLoop(kTraversalIDs, false); |
| 626 |
| 627 // Let's traverse in reverse order. |
| 628 GetFocusManager()->ClearFocus(); |
| 629 AdvanceEntireFocusLoop(kTraversalIDs, true); |
| 630 } |
| 631 |
| 632 // Test toggling full keyboard access correctly changes the focused view on Mac. |
| 633 TEST_F(FocusTraversalTest, FullKeyboardToggle) { |
| 634 // Give focus to kTopCheckBoxID . |
| 635 FindViewByID(kTopCheckBoxID)->RequestFocus(); |
| 636 EXPECT_EQ(kTopCheckBoxID, GetFocusManager()->GetFocusedView()->id()); |
| 637 |
| 638 // Turn off full keyboard access. Focus should move to next view with ALWAYS |
| 639 // focus behavior. |
| 640 GetFocusManager()->SetKeyboardAccessible(false); |
| 641 EXPECT_EQ(kAppleTextfieldID, GetFocusManager()->GetFocusedView()->id()); |
| 642 |
| 643 // Turning on full keyboard access should not change the focused view. |
| 644 GetFocusManager()->SetKeyboardAccessible(true); |
| 645 EXPECT_EQ(kAppleTextfieldID, GetFocusManager()->GetFocusedView()->id()); |
| 646 |
| 647 // Give focus to kSearchButtonID. |
| 648 FindViewByID(kSearchButtonID)->RequestFocus(); |
| 649 EXPECT_EQ(kSearchButtonID, GetFocusManager()->GetFocusedView()->id()); |
| 650 |
| 651 // Turn off full keyboard access. Focus should move to next view with ALWAYS |
| 652 // focus behavior. |
| 653 GetFocusManager()->SetKeyboardAccessible(false); |
| 654 EXPECT_EQ(kThumbnailContainerID, GetFocusManager()->GetFocusedView()->id()); |
| 655 |
| 656 // See focus advances correctly in both directions. |
| 657 GetFocusManager()->AdvanceFocus(false); |
| 658 EXPECT_EQ(kAppleTextfieldID, GetFocusManager()->GetFocusedView()->id()); |
| 659 |
| 660 GetFocusManager()->AdvanceFocus(true); |
| 661 EXPECT_EQ(kThumbnailContainerID, GetFocusManager()->GetFocusedView()->id()); |
| 662 } |
| 663 #endif // OS_MACOSX |
| 664 |
606 TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) { | 665 TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) { |
607 const int kDisabledIDs[] = { | 666 const int kDisabledIDs[] = { |
608 kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID, | 667 kBananaTextfieldID, kFruitCheckBoxID, kComboboxID, kAsparagusButtonID, |
609 kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID, | 668 kCauliflowerButtonID, kClosetLinkID, kVisitingLinkID, kBriceDeNiceLinkID, |
610 kTaxiLinkID, kAsterixLinkID, kHelpButtonID, kBoldCheckBoxID, | 669 kTaxiLinkID, kAsterixLinkID, kHelpButtonID, kBoldCheckBoxID, |
611 kSearchTextfieldID, kHelpLinkID }; | 670 kSearchTextfieldID, kHelpLinkID }; |
612 | 671 |
613 const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID, | 672 const int kTraversalIDs[] = { kTopCheckBoxID, kAppleTextfieldID, |
614 kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID, | 673 kOrangeTextfieldID, kKiwiTextfieldID, kFruitButtonID, kBroccoliButtonID, |
615 kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID, | 674 kRosettaLinkID, kStupeurEtTremblementLinkID, kDinerGameLinkID, |
616 kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, | 675 kRidiculeLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, kCampingLinkID, |
617 kOKButtonID, kCancelButtonID, kStyleContainerID, kItalicCheckBoxID, | 676 kOKButtonID, kCancelButtonID, kStyleContainerID, kItalicCheckBoxID, |
618 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID, | 677 kUnderlinedCheckBoxID, kStyleHelpLinkID, kStyleTextEditID, |
619 kSearchButtonID, kThumbnailContainerID, kThumbnailStarID, | 678 kSearchButtonID, kThumbnailContainerID, kThumbnailStarID, |
620 kThumbnailSuperStarID }; | 679 kThumbnailSuperStarID }; |
621 | 680 |
| 681 SCOPED_TRACE("TraversalWithNonEnabledViews"); |
| 682 |
622 // Let's disable some views. | 683 // Let's disable some views. |
623 for (size_t i = 0; i < arraysize(kDisabledIDs); i++) { | 684 for (size_t i = 0; i < arraysize(kDisabledIDs); i++) { |
624 View* v = FindViewByID(kDisabledIDs[i]); | 685 View* v = FindViewByID(kDisabledIDs[i]); |
625 ASSERT_TRUE(v != NULL); | 686 ASSERT_TRUE(v != NULL); |
626 v->SetEnabled(false); | 687 v->SetEnabled(false); |
627 } | 688 } |
628 | 689 |
629 View* focused_view; | |
630 // Let's do one traversal (several times, to make sure it loops ok). | 690 // Let's do one traversal (several times, to make sure it loops ok). |
631 GetFocusManager()->ClearFocus(); | 691 GetFocusManager()->ClearFocus(); |
632 for (int i = 0; i < 3; ++i) { | 692 AdvanceEntireFocusLoop(kTraversalIDs, false); |
633 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { | |
634 GetFocusManager()->AdvanceFocus(false); | |
635 focused_view = GetFocusManager()->GetFocusedView(); | |
636 EXPECT_TRUE(focused_view != NULL); | |
637 if (focused_view) | |
638 EXPECT_EQ(kTraversalIDs[j], focused_view->id()); | |
639 } | |
640 } | |
641 | 693 |
642 // Same thing in reverse. | 694 // Same thing in reverse. |
643 GetFocusManager()->ClearFocus(); | 695 GetFocusManager()->ClearFocus(); |
644 for (int i = 0; i < 3; ++i) { | 696 AdvanceEntireFocusLoop(kTraversalIDs, true); |
645 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) { | |
646 GetFocusManager()->AdvanceFocus(true); | |
647 focused_view = GetFocusManager()->GetFocusedView(); | |
648 EXPECT_TRUE(focused_view != NULL); | |
649 if (focused_view) | |
650 EXPECT_EQ(kTraversalIDs[j], focused_view->id()); | |
651 } | |
652 } | |
653 } | 697 } |
654 | 698 |
655 TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) { | 699 TEST_F(FocusTraversalTest, TraversalWithInvisibleViews) { |
656 const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID, | 700 const int kInvisibleIDs[] = { kTopCheckBoxID, kOKButtonID, |
657 kThumbnailContainerID }; | 701 kThumbnailContainerID }; |
658 | 702 |
659 const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID, | 703 const int kTraversalIDs[] = { kAppleTextfieldID, kOrangeTextfieldID, |
660 kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID, | 704 kBananaTextfieldID, kKiwiTextfieldID, kFruitButtonID, kFruitCheckBoxID, |
661 kComboboxID, kBroccoliButtonID, kRosettaLinkID, | 705 kComboboxID, kBroccoliButtonID, kRosettaLinkID, |
662 kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID, | 706 kStupeurEtTremblementLinkID, kDinerGameLinkID, kRidiculeLinkID, |
663 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, | 707 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, |
664 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID, | 708 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID, |
665 kCancelButtonID, kHelpButtonID, kStyleContainerID, kBoldCheckBoxID, | 709 kCancelButtonID, kHelpButtonID, kStyleContainerID, kBoldCheckBoxID, |
666 kItalicCheckBoxID, kUnderlinedCheckBoxID, kStyleHelpLinkID, | 710 kItalicCheckBoxID, kUnderlinedCheckBoxID, kStyleHelpLinkID, |
667 kStyleTextEditID, kSearchTextfieldID, kSearchButtonID, kHelpLinkID }; | 711 kStyleTextEditID, kSearchTextfieldID, kSearchButtonID, kHelpLinkID }; |
668 | 712 |
| 713 SCOPED_TRACE("TraversalWithInvisibleViews"); |
669 | 714 |
670 // Let's make some views invisible. | 715 // Let's make some views invisible. |
671 for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) { | 716 for (size_t i = 0; i < arraysize(kInvisibleIDs); i++) { |
672 View* v = FindViewByID(kInvisibleIDs[i]); | 717 View* v = FindViewByID(kInvisibleIDs[i]); |
673 ASSERT_TRUE(v != NULL); | 718 ASSERT_TRUE(v != NULL); |
674 v->SetVisible(false); | 719 v->SetVisible(false); |
675 } | 720 } |
676 | 721 |
677 View* focused_view; | |
678 // Let's do one traversal (several times, to make sure it loops ok). | 722 // Let's do one traversal (several times, to make sure it loops ok). |
679 GetFocusManager()->ClearFocus(); | 723 GetFocusManager()->ClearFocus(); |
680 for (int i = 0; i < 3; ++i) { | 724 AdvanceEntireFocusLoop(kTraversalIDs, false); |
681 for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { | |
682 GetFocusManager()->AdvanceFocus(false); | |
683 focused_view = GetFocusManager()->GetFocusedView(); | |
684 EXPECT_TRUE(focused_view != NULL); | |
685 if (focused_view) | |
686 EXPECT_EQ(kTraversalIDs[j], focused_view->id()); | |
687 } | |
688 } | |
689 | 725 |
690 // Same thing in reverse. | 726 // Same thing in reverse. |
691 GetFocusManager()->ClearFocus(); | 727 GetFocusManager()->ClearFocus(); |
692 for (int i = 0; i < 3; ++i) { | 728 AdvanceEntireFocusLoop(kTraversalIDs, true); |
693 for (int j = arraysize(kTraversalIDs) - 1; j >= 0; --j) { | |
694 GetFocusManager()->AdvanceFocus(true); | |
695 focused_view = GetFocusManager()->GetFocusedView(); | |
696 EXPECT_TRUE(focused_view != NULL); | |
697 if (focused_view) | |
698 EXPECT_EQ(kTraversalIDs[j], focused_view->id()); | |
699 } | |
700 } | |
701 } | 729 } |
702 | 730 |
703 TEST_F(FocusTraversalTest, PaneTraversal) { | 731 TEST_F(FocusTraversalTest, PaneTraversal) { |
704 // Tests trapping the traversal within a pane - useful for full | 732 // Tests trapping the traversal within a pane - useful for full |
705 // keyboard accessibility for toolbars. | 733 // keyboard accessibility for toolbars. |
706 | 734 |
707 // First test the left container. | 735 // First test the left container. |
708 const int kLeftTraversalIDs[] = { | 736 const int kLeftTraversalIDs[] = { |
709 kAppleTextfieldID, | 737 kAppleTextfieldID, |
710 kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID, | 738 kOrangeTextfieldID, kBananaTextfieldID, kKiwiTextfieldID, |
711 kFruitButtonID, kFruitCheckBoxID, kComboboxID }; | 739 kFruitButtonID, kFruitCheckBoxID, kComboboxID }; |
712 | 740 |
| 741 SCOPED_TRACE("PaneTraversal"); |
| 742 |
713 FocusSearch focus_search_left(left_container_, true, false); | 743 FocusSearch focus_search_left(left_container_, true, false); |
714 left_container_->EnablePaneFocus(&focus_search_left); | 744 left_container_->EnablePaneFocus(&focus_search_left); |
715 FindViewByID(kComboboxID)->RequestFocus(); | 745 FindViewByID(kComboboxID)->RequestFocus(); |
716 | 746 |
717 // Traverse the focus hierarchy within the pane several times. | 747 // Traverse the focus hierarchy within the pane several times. |
718 for (int i = 0; i < 3; ++i) { | 748 AdvanceEntireFocusLoop(kLeftTraversalIDs, false); |
719 for (size_t j = 0; j < arraysize(kLeftTraversalIDs); j++) { | |
720 GetFocusManager()->AdvanceFocus(false); | |
721 View* focused_view = GetFocusManager()->GetFocusedView(); | |
722 EXPECT_TRUE(focused_view != NULL); | |
723 if (focused_view) | |
724 EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id()); | |
725 } | |
726 } | |
727 | 749 |
728 // Traverse in reverse order. | 750 // Traverse in reverse order. |
729 FindViewByID(kAppleTextfieldID)->RequestFocus(); | 751 FindViewByID(kAppleTextfieldID)->RequestFocus(); |
730 for (int i = 0; i < 3; ++i) { | 752 AdvanceEntireFocusLoop(kLeftTraversalIDs, true); |
731 for (int j = arraysize(kLeftTraversalIDs) - 1; j >= 0; --j) { | |
732 GetFocusManager()->AdvanceFocus(true); | |
733 View* focused_view = GetFocusManager()->GetFocusedView(); | |
734 EXPECT_TRUE(focused_view != NULL); | |
735 if (focused_view) | |
736 EXPECT_EQ(kLeftTraversalIDs[j], focused_view->id()); | |
737 } | |
738 } | |
739 | 753 |
740 // Now test the right container, but this time with accessibility mode. | 754 // Now test the right container, but this time with accessibility mode. |
741 // Make some links not focusable, but mark one of them as | 755 // Make some links not focusable, but mark one of them as |
742 // "accessibility focusable", so it should show up in the traversal. | 756 // "accessibility focusable", so it should show up in the traversal. |
743 const int kRightTraversalIDs[] = { | 757 const int kRightTraversalIDs[] = { |
744 kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID, | 758 kBroccoliButtonID, kDinerGameLinkID, kRidiculeLinkID, |
745 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, | 759 kClosetLinkID, kVisitingLinkID, kAmelieLinkID, kJoyeuxNoelLinkID, |
746 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID }; | 760 kCampingLinkID, kBriceDeNiceLinkID, kTaxiLinkID, kAsterixLinkID }; |
747 | 761 |
748 FocusSearch focus_search_right(right_container_, true, true); | 762 FocusSearch focus_search_right(right_container_, true, true); |
749 right_container_->EnablePaneFocus(&focus_search_right); | 763 right_container_->EnablePaneFocus(&focus_search_right); |
750 FindViewByID(kRosettaLinkID)->SetFocusBehavior(View::FocusBehavior::NEVER); | 764 FindViewByID(kRosettaLinkID)->SetFocusBehavior(View::FocusBehavior::NEVER); |
751 FindViewByID(kStupeurEtTremblementLinkID) | 765 FindViewByID(kStupeurEtTremblementLinkID) |
752 ->SetFocusBehavior(View::FocusBehavior::NEVER); | 766 ->SetFocusBehavior(View::FocusBehavior::NEVER); |
753 FindViewByID(kDinerGameLinkID) | 767 FindViewByID(kDinerGameLinkID) |
754 ->SetFocusBehavior(View::FocusBehavior::ACCESSIBLE_ONLY); | 768 ->SetFocusBehavior(View::FocusBehavior::ACCESSIBLE_ONLY); |
755 FindViewByID(kAsterixLinkID)->RequestFocus(); | 769 FindViewByID(kAsterixLinkID)->RequestFocus(); |
756 | 770 |
757 // Traverse the focus hierarchy within the pane several times. | 771 // Traverse the focus hierarchy within the pane several times. |
758 for (int i = 0; i < 3; ++i) { | 772 AdvanceEntireFocusLoop(kRightTraversalIDs, false); |
759 for (size_t j = 0; j < arraysize(kRightTraversalIDs); j++) { | |
760 GetFocusManager()->AdvanceFocus(false); | |
761 View* focused_view = GetFocusManager()->GetFocusedView(); | |
762 EXPECT_TRUE(focused_view != NULL); | |
763 if (focused_view) | |
764 EXPECT_EQ(kRightTraversalIDs[j], focused_view->id()); | |
765 } | |
766 } | |
767 | 773 |
768 // Traverse in reverse order. | 774 // Traverse in reverse order. |
769 FindViewByID(kBroccoliButtonID)->RequestFocus(); | 775 FindViewByID(kBroccoliButtonID)->RequestFocus(); |
770 for (int i = 0; i < 3; ++i) { | 776 AdvanceEntireFocusLoop(kRightTraversalIDs, true); |
771 for (int j = arraysize(kRightTraversalIDs) - 1; j >= 0; --j) { | |
772 GetFocusManager()->AdvanceFocus(true); | |
773 View* focused_view = GetFocusManager()->GetFocusedView(); | |
774 EXPECT_TRUE(focused_view != NULL); | |
775 if (focused_view) | |
776 EXPECT_EQ(kRightTraversalIDs[j], focused_view->id()); | |
777 } | |
778 } | |
779 } | 777 } |
780 | 778 |
781 class FocusTraversalNonFocusableTest : public FocusManagerTest { | 779 class FocusTraversalNonFocusableTest : public FocusManagerTest { |
782 public: | 780 public: |
783 ~FocusTraversalNonFocusableTest() override {} | 781 ~FocusTraversalNonFocusableTest() override {} |
784 | 782 |
785 void InitContentView() override; | 783 void InitContentView() override; |
786 | 784 |
787 protected: | 785 protected: |
788 FocusTraversalNonFocusableTest() {} | 786 FocusTraversalNonFocusableTest() {} |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 GetFocusManager()->AdvanceFocus(false); | 845 GetFocusManager()->AdvanceFocus(false); |
848 EXPECT_FALSE(GetFocusManager()->GetFocusedView()); | 846 EXPECT_FALSE(GetFocusManager()->GetFocusedView()); |
849 | 847 |
850 // Advance backwards from the root node. | 848 // Advance backwards from the root node. |
851 GetFocusManager()->ClearFocus(); | 849 GetFocusManager()->ClearFocus(); |
852 GetFocusManager()->AdvanceFocus(true); | 850 GetFocusManager()->AdvanceFocus(true); |
853 EXPECT_FALSE(GetFocusManager()->GetFocusedView()); | 851 EXPECT_FALSE(GetFocusManager()->GetFocusedView()); |
854 } | 852 } |
855 | 853 |
856 } // namespace views | 854 } // namespace views |
OLD | NEW |