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