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/controls/scroll_view.h" | 5 #include "ui/views/controls/scroll_view.h" |
| 6 | 6 |
| 7 #include "base/macros.h" | 7 #include "base/macros.h" |
| 8 #include "base/run_loop.h" | 8 #include "base/run_loop.h" |
| 9 #include "base/test/test_timeouts.h" | 9 #include "base/test/test_timeouts.h" |
| 10 #include "base/threading/thread_task_runner_handle.h" | 10 #include "base/threading/thread_task_runner_handle.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | |
| 13 #include "ui/events/test/event_generator.h" | |
| 12 #include "ui/views/border.h" | 14 #include "ui/views/border.h" |
| 13 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h" | 15 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h" |
| 14 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" | 16 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" |
| 15 #include "ui/views/controls/scrollbar/scroll_bar_views.h" | 17 #include "ui/views/controls/scrollbar/scroll_bar_views.h" |
| 16 #include "ui/views/test/test_views.h" | 18 #include "ui/views/test/test_views.h" |
| 17 #include "ui/views/test/widget_test.h" | 19 #include "ui/views/test/widget_test.h" |
| 18 | 20 |
| 19 #if defined(OS_MACOSX) | 21 #if defined(OS_MACOSX) |
| 20 #include "ui/base/test/scoped_preferred_scroller_style_mac.h" | 22 #include "ui/base/test/scoped_preferred_scroller_style_mac.h" |
| 21 #endif | 23 #endif |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 43 BaseScrollBarThumb* GetScrollBarThumb(ScrollBarOrientation orientation) { | 45 BaseScrollBarThumb* GetScrollBarThumb(ScrollBarOrientation orientation) { |
| 44 return GetBaseScrollBar(orientation)->thumb_; | 46 return GetBaseScrollBar(orientation)->thumb_; |
| 45 } | 47 } |
| 46 | 48 |
| 47 gfx::Point IntegralViewOffset() { | 49 gfx::Point IntegralViewOffset() { |
| 48 return gfx::Point() - gfx::ScrollOffsetToFlooredVector2d(CurrentOffset()); | 50 return gfx::Point() - gfx::ScrollOffsetToFlooredVector2d(CurrentOffset()); |
| 49 } | 51 } |
| 50 | 52 |
| 51 gfx::ScrollOffset CurrentOffset() { return scroll_view_->CurrentOffset(); } | 53 gfx::ScrollOffset CurrentOffset() { return scroll_view_->CurrentOffset(); } |
| 52 | 54 |
| 55 base::Timer* GetScrollBarHideTimer(ScrollBarOrientation orientation) { | |
| 56 return BaseScrollBar::GetHideTimerForTest(GetBaseScrollBar(orientation)); | |
| 57 } | |
| 58 | |
| 53 View* corner_view() { return scroll_view_->corner_view_; } | 59 View* corner_view() { return scroll_view_->corner_view_; } |
| 54 View* contents_viewport() { return scroll_view_->contents_viewport_; } | 60 View* contents_viewport() { return scroll_view_->contents_viewport_; } |
| 55 | 61 |
| 56 private: | 62 private: |
| 57 ScrollView* scroll_view_; | 63 ScrollView* scroll_view_; |
| 58 | 64 |
| 59 DISALLOW_COPY_AND_ASSIGN(ScrollViewTestApi); | 65 DISALLOW_COPY_AND_ASSIGN(ScrollViewTestApi); |
| 60 }; | 66 }; |
| 61 | 67 |
| 62 } // namespace test | 68 } // namespace test |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 DISALLOW_COPY_AND_ASSIGN(ScrollViewTest); | 172 DISALLOW_COPY_AND_ASSIGN(ScrollViewTest); |
| 167 }; | 173 }; |
| 168 | 174 |
| 169 // Test harness that includes a Widget to help test ui::Event handling. | 175 // Test harness that includes a Widget to help test ui::Event handling. |
| 170 class WidgetScrollViewTest : public test::WidgetTest, | 176 class WidgetScrollViewTest : public test::WidgetTest, |
| 171 public ui::CompositorObserver { | 177 public ui::CompositorObserver { |
| 172 public: | 178 public: |
| 173 static const int kDefaultHeight = 100; | 179 static const int kDefaultHeight = 100; |
| 174 static const int kDefaultWidth = 100; | 180 static const int kDefaultWidth = 100; |
| 175 | 181 |
| 176 WidgetScrollViewTest() { | 182 WidgetScrollViewTest() {} |
| 177 #if defined(OS_MACOSX) | 183 |
| 178 // Disable scrollbar hiding (i.e. disable overlay scrollbars) by default. | 184 // Call this before adding the ScrollView to test with overlay scroll bars. |
|
spqchan
2016/11/14 23:27:58
"scroll bars" -> "scrollbars"
tapted
2016/11/15 12:22:23
Done.
| |
| 179 scroller_style_.reset(new ui::test::ScopedPreferredScrollerStyle(false)); | 185 void SetUseOverlayScrollers() { |
| 180 #endif | 186 use_overlay_scrollers_ = true; |
| 181 } | 187 } |
| 182 | 188 |
| 183 // Adds a ScrollView with the given |contents_view| and does layout. | 189 // Adds a ScrollView with the given |contents_view| and does layout. |
| 184 ScrollView* AddScrollViewWithContents(View* contents, | 190 ScrollView* AddScrollViewWithContents(View* contents, |
| 185 bool commit_layers = true) { | 191 bool commit_layers = true) { |
| 192 #if defined(OS_MACOSX) | |
| 193 scroller_style_.reset( | |
| 194 new ui::test::ScopedPreferredScrollerStyle(use_overlay_scrollers_)); | |
| 195 #endif | |
| 196 | |
| 186 const gfx::Rect default_bounds(50, 50, kDefaultWidth, kDefaultHeight); | 197 const gfx::Rect default_bounds(50, 50, kDefaultWidth, kDefaultHeight); |
| 187 widget_ = CreateTopLevelFramelessPlatformWidget(); | 198 widget_ = CreateTopLevelFramelessPlatformWidget(); |
| 188 | 199 |
| 189 ScrollView* scroll_view = new ScrollView(); | 200 ScrollView* scroll_view = new ScrollView(); |
| 190 scroll_view->SetContents(contents); | 201 scroll_view->SetContents(contents); |
| 191 | 202 |
| 192 widget_->SetBounds(default_bounds); | 203 widget_->SetBounds(default_bounds); |
| 193 widget_->Show(); | 204 widget_->Show(); |
| 194 | 205 |
| 195 widget_->SetContentsView(scroll_view); | 206 widget_->SetContentsView(scroll_view); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 quit_closure_.Reset(); | 257 quit_closure_.Reset(); |
| 247 } | 258 } |
| 248 void OnCompositingStarted(ui::Compositor* compositor, | 259 void OnCompositingStarted(ui::Compositor* compositor, |
| 249 base::TimeTicks start_time) override {} | 260 base::TimeTicks start_time) override {} |
| 250 void OnCompositingEnded(ui::Compositor* compositor) override {} | 261 void OnCompositingEnded(ui::Compositor* compositor) override {} |
| 251 void OnCompositingLockStateChanged(ui::Compositor* compositor) override {} | 262 void OnCompositingLockStateChanged(ui::Compositor* compositor) override {} |
| 252 void OnCompositingShuttingDown(ui::Compositor* compositor) override {} | 263 void OnCompositingShuttingDown(ui::Compositor* compositor) override {} |
| 253 | 264 |
| 254 Widget* widget_ = nullptr; | 265 Widget* widget_ = nullptr; |
| 255 | 266 |
| 267 // Disable scrollbar hiding (i.e. disable overlay scrollbars) by default. | |
| 268 bool use_overlay_scrollers_ = false; | |
| 269 | |
| 256 base::Closure quit_closure_; | 270 base::Closure quit_closure_; |
| 257 | 271 |
| 258 #if defined(OS_MACOSX) | 272 #if defined(OS_MACOSX) |
| 259 std::unique_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_; | 273 std::unique_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_; |
| 260 #endif | 274 #endif |
| 261 | 275 |
| 262 DISALLOW_COPY_AND_ASSIGN(WidgetScrollViewTest); | 276 DISALLOW_COPY_AND_ASSIGN(WidgetScrollViewTest); |
| 263 }; | 277 }; |
| 264 | 278 |
| 265 const int WidgetScrollViewTest::kDefaultHeight; | 279 const int WidgetScrollViewTest::kDefaultHeight; |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 731 // Switch to the non-overlay style and check that the ViewPort is now sized | 745 // Switch to the non-overlay style and check that the ViewPort is now sized |
| 732 // to be smaller, and ScrollbarWidth and ScrollbarHeight are non-zero. | 746 // to be smaller, and ScrollbarWidth and ScrollbarHeight are non-zero. |
| 733 SetOverlayScrollersEnabled(false); | 747 SetOverlayScrollersEnabled(false); |
| 734 EXPECT_EQ(100 - scroll_view_.GetScrollBarWidth(), | 748 EXPECT_EQ(100 - scroll_view_.GetScrollBarWidth(), |
| 735 contents->parent()->width()); | 749 contents->parent()->width()); |
| 736 EXPECT_EQ(100 - scroll_view_.GetScrollBarHeight(), | 750 EXPECT_EQ(100 - scroll_view_.GetScrollBarHeight(), |
| 737 contents->parent()->height()); | 751 contents->parent()->height()); |
| 738 EXPECT_NE(0, scroll_view_.GetScrollBarWidth()); | 752 EXPECT_NE(0, scroll_view_.GetScrollBarWidth()); |
| 739 EXPECT_NE(0, scroll_view_.GetScrollBarHeight()); | 753 EXPECT_NE(0, scroll_view_.GetScrollBarHeight()); |
| 740 } | 754 } |
| 741 #endif | 755 |
| 756 // Test overlay scrollbar behavior when just resting fingers on the trackpad. | |
| 757 TEST_F(WidgetScrollViewTest, ScrollersOnRest) { | |
| 758 // Allow expectations to distinguish between fade outs and immediate changes. | |
| 759 ui::ScopedAnimationDurationScaleMode really_animate( | |
| 760 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); | |
| 761 | |
| 762 const float kMaxOpacity = 0.8f; // Constant from cocoa_scroll_bar.mm. | |
| 763 | |
| 764 SetUseOverlayScrollers(); | |
| 765 | |
| 766 // Set up with both scrollers. | |
| 767 ScrollView* scroll_view = AddScrollViewWithContentSize( | |
| 768 gfx::Size(kDefaultWidth * 5, kDefaultHeight * 5)); | |
| 769 ScrollViewTestApi test_api(scroll_view); | |
| 770 BaseScrollBar* bar[]{test_api.GetBaseScrollBar(HORIZONTAL), | |
| 771 test_api.GetBaseScrollBar(VERTICAL)}; | |
| 772 base::Timer* hide_timer[]{test_api.GetScrollBarHideTimer(HORIZONTAL), | |
| 773 test_api.GetScrollBarHideTimer(VERTICAL)}; | |
| 774 | |
| 775 EXPECT_EQ(0, bar[HORIZONTAL]->layer()->opacity()); | |
| 776 EXPECT_EQ(0, bar[VERTICAL]->layer()->opacity()); | |
| 777 | |
| 778 ui::test::EventGenerator generator( | |
| 779 GetContext(), scroll_view->GetWidget()->GetNativeWindow()); | |
| 780 | |
| 781 generator.TrackpadRest(); | |
| 782 // Scrollers should be max opacity without an animation. | |
| 783 EXPECT_EQ(kMaxOpacity, bar[HORIZONTAL]->layer()->opacity()); | |
| 784 EXPECT_EQ(kMaxOpacity, bar[VERTICAL]->layer()->opacity()); | |
| 785 EXPECT_FALSE(hide_timer[HORIZONTAL]->IsRunning()); | |
| 786 EXPECT_FALSE(hide_timer[VERTICAL]->IsRunning()); | |
| 787 | |
| 788 generator.CancelTrackpadRest(); | |
| 789 // Scrollers should start fading out, but only after a delay. | |
| 790 for (ScrollBarOrientation orientation : {HORIZONTAL, VERTICAL}) { | |
| 791 EXPECT_EQ(kMaxOpacity, bar[orientation]->layer()->GetTargetOpacity()); | |
| 792 EXPECT_TRUE(hide_timer[orientation]->IsRunning()); | |
| 793 // Trigger the timer. Should then be fading out. | |
| 794 hide_timer[orientation]->user_task().Run(); | |
| 795 hide_timer[orientation]->Stop(); | |
| 796 EXPECT_EQ(0, bar[orientation]->layer()->GetTargetOpacity()); | |
| 797 } | |
| 798 | |
| 799 // Rest again. | |
| 800 generator.TrackpadRest(); | |
| 801 EXPECT_EQ(kMaxOpacity, bar[HORIZONTAL]->layer()->GetTargetOpacity()); | |
| 802 EXPECT_EQ(kMaxOpacity, bar[VERTICAL]->layer()->GetTargetOpacity()); | |
| 803 | |
| 804 // Scroll vertically. | |
| 805 const float y_offset = 3; | |
| 806 const int kSteps = 1; | |
| 807 const int kNnumFingers = 2; | |
| 808 generator.ScrollSequence(generator.current_location(), base::TimeDelta(), 0, | |
| 809 y_offset, kSteps, kNnumFingers); | |
| 810 | |
| 811 // Horizontal scroller should start fading out immediately. | |
| 812 EXPECT_EQ(kMaxOpacity, bar[HORIZONTAL]->layer()->opacity()); | |
| 813 EXPECT_EQ(0, bar[HORIZONTAL]->layer()->GetTargetOpacity()); | |
| 814 EXPECT_FALSE(hide_timer[HORIZONTAL]->IsRunning()); | |
| 815 | |
| 816 // Vertical should remain visible, but ready to fade out after a delay. | |
| 817 EXPECT_EQ(kMaxOpacity, bar[VERTICAL]->layer()->opacity()); | |
| 818 EXPECT_EQ(kMaxOpacity, bar[VERTICAL]->layer()->GetTargetOpacity()); | |
| 819 EXPECT_TRUE(hide_timer[VERTICAL]->IsRunning()); | |
| 820 | |
| 821 // Scrolling should have occurred. | |
| 822 EXPECT_EQ(gfx::ScrollOffset(0, y_offset), test_api.CurrentOffset()); | |
| 823 | |
| 824 // Then, scrolling horizontally should show the horizontal scroller. The | |
| 825 // vertical scroller should still be visible, running its hide timer. | |
| 826 const float x_offset = 5; | |
| 827 generator.ScrollSequence(generator.current_location(), base::TimeDelta(), | |
| 828 x_offset, 0, kSteps, kNnumFingers); | |
| 829 for (ScrollBarOrientation orientation : {HORIZONTAL, VERTICAL}) { | |
| 830 EXPECT_EQ(kMaxOpacity, bar[orientation]->layer()->opacity()); | |
| 831 EXPECT_EQ(kMaxOpacity, bar[orientation]->layer()->GetTargetOpacity()); | |
| 832 EXPECT_TRUE(hide_timer[orientation]->IsRunning()); | |
| 833 } | |
| 834 | |
| 835 // Now scrolling has occurred in both directions. | |
| 836 EXPECT_EQ(gfx::ScrollOffset(x_offset, y_offset), test_api.CurrentOffset()); | |
| 837 } | |
| 838 | |
| 839 #endif // OS_MACOSX | |
| 742 | 840 |
| 743 // Test that increasing the size of the viewport "below" scrolled content causes | 841 // Test that increasing the size of the viewport "below" scrolled content causes |
| 744 // the content to scroll up so that it still fills the viewport. | 842 // the content to scroll up so that it still fills the viewport. |
| 745 TEST_F(ScrollViewTest, ConstrainScrollToBounds) { | 843 TEST_F(ScrollViewTest, ConstrainScrollToBounds) { |
| 746 ScrollViewTestApi test_api(&scroll_view_); | 844 ScrollViewTestApi test_api(&scroll_view_); |
| 747 | 845 |
| 748 View* contents = InstallContents(); | 846 View* contents = InstallContents(); |
| 749 contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); | 847 contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); |
| 750 scroll_view_.Layout(); | 848 scroll_view_.Layout(); |
| 751 | 849 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 888 // Scroll via ScrollView API. Should be reflected on the impl side. | 986 // Scroll via ScrollView API. Should be reflected on the impl side. |
| 889 offset.set_y(kDefaultHeight * 4); | 987 offset.set_y(kDefaultHeight * 4); |
| 890 scroll_view->contents()->ScrollRectToVisible(offset); | 988 scroll_view->contents()->ScrollRectToVisible(offset); |
| 891 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), test_api.CurrentOffset()); | 989 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), test_api.CurrentOffset()); |
| 892 | 990 |
| 893 EXPECT_TRUE(compositor->GetScrollOffsetForLayer(layer_id, &impl_offset)); | 991 EXPECT_TRUE(compositor->GetScrollOffsetForLayer(layer_id, &impl_offset)); |
| 894 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), impl_offset); | 992 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), impl_offset); |
| 895 } | 993 } |
| 896 | 994 |
| 897 } // namespace views | 995 } // namespace views |
| OLD | NEW |