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