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

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

Issue 2189583004: [not for review - epic CL] Adding Elastic+Momentum+Layered scrolling to views::ScrollView Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Combined rebase 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
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/feature_list.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
8 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "ui/compositor/overscroll/ui_scroll_input_manager.h"
9 #include "ui/events/event.h" 11 #include "ui/events/event.h"
10 #include "ui/gfx/canvas.h" 12 #include "ui/gfx/canvas.h"
11 #include "ui/native_theme/native_theme.h" 13 #include "ui/native_theme/native_theme.h"
14 #include "ui/views/background.h"
12 #include "ui/views/border.h" 15 #include "ui/views/border.h"
13 #include "ui/views/style/platform_style.h" 16 #include "ui/views/style/platform_style.h"
14 #include "ui/views/widget/root_view.h" 17 #include "ui/views/widget/widget.h"
15 18
16 namespace views { 19 namespace views {
17 20
18 const char ScrollView::kViewClassName[] = "ScrollView"; 21 const char ScrollView::kViewClassName[] = "ScrollView";
19 22
20 namespace { 23 namespace {
21 24
25 const base::Feature kToolkitViewsScrollWithLayers {
26 "ToolkitViewsScrollWithLayers",
27 #if defined(OS_MACOSX)
28 base::FEATURE_ENABLED_BY_DEFAULT
29 #else
30 base::FEATURE_DISABLED_BY_DEFAULT
31 #endif
32 };
33
22 // Subclass of ScrollView that resets the border when the theme changes. 34 // Subclass of ScrollView that resets the border when the theme changes.
23 class ScrollViewWithBorder : public views::ScrollView { 35 class ScrollViewWithBorder : public views::ScrollView {
24 public: 36 public:
25 ScrollViewWithBorder() {} 37 ScrollViewWithBorder() {}
26 38
27 // View overrides; 39 // View overrides;
28 void OnNativeThemeChanged(const ui::NativeTheme* theme) override { 40 void OnNativeThemeChanged(const ui::NativeTheme* theme) override {
29 SetBorder(Border::CreateSolidBorder( 41 SetBorder(Border::CreateSolidBorder(
30 1, 42 1,
31 theme->GetSystemColor(ui::NativeTheme::kColorId_UnfocusedBorderColor))); 43 theme->GetSystemColor(ui::NativeTheme::kColorId_UnfocusedBorderColor)));
(...skipping 25 matching lines...) Expand all
57 int CheckScrollBounds(int viewport_size, int content_size, int current_pos) { 69 int CheckScrollBounds(int viewport_size, int content_size, int current_pos) {
58 int max = std::max(content_size - viewport_size, 0); 70 int max = std::max(content_size - viewport_size, 0);
59 if (current_pos < 0) 71 if (current_pos < 0)
60 return 0; 72 return 0;
61 if (current_pos > max) 73 if (current_pos > max)
62 return max; 74 return max;
63 return current_pos; 75 return current_pos;
64 } 76 }
65 77
66 // Make sure the content is not scrolled out of bounds 78 // Make sure the content is not scrolled out of bounds
67 void CheckScrollBounds(View* viewport, View* view) { 79 void CheckScrollBounds(View* viewport, View* container, View* view) {
68 if (!view) 80 if (!view)
69 return; 81 return;
70 82
71 int x = CheckScrollBounds(viewport->width(), view->width(), -view->x()); 83 gfx::ScrollOffset offset = container
72 int y = CheckScrollBounds(viewport->height(), view->height(), -view->y()); 84 ? container->layer()->CurrentScrollOffset()
85 : gfx::ScrollOffset(-view->x(), -view->y());
73 86
74 // This is no op if bounds are the same 87 int x = CheckScrollBounds(viewport->width(), view->width(), offset.x());
75 view->SetBounds(-x, -y, view->width(), view->height()); 88 int y = CheckScrollBounds(viewport->height(), view->height(), offset.y());
89
90 if (container) {
91 container->layer()->SetScrollOffset(gfx::ScrollOffset(x, y));
92 } else {
93 // This is no op if bounds are the same
94 view->SetBounds(-x, -y, view->width(), view->height());
95 }
76 } 96 }
77 97
78 // Used by ScrollToPosition() to make sure the new position fits within the 98 // Used by ScrollToPosition() to make sure the new position fits within the
79 // allowed scroll range. 99 // allowed scroll range.
80 int AdjustPosition(int current_position, 100 int AdjustPosition(int current_position,
81 int new_position, 101 int new_position,
82 int content_size, 102 int content_size,
83 int viewport_size) { 103 int viewport_size) {
84 if (-current_position == new_position) 104 if (-current_position == new_position)
85 return new_position; 105 return new_position;
86 if (new_position < 0) 106 if (new_position < 0)
87 return 0; 107 return 0;
88 const int max_position = std::max(0, content_size - viewport_size); 108 const int max_position = std::max(0, content_size - viewport_size);
89 return (new_position > max_position) ? max_position : new_position; 109 return (new_position > max_position) ? max_position : new_position;
90 } 110 }
91 111
112 class ScrollViewContainer : public View {
113 public:
114 ScrollViewContainer() {}
115
116 // View:
117 void ChildPreferredSizeChanged(View* child) override {
118 PreferredSizeChanged();
119 }
120
121 private:
122 DISALLOW_COPY_AND_ASSIGN(ScrollViewContainer);
123 };
124
92 } // namespace 125 } // namespace
93 126
94 // Viewport contains the contents View of the ScrollView. 127 // Viewport contains the contents View of the ScrollView.
95 class ScrollView::Viewport : public View { 128 class ScrollView::Viewport : public View {
96 public: 129 public:
97 Viewport() {} 130 Viewport() {}
98 ~Viewport() override {} 131 ~Viewport() override {}
99 132
100 const char* GetClassName() const override { return "ScrollView::Viewport"; } 133 const char* GetClassName() const override { return "ScrollView::Viewport"; }
101 134
102 void ScrollRectToVisible(const gfx::Rect& rect) override { 135 void ScrollRectToVisible(const gfx::Rect& rect) override {
103 if (!has_children() || !parent()) 136 if (!has_children() || !parent())
104 return; 137 return;
105 138
106 View* contents = child_at(0); 139 View* contents = child_at(0);
107 gfx::Rect scroll_rect(rect); 140 gfx::Rect scroll_rect(rect);
141
142 ScrollView* scroll_view = static_cast<ScrollView*>(parent());
143 if (contents == scroll_view->contents_container_) {
144 // With layer scrolling, there's no need to "undo" the offset done in the
145 // child's View::ScrollRectToVisible() before it calls this.
146 DCHECK_EQ(0, contents->x());
147 DCHECK_EQ(0, contents->y());
148 }
149
108 scroll_rect.Offset(-contents->x(), -contents->y()); 150 scroll_rect.Offset(-contents->x(), -contents->y());
109 static_cast<ScrollView*>(parent())->ScrollContentsRegionToBeVisible( 151 scroll_view->ScrollContentsRegionToBeVisible(scroll_rect);
110 scroll_rect);
111 } 152 }
112 153
113 void ChildPreferredSizeChanged(View* child) override { 154 void ChildPreferredSizeChanged(View* child) override {
114 if (parent()) 155 if (parent())
115 parent()->Layout(); 156 parent()->Layout();
116 } 157 }
117 158
118 private: 159 private:
119 DISALLOW_COPY_AND_ASSIGN(Viewport); 160 DISALLOW_COPY_AND_ASSIGN(Viewport);
120 }; 161 };
121 162
122 ScrollView::ScrollView() 163 ScrollView::ScrollView()
123 : contents_(NULL), 164 : contents_(NULL),
165 contents_container_(nullptr),
124 contents_viewport_(new Viewport()), 166 contents_viewport_(new Viewport()),
125 header_(NULL), 167 header_(NULL),
126 header_viewport_(new Viewport()), 168 header_viewport_(new Viewport()),
127 horiz_sb_(PlatformStyle::CreateScrollBar(true).release()), 169 horiz_sb_(PlatformStyle::CreateScrollBar(true).release()),
128 vert_sb_(PlatformStyle::CreateScrollBar(false).release()), 170 vert_sb_(PlatformStyle::CreateScrollBar(false).release()),
129 corner_view_(new ScrollCornerView()), 171 corner_view_(new ScrollCornerView()),
130 min_height_(-1), 172 min_height_(-1),
131 max_height_(-1), 173 max_height_(-1),
132 hide_horizontal_scrollbar_(false) { 174 hide_horizontal_scrollbar_(false) {
133 set_notify_enter_exit_on_child(true); 175 set_notify_enter_exit_on_child(true);
134 176
135 AddChildView(contents_viewport_); 177 AddChildView(contents_viewport_);
136 AddChildView(header_viewport_); 178 AddChildView(header_viewport_);
137 179
138 // Don't add the scrollbars as children until we discover we need them 180 // Don't add the scrollbars as children until we discover we need them
139 // (ShowOrHideScrollBar). 181 // (ShowOrHideScrollBar).
140 horiz_sb_->SetVisible(false); 182 horiz_sb_->SetVisible(false);
141 horiz_sb_->set_controller(this); 183 horiz_sb_->set_controller(this);
142 vert_sb_->SetVisible(false); 184 vert_sb_->SetVisible(false);
143 vert_sb_->set_controller(this); 185 vert_sb_->set_controller(this);
144 corner_view_->SetVisible(false); 186 corner_view_->SetVisible(false);
187
188 if (!base::FeatureList::IsEnabled(kToolkitViewsScrollWithLayers))
189 return;
190
191 contents_container_ = new ScrollViewContainer();
192 contents_viewport_->AddChildView(contents_container_);
193 contents_viewport_->SetPaintToLayer(true);
194 contents_viewport_->set_background(
195 Background::CreateSolidBackground(SK_ColorWHITE));
196 contents_viewport_->layer()->SetMasksToBounds(true);
197
198 contents_container_->SetPaintToLayer(true);
sky 2016/08/02 17:29:45 Would it be possible to to turn on paint to layer
tapted 2016/08/03 00:18:58 One issue was that there's no guarantee that |cont
199 contents_container_->set_background(
200 Background::CreateSolidBackground(SK_ColorWHITE));
201 contents_container_->layer()->SetScrollable(
202 contents_viewport_->layer(), true /* can_overscroll */,
203 base::Bind(&ScrollView::OnLayerScrolled, base::Unretained(this)));
145 } 204 }
146 205
147 ScrollView::~ScrollView() { 206 ScrollView::~ScrollView() {
148 // The scrollbars may not have been added, delete them to ensure they get 207 // The scrollbars may not have been added, delete them to ensure they get
149 // deleted. 208 // deleted.
150 delete horiz_sb_; 209 delete horiz_sb_;
151 delete vert_sb_; 210 delete vert_sb_;
152 delete corner_view_; 211 delete corner_view_;
153 } 212 }
154 213
155 // static 214 // static
156 ScrollView* ScrollView::CreateScrollViewWithBorder() { 215 ScrollView* ScrollView::CreateScrollViewWithBorder() {
157 return new ScrollViewWithBorder(); 216 return new ScrollViewWithBorder();
158 } 217 }
159 218
160 void ScrollView::SetContents(View* a_view) { 219 void ScrollView::SetContents(View* a_view) {
161 SetHeaderOrContents(contents_viewport_, a_view, &contents_); 220 View* parent = contents_container_ ? contents_container_ : contents_viewport_;
221 SetHeaderOrContents(parent, a_view, &contents_);
162 } 222 }
163 223
164 void ScrollView::SetHeader(View* header) { 224 void ScrollView::SetHeader(View* header) {
165 SetHeaderOrContents(header_viewport_, header, &header_); 225 SetHeaderOrContents(header_viewport_, header, &header_);
166 } 226 }
167 227
168 gfx::Rect ScrollView::GetVisibleRect() const { 228 gfx::Rect ScrollView::GetVisibleRect() const {
169 if (!contents_) 229 if (!contents_)
170 return gfx::Rect(); 230 return gfx::Rect();
171 return gfx::Rect(-contents_->x(), -contents_->y(), 231 gfx::ScrollOffset offset = CurrentOffset();
172 contents_viewport_->width(), contents_viewport_->height()); 232 return gfx::Rect(offset.x(), offset.y(), contents_viewport_->width(),
233 contents_viewport_->height());
173 } 234 }
174 235
175 void ScrollView::ClipHeightTo(int min_height, int max_height) { 236 void ScrollView::ClipHeightTo(int min_height, int max_height) {
176 min_height_ = min_height; 237 min_height_ = min_height;
177 max_height_ = max_height; 238 max_height_ = max_height;
178 } 239 }
179 240
180 int ScrollView::GetScrollBarWidth() const { 241 int ScrollView::GetScrollBarWidth() const {
181 return vert_sb_ ? vert_sb_->GetLayoutSize() : 0; 242 return vert_sb_ ? vert_sb_->GetLayoutSize() : 0;
182 } 243 }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 // viewport_size is the total client space available. 321 // viewport_size is the total client space available.
261 gfx::Size viewport_size = viewport_bounds.size(); 322 gfx::Size viewport_size = viewport_bounds.size();
262 // Assumes a vertical scrollbar since most of the current views are designed 323 // Assumes a vertical scrollbar since most of the current views are designed
263 // for this. 324 // for this.
264 int horiz_sb_height = GetScrollBarHeight(); 325 int horiz_sb_height = GetScrollBarHeight();
265 int vert_sb_width = GetScrollBarWidth(); 326 int vert_sb_width = GetScrollBarWidth();
266 viewport_bounds.set_width(viewport_bounds.width() - vert_sb_width); 327 viewport_bounds.set_width(viewport_bounds.width() - vert_sb_width);
267 // Update the bounds right now so the inner views can fit in it. 328 // Update the bounds right now so the inner views can fit in it.
268 contents_viewport_->SetBoundsRect(viewport_bounds); 329 contents_viewport_->SetBoundsRect(viewport_bounds);
269 330
270 // Give |contents_| a chance to update its bounds if it depends on the 331 // Give |contents_| a chance to update its bounds if it depends on its parent
271 // viewport. 332 // bounds.
272 if (contents_) 333 if (contents_) {
334 // The container bounds may need to be made larger later, but use the
335 // viewport bounds to layout the contents.
336 if (contents_container_)
337 contents_container_->SetBoundsRect(viewport_bounds);
273 contents_->Layout(); 338 contents_->Layout();
339 }
274 340
275 bool should_layout_contents = false; 341 bool should_layout_contents = false;
276 bool horiz_sb_required = false; 342 bool horiz_sb_required = false;
277 bool vert_sb_required = false; 343 bool vert_sb_required = false;
278 if (contents_) { 344 if (contents_) {
279 gfx::Size content_size = contents_->size(); 345 gfx::Size content_size = contents_->size();
280 ComputeScrollBarsVisibility(viewport_size, 346 ComputeScrollBarsVisibility(viewport_size,
281 content_size, 347 content_size,
282 &horiz_sb_required, 348 &horiz_sb_required,
283 &vert_sb_required); 349 &vert_sb_required);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 viewport_bounds.bottom() - contents_y - height_offset); 385 viewport_bounds.bottom() - contents_y - height_offset);
320 } 386 }
321 if (corner_view_required) { 387 if (corner_view_required) {
322 // Show the resize corner. 388 // Show the resize corner.
323 corner_view_->SetBounds(vert_sb_->bounds().x(), horiz_sb_->bounds().y(), 389 corner_view_->SetBounds(vert_sb_->bounds().x(), horiz_sb_->bounds().y(),
324 vert_sb_width, horiz_sb_height); 390 vert_sb_width, horiz_sb_height);
325 } 391 }
326 392
327 // Update to the real client size with the visible scrollbars. 393 // Update to the real client size with the visible scrollbars.
328 contents_viewport_->SetBoundsRect(viewport_bounds); 394 contents_viewport_->SetBoundsRect(viewport_bounds);
329 if (should_layout_contents && contents_) 395 if (should_layout_contents && contents_) {
396 if (contents_container_)
397 contents_container_->SetBoundsRect(viewport_bounds);
330 contents_->Layout(); 398 contents_->Layout();
399 }
400
401 // Even when |contents_| needs to scroll, it can still be narrower or wider
402 // the viewport. So ensure the scrolling layer can fill the viewport, so that
403 // events will correctly hit it, and overscroll looks correct.
404 if (contents_container_) {
405 gfx::Size container_size = contents_ ? contents_->size() : gfx::Size();
406 container_size.SetToMax(viewport_bounds.size());
407 contents_container_->SetBoundsRect(gfx::Rect(container_size));
408 }
331 409
332 header_viewport_->SetBounds(contents_x, contents_y, 410 header_viewport_->SetBounds(contents_x, contents_y,
333 viewport_bounds.width(), header_height); 411 viewport_bounds.width(), header_height);
334 if (header_) 412 if (header_)
335 header_->Layout(); 413 header_->Layout();
336 414
337 CheckScrollBounds(header_viewport_, header_); 415 CheckScrollBounds(header_viewport_, nullptr, header_);
338 CheckScrollBounds(contents_viewport_, contents_); 416 CheckScrollBounds(contents_viewport_, contents_container_, contents_);
417
339 SchedulePaint(); 418 SchedulePaint();
340 UpdateScrollBarPositions(); 419 UpdateScrollBarPositions();
341 } 420 }
342 421
343 bool ScrollView::OnKeyPressed(const ui::KeyEvent& event) { 422 bool ScrollView::OnKeyPressed(const ui::KeyEvent& event) {
344 bool processed = false; 423 bool processed = false;
345 424
346 // Give vertical scrollbar priority 425 // Give vertical scrollbar priority
347 if (vert_sb_->visible()) 426 if (vert_sb_->visible())
348 processed = vert_sb_->OnKeyPressed(event); 427 processed = vert_sb_->OnKeyPressed(event);
(...skipping 23 matching lines...) Expand all
372 vert_sb_->OnMouseEnteredScrollView(event); 451 vert_sb_->OnMouseEnteredScrollView(event);
373 } 452 }
374 453
375 void ScrollView::OnMouseExited(const ui::MouseEvent& event) { 454 void ScrollView::OnMouseExited(const ui::MouseEvent& event) {
376 if (horiz_sb_) 455 if (horiz_sb_)
377 horiz_sb_->OnMouseExitedScrollView(event); 456 horiz_sb_->OnMouseExitedScrollView(event);
378 if (vert_sb_) 457 if (vert_sb_)
379 vert_sb_->OnMouseExitedScrollView(event); 458 vert_sb_->OnMouseExitedScrollView(event);
380 } 459 }
381 460
461 void ScrollView::OnScrollEvent(ui::ScrollEvent* event) {
462 #if defined(OS_MACOSX)
463 ui::UIScrollInputManager* compositor_scroller =
464 GetWidget()->GetCompositor()->scroll_input_manager();
465 if (compositor_scroller)
466 compositor_scroller->OnScrollEvent(*event);
467 #endif
468 }
469
382 void ScrollView::OnGestureEvent(ui::GestureEvent* event) { 470 void ScrollView::OnGestureEvent(ui::GestureEvent* event) {
383 // If the event happened on one of the scrollbars, then those events are 471 // If the event happened on one of the scrollbars, then those events are
384 // sent directly to the scrollbars. Otherwise, only scroll events are sent to 472 // sent directly to the scrollbars. Otherwise, only scroll events are sent to
385 // the scrollbars. 473 // the scrollbars.
386 bool scroll_event = event->type() == ui::ET_GESTURE_SCROLL_UPDATE || 474 bool scroll_event = event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
387 event->type() == ui::ET_GESTURE_SCROLL_BEGIN || 475 event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
388 event->type() == ui::ET_GESTURE_SCROLL_END || 476 event->type() == ui::ET_GESTURE_SCROLL_END ||
389 event->type() == ui::ET_SCROLL_FLING_START; 477 event->type() == ui::ET_SCROLL_FLING_START;
390 478
391 if (vert_sb_->visible()) { 479 if (vert_sb_->visible()) {
392 if (vert_sb_->bounds().Contains(event->location()) || scroll_event) 480 if (vert_sb_->bounds().Contains(event->location()) || scroll_event)
393 vert_sb_->OnGestureEvent(event); 481 vert_sb_->OnGestureEvent(event);
394 } 482 }
395 if (!event->handled() && horiz_sb_->visible()) { 483 if (!event->handled() && horiz_sb_->visible()) {
396 if (horiz_sb_->bounds().Contains(event->location()) || scroll_event) 484 if (horiz_sb_->bounds().Contains(event->location()) || scroll_event)
397 horiz_sb_->OnGestureEvent(event); 485 horiz_sb_->OnGestureEvent(event);
398 } 486 }
399 } 487 }
400 488
401 const char* ScrollView::GetClassName() const { 489 const char* ScrollView::GetClassName() const {
402 return kViewClassName; 490 return kViewClassName;
403 } 491 }
404 492
493 ScrollView* ScrollView::EnclosingScrollView() {
494 return this;
495 }
496
405 void ScrollView::ScrollToPosition(ScrollBar* source, int position) { 497 void ScrollView::ScrollToPosition(ScrollBar* source, int position) {
406 if (!contents_) 498 if (!contents_)
407 return; 499 return;
408 500
501 gfx::ScrollOffset offset = CurrentOffset();
409 if (source == horiz_sb_ && horiz_sb_->visible()) { 502 if (source == horiz_sb_ && horiz_sb_->visible()) {
410 position = AdjustPosition(contents_->x(), position, contents_->width(), 503 position = AdjustPosition(offset.x(), position, contents_->width(),
411 contents_viewport_->width()); 504 contents_viewport_->width());
412 if (-contents_->x() == position) 505 if (offset.x() == position)
413 return; 506 return;
414 contents_->SetX(-position); 507 offset.set_x(position);
415 if (header_) {
416 header_->SetX(-position);
417 header_->SchedulePaintInRect(header_->GetVisibleBounds());
418 }
419 } else if (source == vert_sb_ && vert_sb_->visible()) { 508 } else if (source == vert_sb_ && vert_sb_->visible()) {
420 position = AdjustPosition(contents_->y(), position, contents_->height(), 509 position = AdjustPosition(offset.y(), position, contents_->height(),
421 contents_viewport_->height()); 510 contents_viewport_->height());
422 if (-contents_->y() == position) 511 if (offset.y() == position)
423 return; 512 return;
424 contents_->SetY(-position); 513 offset.set_y(position);
425 } 514 }
426 contents_->SchedulePaintInRect(contents_->GetVisibleBounds()); 515 ScrollToOffset(offset);
516
517 if (!contents_container_)
518 contents_->SchedulePaintInRect(contents_->GetVisibleBounds());
427 } 519 }
428 520
429 int ScrollView::GetScrollIncrement(ScrollBar* source, bool is_page, 521 int ScrollView::GetScrollIncrement(ScrollBar* source, bool is_page,
430 bool is_positive) { 522 bool is_positive) {
431 bool is_horizontal = source->IsHorizontal(); 523 bool is_horizontal = source->IsHorizontal();
432 int amount = 0; 524 int amount = 0;
433 if (contents_) { 525 if (contents_) {
434 if (is_page) { 526 if (is_page) {
435 amount = contents_->GetPageScrollIncrement( 527 amount = contents_->GetPageScrollIncrement(
436 this, is_horizontal, is_positive); 528 this, is_horizontal, is_positive);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 // corner. This is done by setting the offset to -X or -Y. For down 589 // corner. This is done by setting the offset to -X or -Y. For down
498 // or right shifts we need to make sure it appears in the 590 // or right shifts we need to make sure it appears in the
499 // lower/right corner. This is calculated by taking max_x or max_y 591 // lower/right corner. This is calculated by taking max_x or max_y
500 // and scaling it back by the size of the viewport. 592 // and scaling it back by the size of the viewport.
501 const int new_x = 593 const int new_x =
502 (vis_rect.x() > x) ? x : std::max(0, max_x - contents_viewport_->width()); 594 (vis_rect.x() > x) ? x : std::max(0, max_x - contents_viewport_->width());
503 const int new_y = 595 const int new_y =
504 (vis_rect.y() > y) ? y : std::max(0, max_y - 596 (vis_rect.y() > y) ? y : std::max(0, max_y -
505 contents_viewport_->height()); 597 contents_viewport_->height());
506 598
507 contents_->SetX(-new_x); 599 ScrollToOffset(gfx::ScrollOffset(new_x, new_y));
508 if (header_)
509 header_->SetX(-new_x);
510 contents_->SetY(-new_y);
511 UpdateScrollBarPositions(); 600 UpdateScrollBarPositions();
512 } 601 }
513 602
514 void ScrollView::ComputeScrollBarsVisibility(const gfx::Size& vp_size, 603 void ScrollView::ComputeScrollBarsVisibility(const gfx::Size& vp_size,
515 const gfx::Size& content_size, 604 const gfx::Size& content_size,
516 bool* horiz_is_shown, 605 bool* horiz_is_shown,
517 bool* vert_is_shown) const { 606 bool* vert_is_shown) const {
518 // Try to fit both ways first, then try vertical bar only, then horizontal 607 // Try to fit both ways first, then try vertical bar only, then horizontal
519 // bar only, then defaults to both shown. 608 // bar only, then defaults to both shown.
520 if (content_size.width() <= vp_size.width() && 609 if (content_size.width() <= vp_size.width() &&
(...skipping 27 matching lines...) Expand all
548 } else { 637 } else {
549 RemoveChildView(control); 638 RemoveChildView(control);
550 control->SetVisible(false); 639 control->SetVisible(false);
551 } 640 }
552 } 641 }
553 642
554 void ScrollView::UpdateScrollBarPositions() { 643 void ScrollView::UpdateScrollBarPositions() {
555 if (!contents_) 644 if (!contents_)
556 return; 645 return;
557 646
647 const gfx::ScrollOffset offset = CurrentOffset();
558 if (horiz_sb_->visible()) { 648 if (horiz_sb_->visible()) {
559 int vw = contents_viewport_->width(); 649 int vw = contents_viewport_->width();
560 int cw = contents_->width(); 650 int cw = contents_->width();
561 int origin = contents_->x(); 651 horiz_sb_->Update(vw, cw, offset.x());
562 horiz_sb_->Update(vw, cw, -origin);
563 } 652 }
564 if (vert_sb_->visible()) { 653 if (vert_sb_->visible()) {
565 int vh = contents_viewport_->height(); 654 int vh = contents_viewport_->height();
566 int ch = contents_->height(); 655 int ch = contents_->height();
567 int origin = contents_->y(); 656 vert_sb_->Update(vh, ch, offset.y());
568 vert_sb_->Update(vh, ch, -origin);
569 } 657 }
570 } 658 }
571 659
660 gfx::ScrollOffset ScrollView::CurrentOffset() const {
661 if (contents_container_)
662 return contents_container_->layer()->CurrentScrollOffset();
663 return gfx::ScrollOffset(-contents_->x(), -contents_->y());
664 }
665
666 void ScrollView::ScrollToOffset(const gfx::ScrollOffset& offset) {
667 if (contents_container_) {
668 contents_container_->layer()->SetScrollOffset(offset);
669
670 // TODO(tapted): Remove this call to OnLayerScrolled(). It's unnecessary,
671 // but will only be invoked (asynchronously) when a Compositor is present
672 // and commits a frame, which isn't true in some tests.
673 OnLayerScrolled();
674 } else {
675 contents_->SetPosition(gfx::Point(-offset.x(), -offset.y()));
676 ScrollHeader();
677 }
678 }
679
680 void ScrollView::OnLayerScrolled() {
681 UpdateScrollBarPositions();
682 ScrollHeader();
683 }
684
685 void ScrollView::ScrollHeader() {
686 if (!header_)
687 return;
688
689 int x_offset = CurrentOffset().x();
690 if (header_->x() != -x_offset) {
691 header_->SetX(-x_offset);
692 header_->SchedulePaintInRect(header_->GetVisibleBounds());
693 }
694 }
695
572 // VariableRowHeightScrollHelper ---------------------------------------------- 696 // VariableRowHeightScrollHelper ----------------------------------------------
573 697
574 VariableRowHeightScrollHelper::VariableRowHeightScrollHelper( 698 VariableRowHeightScrollHelper::VariableRowHeightScrollHelper(
575 Controller* controller) : controller_(controller) { 699 Controller* controller) : controller_(controller) {
576 } 700 }
577 701
578 VariableRowHeightScrollHelper::~VariableRowHeightScrollHelper() { 702 VariableRowHeightScrollHelper::~VariableRowHeightScrollHelper() {
579 } 703 }
580 704
581 int VariableRowHeightScrollHelper::GetPageScrollIncrement( 705 int VariableRowHeightScrollHelper::GetPageScrollIncrement(
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 760
637 VariableRowHeightScrollHelper::RowInfo 761 VariableRowHeightScrollHelper::RowInfo
638 FixedRowHeightScrollHelper::GetRowInfo(int y) { 762 FixedRowHeightScrollHelper::GetRowInfo(int y) {
639 if (y < top_margin_) 763 if (y < top_margin_)
640 return RowInfo(0, top_margin_); 764 return RowInfo(0, top_margin_);
641 return RowInfo((y - top_margin_) / row_height_ * row_height_ + top_margin_, 765 return RowInfo((y - top_margin_) / row_height_ * row_height_ + top_margin_,
642 row_height_); 766 row_height_);
643 } 767 }
644 768
645 } // namespace views 769 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698