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

Side by Side Diff: content/browser/web_contents/aura/gesture_nav_simple.cc

Issue 2656463002: Implement MD simple gesture nav (Closed)
Patch Set: Rebased Created 3 years, 10 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "content/browser/web_contents/aura/gesture_nav_simple.h" 5 #include "content/browser/web_contents/aura/gesture_nav_simple.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "cc/layers/layer.h"
11 #include "cc/paint/paint_flags.h" 10 #include "cc/paint/paint_flags.h"
12 #include "content/browser/frame_host/navigation_controller_impl.h" 11 #include "content/browser/frame_host/navigation_controller_impl.h"
13 #include "content/browser/renderer_host/overscroll_controller.h" 12 #include "content/browser/renderer_host/overscroll_controller.h"
14 #include "content/browser/web_contents/web_contents_impl.h" 13 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/browser/web_contents/web_contents_view.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/overscroll_configuration.h" 14 #include "content/public/browser/overscroll_configuration.h"
18 #include "content/public/common/content_client.h" 15 #include "third_party/skia/include/core/SkDrawLooper.h"
19 #include "ui/aura/window.h" 16 #include "ui/aura/window.h"
20 #include "ui/compositor/layer.h" 17 #include "ui/compositor/layer.h"
21 #include "ui/compositor/layer_animation_observer.h"
22 #include "ui/compositor/layer_delegate.h" 18 #include "ui/compositor/layer_delegate.h"
23 #include "ui/compositor/paint_recorder.h" 19 #include "ui/compositor/paint_recorder.h"
24 #include "ui/compositor/scoped_layer_animation_settings.h" 20 #include "ui/gfx/animation/animation_delegate.h"
21 #include "ui/gfx/animation/linear_animation.h"
25 #include "ui/gfx/animation/tween.h" 22 #include "ui/gfx/animation/tween.h"
26 #include "ui/gfx/canvas.h" 23 #include "ui/gfx/canvas.h"
27 #include "ui/gfx/image/image.h" 24 #include "ui/gfx/color_palette.h"
28 #include "ui/resources/grit/ui_resources.h" 25 #include "ui/gfx/paint_vector_icon.h"
26 #include "ui/gfx/shadow_value.h"
27 #include "ui/gfx/skia_paint_util.h"
28 #include "ui/vector_icons/vector_icons.h"
29 29
30 namespace content { 30 namespace content {
31 31
32 namespace { 32 namespace {
33 33
34 const int kArrowHeight = 280; 34 // Parameters defining the arrow icon inside the affordance.
35 const int kArrowWidth = 140; 35 const int kArrowSize = 16;
36 const float kMinOpacity = 0.25f; 36 const SkColor kArrowColor = gfx::kGoogleBlue500;
37
38 // Parameters defining the background circle of the affordance.
39 const int kBackgroundRadius = 18;
40 const SkColor kBackgroundColor = SK_ColorWHITE;
41 const int kBgShadowOffsetY = 2;
42 const int kBgShadowBlurRadius = 8;
43 const SkColor kBgShadowColor = SkColorSetA(SK_ColorBLACK, 0x4D);
44
45 // Parameters defining the affordance ripple. The ripple fades in and grows as
46 // the user drags the affordance until it reaches |kMaxRippleRadius|. If the
47 // overscroll is successful, the ripple will burst by fading out and growing to
48 // |kMaxRippleBurstRadius|.
49 const int kMaxRippleRadius = 54;
50 const SkColor kRippleColor = SkColorSetA(gfx::kGoogleBlue500, 0x33);
51 const int kMaxRippleBurstRadius = 72;
52 const gfx::Tween::Type kBurstAnimationTweenType = gfx::Tween::EASE_IN;
53 const int kRippleBurstAnimationDuration = 160;
54
55 // Offset of the affordance when it is at the maximum distance with content
56 // border. Since the affordance is initially out of content bounds, this is the
57 // offset of the farther side of the affordance (which equals 128 + 18).
58 const int kMaxAffordanceOffset = 146;
59
60 // Parameters defining animation when the affordance is aborted.
61 const gfx::Tween::Type kAbortAnimationTweenType = gfx::Tween::EASE_IN;
62 const int kAbortAnimationDuration = 300;
37 63
38 bool ShouldNavigateForward(const NavigationController& controller, 64 bool ShouldNavigateForward(const NavigationController& controller,
39 OverscrollMode mode) { 65 OverscrollMode mode) {
40 return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) && 66 return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
41 controller.CanGoForward(); 67 controller.CanGoForward();
42 } 68 }
43 69
44 bool ShouldNavigateBack(const NavigationController& controller, 70 bool ShouldNavigateBack(const NavigationController& controller,
45 OverscrollMode mode) { 71 OverscrollMode mode) {
46 return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) && 72 return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
47 controller.CanGoBack(); 73 controller.CanGoBack();
48 } 74 }
49 75
50 // An animation observers that deletes itself and a pointer after the end of the 76 } // namespace
51 // animation. 77
52 template <class T> 78 // This class is responsible for creating, painting, and positioning the layer
53 class DeleteAfterAnimation : public ui::ImplicitAnimationObserver { 79 // for the gesture nav affordance.
80 class GestureNavSimple::Affordance : public ui::LayerDelegate,
81 public gfx::AnimationDelegate {
54 public: 82 public:
55 explicit DeleteAfterAnimation(std::unique_ptr<T> object) 83 Affordance(OverscrollMode mode, const gfx::Rect& content_bounds);
56 : object_(std::move(object)) {} 84 ~Affordance() override;
85
86 // Sets progress of affordance drag as a value between 0 and 1.
87 void SetDragProgress(float progress);
88
89 // Aborts the affordance and animates it back. This will delete |this|
90 // instance after the animation.
91 void Abort();
92
93 // Completes the affordance by doing a ripple burst animation. This will
94 // delete |this| instance after the animation.
95 void Complete();
96
97 // Returns the root layer of the affordance.
98 ui::Layer* root_layer() const { return root_layer_.get(); }
57 99
58 private: 100 private:
59 friend class base::DeleteHelper<DeleteAfterAnimation<T> >; 101 enum class State { DRAGGING, ABORTING, COMPLETING };
60 102
61 ~DeleteAfterAnimation() override {} 103 void UpdateTransform();
62 104 void SchedulePaint();
63 // ui::ImplicitAnimationObserver: 105 void SetAbortProgress(float progress);
64 void OnImplicitAnimationsCompleted() override { 106 void SetCompleteProgress(float progress);
65 // Deleting an observer when a ScopedLayerAnimationSettings is iterating 107
66 // over them can cause a crash (which can happen during tests). So instead, 108 // ui::LayerDelegate:
67 // schedule this observer to be deleted soon. 109 void OnPaintLayer(const ui::PaintContext& context) override;
68 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this); 110 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
111 void OnDeviceScaleFactorChanged(float device_scale_factor) override;
112
113 // gfx::AnimationDelegate:
114 void AnimationEnded(const gfx::Animation* animation) override;
115 void AnimationProgressed(const gfx::Animation* animation) override;
116 void AnimationCanceled(const gfx::Animation* animation) override;
117
118 const OverscrollMode mode_;
119
120 // Root layer of the affordance. This is used to clip the affordance to the
121 // content bounds.
122 std::unique_ptr<ui::Layer> root_layer_;
123
124 // Layer that actually paints the affordance.
125 std::unique_ptr<ui::Layer> painted_layer_;
126
127 // Arrow image to be used for the affordance.
128 const gfx::Image image_;
129
130 // Values that determine current state of the affordance.
131 State state_ = State::DRAGGING;
132 float drag_progress_ = 0.f;
133 float abort_progress_ = 0.f;
134 float complete_progress_ = 0.f;
135
136 std::unique_ptr<gfx::LinearAnimation> animation_;
137
138 DISALLOW_COPY_AND_ASSIGN(Affordance);
139 };
140
141 GestureNavSimple::Affordance::Affordance(OverscrollMode mode,
142 const gfx::Rect& content_bounds)
143 : mode_(mode),
144 root_layer_(base::MakeUnique<ui::Layer>(ui::LAYER_NOT_DRAWN)),
145 painted_layer_(base::MakeUnique<ui::Layer>(ui::LAYER_TEXTURED)),
146 image_(gfx::CreateVectorIcon(
147 mode == OVERSCROLL_EAST ? ui::kBackArrowIcon : ui::kForwardArrowIcon,
148 kArrowSize,
149 kArrowColor)) {
150 DCHECK(mode == OVERSCROLL_EAST || mode == OVERSCROLL_WEST);
151 DCHECK(!image_.IsEmpty());
152
153 root_layer_->SetBounds(content_bounds);
154 root_layer_->SetMasksToBounds(true);
155
156 painted_layer_->SetFillsBoundsOpaquely(false);
157 int x =
158 mode_ == OVERSCROLL_EAST
159 ? -kMaxRippleBurstRadius - kBackgroundRadius
160 : content_bounds.width() - kMaxRippleBurstRadius + kBackgroundRadius;
161 int y = std::max(0, content_bounds.height() / 2 - kMaxRippleBurstRadius);
162 painted_layer_->SetBounds(
163 gfx::Rect(x, y, 2 * kMaxRippleBurstRadius, 2 * kMaxRippleBurstRadius));
164 painted_layer_->set_delegate(this);
165
166 root_layer_->Add(painted_layer_.get());
167 }
168
169 GestureNavSimple::Affordance::~Affordance() {}
170
171 void GestureNavSimple::Affordance::SetDragProgress(float progress) {
172 DCHECK_EQ(State::DRAGGING, state_);
173 DCHECK_LE(0.f, progress);
174 DCHECK_GE(1.f, progress);
175
176 if (drag_progress_ == progress)
177 return;
178 drag_progress_ = progress;
179
180 UpdateTransform();
181 SchedulePaint();
182 }
183
184 void GestureNavSimple::Affordance::Abort() {
185 DCHECK_EQ(State::DRAGGING, state_);
186
187 state_ = State::ABORTING;
188
189 animation_.reset(
190 new gfx::LinearAnimation(drag_progress_ * kAbortAnimationDuration,
191 gfx::LinearAnimation::kDefaultFrameRate, this));
192 animation_->Start();
193 }
194
195 void GestureNavSimple::Affordance::Complete() {
196 DCHECK_EQ(State::DRAGGING, state_);
197 DCHECK_EQ(1.f, drag_progress_);
198
199 state_ = State::COMPLETING;
200
201 animation_.reset(
202 new gfx::LinearAnimation(kRippleBurstAnimationDuration,
203 gfx::LinearAnimation::kDefaultFrameRate, this));
204 animation_->Start();
205 }
206
207 void GestureNavSimple::Affordance::UpdateTransform() {
208 float offset = (1 - abort_progress_) * drag_progress_ * kMaxAffordanceOffset;
209 gfx::Transform transform;
210 transform.Translate(mode_ == OVERSCROLL_EAST ? offset : -offset, 0);
211 painted_layer_->SetTransform(transform);
212 }
213
214 void GestureNavSimple::Affordance::SchedulePaint() {
215 painted_layer_->SchedulePaint(gfx::Rect(painted_layer_->size()));
216 }
217
218 void GestureNavSimple::Affordance::SetAbortProgress(float progress) {
219 DCHECK_EQ(State::ABORTING, state_);
220 DCHECK_LE(0.f, progress);
221 DCHECK_GE(1.f, progress);
222
223 if (abort_progress_ == progress)
224 return;
225 abort_progress_ = progress;
226
227 UpdateTransform();
228 SchedulePaint();
229 }
230
231 void GestureNavSimple::Affordance::SetCompleteProgress(float progress) {
232 DCHECK_EQ(State::COMPLETING, state_);
233 DCHECK_LE(0.f, progress);
234 DCHECK_GE(1.f, progress);
235
236 if (complete_progress_ == progress)
237 return;
238 complete_progress_ = progress;
239
240 painted_layer_->SetOpacity(1 - complete_progress_);
241 SchedulePaint();
242 }
243
244 void GestureNavSimple::Affordance::OnPaintLayer(
245 const ui::PaintContext& context) {
246 DCHECK(drag_progress_ == 1.f || state_ != State::COMPLETING);
247 DCHECK(abort_progress_ == 0.f || state_ == State::ABORTING);
248 DCHECK(complete_progress_ == 0.f || state_ == State::COMPLETING);
249
250 ui::PaintRecorder recorder(context, painted_layer_->size());
251 gfx::Canvas* canvas = recorder.canvas();
252
253 gfx::PointF center_point(kMaxRippleBurstRadius, kMaxRippleBurstRadius);
254 float progress = (1 - abort_progress_) * drag_progress_;
255
256 // Draw the ripple.
257 cc::PaintFlags ripple_paint;
258 ripple_paint.setAntiAlias(true);
259 ripple_paint.setStyle(cc::PaintFlags::kFill_Style);
260 ripple_paint.setColor(kRippleColor);
261 float ripple_radius;
262 if (state_ == State::COMPLETING) {
263 ripple_radius =
264 kMaxRippleRadius +
265 complete_progress_ * (kMaxRippleBurstRadius - kMaxRippleRadius);
266 } else {
267 ripple_radius =
268 kBackgroundRadius + progress * (kMaxRippleRadius - kBackgroundRadius);
69 } 269 }
70 270 canvas->DrawCircle(center_point, ripple_radius, ripple_paint);
71 std::unique_ptr<T> object_; 271
72 DISALLOW_COPY_AND_ASSIGN(DeleteAfterAnimation); 272 // Draw the arrow background circle with the shadow.
73 }; 273 cc::PaintFlags bg_paint;
74 274 bg_paint.setAntiAlias(true);
75 } // namespace 275 bg_paint.setStyle(cc::PaintFlags::kFill_Style);
76 276 bg_paint.setColor(kBackgroundColor);
77 // A layer delegate that paints the shield with the arrow in it. 277 gfx::ShadowValues shadow;
78 class ArrowLayerDelegate : public ui::LayerDelegate { 278 shadow.emplace_back(gfx::Vector2d(0, kBgShadowOffsetY), kBgShadowBlurRadius,
79 public: 279 kBgShadowColor);
80 explicit ArrowLayerDelegate(int resource_id) 280 bg_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadow));
81 : image_(GetContentClient()->GetNativeImageNamed(resource_id)), 281 canvas->DrawCircle(center_point, kBackgroundRadius, bg_paint);
82 left_arrow_(resource_id == IDR_BACK_ARROW) { 282
83 CHECK(!image_.IsEmpty()); 283 // Draw the arrow.
284 float arrow_x = center_point.x() - kArrowSize / 2.f;
285 float arrow_y = center_point.y() - kArrowSize / 2.f;
286 // Calculate the offset for the arrow relative to its circular background.
287 float arrow_x_offset =
288 (1 - progress) * (-kBackgroundRadius + kArrowSize / 2.f);
289 arrow_x += mode_ == OVERSCROLL_EAST ? arrow_x_offset : -arrow_x_offset;
290 uint8_t arrow_alpha =
291 static_cast<uint8_t>(std::min(0xFF, static_cast<int>(progress * 0xFF)));
292 canvas->DrawImageInt(*image_.ToImageSkia(), static_cast<int>(arrow_x),
293 static_cast<int>(arrow_y), arrow_alpha);
294 }
295
296 void GestureNavSimple::Affordance::OnDelegatedFrameDamage(
297 const gfx::Rect& damage_rect_in_dip) {}
298
299 void GestureNavSimple::Affordance::OnDeviceScaleFactorChanged(
300 float device_scale_factor) {}
301
302 void GestureNavSimple::Affordance::AnimationEnded(
303 const gfx::Animation* animation) {
304 delete this;
305 }
306
307 void GestureNavSimple::Affordance::AnimationProgressed(
308 const gfx::Animation* animation) {
309 switch (state_) {
310 case State::DRAGGING:
311 NOTREACHED();
312 break;
313 case State::ABORTING:
314 SetAbortProgress(gfx::Tween::CalculateValue(
315 kAbortAnimationTweenType, animation->GetCurrentValue()));
316 break;
317 case State::COMPLETING:
318 SetCompleteProgress(gfx::Tween::CalculateValue(
319 kBurstAnimationTweenType, animation->GetCurrentValue()));
320 break;
84 } 321 }
85 322 }
86 ~ArrowLayerDelegate() override {} 323
87 324 void GestureNavSimple::Affordance::AnimationCanceled(
88 bool left() const { return left_arrow_; } 325 const gfx::Animation* animation) {
89 326 NOTREACHED();
90 private: 327 }
91 // ui::LayerDelegate: 328
92 void OnPaintLayer(const ui::PaintContext& context) override {
93 cc::PaintFlags paint;
94 paint.setColor(SkColorSetARGB(0xa0, 0, 0, 0));
95 paint.setStyle(cc::PaintFlags::kFill_Style);
96 paint.setAntiAlias(true);
97
98 // Set the recording size to be the size of the |arrow_| layer, and draw a
99 // half circle (the other half will be clipped), then an arrow image inside
100 // it.
101 ui::PaintRecorder recorder(context, gfx::Size(kArrowWidth, kArrowHeight));
102 recorder.canvas()->DrawCircle(
103 gfx::Point(left_arrow_ ? 0 : kArrowWidth, kArrowHeight / 2),
104 kArrowWidth, paint);
105 recorder.canvas()->DrawImageInt(
106 *image_.ToImageSkia(), left_arrow_ ? 0 : kArrowWidth - image_.Width(),
107 (kArrowHeight - image_.Height()) / 2);
108 }
109
110 void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
111
112 void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
113
114 const gfx::Image& image_;
115 const bool left_arrow_;
116
117 DISALLOW_COPY_AND_ASSIGN(ArrowLayerDelegate);
118 };
119 329
120 GestureNavSimple::GestureNavSimple(WebContentsImpl* web_contents) 330 GestureNavSimple::GestureNavSimple(WebContentsImpl* web_contents)
121 : web_contents_(web_contents), 331 : web_contents_(web_contents),
122 completion_threshold_(0.f) {} 332 completion_threshold_(0.f) {}
123 333
124 GestureNavSimple::~GestureNavSimple() {} 334 GestureNavSimple::~GestureNavSimple() {}
125 335
126 void GestureNavSimple::ApplyEffectsAndDestroy(const gfx::Transform& transform,
127 float opacity) {
128 ui::Layer* layer = arrow_.get();
129 ui::ScopedLayerAnimationSettings settings(arrow_->GetAnimator());
130 settings.AddObserver(
131 new DeleteAfterAnimation<ArrowLayerDelegate>(std::move(arrow_delegate_)));
132 settings.AddObserver(new DeleteAfterAnimation<ui::Layer>(std::move(arrow_)));
133 settings.AddObserver(
134 new DeleteAfterAnimation<ui::Layer>(std::move(clip_layer_)));
135 layer->SetTransform(transform);
136 layer->SetOpacity(opacity);
137 }
138
139 void GestureNavSimple::AbortGestureAnimation() { 336 void GestureNavSimple::AbortGestureAnimation() {
140 if (!arrow_) 337 if (!affordance_)
141 return; 338 return;
142 gfx::Transform transform; 339 // Release the unique pointer. The affordance will delete itself upon
143 transform.Translate(arrow_delegate_->left() ? -kArrowWidth : kArrowWidth, 0); 340 // completion of animation.
144 ApplyEffectsAndDestroy(transform, kMinOpacity); 341 Affordance* affordance = affordance_.release();
342 affordance->Abort();
145 } 343 }
146 344
147 void GestureNavSimple::CompleteGestureAnimation() { 345 void GestureNavSimple::CompleteGestureAnimation() {
148 if (!arrow_) 346 if (!affordance_)
149 return; 347 return;
150 // Make sure the fade-out starts from the complete state. 348 // Release the unique pointer. The affordance will delete itself upon
151 ApplyEffectsForDelta(completion_threshold_); 349 // completion of animation.
152 ApplyEffectsAndDestroy(arrow_->transform(), 0.f); 350 Affordance* affordance = affordance_.release();
153 } 351 affordance->Complete();
154
155 bool GestureNavSimple::ApplyEffectsForDelta(float delta_x) {
156 if (!arrow_)
157 return false;
158 CHECK_GT(completion_threshold_, 0.f);
159 CHECK_GE(delta_x, 0.f);
160 double complete = std::min(1.f, delta_x / completion_threshold_);
161 float translate_x = gfx::Tween::FloatValueBetween(complete, -kArrowWidth, 0);
162 gfx::Transform transform;
163 transform.Translate(arrow_delegate_->left() ? translate_x : -translate_x,
164 0.f);
165 arrow_->SetTransform(transform);
166 arrow_->SetOpacity(gfx::Tween::FloatValueBetween(complete, kMinOpacity, 1.f));
167 return true;
168 } 352 }
169 353
170 gfx::Rect GestureNavSimple::GetVisibleBounds() const { 354 gfx::Rect GestureNavSimple::GetVisibleBounds() const {
171 return web_contents_->GetNativeView()->bounds(); 355 return web_contents_->GetNativeView()->bounds();
172 } 356 }
173 357
174 bool GestureNavSimple::OnOverscrollUpdate(float delta_x, float delta_y) { 358 bool GestureNavSimple::OnOverscrollUpdate(float delta_x, float delta_y) {
175 return ApplyEffectsForDelta(std::abs(delta_x) + 50.f); 359 if (!affordance_)
360 return false;
361 affordance_->SetDragProgress(
362 std::min(1.f, std::abs(delta_x) / completion_threshold_));
363 return true;
176 } 364 }
177 365
178 void GestureNavSimple::OnOverscrollComplete(OverscrollMode overscroll_mode) { 366 void GestureNavSimple::OnOverscrollComplete(OverscrollMode overscroll_mode) {
179 CompleteGestureAnimation(); 367 CompleteGestureAnimation();
180 368
181 NavigationControllerImpl& controller = web_contents_->GetController(); 369 NavigationControllerImpl& controller = web_contents_->GetController();
182 if (ShouldNavigateForward(controller, overscroll_mode)) 370 if (ShouldNavigateForward(controller, overscroll_mode))
183 controller.GoForward(); 371 controller.GoForward();
184 else if (ShouldNavigateBack(controller, overscroll_mode)) 372 else if (ShouldNavigateBack(controller, overscroll_mode))
185 controller.GoBack(); 373 controller.GoBack();
186 } 374 }
187 375
188 void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode, 376 void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode,
189 OverscrollMode new_mode) { 377 OverscrollMode new_mode) {
190 NavigationControllerImpl& controller = web_contents_->GetController(); 378 NavigationControllerImpl& controller = web_contents_->GetController();
191 if (!ShouldNavigateForward(controller, new_mode) && 379 if (!ShouldNavigateForward(controller, new_mode) &&
192 !ShouldNavigateBack(controller, new_mode)) { 380 !ShouldNavigateBack(controller, new_mode)) {
193 AbortGestureAnimation(); 381 AbortGestureAnimation();
194 return; 382 return;
195 } 383 }
196 384
197 arrow_.reset(new ui::Layer(ui::LAYER_TEXTURED));
198 // Note that RTL doesn't affect the arrow that should be displayed.
199 int resource_id = 0;
200 if (new_mode == OVERSCROLL_WEST)
201 resource_id = IDR_FORWARD_ARROW;
202 else if (new_mode == OVERSCROLL_EAST)
203 resource_id = IDR_BACK_ARROW;
204 else
205 NOTREACHED();
206
207 arrow_delegate_.reset(new ArrowLayerDelegate(resource_id));
208 arrow_->set_delegate(arrow_delegate_.get());
209 arrow_->SetFillsBoundsOpaquely(false);
210
211 aura::Window* window = web_contents_->GetNativeView(); 385 aura::Window* window = web_contents_->GetNativeView();
212 const gfx::Rect& window_bounds = window->bounds(); 386 const gfx::Rect& window_bounds = window->bounds();
213 completion_threshold_ = window_bounds.width() * 387 completion_threshold_ =
214 GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE); 388 window_bounds.width() *
389 GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE) -
390 GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
215 391
216 // Align on the left or right edge. 392 affordance_.reset(new Affordance(new_mode, window_bounds));
217 int x = (resource_id == IDR_BACK_ARROW) ? 0 :
218 (window_bounds.width() - kArrowWidth);
219 // Align in the center vertically.
220 int y = std::max(0, (window_bounds.height() - kArrowHeight) / 2);
221 arrow_->SetBounds(gfx::Rect(x, y, kArrowWidth, kArrowHeight));
222 ApplyEffectsForDelta(0.f);
223 393
224 // Adding the arrow as a child of the content window is not sufficient, 394 // Adding the affordance as a child of the content window is not sufficient,
225 // because it is possible for a new layer to be parented on top of the arrow 395 // because it is possible for a new layer to be parented on top of the
226 // layer (e.g. when the navigated-to page is displayed while the completion 396 // affordance layer (e.g. when the navigated-to page is displayed while the
227 // animation is in progress). So instead, a clip layer (that doesn't paint) is 397 // completion animation is in progress). So instead, it is installed on top of
228 // installed on top of the content window as its sibling, and the arrow layer 398 // the content window as its sibling. Note that the affordance itself makes
229 // is added to that clip layer. 399 // sure that its contents are clipped to the bounds given to it.
230 clip_layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN));
231 clip_layer_->SetBounds(window->layer()->bounds());
232 clip_layer_->SetMasksToBounds(true);
233 clip_layer_->Add(arrow_.get());
234
235 ui::Layer* parent = window->layer()->parent(); 400 ui::Layer* parent = window->layer()->parent();
236 parent->Add(clip_layer_.get()); 401 parent->Add(affordance_->root_layer());
237 parent->StackAtTop(clip_layer_.get()); 402 parent->StackAtTop(affordance_->root_layer());
238 } 403 }
239 404
240 } // namespace content 405 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698