Chromium Code Reviews| 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 |