Chromium Code Reviews| 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 |