158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// found in the LICENSE file.
458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "cc/layers/scrollbar_layer_impl_base.h"
658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include <algorithm>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "cc/trees/layer_tree_impl.h"
958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "ui/gfx/rect_conversions.h"
1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace cc {
1258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ScrollbarLayerImplBase::ScrollbarLayerImplBase(
1458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    LayerTreeImpl* tree_impl,
1558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    int id,
1658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    ScrollbarOrientation orientation,
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_left_side_vertical_scrollbar,
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool is_overlay)
1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : LayerImpl(tree_impl, id),
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      scroll_layer_(NULL),
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      clip_layer_(NULL),
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      is_overlay_scrollbar_(is_overlay),
2358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      thumb_thickness_scale_factor_(1.f),
2458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      current_pos_(0.f),
2558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      maximum_(0),
2658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      orientation_(orientation),
2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar),
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      vertical_adjust_(0.f),
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      visible_to_total_length_ratio_(1.f) {}
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ScrollbarLayerImplBase::~ScrollbarLayerImplBase() {}
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ScrollbarLayerImplBase::PushPropertiesTo(LayerImpl* layer) {
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  float active_opacity = layer->opacity();
3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  LayerImpl::PushPropertiesTo(layer);
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  layer->SetOpacity(active_opacity);
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(layer->ToScrollbarLayer());
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  layer->ToScrollbarLayer()->set_is_overlay_scrollbar(is_overlay_scrollbar_);
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PushScrollClipPropertiesTo(layer);
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScrollbarLayerImplBase::PushScrollClipPropertiesTo(LayerImpl* layer) {
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(layer->ToScrollbarLayer());
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  layer->ToScrollbarLayer()->SetScrollLayerAndClipLayerByIds(ScrollLayerId(),
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                                             ClipLayerId());
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ScrollbarLayerImplBase* ScrollbarLayerImplBase::ToScrollbarLayer() {
4958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return this;
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace {
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liutypedef void (LayerImpl::*ScrollbarRegistrationOperation)(
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    ScrollbarLayerImplBase*);
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid RegisterScrollbarWithLayers(ScrollbarLayerImplBase* scrollbar,
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 LayerImpl* container_layer,
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 LayerImpl* scroll_layer,
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 ScrollbarRegistrationOperation operation) {
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!container_layer || !scroll_layer)
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return;
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(scrollbar);
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Scrollbars must be notifed of changes to their scroll and container layers
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // and all scrollable layers in between.
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (LayerImpl* current_layer = scroll_layer;
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       current_layer && current_layer != container_layer->parent();
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       current_layer = current_layer->parent()) {
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // TODO(wjmaclean) We shouldn't need to exempt the scroll_layer from the
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // scrollable() test below. https://crbug.com/367858.
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (current_layer->scrollable() || current_layer == container_layer ||
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        current_layer == scroll_layer)
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      (current_layer->*operation)(scrollbar);
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid ScrollbarLayerImplBase::SetScrollLayerAndClipLayerByIds(
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int scroll_layer_id,
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int clip_layer_id) {
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LayerImpl* scroll_layer = layer_tree_impl()->LayerById(scroll_layer_id);
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LayerImpl* clip_layer = layer_tree_impl()->LayerById(clip_layer_id);
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (scroll_layer_ == scroll_layer && clip_layer_ == clip_layer)
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RegisterScrollbarWithLayers(
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      this, clip_layer_, scroll_layer_, &LayerImpl::RemoveScrollbar);
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scroll_layer_ = scroll_layer;
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  clip_layer_ = clip_layer;
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RegisterScrollbarWithLayers(
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      this, clip_layer_, scroll_layer_, &LayerImpl::AddScrollbar);
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  ScrollbarParametersDidChange();
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)gfx::Rect ScrollbarLayerImplBase::ScrollbarLayerRectToContentRect(
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::RectF& layer_rect) const {
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Don't intersect with the bounds as in LayerRectToContentRect() because
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // layer_rect here might be in coordinates of the containing layer.
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  gfx::RectF content_rect = gfx::ScaleRect(layer_rect,
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      contents_scale_x(),
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      contents_scale_y());
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return gfx::ToEnclosingRect(content_rect);
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ScrollbarLayerImplBase::SetCurrentPos(float current_pos) {
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (current_pos_ == current_pos)
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  current_pos_ = current_pos;
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NoteLayerPropertyChanged();
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ScrollbarLayerImplBase::SetMaximum(int maximum) {
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (maximum_ == maximum)
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  maximum_ = maximum;
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NoteLayerPropertyChanged();
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ScrollbarLayerImplBase::SetVerticalAdjust(float vertical_adjust) {
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (vertical_adjust_ == vertical_adjust)
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  vertical_adjust_ = vertical_adjust;
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NoteLayerPropertyChanged();
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ScrollbarLayerImplBase::SetVisibleToTotalLengthRatio(float ratio) {
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!IsThumbResizable())
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (visible_to_total_length_ratio_ == ratio)
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  visible_to_total_length_ratio_ = ratio;
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NoteLayerPropertyChanged();
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool ScrollbarLayerImplBase::SetThumbThicknessScaleFactor(float factor) {
1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (thumb_thickness_scale_factor_ == factor)
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return false;
1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  thumb_thickness_scale_factor_ = factor;
1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  NoteLayerPropertyChanged();
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return true;
1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRect() const {
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Thumb extent is the length of the thumb in the scrolling direction, thumb
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // thickness is in the perpendicular direction. Here's an example of a
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // horizontal scrollbar - inputs are above the scrollbar, computed values
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // below:
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //    |<------------------- track_length_ ------------------->|
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |--| <-- start_offset
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // +--+----------------------------+------------------+-------+--+
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |<||                            |##################|       ||>|
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // +--+----------------------------+------------------+-------+--+
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //                                 |<- thumb_length ->|
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |<------- thumb_offset -------->|
16858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // For painted, scrollbars, the length is fixed. For solid color scrollbars we
17058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // have to compute it. The ratio of the thumb's length to the track's length
17158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // is the same as that of the visible viewport to the total viewport, unless
17258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // that would make the thumb's length less than its thickness.
17358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
17458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // vertical_adjust_ is used when the layer geometry from the main thread is
17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // not in sync with what the user sees. For instance on Android scrolling the
17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // top bar controls out of view reveals more of the page content. We want the
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // root layer scrollbars to reflect what the user sees even if we haven't
17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // received new layer geometry from the main thread.  If the user has scrolled
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // down by 50px and the initial viewport size was 950px the geometry would
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // look something like this:
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // vertical_adjust_ = 50, scroll position 0, visible ratios 99%
18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Layer geometry:             Desired thumb positions:
18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // +--------------------+-+   +----------------------+   <-- 0px
18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |v|   |                     #|
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |e|   |                     #|
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |r|   |                     #|
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |t|   |                     #|
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |i|   |                     #|
19058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |c|   |                     #|
19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |a|   |                     #|
19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |l|   |                     #|
19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    | |   |                     #|
19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |l|   |                     #|
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |a|   |                     #|
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |y|   |                     #|
19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |e|   |                     #|
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                    |r|   |                     #|
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // +--------------------+-+   |                     #|
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // | horizontal  layer  | |   |                     #|
20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // +--------------------+-+   |                     #|  <-- 950px
20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                      |   |                     #|
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // |                      |   |##################### |
20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // +----------------------+   +----------------------+  <-- 1000px
20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  //
20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The layer geometry is set up for a 950px tall viewport, but the user can
20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // actually see down to 1000px. Thus we have to move the quad for the
20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // horizontal scrollbar down by the vertical_adjust_ factor and lay the
20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // vertical thumb out on a track lengthed by the vertical_adjust_ factor. This
21058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // means the quads may extend outside the layer's bounds.
21158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // With the length known, we can compute the thumb's position.
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  float track_length = TrackLength();
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int thumb_length = ThumbLength();
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int thumb_thickness = ThumbThickness();
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // With the length known, we can compute the thumb's position.
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  float clamped_current_pos =
21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      std::min(std::max(current_pos_, 0.f), static_cast<float>(maximum_));
2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  int thumb_offset = TrackStart();
2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (maximum_ > 0) {
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    float ratio = clamped_current_pos / maximum_;
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    float max_offset = track_length - thumb_length;
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    thumb_offset += static_cast<int>(ratio * max_offset);
2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
22758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  float thumb_thickness_adjustment =
22958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      thumb_thickness * (1.f - thumb_thickness_scale_factor_);
23058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  gfx::RectF thumb_rect;
23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (orientation_ == HORIZONTAL) {
23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    thumb_rect = gfx::RectF(thumb_offset,
23458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                            vertical_adjust_ + thumb_thickness_adjustment,
23558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                            thumb_length,
23658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                            thumb_thickness - thumb_thickness_adjustment);
23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
23858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    thumb_rect = gfx::RectF(
23958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        is_left_side_vertical_scrollbar_
24058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            ? bounds().width() - thumb_thickness
24158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            : thumb_thickness_adjustment,
24258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        thumb_offset,
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        thumb_thickness - thumb_thickness_adjustment,
24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        thumb_length);
24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return ScrollbarLayerRectToContentRect(thumb_rect);
24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScrollbarLayerImplBase::ScrollbarParametersDidChange() {
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!clip_layer_ || !scroll_layer_)
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scroll_layer_->SetScrollbarPosition(this, clip_layer_);
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}  // namespace cc
258