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