• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "cc/layers/scrollbar_layer_impl_base.h"
6 
7 #include <algorithm>
8 #include "cc/layers/layer.h"
9 #include "ui/gfx/rect_conversions.h"
10 
11 namespace cc {
12 
ScrollbarLayerImplBase(LayerTreeImpl * tree_impl,int id,ScrollbarOrientation orientation,bool is_left_side_vertical_scrollbar)13 ScrollbarLayerImplBase::ScrollbarLayerImplBase(
14     LayerTreeImpl* tree_impl,
15     int id,
16     ScrollbarOrientation orientation,
17     bool is_left_side_vertical_scrollbar)
18     : LayerImpl(tree_impl, id),
19       scroll_layer_id_(Layer::INVALID_ID),
20       is_overlay_scrollbar_(false),
21       thumb_thickness_scale_factor_(1.f),
22       current_pos_(0.f),
23       maximum_(0),
24       orientation_(orientation),
25       is_left_side_vertical_scrollbar_(is_left_side_vertical_scrollbar),
26       vertical_adjust_(0.f),
27       visible_to_total_length_ratio_(1.f) {}
28 
PushPropertiesTo(LayerImpl * layer)29 void ScrollbarLayerImplBase::PushPropertiesTo(LayerImpl* layer) {
30   LayerImpl::PushPropertiesTo(layer);
31 }
32 
ToScrollbarLayer()33 ScrollbarLayerImplBase* ScrollbarLayerImplBase::ToScrollbarLayer() {
34   return this;
35 }
36 
ScrollbarLayerRectToContentRect(gfx::RectF layer_rect) const37 gfx::Rect ScrollbarLayerImplBase::ScrollbarLayerRectToContentRect(
38     gfx::RectF layer_rect) const {
39   // Don't intersect with the bounds as in LayerRectToContentRect() because
40   // layer_rect here might be in coordinates of the containing layer.
41   gfx::RectF content_rect = gfx::ScaleRect(layer_rect,
42       contents_scale_x(),
43       contents_scale_y());
44   return gfx::ToEnclosingRect(content_rect);
45 }
46 
SetCurrentPos(float current_pos)47 void ScrollbarLayerImplBase::SetCurrentPos(float current_pos) {
48   if (current_pos_ == current_pos)
49     return;
50   current_pos_ = current_pos;
51   NoteLayerPropertyChanged();
52 }
53 
SetMaximum(int maximum)54 void ScrollbarLayerImplBase::SetMaximum(int maximum) {
55   if (maximum_ == maximum)
56     return;
57   maximum_ = maximum;
58   NoteLayerPropertyChanged();
59 }
60 
SetVerticalAdjust(float vertical_adjust)61 void ScrollbarLayerImplBase::SetVerticalAdjust(float vertical_adjust) {
62   if (vertical_adjust_ == vertical_adjust)
63     return;
64   vertical_adjust_ = vertical_adjust;
65   NoteLayerPropertyChanged();
66 }
67 
SetVisibleToTotalLengthRatio(float ratio)68 void ScrollbarLayerImplBase::SetVisibleToTotalLengthRatio(float ratio) {
69   if (visible_to_total_length_ratio_ == ratio)
70     return;
71   visible_to_total_length_ratio_ = ratio;
72   NoteLayerPropertyChanged();
73 }
74 
SetThumbThicknessScaleFactor(float factor)75 void ScrollbarLayerImplBase::SetThumbThicknessScaleFactor(float factor) {
76   if (thumb_thickness_scale_factor_ == factor)
77     return;
78   thumb_thickness_scale_factor_ = factor;
79   NoteLayerPropertyChanged();
80 }
81 
ComputeThumbQuadRect() const82 gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRect() const {
83   // Thumb extent is the length of the thumb in the scrolling direction, thumb
84   // thickness is in the perpendicular direction. Here's an example of a
85   // horizontal scrollbar - inputs are above the scrollbar, computed values
86   // below:
87   //
88   //    |<------------------- track_length_ ------------------->|
89   //
90   // |--| <-- start_offset
91   //
92   // +--+----------------------------+------------------+-------+--+
93   // |<||                            |##################|       ||>|
94   // +--+----------------------------+------------------+-------+--+
95   //
96   //                                 |<- thumb_length ->|
97   //
98   // |<------- thumb_offset -------->|
99   //
100   // For painted, scrollbars, the length is fixed. For solid color scrollbars we
101   // have to compute it. The ratio of the thumb's length to the track's length
102   // is the same as that of the visible viewport to the total viewport, unless
103   // that would make the thumb's length less than its thickness.
104   //
105   // vertical_adjust_ is used when the layer geometry from the main thread is
106   // not in sync with what the user sees. For instance on Android scrolling the
107   // top bar controls out of view reveals more of the page content. We want the
108   // root layer scrollbars to reflect what the user sees even if we haven't
109   // received new layer geometry from the main thread.  If the user has scrolled
110   // down by 50px and the initial viewport size was 950px the geometry would
111   // look something like this:
112   //
113   // vertical_adjust_ = 50, scroll position 0, visible ratios 99%
114   // Layer geometry:             Desired thumb positions:
115   // +--------------------+-+   +----------------------+   <-- 0px
116   // |                    |v|   |                     #|
117   // |                    |e|   |                     #|
118   // |                    |r|   |                     #|
119   // |                    |t|   |                     #|
120   // |                    |i|   |                     #|
121   // |                    |c|   |                     #|
122   // |                    |a|   |                     #|
123   // |                    |l|   |                     #|
124   // |                    | |   |                     #|
125   // |                    |l|   |                     #|
126   // |                    |a|   |                     #|
127   // |                    |y|   |                     #|
128   // |                    |e|   |                     #|
129   // |                    |r|   |                     #|
130   // +--------------------+-+   |                     #|
131   // | horizontal  layer  | |   |                     #|
132   // +--------------------+-+   |                     #|  <-- 950px
133   // |                      |   |                     #|
134   // |                      |   |##################### |
135   // +----------------------+   +----------------------+  <-- 1000px
136   //
137   // The layer geometry is set up for a 950px tall viewport, but the user can
138   // actually see down to 1000px. Thus we have to move the quad for the
139   // horizontal scrollbar down by the vertical_adjust_ factor and lay the
140   // vertical thumb out on a track lengthed by the vertical_adjust_ factor. This
141   // means the quads may extend outside the layer's bounds.
142 
143   // With the length known, we can compute the thumb's position.
144   float track_length = TrackLength();
145   int thumb_length = ThumbLength();
146   int thumb_thickness = ThumbThickness();
147 
148   // With the length known, we can compute the thumb's position.
149   float clamped_current_pos =
150       std::min(std::max(current_pos_, 0.f), static_cast<float>(maximum_));
151   float ratio = clamped_current_pos / maximum_;
152   float max_offset = track_length - thumb_length;
153   int thumb_offset = static_cast<int>(ratio * max_offset) + TrackStart();
154 
155   float thumb_thickness_adjustment =
156       thumb_thickness * (1.f - thumb_thickness_scale_factor_);
157 
158   gfx::RectF thumb_rect;
159   if (orientation_ == HORIZONTAL) {
160     thumb_rect = gfx::RectF(thumb_offset,
161                             vertical_adjust_ + thumb_thickness_adjustment,
162                             thumb_length,
163                             thumb_thickness - thumb_thickness_adjustment);
164   } else {
165     thumb_rect = gfx::RectF(
166         is_left_side_vertical_scrollbar_
167             ? bounds().width() - thumb_thickness
168             : thumb_thickness_adjustment,
169         thumb_offset,
170         thumb_thickness - thumb_thickness_adjustment,
171         thumb_length);
172   }
173 
174   return ScrollbarLayerRectToContentRect(thumb_rect);
175 }
176 
177 }  // namespace cc
178