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

Unified Diff: content/browser/web_contents/aura/window_slider.cc

Issue 1076743003: Revert of Refactor GestureNavigation to eliminate code redundancy (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/web_contents/aura/window_slider.cc
diff --git a/content/browser/web_contents/aura/window_slider.cc b/content/browser/web_contents/aura/window_slider.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f7ffa7e38392c0607513efa7219946bd47d34ba5
--- /dev/null
+++ b/content/browser/web_contents/aura/window_slider.cc
@@ -0,0 +1,309 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/web_contents/aura/window_slider.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
+#include "content/public/browser/overscroll_configuration.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer_animation_observer.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/events/event.h"
+
+namespace content {
+
+namespace {
+
+// An animation observer that runs a callback at the end of the animation, and
+// destroys itself.
+class CallbackAnimationObserver : public ui::ImplicitAnimationObserver {
+ public:
+ CallbackAnimationObserver(const base::Closure& closure)
+ : closure_(closure) {
+ }
+
+ ~CallbackAnimationObserver() override {}
+
+ private:
+ // Overridden from ui::ImplicitAnimationObserver:
+ void OnImplicitAnimationsCompleted() override {
+ if (!closure_.is_null())
+ closure_.Run();
+ base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ }
+
+ const base::Closure closure_;
+
+ DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
+};
+
+} // namespace
+
+WindowSlider::WindowSlider(Delegate* delegate,
+ aura::Window* event_window,
+ aura::Window* owner)
+ : delegate_(delegate),
+ event_window_(event_window),
+ owner_(owner),
+ active_animator_(NULL),
+ delta_x_(0.f),
+ active_start_threshold_(0.f),
+ start_threshold_touchscreen_(content::GetOverscrollConfig(
+ content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN)),
+ start_threshold_touchpad_(content::GetOverscrollConfig(
+ content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD)),
+ complete_threshold_(content::GetOverscrollConfig(
+ content::OVERSCROLL_CONFIG_HORIZ_THRESHOLD_COMPLETE)),
+ weak_factory_(this) {
+ event_window_->AddPreTargetHandler(this);
+
+ event_window_->AddObserver(this);
+ owner_->AddObserver(this);
+}
+
+WindowSlider::~WindowSlider() {
+ if (event_window_) {
+ event_window_->RemovePreTargetHandler(this);
+ event_window_->RemoveObserver(this);
+ }
+ if (owner_)
+ owner_->RemoveObserver(this);
+ delegate_->OnWindowSliderDestroyed();
+}
+
+void WindowSlider::ChangeOwner(aura::Window* new_owner) {
+ if (owner_)
+ owner_->RemoveObserver(this);
+ owner_ = new_owner;
+ if (owner_) {
+ owner_->AddObserver(this);
+ UpdateForScroll(0.f, 0.f);
+ }
+}
+
+bool WindowSlider::IsSlideInProgress() const {
+ // if active_start_threshold_ is 0, it means that sliding hasn't been started
+ return active_start_threshold_ != 0 && (slider_.get() || active_animator_);
+}
+
+void WindowSlider::SetupSliderLayer() {
+ ui::Layer* parent = owner_->layer()->parent();
+ parent->Add(slider_.get());
+ if (delta_x_ < 0)
+ parent->StackAbove(slider_.get(), owner_->layer());
+ else
+ parent->StackBelow(slider_.get(), owner_->layer());
+ slider_->SetBounds(owner_->layer()->bounds());
+ slider_->SetVisible(true);
+}
+
+void WindowSlider::UpdateForScroll(float x_offset, float y_offset) {
+ if (active_animator_) {
+ // If there is an active animation, complete it before processing the scroll
+ // so that the callbacks that are invoked on the Delegate are consistent.
+ // Completing the animation may destroy WindowSlider through the animation
+ // callback, so we can't continue processing the scroll event here.
+ delta_x_ += x_offset;
+ CompleteActiveAnimations();
+ return;
+ }
+
+ float old_delta = delta_x_;
+ delta_x_ += x_offset;
+ if (fabs(delta_x_) < active_start_threshold_ && !slider_.get())
+ return;
+
+ if ((old_delta < 0 && delta_x_ > 0) ||
+ (old_delta > 0 && delta_x_ < 0)) {
+ slider_.reset();
+ shadow_.reset();
+ }
+
+ float translate = 0.f;
+ ui::Layer* translate_layer = NULL;
+
+ if (!slider_.get()) {
+ slider_.reset(delta_x_ < 0 ? delegate_->CreateFrontLayer() :
+ delegate_->CreateBackLayer());
+ if (!slider_.get())
+ return;
+ SetupSliderLayer();
+ }
+
+ if (delta_x_ <= -active_start_threshold_) {
+ translate = owner_->bounds().width() +
+ std::max(delta_x_ + active_start_threshold_,
+ static_cast<float>(-owner_->bounds().width()));
+ translate_layer = slider_.get();
+ } else if (delta_x_ >= active_start_threshold_) {
+ translate = std::min(delta_x_ - active_start_threshold_,
+ static_cast<float>(owner_->bounds().width()));
+ translate_layer = owner_->layer();
+ } else {
+ return;
+ }
+
+ if (!shadow_.get())
+ shadow_.reset(new ShadowLayerDelegate(translate_layer));
+
+ gfx::Transform transform;
+ transform.Translate(translate, 0);
+ translate_layer->SetTransform(transform);
+}
+
+void WindowSlider::CompleteOrResetSlide() {
+ if (!slider_.get())
+ return;
+
+ int width = owner_->bounds().width();
+ float ratio = (fabs(delta_x_) - active_start_threshold_) / width;
+ if (ratio < complete_threshold_) {
+ ResetSlide();
+ return;
+ }
+
+ ui::Layer* sliding = delta_x_ < 0 ? slider_.get() : owner_->layer();
+ active_animator_ = sliding->GetAnimator();
+
+ ui::ScopedLayerAnimationSettings settings(active_animator_);
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
+ settings.AddObserver(new CallbackAnimationObserver(
+ base::Bind(&WindowSlider::SlideAnimationCompleted,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(&slider_),
+ base::Passed(&shadow_))));
+
+ gfx::Transform transform;
+ transform.Translate(delta_x_ < 0 ? 0 : width, 0);
+ delta_x_ = 0;
+ delegate_->OnWindowSlideCompleting();
+ sliding->SetTransform(transform);
+}
+
+void WindowSlider::CompleteActiveAnimations() {
+ if (active_animator_)
+ active_animator_->StopAnimating();
+}
+
+void WindowSlider::ResetSlide() {
+ if (!slider_.get())
+ return;
+
+ // Reset the state of the sliding layer.
+ if (slider_.get()) {
+ ui::Layer* translate_layer;
+ gfx::Transform transform;
+ if (delta_x_ < 0) {
+ translate_layer = slider_.get();
+ transform.Translate(translate_layer->bounds().width(), 0);
+ } else {
+ translate_layer = owner_->layer();
+ }
+
+ active_animator_ = translate_layer->GetAnimator();
+ ui::ScopedLayerAnimationSettings settings(active_animator_);
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
+ settings.AddObserver(new CallbackAnimationObserver(
+ base::Bind(&WindowSlider::ResetSlideAnimationCompleted,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(&slider_),
+ base::Passed(&shadow_))));
+ translate_layer->SetTransform(transform);
+ }
+
+ delta_x_ = 0.f;
+}
+
+void WindowSlider::SlideAnimationCompleted(
+ scoped_ptr<ui::Layer> layer, scoped_ptr<ShadowLayerDelegate> shadow) {
+ active_animator_ = NULL;
+ shadow.reset();
+ delegate_->OnWindowSlideCompleted(layer.Pass());
+}
+
+void WindowSlider::ResetSlideAnimationCompleted(
+ scoped_ptr<ui::Layer> layer, scoped_ptr<ShadowLayerDelegate> shadow) {
+ active_animator_ = NULL;
+ shadow.reset();
+ layer.reset();
+ delegate_->OnWindowSlideAborted();
+}
+
+void WindowSlider::OnKeyEvent(ui::KeyEvent* event) {
+ ResetSlide();
+}
+
+void WindowSlider::OnMouseEvent(ui::MouseEvent* event) {
+ if (!(event->flags() & ui::EF_IS_SYNTHESIZED))
+ ResetSlide();
+}
+
+void WindowSlider::OnScrollEvent(ui::ScrollEvent* event) {
+ active_start_threshold_ = start_threshold_touchpad_;
+ if (event->type() == ui::ET_SCROLL)
+ UpdateForScroll(event->x_offset_ordinal(), event->y_offset_ordinal());
+ else if (event->type() == ui::ET_SCROLL_FLING_START)
+ CompleteOrResetSlide();
+ else
+ ResetSlide();
+ event->SetHandled();
+}
+
+void WindowSlider::OnGestureEvent(ui::GestureEvent* event) {
+ active_start_threshold_ = start_threshold_touchscreen_;
+ const ui::GestureEventDetails& details = event->details();
+ switch (event->type()) {
+ case ui::ET_GESTURE_SCROLL_BEGIN:
+ CompleteActiveAnimations();
+ break;
+
+ case ui::ET_GESTURE_SCROLL_UPDATE:
+ UpdateForScroll(details.scroll_x(), details.scroll_y());
+ break;
+
+ case ui::ET_GESTURE_SCROLL_END:
+ CompleteOrResetSlide();
+ break;
+
+ case ui::ET_SCROLL_FLING_START:
+ CompleteOrResetSlide();
+ break;
+
+ case ui::ET_GESTURE_PINCH_BEGIN:
+ case ui::ET_GESTURE_PINCH_UPDATE:
+ case ui::ET_GESTURE_PINCH_END:
+ ResetSlide();
+ break;
+
+ default:
+ break;
+ }
+
+ event->SetHandled();
+}
+
+void WindowSlider::OnWindowRemovingFromRootWindow(aura::Window* window,
+ aura::Window* new_root) {
+ if (window == event_window_) {
+ window->RemoveObserver(this);
+ window->RemovePreTargetHandler(this);
+ event_window_ = NULL;
+ } else if (window == owner_) {
+ window->RemoveObserver(this);
+ owner_ = NULL;
+ delete this;
+ } else {
+ NOTREACHED();
+ }
+}
+
+} // namespace content
« no previous file with comments | « content/browser/web_contents/aura/window_slider.h ('k') | content/browser/web_contents/aura/window_slider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698