Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: ui/views/controls/scroll_view_unittest.cc

Issue 2188133002: Scroll with Layers in views::ScrollView (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@20160728-MacViews-ScrollTrack
Patch Set: bugref, scale_delta DCHECK + comment Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/controls/scroll_view.cc ('k') | ui/views/view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
9 #include "base/test/test_timeouts.h"
10 #include "base/threading/thread_task_runner_handle.h"
8 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/views/border.h" 12 #include "ui/views/border.h"
10 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h" 13 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
11 #include "ui/views/controls/scrollbar/native_scroll_bar.h" 14 #include "ui/views/controls/scrollbar/native_scroll_bar.h"
12 #include "ui/views/controls/scrollbar/native_scroll_bar_views.h" 15 #include "ui/views/controls/scrollbar/native_scroll_bar_views.h"
13 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" 16 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
14 #include "ui/views/test/test_views.h" 17 #include "ui/views/test/test_views.h"
15 #include "ui/views/test/widget_test.h" 18 #include "ui/views/test/widget_test.h"
16 19
17 #if defined(OS_MACOSX) 20 #if defined(OS_MACOSX)
(...skipping 21 matching lines...) Expand all
39 } 42 }
40 43
41 const base::Timer& GetScrollBarTimer(ScrollBarOrientation orientation) { 44 const base::Timer& GetScrollBarTimer(ScrollBarOrientation orientation) {
42 return GetBaseScrollBar(orientation)->repeater_.timer_for_testing(); 45 return GetBaseScrollBar(orientation)->repeater_.timer_for_testing();
43 } 46 }
44 47
45 BaseScrollBarThumb* GetScrollBarThumb(ScrollBarOrientation orientation) { 48 BaseScrollBarThumb* GetScrollBarThumb(ScrollBarOrientation orientation) {
46 return GetBaseScrollBar(orientation)->thumb_; 49 return GetBaseScrollBar(orientation)->thumb_;
47 } 50 }
48 51
52 gfx::Point IntegralViewOffset() {
53 return gfx::Point() - gfx::ScrollOffsetToFlooredVector2d(CurrentOffset());
54 }
55
56 gfx::ScrollOffset CurrentOffset() { return scroll_view_->CurrentOffset(); }
57
49 View* corner_view() { return scroll_view_->corner_view_; } 58 View* corner_view() { return scroll_view_->corner_view_; }
59 View* contents_viewport() { return scroll_view_->contents_viewport_; }
50 60
51 private: 61 private:
52 ScrollView* scroll_view_; 62 ScrollView* scroll_view_;
53 63
54 DISALLOW_COPY_AND_ASSIGN(ScrollViewTestApi); 64 DISALLOW_COPY_AND_ASSIGN(ScrollViewTestApi);
55 }; 65 };
56 66
57 } // namespace test 67 } // namespace test
58 68
59 namespace { 69 namespace {
60 70
61 const int kWidth = 100; 71 const int kWidth = 100;
62 const int kMinHeight = 50; 72 const int kMinHeight = 50;
63 const int kMaxHeight = 100; 73 const int kMaxHeight = 100;
64 74
65 // View implementation that allows setting the preferred size. 75 // View implementation that allows setting the preferred size.
66 class CustomView : public View { 76 class CustomView : public View {
67 public: 77 public:
68 CustomView() {} 78 CustomView() {}
69 79
70 void SetPreferredSize(const gfx::Size& size) { 80 void SetPreferredSize(const gfx::Size& size) {
71 preferred_size_ = size; 81 preferred_size_ = size;
72 PreferredSizeChanged(); 82 PreferredSizeChanged();
73 } 83 }
74 84
85 const gfx::Point last_location() const { return last_location_; }
86
75 gfx::Size GetPreferredSize() const override { return preferred_size_; } 87 gfx::Size GetPreferredSize() const override { return preferred_size_; }
76 88
77 void Layout() override { 89 void Layout() override {
78 gfx::Size pref = GetPreferredSize(); 90 gfx::Size pref = GetPreferredSize();
79 int width = pref.width(); 91 int width = pref.width();
80 int height = pref.height(); 92 int height = pref.height();
81 if (parent()) { 93 if (parent()) {
82 width = std::max(parent()->width(), width); 94 width = std::max(parent()->width(), width);
83 height = std::max(parent()->height(), height); 95 height = std::max(parent()->height(), height);
84 } 96 }
85 SetBounds(x(), y(), width, height); 97 SetBounds(x(), y(), width, height);
86 } 98 }
87 99
100 bool OnMousePressed(const ui::MouseEvent& event) override {
101 last_location_ = event.location();
102 return true;
103 }
104
88 private: 105 private:
89 gfx::Size preferred_size_; 106 gfx::Size preferred_size_;
107 gfx::Point last_location_;
90 108
91 DISALLOW_COPY_AND_ASSIGN(CustomView); 109 DISALLOW_COPY_AND_ASSIGN(CustomView);
92 }; 110 };
93 111
94 void CheckScrollbarVisibility(const ScrollView& scroll_view, 112 void CheckScrollbarVisibility(const ScrollView& scroll_view,
95 ScrollBarOrientation orientation, 113 ScrollBarOrientation orientation,
96 bool should_be_visible) { 114 bool should_be_visible) {
97 const ScrollBar* scrollbar = orientation == HORIZONTAL 115 const ScrollBar* scrollbar = orientation == HORIZONTAL
98 ? scroll_view.horizontal_scroll_bar() 116 ? scroll_view.horizontal_scroll_bar()
99 : scroll_view.vertical_scroll_bar(); 117 : scroll_view.vertical_scroll_bar();
100 if (should_be_visible) { 118 if (should_be_visible) {
101 ASSERT_TRUE(scrollbar); 119 ASSERT_TRUE(scrollbar);
102 EXPECT_TRUE(scrollbar->visible()); 120 EXPECT_TRUE(scrollbar->visible());
103 } else { 121 } else {
104 EXPECT_TRUE(!scrollbar || !scrollbar->visible()); 122 EXPECT_TRUE(!scrollbar || !scrollbar->visible());
105 } 123 }
106 } 124 }
107 125
108 ui::MouseEvent TestLeftMouseAt(const gfx::Point& location, ui::EventType type) { 126 ui::MouseEvent TestLeftMouseAt(const gfx::Point& location, ui::EventType type) {
109 return ui::MouseEvent(type, location, location, base::TimeTicks(), 127 return ui::MouseEvent(type, location, location, base::TimeTicks(),
110 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 128 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
111 } 129 }
112 130
113 } // namespace 131 } // namespace
114 132
115 using test::ScrollViewTestApi; 133 using test::ScrollViewTestApi;
116 134
117 // Test harness that includes a Widget to help test ui::Event handling. 135 // Test harness that includes a Widget to help test ui::Event handling.
118 class WidgetScrollViewTest : public test::WidgetTest { 136 class WidgetScrollViewTest : public test::WidgetTest,
137 public ui::CompositorObserver {
119 public: 138 public:
120 static const int kDefaultHeight = 100; 139 static const int kDefaultHeight = 100;
121 static const int kDefaultWidth = 100; 140 static const int kDefaultWidth = 100;
122 141
123 WidgetScrollViewTest() { 142 WidgetScrollViewTest() {
124 #if defined(OS_MACOSX) 143 #if defined(OS_MACOSX)
125 // Disable scrollbar hiding (i.e. disable overlay scrollbars) by default. 144 // Disable scrollbar hiding (i.e. disable overlay scrollbars) by default.
126 scroller_style_.reset(new ui::test::ScopedPreferredScrollerStyle(false)); 145 scroller_style_.reset(new ui::test::ScopedPreferredScrollerStyle(false));
127 #endif 146 #endif
128 } 147 }
129 148
130 // Adds a ScrollView with a contents view of the given |size| and does layout. 149 // Adds a ScrollView with the given |contents_view| and does layout.
131 ScrollView* AddScrollViewWithContentSize(const gfx::Size& contents_size) { 150 ScrollView* AddScrollViewWithContents(View* contents,
151 bool commit_layers = true) {
132 const gfx::Rect default_bounds(50, 50, kDefaultWidth, kDefaultHeight); 152 const gfx::Rect default_bounds(50, 50, kDefaultWidth, kDefaultHeight);
133 widget_ = CreateTopLevelFramelessPlatformWidget(); 153 widget_ = CreateTopLevelFramelessPlatformWidget();
134 154
135 ScrollView* scroll_view = new ScrollView(); 155 ScrollView* scroll_view = new ScrollView();
136 View* contents = new View;
137 scroll_view->SetContents(contents); 156 scroll_view->SetContents(contents);
138 contents->SetSize(contents_size);
139 157
140 widget_->SetBounds(default_bounds); 158 widget_->SetBounds(default_bounds);
141 widget_->Show(); 159 widget_->Show();
142 160
143 widget_->SetContentsView(scroll_view); 161 widget_->SetContentsView(scroll_view);
144 scroll_view->Layout(); 162 scroll_view->Layout();
163
164 widget_->GetCompositor()->AddObserver(this);
165
166 // Ensure the Compositor has committed layer changes before attempting to
167 // use them for impl-side scrolling. Note that simply RunUntilIdle() works
168 // when tests are run in isolation, but compositor scheduling can interact
169 // between test runs in the general case.
170 if (commit_layers)
171 WaitForCommit();
145 return scroll_view; 172 return scroll_view;
146 } 173 }
147 174
175 // Adds a ScrollView with a contents view of the given |size| and does layout.
176 ScrollView* AddScrollViewWithContentSize(const gfx::Size& contents_size,
177 bool commit_layers = true) {
178 View* contents = new View;
179 contents->SetSize(contents_size);
180 return AddScrollViewWithContents(contents, commit_layers);
181 }
182
183 // Wait for a commit to be observed on the compositor.
184 void WaitForCommit() {
185 base::RunLoop run_loop;
186 quit_closure_ = run_loop.QuitClosure();
187 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
188 FROM_HERE, quit_closure_, TestTimeouts::action_timeout());
189 run_loop.Run();
190 EXPECT_TRUE(quit_closure_.is_null()) << "Timed out waiting for a commit.";
191 }
192
193 void TestClickAt(const gfx::Point& location) {
194 ui::MouseEvent press(TestLeftMouseAt(location, ui::ET_MOUSE_PRESSED));
195 ui::MouseEvent release(TestLeftMouseAt(location, ui::ET_MOUSE_RELEASED));
196 widget_->OnMouseEvent(&press);
197 widget_->OnMouseEvent(&release);
198 }
199
148 // testing::Test: 200 // testing::Test:
149 void TearDown() override { 201 void TearDown() override {
202 widget_->GetCompositor()->RemoveObserver(this);
150 if (widget_) 203 if (widget_)
151 widget_->CloseNow(); 204 widget_->CloseNow();
152 WidgetTest::TearDown(); 205 WidgetTest::TearDown();
153 } 206 }
154 207
155 private: 208 private:
209 // ui::CompositorObserver:
210 void OnCompositingDidCommit(ui::Compositor* compositor) override {
211 quit_closure_.Run();
212 quit_closure_.Reset();
213 }
214 void OnCompositingStarted(ui::Compositor* compositor,
215 base::TimeTicks start_time) override {}
216 void OnCompositingEnded(ui::Compositor* compositor) override {}
217 void OnCompositingAborted(ui::Compositor* compositor) override {}
218 void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
219 void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
220
156 Widget* widget_ = nullptr; 221 Widget* widget_ = nullptr;
157 222
223 base::Closure quit_closure_;
224
158 #if defined(OS_MACOSX) 225 #if defined(OS_MACOSX)
159 std::unique_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_; 226 std::unique_ptr<ui::test::ScopedPreferredScrollerStyle> scroller_style_;
160 #endif 227 #endif
161 228
162 DISALLOW_COPY_AND_ASSIGN(WidgetScrollViewTest); 229 DISALLOW_COPY_AND_ASSIGN(WidgetScrollViewTest);
163 }; 230 };
164 231
165 const int WidgetScrollViewTest::kDefaultHeight; 232 const int WidgetScrollViewTest::kDefaultHeight;
166 const int WidgetScrollViewTest::kDefaultWidth; 233 const int WidgetScrollViewTest::kDefaultWidth;
167 234
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 scroll_view.SetHeader(header); 364 scroll_view.SetHeader(header);
298 View* header_parent = header->parent(); 365 View* header_parent = header->parent();
299 scroll_view.SetContents(contents); 366 scroll_view.SetContents(contents);
300 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); 367 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
301 scroll_view.Layout(); 368 scroll_view.Layout();
302 // |header|s preferred size is empty, which should result in all space going 369 // |header|s preferred size is empty, which should result in all space going
303 // to contents. 370 // to contents.
304 EXPECT_EQ("0,0 100x0", header->parent()->bounds().ToString()); 371 EXPECT_EQ("0,0 100x0", header->parent()->bounds().ToString());
305 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString()); 372 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
306 373
374 // With layered scrolling, ScrollView::Layout() will impose a size on the
375 // contents that fills the viewport. Since the test view doesn't have its own
376 // Layout, reset it in this case so that adding a header doesn't shift the
377 // contents down and require scrollbars.
378 if (contents->layer()) {
379 EXPECT_EQ("0,0 100x100", contents->bounds().ToString());
380 contents->SetBoundsRect(gfx::Rect());
381 }
382 EXPECT_EQ("0,0 0x0", contents->bounds().ToString());
383
307 // Get the header a height of 20. 384 // Get the header a height of 20.
308 header->SetPreferredSize(gfx::Size(10, 20)); 385 header->SetPreferredSize(gfx::Size(10, 20));
309 EXPECT_EQ("0,0 100x20", header->parent()->bounds().ToString()); 386 EXPECT_EQ("0,0 100x20", header->parent()->bounds().ToString());
310 EXPECT_EQ("0,20 100x80", contents->parent()->bounds().ToString()); 387 EXPECT_EQ("0,20 100x80", contents->parent()->bounds().ToString());
388 if (contents->layer()) {
389 EXPECT_EQ("0,0 100x80", contents->bounds().ToString());
390 contents->SetBoundsRect(gfx::Rect());
391 }
392 EXPECT_EQ("0,0 0x0", contents->bounds().ToString());
311 393
312 // Remove the header. 394 // Remove the header.
313 scroll_view.SetHeader(NULL); 395 scroll_view.SetHeader(NULL);
314 // SetHeader(NULL) deletes header. 396 // SetHeader(NULL) deletes header.
315 header = NULL; 397 header = NULL;
316 EXPECT_EQ("0,0 100x0", header_parent->bounds().ToString()); 398 EXPECT_EQ("0,0 100x0", header_parent->bounds().ToString());
317 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString()); 399 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
318 } 400 }
319 401
320 // Verifies the scrollbars are added as necessary when a header is present. 402 // Verifies the scrollbars are added as necessary when a header is present.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 EXPECT_EQ(20, header->parent()->height()); 460 EXPECT_EQ(20, header->parent()->height());
379 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL); 461 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
380 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible()); 462 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
381 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL); 463 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
382 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible()); 464 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
383 } 465 }
384 466
385 // Verifies the header scrolls horizontally with the content. 467 // Verifies the header scrolls horizontally with the content.
386 TEST(ScrollViewTest, HeaderScrollsWithContent) { 468 TEST(ScrollViewTest, HeaderScrollsWithContent) {
387 ScrollView scroll_view; 469 ScrollView scroll_view;
470 ScrollViewTestApi test_api(&scroll_view);
388 CustomView* contents = new CustomView; 471 CustomView* contents = new CustomView;
389 scroll_view.SetContents(contents); 472 scroll_view.SetContents(contents);
390 contents->SetPreferredSize(gfx::Size(500, 500)); 473 contents->SetPreferredSize(gfx::Size(500, 500));
391 474
392 CustomView* header = new CustomView; 475 CustomView* header = new CustomView;
393 scroll_view.SetHeader(header); 476 scroll_view.SetHeader(header);
394 header->SetPreferredSize(gfx::Size(500, 20)); 477 header->SetPreferredSize(gfx::Size(500, 20));
395 478
396 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); 479 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
397 EXPECT_EQ("0,0", contents->bounds().origin().ToString()); 480 EXPECT_EQ("0,0", test_api.IntegralViewOffset().ToString());
398 EXPECT_EQ("0,0", header->bounds().origin().ToString()); 481 EXPECT_EQ("0,0", header->bounds().origin().ToString());
399 482
400 // Scroll the horizontal scrollbar. 483 // Scroll the horizontal scrollbar.
401 ASSERT_TRUE(scroll_view.horizontal_scroll_bar()); 484 ASSERT_TRUE(scroll_view.horizontal_scroll_bar());
402 scroll_view.ScrollToPosition( 485 scroll_view.ScrollToPosition(
403 const_cast<ScrollBar*>(scroll_view.horizontal_scroll_bar()), 1); 486 const_cast<ScrollBar*>(scroll_view.horizontal_scroll_bar()), 1);
404 EXPECT_EQ("-1,0", contents->bounds().origin().ToString()); 487 EXPECT_EQ("-1,0", test_api.IntegralViewOffset().ToString());
405 EXPECT_EQ("-1,0", header->bounds().origin().ToString()); 488 EXPECT_EQ("-1,0", header->bounds().origin().ToString());
406 489
407 // Scrolling the vertical scrollbar shouldn't effect the header. 490 // Scrolling the vertical scrollbar shouldn't effect the header.
408 ASSERT_TRUE(scroll_view.vertical_scroll_bar()); 491 ASSERT_TRUE(scroll_view.vertical_scroll_bar());
409 scroll_view.ScrollToPosition( 492 scroll_view.ScrollToPosition(
410 const_cast<ScrollBar*>(scroll_view.vertical_scroll_bar()), 1); 493 const_cast<ScrollBar*>(scroll_view.vertical_scroll_bar()), 1);
411 EXPECT_EQ("-1,-1", contents->bounds().origin().ToString()); 494 EXPECT_EQ("-1,-1", test_api.IntegralViewOffset().ToString());
412 EXPECT_EQ("-1,0", header->bounds().origin().ToString()); 495 EXPECT_EQ("-1,0", header->bounds().origin().ToString());
413 } 496 }
414 497
415 // Verifies ScrollRectToVisible() on the child works. 498 // Verifies ScrollRectToVisible() on the child works.
416 TEST(ScrollViewTest, ScrollRectToVisible) { 499 TEST(ScrollViewTest, ScrollRectToVisible) {
500 #if defined(OS_MACOSX)
501 ui::test::ScopedPreferredScrollerStyle scroller_style_override(false);
502 #endif
417 ScrollView scroll_view; 503 ScrollView scroll_view;
504 ScrollViewTestApi test_api(&scroll_view);
418 CustomView* contents = new CustomView; 505 CustomView* contents = new CustomView;
419 scroll_view.SetContents(contents); 506 scroll_view.SetContents(contents);
420 contents->SetPreferredSize(gfx::Size(500, 1000)); 507 contents->SetPreferredSize(gfx::Size(500, 1000));
421 508
422 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); 509 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
423 scroll_view.Layout(); 510 scroll_view.Layout();
424 EXPECT_EQ("0,0", contents->bounds().origin().ToString()); 511 EXPECT_EQ("0,0", test_api.IntegralViewOffset().ToString());
425 512
426 // Scroll to y=405 height=10, this should make the y position of the content 513 // Scroll to y=405 height=10, this should make the y position of the content
427 // at (405 + 10) - viewport_height (scroll region bottom aligned). 514 // at (405 + 10) - viewport_height (scroll region bottom aligned).
428 contents->ScrollRectToVisible(gfx::Rect(0, 405, 10, 10)); 515 contents->ScrollRectToVisible(gfx::Rect(0, 405, 10, 10));
429 const int viewport_height = contents->parent()->height(); 516 const int viewport_height = test_api.contents_viewport()->height();
430 EXPECT_EQ(-(415 - viewport_height), contents->y()); 517
518 // Expect there to be a horizontal scrollbar, making the viewport shorter.
519 EXPECT_LT(viewport_height, 100);
520
521 gfx::ScrollOffset offset = test_api.CurrentOffset();
522 EXPECT_EQ(415 - viewport_height, offset.y());
431 523
432 // Scroll to the current y-location and 10x10; should do nothing. 524 // Scroll to the current y-location and 10x10; should do nothing.
433 contents->ScrollRectToVisible(gfx::Rect(0, -contents->y(), 10, 10)); 525 contents->ScrollRectToVisible(gfx::Rect(0, offset.y(), 10, 10));
434 EXPECT_EQ(-(415 - viewport_height), contents->y()); 526 EXPECT_EQ(415 - viewport_height, test_api.CurrentOffset().y());
435 } 527 }
436 528
437 // Verifies ClipHeightTo() uses the height of the content when it is between the 529 // Verifies ClipHeightTo() uses the height of the content when it is between the
438 // minimum and maximum height values. 530 // minimum and maximum height values.
439 TEST(ScrollViewTest, ClipHeightToNormalContentHeight) { 531 TEST(ScrollViewTest, ClipHeightToNormalContentHeight) {
440 ScrollView scroll_view; 532 ScrollView scroll_view;
441 533
442 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight); 534 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
443 535
444 const int kNormalContentHeight = 75; 536 const int kNormalContentHeight = 75;
445 scroll_view.SetContents( 537 scroll_view.SetContents(
446 new views::StaticSizedView(gfx::Size(kWidth, kNormalContentHeight))); 538 new views::StaticSizedView(gfx::Size(kWidth, kNormalContentHeight)));
447 539
448 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), 540 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
449 scroll_view.GetPreferredSize()); 541 scroll_view.GetPreferredSize());
450 542
451 scroll_view.SizeToPreferredSize(); 543 scroll_view.SizeToPreferredSize();
452 scroll_view.Layout(); 544 scroll_view.Layout();
453 545
454 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), 546 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
455 scroll_view.contents()->size()); 547 scroll_view.contents()->size());
456 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), scroll_view.size()); 548 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), scroll_view.size());
457 } 549 }
458 550
459 // Verifies ClipHeightTo() uses the minimum height when the content is shorter 551 // Verifies ClipHeightTo() uses the minimum height when the content is shorter
460 // thamn the minimum height value. 552 // than the minimum height value.
461 TEST(ScrollViewTest, ClipHeightToShortContentHeight) { 553 TEST(ScrollViewTest, ClipHeightToShortContentHeight) {
462 ScrollView scroll_view; 554 ScrollView scroll_view;
463 555
464 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight); 556 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
465 557
466 const int kShortContentHeight = 10; 558 const int kShortContentHeight = 10;
467 scroll_view.SetContents( 559 View* contents =
468 new views::StaticSizedView(gfx::Size(kWidth, kShortContentHeight))); 560 new views::StaticSizedView(gfx::Size(kWidth, kShortContentHeight));
561 scroll_view.SetContents(contents);
469 562
470 EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.GetPreferredSize()); 563 EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.GetPreferredSize());
471 564
472 scroll_view.SizeToPreferredSize(); 565 scroll_view.SizeToPreferredSize();
473 scroll_view.Layout(); 566 scroll_view.Layout();
474 567
475 EXPECT_EQ(gfx::Size(kWidth, kShortContentHeight), 568 // Layered scrolling requires the contents to fill the viewport.
476 scroll_view.contents()->size()); 569 if (contents->layer()) {
570 EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.contents()->size());
571 } else {
572 EXPECT_EQ(gfx::Size(kWidth, kShortContentHeight),
573 scroll_view.contents()->size());
574 }
477 EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.size()); 575 EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.size());
478 } 576 }
479 577
480 // Verifies ClipHeightTo() uses the maximum height when the content is longer 578 // Verifies ClipHeightTo() uses the maximum height when the content is longer
481 // thamn the maximum height value. 579 // thamn the maximum height value.
482 TEST(ScrollViewTest, ClipHeightToTallContentHeight) { 580 TEST(ScrollViewTest, ClipHeightToTallContentHeight) {
483 ScrollView scroll_view; 581 ScrollView scroll_view;
484 582
485 // Use a scrollbar that is disabled by default, so the width of the content is 583 // Use a scrollbar that is disabled by default, so the width of the content is
486 // not affected. 584 // not affected.
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 scroller_style_override.reset( 719 scroller_style_override.reset(
622 new ui::test::ScopedPreferredScrollerStyle(false)); 720 new ui::test::ScopedPreferredScrollerStyle(false));
623 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width()); 721 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
624 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(), 722 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
625 contents->parent()->height()); 723 contents->parent()->height());
626 EXPECT_NE(0, scroll_view.GetScrollBarWidth()); 724 EXPECT_NE(0, scroll_view.GetScrollBarWidth());
627 EXPECT_NE(0, scroll_view.GetScrollBarHeight()); 725 EXPECT_NE(0, scroll_view.GetScrollBarHeight());
628 } 726 }
629 #endif 727 #endif
630 728
729 // Test that increasing the size of the viewport "below" scrolled content causes
730 // the content to scroll up so that it still fills the viewport.
731 TEST(ScrollViewTest, ConstrainScrollToBounds) {
732 ScrollView scroll_view;
733 ScrollViewTestApi test_api(&scroll_view);
734
735 View* contents = new View;
736 contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
737 scroll_view.SetContents(contents);
738 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
739 scroll_view.Layout();
740
741 EXPECT_EQ(gfx::ScrollOffset(), test_api.CurrentOffset());
742
743 // Scroll as far as it goes and query location to discount scroll bars.
744 contents->ScrollRectToVisible(gfx::Rect(300, 300, 1, 1));
745 const gfx::ScrollOffset fully_scrolled = test_api.CurrentOffset();
746 EXPECT_NE(gfx::ScrollOffset(), fully_scrolled);
747
748 // Making the viewport 55 pixels taller should scroll up the same amount.
749 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 155));
750 scroll_view.Layout();
751 EXPECT_EQ(fully_scrolled.y() - 55, test_api.CurrentOffset().y());
752 EXPECT_EQ(fully_scrolled.x(), test_api.CurrentOffset().x());
753
754 // And 77 pixels wider should scroll left. Also make it short again: the y-
755 // offset from the last change should remain.
756 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 177, 100));
757 scroll_view.Layout();
758 EXPECT_EQ(fully_scrolled.y() - 55, test_api.CurrentOffset().y());
759 EXPECT_EQ(fully_scrolled.x() - 77, test_api.CurrentOffset().x());
760 }
761
631 // Test scrolling behavior when clicking on the scroll track. 762 // Test scrolling behavior when clicking on the scroll track.
632 TEST_F(WidgetScrollViewTest, ScrollTrackScrolling) { 763 TEST_F(WidgetScrollViewTest, ScrollTrackScrolling) {
633 // Set up with a vertical scroller. 764 // Set up with a vertical scroller.
634 ScrollView* scroll_view = 765 ScrollView* scroll_view =
635 AddScrollViewWithContentSize(gfx::Size(10, kDefaultHeight * 5)); 766 AddScrollViewWithContentSize(gfx::Size(10, kDefaultHeight * 5));
636 ScrollViewTestApi test_api(scroll_view); 767 ScrollViewTestApi test_api(scroll_view);
637 BaseScrollBar* scroll_bar = test_api.GetBaseScrollBar(VERTICAL); 768 BaseScrollBar* scroll_bar = test_api.GetBaseScrollBar(VERTICAL);
638 View* thumb = test_api.GetScrollBarThumb(VERTICAL); 769 View* thumb = test_api.GetScrollBarThumb(VERTICAL);
639 770
640 // Click in the middle of the track, ensuring it's below the thumb. 771 // Click in the middle of the track, ensuring it's below the thumb.
(...skipping 13 matching lines...) Expand all
654 785
655 // While the mouse is pressed, timer should trigger more scroll events. 786 // While the mouse is pressed, timer should trigger more scroll events.
656 EXPECT_TRUE(timer.IsRunning()); 787 EXPECT_TRUE(timer.IsRunning());
657 788
658 // Upon release timer should stop (and scroll position should remain). 789 // Upon release timer should stop (and scroll position should remain).
659 scroll_bar->OnMouseEvent(&release); 790 scroll_bar->OnMouseEvent(&release);
660 EXPECT_FALSE(timer.IsRunning()); 791 EXPECT_FALSE(timer.IsRunning());
661 EXPECT_EQ(kDefaultHeight, scroll_view->GetVisibleRect().y()); 792 EXPECT_EQ(kDefaultHeight, scroll_view->GetVisibleRect().y());
662 } 793 }
663 794
795 // Test that LocatedEvents are transformed correctly when scrolling.
796 TEST_F(WidgetScrollViewTest, EventLocation) {
797 // Set up with both scrollers.
798 CustomView* contents = new CustomView;
799 contents->SetPreferredSize(gfx::Size(kDefaultHeight * 5, kDefaultHeight * 5));
800 AddScrollViewWithContents(contents);
801
802 const gfx::Point location_in_widget(10, 10);
803
804 // Click without scrolling.
805 TestClickAt(location_in_widget);
806 EXPECT_EQ(location_in_widget, contents->last_location());
807
808 // Scroll down a page.
809 contents->ScrollRectToVisible(
810 gfx::Rect(0, kDefaultHeight, 1, kDefaultHeight));
811 TestClickAt(location_in_widget);
812 EXPECT_EQ(gfx::Point(10, 10 + kDefaultHeight), contents->last_location());
813
814 // Scroll right a page (and back up).
815 contents->ScrollRectToVisible(gfx::Rect(kDefaultWidth, 0, kDefaultWidth, 1));
816 TestClickAt(location_in_widget);
817 EXPECT_EQ(gfx::Point(10 + kDefaultWidth, 10), contents->last_location());
818
819 // Scroll both directions.
820 contents->ScrollRectToVisible(
821 gfx::Rect(kDefaultWidth, kDefaultHeight, kDefaultWidth, kDefaultHeight));
822 TestClickAt(location_in_widget);
823 EXPECT_EQ(gfx::Point(10 + kDefaultWidth, 10 + kDefaultHeight),
824 contents->last_location());
825 }
826
827 // Test that views scroll offsets are in sync with the layer scroll offsets.
828 TEST_F(WidgetScrollViewTest, ScrollOffsetUsingLayers) {
829 // Set up with a vertical scroller, but don't commit the layer changes yet.
830 ScrollView* scroll_view =
831 AddScrollViewWithContentSize(gfx::Size(10, kDefaultHeight * 5), false);
832 ScrollViewTestApi test_api(scroll_view);
833
834 EXPECT_EQ(gfx::ScrollOffset(0, 0), test_api.CurrentOffset());
835
836 // UI code may request a scroll before layer changes are committed.
837 gfx::Rect offset(0, kDefaultHeight * 2, 1, kDefaultHeight);
838 scroll_view->contents()->ScrollRectToVisible(offset);
839 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), test_api.CurrentOffset());
840
841 // The following only makes sense when layered scrolling is enabled.
842 View* container = scroll_view->contents();
843 #if defined(OS_MACOSX)
844 // Sanity check: Mac should always scroll with layers.
845 EXPECT_TRUE(container->layer());
846 #endif
847 if (!container->layer())
848 return;
849
850 // Container and viewport should have layers.
851 EXPECT_TRUE(container->layer());
852 EXPECT_TRUE(test_api.contents_viewport()->layer());
853
854 // In a Widget, so there should be a compositor.
855 ui::Compositor* compositor = container->layer()->GetCompositor();
856 EXPECT_TRUE(compositor);
857
858 // But setting on the impl side should fail since the layer isn't committed.
859 int layer_id = container->layer()->cc_layer_for_testing()->id();
860 EXPECT_FALSE(compositor->ScrollLayerTo(layer_id, gfx::ScrollOffset(0, 0)));
861 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), test_api.CurrentOffset());
862
863 WaitForCommit();
864 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), test_api.CurrentOffset());
865
866 // Upon commit, the impl side should report the same value too.
867 gfx::ScrollOffset impl_offset;
868 EXPECT_TRUE(compositor->GetScrollOffsetForLayer(layer_id, &impl_offset));
869 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), impl_offset);
870
871 // Now impl-side scrolling should work, and also update the ScrollView.
872 offset.set_y(kDefaultHeight * 3);
873 EXPECT_TRUE(
874 compositor->ScrollLayerTo(layer_id, gfx::ScrollOffset(0, offset.y())));
875 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), test_api.CurrentOffset());
876
877 // Scroll via ScrollView API. Should be reflected on the impl side.
878 offset.set_y(kDefaultHeight * 4);
879 scroll_view->contents()->ScrollRectToVisible(offset);
880 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), test_api.CurrentOffset());
881
882 EXPECT_TRUE(compositor->GetScrollOffsetForLayer(layer_id, &impl_offset));
883 EXPECT_EQ(gfx::ScrollOffset(0, offset.y()), impl_offset);
884 }
885
664 } // namespace views 886 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/scroll_view.cc ('k') | ui/views/view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698