OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.h" | 5 #include "chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.h" |
6 | 6 |
7 ScrollEndEffectController* ScrollEndEffectController::Create() { | 7 #include "chrome/browser/ui/views/frame/browser_frame.h" |
8 return new ScrollEndEffectControllerAsh(); | 8 #include "chrome/browser/ui/views/frame/browser_view.h" |
9 #include "content/public/browser/web_contents.h" | |
10 #include "content/public/browser/web_contents_view.h" | |
11 #include "ui/aura/window.h" | |
12 #include "ui/compositor/layer_type.h" | |
13 #include "ui/gfx/rect.h" | |
14 #include "ui/gfx/transform.h" | |
15 | |
16 namespace { | |
17 // This factor is used to control how much translation is applied relative to | |
18 // the size of the window. Specifically translation is limited to a max of | |
19 // window_size * factor. | |
20 const float kScrollEndEffectFactor = 0.10; | |
9 } | 21 } |
10 | 22 |
11 ScrollEndEffectControllerAsh::ScrollEndEffectControllerAsh() { | 23 ScrollEndEffectController* ScrollEndEffectController::Create( |
24 BrowserView* view) { | |
25 return new ScrollEndEffectControllerAsh(view); | |
26 } | |
27 | |
28 ScrollEndEffectControllerAsh::ScrollEndEffectControllerAsh(BrowserView* view) | |
29 : browser_view_(view), | |
30 is_effect_active_(false), | |
31 browser_frame_layer_(NULL), | |
32 web_contents_layer_(NULL), | |
33 non_client_layer_(NULL), | |
34 web_contents_parent_(NULL), | |
35 non_client_view_(NULL) { | |
12 } | 36 } |
13 | 37 |
14 ScrollEndEffectControllerAsh::~ScrollEndEffectControllerAsh() { | 38 ScrollEndEffectControllerAsh::~ScrollEndEffectControllerAsh() { |
15 } | 39 } |
16 | 40 |
17 void ScrollEndEffectControllerAsh::OverscrollUpdate(int delta_y) { | 41 void ScrollEndEffectControllerAsh::OverscrollUpdate(int delta_y) { |
18 // TODO(rharrison): Implement initial version of scroll end effect | 42 if (browser_view_ == NULL || browser_view_->frame() == NULL) { |
43 return; | |
44 } | |
45 | |
46 if (delta_y == 0 && is_effect_active_) { | |
47 if (browser_frame_layer_) { | |
48 ApplyDelta(browser_frame_layer_, browser_frame_layer_->bounds(), 0); | |
49 DeactivateEffect(); | |
50 } | |
51 return; | |
52 } | |
53 | |
54 if (!is_effect_active_) | |
55 ActivateEffect(); | |
56 | |
57 int capped_delta_y = delta_y; | |
58 gfx::Rect bounds = browser_frame_layer_->bounds(); | |
59 // Limiting the delta size being a proportion of the frame bounds size. | |
60 if (capped_delta_y > 0) { | |
61 capped_delta_y = std::min(static_cast<int>(roundf(bounds.height() * | |
62 kScrollEndEffectFactor)), | |
63 capped_delta_y); | |
64 } else if (capped_delta_y < 0) { | |
65 capped_delta_y = -std::min(static_cast<int>(roundf(bounds.height() * | |
66 kScrollEndEffectFactor)), | |
67 -capped_delta_y); | |
68 } | |
69 ApplyDelta(browser_frame_layer_, bounds, capped_delta_y); | |
19 } | 70 } |
71 | |
72 void ScrollEndEffectControllerAsh::ActivateEffect() { | |
73 is_effect_active_ = true; | |
74 | |
75 // Get layers for all of the parts to be manipulated | |
76 browser_frame_layer_ = browser_view_->frame()->GetLayer(); | |
77 web_contents_layer_ = browser_view_-> GetActiveWebContents()->GetView()-> | |
78 GetNativeView()->layer(); | |
79 non_client_view_ = browser_view_->frame()->GetContentsView(); | |
80 non_client_view_->SetPaintToLayer(true); | |
81 non_client_layer_ = non_client_view_->layer(); | |
82 non_client_layer_->SetFillsBoundsOpaquely(false); | |
83 // non_client_layer_->SetOpacity(0.5); | |
84 | |
85 CHECK(web_contents_layer_ != NULL); | |
sadrul
2013/08/20 16:14:59
CHECK(web_contents_layer_), or CHECK_NE
rharrison
2013/08/20 19:57:41
Done.
| |
86 CHECK(non_client_layer_ != NULL); | |
87 | |
88 // Setup clipping layers | |
89 frame_clipping_layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN)); | |
90 frame_clipping_layer_->set_name("OverscrollFrameClippingLayer"); | |
91 frame_clipping_layer_->SetMasksToBounds(true); | |
92 gfx::Rect frame_clipping_bounds = browser_frame_layer_->bounds(); | |
93 frame_clipping_bounds.set_origin(gfx::Point(0,0)); | |
sadrul
2013/08/20 16:14:59
gfx::Point()
rharrison
2013/08/20 19:57:41
Done.
| |
94 frame_clipping_layer_->SetBounds(frame_clipping_bounds); | |
95 | |
96 web_clipping_layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN)); | |
97 web_clipping_layer_->set_name("OverscrollWebClippingLayer"); | |
98 web_clipping_layer_->SetMasksToBounds(true); | |
99 gfx::Rect web_clipping_bounds = browser_frame_layer_->bounds(); | |
100 non_content_height_ = browser_frame_layer_->bounds().height() - | |
101 web_contents_layer_->bounds().height(); | |
102 web_clipping_bounds.set_height(browser_frame_layer_->bounds().height() - | |
103 non_content_height_); | |
104 web_clipping_bounds.set_origin(gfx::Point(0, non_content_height_)); | |
105 web_clipping_layer_->SetBounds(web_clipping_bounds); | |
106 | |
107 // Move the web contents since bounds are relative to the parent layer | |
108 gfx::Rect web_contents_bounds = web_clipping_bounds; | |
109 web_contents_parent_ = web_contents_layer_->parent(); | |
110 web_contents_bounds.set_origin(gfx::Point(0, 0)); | |
111 web_contents_bounds_ = web_contents_layer_->bounds(); | |
112 web_contents_layer_->SetBounds(web_contents_bounds); | |
113 | |
114 // Adjust the toplogy of the layer tree to add clipping layers | |
115 browser_frame_layer_->Add(frame_clipping_layer_.get()); | |
116 frame_clipping_layer_->Add(non_client_layer_); | |
117 frame_clipping_layer_->Add(web_clipping_layer_.get()); | |
118 web_clipping_layer_->Add(web_contents_layer_); | |
sadrul
2013/08/20 16:14:59
I think this looks reasonable. Two notes:
* Is it
rharrison
2013/08/20 19:57:41
Done.
| |
119 } | |
120 | |
121 void ScrollEndEffectControllerAsh::DeactivateEffect() { | |
122 is_effect_active_ = false; | |
123 | |
124 web_contents_layer_->SetBounds(web_contents_bounds_); | |
125 web_contents_parent_->Add(web_contents_layer_); | |
126 web_contents_parent_ = NULL; | |
127 web_contents_layer_ = NULL; | |
128 | |
129 frame_clipping_layer_->Remove(non_client_layer_); | |
130 non_client_view_->SetPaintToLayer(false); | |
131 non_client_layer_ = NULL; | |
132 non_client_view_ = NULL; | |
133 | |
134 frame_clipping_layer_->Remove(web_clipping_layer_.get()); | |
135 web_clipping_layer_.reset(); | |
136 browser_frame_layer_->Remove(frame_clipping_layer_.get()); | |
137 frame_clipping_layer_.reset(); | |
138 browser_frame_layer_ = NULL; | |
139 } | |
140 | |
141 void ScrollEndEffectControllerAsh::ApplyDelta(ui::Layer* frame, | |
142 gfx::Rect bounds, | |
143 int delta_y) { | |
144 float scale_factor = std::abs(delta_y); | |
145 scale_factor /= bounds.height(); | |
146 scale_factor = 1 - scale_factor; | |
147 | |
148 gfx::Transform frame_transform; | |
149 if (delta_y > 0) { | |
150 frame_transform.Translate(0, delta_y); | |
151 frame_transform.Scale(1, scale_factor); | |
152 } else { | |
153 frame_transform.Scale(1, scale_factor); | |
154 } | |
155 gfx::Transform counter_transform; | |
156 CHECK(frame_transform.GetInverse(&counter_transform)); | |
157 frame->SetTransform(frame_transform); | |
158 | |
159 // Ensure that we apply the counter translation about origin of the web | |
160 // contents | |
161 gfx::Transform web_to_frame_transform; | |
162 web_to_frame_transform.Translate(0, -non_content_height_); | |
163 gfx::Transform frame_to_web_transform; | |
164 frame_to_web_transform.Translate(0, non_content_height_); | |
165 gfx::Transform web_clipping_transform = counter_transform; | |
166 web_clipping_transform.ConcatTransform(web_to_frame_transform); | |
167 web_clipping_transform.PreconcatTransform(frame_to_web_transform); | |
168 | |
169 if (delta_y >= 0) { | |
170 web_clipping_transform.Translate(0, delta_y); | |
171 } | |
172 web_clipping_layer_->SetTransform(web_clipping_transform); | |
173 | |
174 if (delta_y <= 0) { | |
175 gfx::Transform web_contents_transform; | |
176 web_contents_transform.Translate(0, delta_y); | |
177 web_contents_layer_->SetTransform(web_contents_transform); | |
178 } | |
179 | |
180 gfx::Transform non_client_transform = counter_transform; | |
181 if (delta_y >= 0) { | |
182 non_client_transform.Translate(0, delta_y); | |
183 } | |
184 non_client_layer_->SetTransform(non_client_transform); | |
185 } | |
186 | |
OLD | NEW |