| Index: content/browser/web_contents/aura/gesture_nav_simple.cc
|
| diff --git a/content/browser/web_contents/aura/gesture_nav_simple.cc b/content/browser/web_contents/aura/gesture_nav_simple.cc
|
| index cef6749cae6cc9163613a7aee38f8e069d97eab5..e6c3601ecb7129d54fc003f2f688f6f05298029c 100644
|
| --- a/content/browser/web_contents/aura/gesture_nav_simple.cc
|
| +++ b/content/browser/web_contents/aura/gesture_nav_simple.cc
|
| @@ -7,33 +7,59 @@
|
| #include <utility>
|
|
|
| #include "base/macros.h"
|
| -#include "cc/layers/layer.h"
|
| #include "cc/paint/paint_flags.h"
|
| #include "content/browser/frame_host/navigation_controller_impl.h"
|
| #include "content/browser/renderer_host/overscroll_controller.h"
|
| #include "content/browser/web_contents/web_contents_impl.h"
|
| -#include "content/browser/web_contents/web_contents_view.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/overscroll_configuration.h"
|
| -#include "content/public/common/content_client.h"
|
| +#include "third_party/skia/include/core/SkDrawLooper.h"
|
| #include "ui/aura/window.h"
|
| #include "ui/compositor/layer.h"
|
| -#include "ui/compositor/layer_animation_observer.h"
|
| #include "ui/compositor/layer_delegate.h"
|
| #include "ui/compositor/paint_recorder.h"
|
| -#include "ui/compositor/scoped_layer_animation_settings.h"
|
| +#include "ui/gfx/animation/animation_delegate.h"
|
| +#include "ui/gfx/animation/linear_animation.h"
|
| #include "ui/gfx/animation/tween.h"
|
| #include "ui/gfx/canvas.h"
|
| -#include "ui/gfx/image/image.h"
|
| -#include "ui/resources/grit/ui_resources.h"
|
| +#include "ui/gfx/color_palette.h"
|
| +#include "ui/gfx/paint_vector_icon.h"
|
| +#include "ui/gfx/shadow_value.h"
|
| +#include "ui/gfx/skia_paint_util.h"
|
| +#include "ui/vector_icons/vector_icons.h"
|
|
|
| namespace content {
|
|
|
| namespace {
|
|
|
| -const int kArrowHeight = 280;
|
| -const int kArrowWidth = 140;
|
| -const float kMinOpacity = 0.25f;
|
| +// Parameters defining the arrow icon inside the affordance.
|
| +const int kArrowSize = 16;
|
| +const SkColor kArrowColor = gfx::kGoogleBlue500;
|
| +
|
| +// Parameters defining the background circle of the affordance.
|
| +const int kBackgroundRadius = 18;
|
| +const SkColor kBackgroundColor = SK_ColorWHITE;
|
| +const int kBgShadowOffsetY = 2;
|
| +const int kBgShadowBlurRadius = 8;
|
| +const SkColor kBgShadowColor = SkColorSetA(SK_ColorBLACK, 0x4D);
|
| +
|
| +// Parameters defining the affordance ripple. The ripple fades in and grows as
|
| +// the user drags the affordance until it reaches |kMaxRippleRadius|. If the
|
| +// overscroll is successful, the ripple will burst by fading out and growing to
|
| +// |kMaxRippleBurstRadius|.
|
| +const int kMaxRippleRadius = 54;
|
| +const SkColor kRippleColor = SkColorSetA(gfx::kGoogleBlue500, 0x33);
|
| +const int kMaxRippleBurstRadius = 72;
|
| +const gfx::Tween::Type kBurstAnimationTweenType = gfx::Tween::EASE_IN;
|
| +const int kRippleBurstAnimationDuration = 160;
|
| +
|
| +// Offset of the affordance when it is at the maximum distance with content
|
| +// border. Since the affordance is initially out of content bounds, this is the
|
| +// offset of the farther side of the affordance (which equals 128 + 18).
|
| +const int kMaxAffordanceOffset = 146;
|
| +
|
| +// Parameters defining animation when the affordance is aborted.
|
| +const gfx::Tween::Type kAbortAnimationTweenType = gfx::Tween::EASE_IN;
|
| +const int kAbortAnimationDuration = 300;
|
|
|
| bool ShouldNavigateForward(const NavigationController& controller,
|
| OverscrollMode mode) {
|
| @@ -47,75 +73,259 @@ bool ShouldNavigateBack(const NavigationController& controller,
|
| controller.CanGoBack();
|
| }
|
|
|
| -// An animation observers that deletes itself and a pointer after the end of the
|
| -// animation.
|
| -template <class T>
|
| -class DeleteAfterAnimation : public ui::ImplicitAnimationObserver {
|
| +} // namespace
|
| +
|
| +// This class is responsible for creating, painting, and positioning the layer
|
| +// for the gesture nav affordance.
|
| +class GestureNavSimple::Affordance : public ui::LayerDelegate,
|
| + public gfx::AnimationDelegate {
|
| public:
|
| - explicit DeleteAfterAnimation(std::unique_ptr<T> object)
|
| - : object_(std::move(object)) {}
|
| + Affordance(OverscrollMode mode, const gfx::Rect& content_bounds);
|
| + ~Affordance() override;
|
| +
|
| + // Sets progress of affordance drag as a value between 0 and 1.
|
| + void SetDragProgress(float progress);
|
| +
|
| + // Aborts the affordance and animates it back. This will delete |this|
|
| + // instance after the animation.
|
| + void Abort();
|
| +
|
| + // Completes the affordance by doing a ripple burst animation. This will
|
| + // delete |this| instance after the animation.
|
| + void Complete();
|
| +
|
| + // Returns the root layer of the affordance.
|
| + ui::Layer* root_layer() const { return root_layer_.get(); }
|
|
|
| private:
|
| - friend class base::DeleteHelper<DeleteAfterAnimation<T> >;
|
| + enum class State { DRAGGING, ABORTING, COMPLETING };
|
|
|
| - ~DeleteAfterAnimation() override {}
|
| + void UpdateTransform();
|
| + void SchedulePaint();
|
| + void SetAbortProgress(float progress);
|
| + void SetCompleteProgress(float progress);
|
|
|
| - // ui::ImplicitAnimationObserver:
|
| - void OnImplicitAnimationsCompleted() override {
|
| - // Deleting an observer when a ScopedLayerAnimationSettings is iterating
|
| - // over them can cause a crash (which can happen during tests). So instead,
|
| - // schedule this observer to be deleted soon.
|
| - BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
|
| - }
|
| + // ui::LayerDelegate:
|
| + void OnPaintLayer(const ui::PaintContext& context) override;
|
| + void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
|
| + void OnDeviceScaleFactorChanged(float device_scale_factor) override;
|
| +
|
| + // gfx::AnimationDelegate:
|
| + void AnimationEnded(const gfx::Animation* animation) override;
|
| + void AnimationProgressed(const gfx::Animation* animation) override;
|
| + void AnimationCanceled(const gfx::Animation* animation) override;
|
|
|
| - std::unique_ptr<T> object_;
|
| - DISALLOW_COPY_AND_ASSIGN(DeleteAfterAnimation);
|
| + const OverscrollMode mode_;
|
| +
|
| + // Root layer of the affordance. This is used to clip the affordance to the
|
| + // content bounds.
|
| + std::unique_ptr<ui::Layer> root_layer_;
|
| +
|
| + // Layer that actually paints the affordance.
|
| + std::unique_ptr<ui::Layer> painted_layer_;
|
| +
|
| + // Arrow image to be used for the affordance.
|
| + const gfx::Image image_;
|
| +
|
| + // Values that determine current state of the affordance.
|
| + State state_ = State::DRAGGING;
|
| + float drag_progress_ = 0.f;
|
| + float abort_progress_ = 0.f;
|
| + float complete_progress_ = 0.f;
|
| +
|
| + std::unique_ptr<gfx::LinearAnimation> animation_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Affordance);
|
| };
|
|
|
| -} // namespace
|
| +GestureNavSimple::Affordance::Affordance(OverscrollMode mode,
|
| + const gfx::Rect& content_bounds)
|
| + : mode_(mode),
|
| + root_layer_(base::MakeUnique<ui::Layer>(ui::LAYER_NOT_DRAWN)),
|
| + painted_layer_(base::MakeUnique<ui::Layer>(ui::LAYER_TEXTURED)),
|
| + image_(gfx::CreateVectorIcon(
|
| + mode == OVERSCROLL_EAST ? ui::kBackArrowIcon : ui::kForwardArrowIcon,
|
| + kArrowSize,
|
| + kArrowColor)) {
|
| + DCHECK(mode == OVERSCROLL_EAST || mode == OVERSCROLL_WEST);
|
| + DCHECK(!image_.IsEmpty());
|
| +
|
| + root_layer_->SetBounds(content_bounds);
|
| + root_layer_->SetMasksToBounds(true);
|
| +
|
| + painted_layer_->SetFillsBoundsOpaquely(false);
|
| + int x =
|
| + mode_ == OVERSCROLL_EAST
|
| + ? -kMaxRippleBurstRadius - kBackgroundRadius
|
| + : content_bounds.width() - kMaxRippleBurstRadius + kBackgroundRadius;
|
| + int y = std::max(0, content_bounds.height() / 2 - kMaxRippleBurstRadius);
|
| + painted_layer_->SetBounds(
|
| + gfx::Rect(x, y, 2 * kMaxRippleBurstRadius, 2 * kMaxRippleBurstRadius));
|
| + painted_layer_->set_delegate(this);
|
| +
|
| + root_layer_->Add(painted_layer_.get());
|
| +}
|
|
|
| -// A layer delegate that paints the shield with the arrow in it.
|
| -class ArrowLayerDelegate : public ui::LayerDelegate {
|
| - public:
|
| - explicit ArrowLayerDelegate(int resource_id)
|
| - : image_(GetContentClient()->GetNativeImageNamed(resource_id)),
|
| - left_arrow_(resource_id == IDR_BACK_ARROW) {
|
| - CHECK(!image_.IsEmpty());
|
| - }
|
| +GestureNavSimple::Affordance::~Affordance() {}
|
|
|
| - ~ArrowLayerDelegate() override {}
|
| +void GestureNavSimple::Affordance::SetDragProgress(float progress) {
|
| + DCHECK_EQ(State::DRAGGING, state_);
|
| + DCHECK_LE(0.f, progress);
|
| + DCHECK_GE(1.f, progress);
|
|
|
| - bool left() const { return left_arrow_; }
|
| + if (drag_progress_ == progress)
|
| + return;
|
| + drag_progress_ = progress;
|
|
|
| - private:
|
| - // ui::LayerDelegate:
|
| - void OnPaintLayer(const ui::PaintContext& context) override {
|
| - cc::PaintFlags paint;
|
| - paint.setColor(SkColorSetARGB(0xa0, 0, 0, 0));
|
| - paint.setStyle(cc::PaintFlags::kFill_Style);
|
| - paint.setAntiAlias(true);
|
| -
|
| - // Set the recording size to be the size of the |arrow_| layer, and draw a
|
| - // half circle (the other half will be clipped), then an arrow image inside
|
| - // it.
|
| - ui::PaintRecorder recorder(context, gfx::Size(kArrowWidth, kArrowHeight));
|
| - recorder.canvas()->DrawCircle(
|
| - gfx::Point(left_arrow_ ? 0 : kArrowWidth, kArrowHeight / 2),
|
| - kArrowWidth, paint);
|
| - recorder.canvas()->DrawImageInt(
|
| - *image_.ToImageSkia(), left_arrow_ ? 0 : kArrowWidth - image_.Width(),
|
| - (kArrowHeight - image_.Height()) / 2);
|
| + UpdateTransform();
|
| + SchedulePaint();
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::Abort() {
|
| + DCHECK_EQ(State::DRAGGING, state_);
|
| +
|
| + state_ = State::ABORTING;
|
| +
|
| + animation_.reset(
|
| + new gfx::LinearAnimation(drag_progress_ * kAbortAnimationDuration,
|
| + gfx::LinearAnimation::kDefaultFrameRate, this));
|
| + animation_->Start();
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::Complete() {
|
| + DCHECK_EQ(State::DRAGGING, state_);
|
| + DCHECK_EQ(1.f, drag_progress_);
|
| +
|
| + state_ = State::COMPLETING;
|
| +
|
| + animation_.reset(
|
| + new gfx::LinearAnimation(kRippleBurstAnimationDuration,
|
| + gfx::LinearAnimation::kDefaultFrameRate, this));
|
| + animation_->Start();
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::UpdateTransform() {
|
| + float offset = (1 - abort_progress_) * drag_progress_ * kMaxAffordanceOffset;
|
| + gfx::Transform transform;
|
| + transform.Translate(mode_ == OVERSCROLL_EAST ? offset : -offset, 0);
|
| + painted_layer_->SetTransform(transform);
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::SchedulePaint() {
|
| + painted_layer_->SchedulePaint(gfx::Rect(painted_layer_->size()));
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::SetAbortProgress(float progress) {
|
| + DCHECK_EQ(State::ABORTING, state_);
|
| + DCHECK_LE(0.f, progress);
|
| + DCHECK_GE(1.f, progress);
|
| +
|
| + if (abort_progress_ == progress)
|
| + return;
|
| + abort_progress_ = progress;
|
| +
|
| + UpdateTransform();
|
| + SchedulePaint();
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::SetCompleteProgress(float progress) {
|
| + DCHECK_EQ(State::COMPLETING, state_);
|
| + DCHECK_LE(0.f, progress);
|
| + DCHECK_GE(1.f, progress);
|
| +
|
| + if (complete_progress_ == progress)
|
| + return;
|
| + complete_progress_ = progress;
|
| +
|
| + painted_layer_->SetOpacity(1 - complete_progress_);
|
| + SchedulePaint();
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::OnPaintLayer(
|
| + const ui::PaintContext& context) {
|
| + DCHECK(drag_progress_ == 1.f || state_ != State::COMPLETING);
|
| + DCHECK(abort_progress_ == 0.f || state_ == State::ABORTING);
|
| + DCHECK(complete_progress_ == 0.f || state_ == State::COMPLETING);
|
| +
|
| + ui::PaintRecorder recorder(context, painted_layer_->size());
|
| + gfx::Canvas* canvas = recorder.canvas();
|
| +
|
| + gfx::PointF center_point(kMaxRippleBurstRadius, kMaxRippleBurstRadius);
|
| + float progress = (1 - abort_progress_) * drag_progress_;
|
| +
|
| + // Draw the ripple.
|
| + cc::PaintFlags ripple_paint;
|
| + ripple_paint.setAntiAlias(true);
|
| + ripple_paint.setStyle(cc::PaintFlags::kFill_Style);
|
| + ripple_paint.setColor(kRippleColor);
|
| + float ripple_radius;
|
| + if (state_ == State::COMPLETING) {
|
| + ripple_radius =
|
| + kMaxRippleRadius +
|
| + complete_progress_ * (kMaxRippleBurstRadius - kMaxRippleRadius);
|
| + } else {
|
| + ripple_radius =
|
| + kBackgroundRadius + progress * (kMaxRippleRadius - kBackgroundRadius);
|
| }
|
| + canvas->DrawCircle(center_point, ripple_radius, ripple_paint);
|
| +
|
| + // Draw the arrow background circle with the shadow.
|
| + cc::PaintFlags bg_paint;
|
| + bg_paint.setAntiAlias(true);
|
| + bg_paint.setStyle(cc::PaintFlags::kFill_Style);
|
| + bg_paint.setColor(kBackgroundColor);
|
| + gfx::ShadowValues shadow;
|
| + shadow.emplace_back(gfx::Vector2d(0, kBgShadowOffsetY), kBgShadowBlurRadius,
|
| + kBgShadowColor);
|
| + bg_paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadow));
|
| + canvas->DrawCircle(center_point, kBackgroundRadius, bg_paint);
|
| +
|
| + // Draw the arrow.
|
| + float arrow_x = center_point.x() - kArrowSize / 2.f;
|
| + float arrow_y = center_point.y() - kArrowSize / 2.f;
|
| + // Calculate the offset for the arrow relative to its circular background.
|
| + float arrow_x_offset =
|
| + (1 - progress) * (-kBackgroundRadius + kArrowSize / 2.f);
|
| + arrow_x += mode_ == OVERSCROLL_EAST ? arrow_x_offset : -arrow_x_offset;
|
| + uint8_t arrow_alpha =
|
| + static_cast<uint8_t>(std::min(0xFF, static_cast<int>(progress * 0xFF)));
|
| + canvas->DrawImageInt(*image_.ToImageSkia(), static_cast<int>(arrow_x),
|
| + static_cast<int>(arrow_y), arrow_alpha);
|
| +}
|
|
|
| - void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
|
| +void GestureNavSimple::Affordance::OnDelegatedFrameDamage(
|
| + const gfx::Rect& damage_rect_in_dip) {}
|
|
|
| - void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
|
| +void GestureNavSimple::Affordance::OnDeviceScaleFactorChanged(
|
| + float device_scale_factor) {}
|
|
|
| - const gfx::Image& image_;
|
| - const bool left_arrow_;
|
| +void GestureNavSimple::Affordance::AnimationEnded(
|
| + const gfx::Animation* animation) {
|
| + delete this;
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::AnimationProgressed(
|
| + const gfx::Animation* animation) {
|
| + switch (state_) {
|
| + case State::DRAGGING:
|
| + NOTREACHED();
|
| + break;
|
| + case State::ABORTING:
|
| + SetAbortProgress(gfx::Tween::CalculateValue(
|
| + kAbortAnimationTweenType, animation->GetCurrentValue()));
|
| + break;
|
| + case State::COMPLETING:
|
| + SetCompleteProgress(gfx::Tween::CalculateValue(
|
| + kBurstAnimationTweenType, animation->GetCurrentValue()));
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void GestureNavSimple::Affordance::AnimationCanceled(
|
| + const gfx::Animation* animation) {
|
| + NOTREACHED();
|
| +}
|
|
|
| - DISALLOW_COPY_AND_ASSIGN(ArrowLayerDelegate);
|
| -};
|
|
|
| GestureNavSimple::GestureNavSimple(WebContentsImpl* web_contents)
|
| : web_contents_(web_contents),
|
| @@ -123,48 +333,22 @@ GestureNavSimple::GestureNavSimple(WebContentsImpl* web_contents)
|
|
|
| GestureNavSimple::~GestureNavSimple() {}
|
|
|
| -void GestureNavSimple::ApplyEffectsAndDestroy(const gfx::Transform& transform,
|
| - float opacity) {
|
| - ui::Layer* layer = arrow_.get();
|
| - ui::ScopedLayerAnimationSettings settings(arrow_->GetAnimator());
|
| - settings.AddObserver(
|
| - new DeleteAfterAnimation<ArrowLayerDelegate>(std::move(arrow_delegate_)));
|
| - settings.AddObserver(new DeleteAfterAnimation<ui::Layer>(std::move(arrow_)));
|
| - settings.AddObserver(
|
| - new DeleteAfterAnimation<ui::Layer>(std::move(clip_layer_)));
|
| - layer->SetTransform(transform);
|
| - layer->SetOpacity(opacity);
|
| -}
|
| -
|
| void GestureNavSimple::AbortGestureAnimation() {
|
| - if (!arrow_)
|
| + if (!affordance_)
|
| return;
|
| - gfx::Transform transform;
|
| - transform.Translate(arrow_delegate_->left() ? -kArrowWidth : kArrowWidth, 0);
|
| - ApplyEffectsAndDestroy(transform, kMinOpacity);
|
| + // Release the unique pointer. The affordance will delete itself upon
|
| + // completion of animation.
|
| + Affordance* affordance = affordance_.release();
|
| + affordance->Abort();
|
| }
|
|
|
| void GestureNavSimple::CompleteGestureAnimation() {
|
| - if (!arrow_)
|
| + if (!affordance_)
|
| return;
|
| - // Make sure the fade-out starts from the complete state.
|
| - ApplyEffectsForDelta(completion_threshold_);
|
| - ApplyEffectsAndDestroy(arrow_->transform(), 0.f);
|
| -}
|
| -
|
| -bool GestureNavSimple::ApplyEffectsForDelta(float delta_x) {
|
| - if (!arrow_)
|
| - return false;
|
| - CHECK_GT(completion_threshold_, 0.f);
|
| - CHECK_GE(delta_x, 0.f);
|
| - double complete = std::min(1.f, delta_x / completion_threshold_);
|
| - float translate_x = gfx::Tween::FloatValueBetween(complete, -kArrowWidth, 0);
|
| - gfx::Transform transform;
|
| - transform.Translate(arrow_delegate_->left() ? translate_x : -translate_x,
|
| - 0.f);
|
| - arrow_->SetTransform(transform);
|
| - arrow_->SetOpacity(gfx::Tween::FloatValueBetween(complete, kMinOpacity, 1.f));
|
| - return true;
|
| + // Release the unique pointer. The affordance will delete itself upon
|
| + // completion of animation.
|
| + Affordance* affordance = affordance_.release();
|
| + affordance->Complete();
|
| }
|
|
|
| gfx::Rect GestureNavSimple::GetVisibleBounds() const {
|
| @@ -172,7 +356,11 @@ gfx::Rect GestureNavSimple::GetVisibleBounds() const {
|
| }
|
|
|
| bool GestureNavSimple::OnOverscrollUpdate(float delta_x, float delta_y) {
|
| - return ApplyEffectsForDelta(std::abs(delta_x) + 50.f);
|
| + if (!affordance_)
|
| + return false;
|
| + affordance_->SetDragProgress(
|
| + std::min(1.f, std::abs(delta_x) / completion_threshold_));
|
| + return true;
|
| }
|
|
|
| void GestureNavSimple::OnOverscrollComplete(OverscrollMode overscroll_mode) {
|
| @@ -194,47 +382,24 @@ void GestureNavSimple::OnOverscrollModeChange(OverscrollMode old_mode,
|
| return;
|
| }
|
|
|
| - arrow_.reset(new ui::Layer(ui::LAYER_TEXTURED));
|
| - // Note that RTL doesn't affect the arrow that should be displayed.
|
| - int resource_id = 0;
|
| - if (new_mode == OVERSCROLL_WEST)
|
| - resource_id = IDR_FORWARD_ARROW;
|
| - else if (new_mode == OVERSCROLL_EAST)
|
| - resource_id = IDR_BACK_ARROW;
|
| - else
|
| - NOTREACHED();
|
| -
|
| - arrow_delegate_.reset(new ArrowLayerDelegate(resource_id));
|
| - arrow_->set_delegate(arrow_delegate_.get());
|
| - arrow_->SetFillsBoundsOpaquely(false);
|
| -
|
| aura::Window* window = web_contents_->GetNativeView();
|
| const gfx::Rect& window_bounds = window->bounds();
|
| - completion_threshold_ = window_bounds.width() *
|
| - GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE);
|
| -
|
| - // Align on the left or right edge.
|
| - int x = (resource_id == IDR_BACK_ARROW) ? 0 :
|
| - (window_bounds.width() - kArrowWidth);
|
| - // Align in the center vertically.
|
| - int y = std::max(0, (window_bounds.height() - kArrowHeight) / 2);
|
| - arrow_->SetBounds(gfx::Rect(x, y, kArrowWidth, kArrowHeight));
|
| - ApplyEffectsForDelta(0.f);
|
| -
|
| - // Adding the arrow as a child of the content window is not sufficient,
|
| - // because it is possible for a new layer to be parented on top of the arrow
|
| - // layer (e.g. when the navigated-to page is displayed while the completion
|
| - // animation is in progress). So instead, a clip layer (that doesn't paint) is
|
| - // installed on top of the content window as its sibling, and the arrow layer
|
| - // is added to that clip layer.
|
| - clip_layer_.reset(new ui::Layer(ui::LAYER_NOT_DRAWN));
|
| - clip_layer_->SetBounds(window->layer()->bounds());
|
| - clip_layer_->SetMasksToBounds(true);
|
| - clip_layer_->Add(arrow_.get());
|
| -
|
| + completion_threshold_ =
|
| + window_bounds.width() *
|
| + GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE) -
|
| + GetOverscrollConfig(OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
|
| +
|
| + affordance_.reset(new Affordance(new_mode, window_bounds));
|
| +
|
| + // Adding the affordance as a child of the content window is not sufficient,
|
| + // because it is possible for a new layer to be parented on top of the
|
| + // affordance layer (e.g. when the navigated-to page is displayed while the
|
| + // completion animation is in progress). So instead, it is installed on top of
|
| + // the content window as its sibling. Note that the affordance itself makes
|
| + // sure that its contents are clipped to the bounds given to it.
|
| ui::Layer* parent = window->layer()->parent();
|
| - parent->Add(clip_layer_.get());
|
| - parent->StackAtTop(clip_layer_.get());
|
| + parent->Add(affordance_->root_layer());
|
| + parent->StackAtTop(affordance_->root_layer());
|
| }
|
|
|
| } // namespace content
|
|
|