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

Unified Diff: content/browser/web_contents/web_contents_view_aura.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
« no previous file with comments | « content/browser/web_contents/web_contents_view_aura.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/web_contents/web_contents_view_aura.cc
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index f7544eb39fd01245273e971fe5e47c2113da62ac..68e28b305701b2912c29cc1f56e1018a1799c0b0 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -22,6 +22,8 @@
#include "content/browser/renderer_host/web_input_event_aura.h"
#include "content/browser/web_contents/aura/gesture_nav_simple.h"
#include "content/browser/web_contents/aura/overscroll_navigation_overlay.h"
+#include "content/browser/web_contents/aura/shadow_layer_delegate.h"
+#include "content/browser/web_contents/aura/window_slider.h"
#include "content/browser/web_contents/touch_editable_impl_aura.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/content_browser_client.h"
@@ -49,6 +51,7 @@
#include "ui/aura/window_observer.h"
#include "ui/aura/window_tree_host.h"
#include "ui/aura/window_tree_host_observer.h"
+#include "ui/aura_extra/image_window_delegate.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/base/dragdrop/drag_drop_types.h"
@@ -57,6 +60,7 @@
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/canvas.h"
@@ -84,6 +88,18 @@
switches::kScrollEndEffect) == "1";
}
+bool ShouldNavigateForward(const NavigationController& controller,
+ OverscrollMode mode) {
+ return mode == (base::i18n::IsRTL() ? OVERSCROLL_EAST : OVERSCROLL_WEST) &&
+ controller.CanGoForward();
+}
+
+bool ShouldNavigateBack(const NavigationController& controller,
+ OverscrollMode mode) {
+ return mode == (base::i18n::IsRTL() ? OVERSCROLL_WEST : OVERSCROLL_EAST) &&
+ controller.CanGoBack();
+}
+
RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
RenderWidgetHostView* view) {
if (!view || RenderViewHostFactory::has_factory())
@@ -96,6 +112,65 @@
return NULL;
return static_cast<RenderWidgetHostViewAura*>(view);
}
+
+// The window delegate for the overscroll window. This redirects trackpad events
+// to the web-contents window. The delegate destroys itself when the window is
+// destroyed.
+class OverscrollWindowDelegate : public aura_extra::ImageWindowDelegate {
+ public:
+ OverscrollWindowDelegate(WebContentsImpl* web_contents,
+ OverscrollMode overscroll_mode)
+ : web_contents_(web_contents),
+ forward_events_(true) {
+ const NavigationControllerImpl& controller = web_contents->GetController();
+ const NavigationEntryImpl* entry = NULL;
+ if (ShouldNavigateForward(controller, overscroll_mode)) {
+ entry = controller.GetEntryAtOffset(1);
+ } else if (ShouldNavigateBack(controller, overscroll_mode)) {
+ entry = controller.GetEntryAtOffset(-1);
+ }
+
+ gfx::Image image;
+ if (entry && entry->screenshot().get()) {
+ std::vector<gfx::ImagePNGRep> image_reps;
+ image_reps.push_back(gfx::ImagePNGRep(entry->screenshot(), 1.0f));
+ image = gfx::Image(image_reps);
+ }
+ SetImage(image);
+ }
+
+ void stop_forwarding_events() { forward_events_ = false; }
+
+ private:
+ ~OverscrollWindowDelegate() override {}
+
+ aura::Window* web_contents_window() {
+ return web_contents_->GetView()->GetContentNativeView();
+ }
+
+ // Overridden from ui::EventHandler.
+ void OnScrollEvent(ui::ScrollEvent* event) override {
+ if (forward_events_ && web_contents_window())
+ web_contents_window()->delegate()->OnScrollEvent(event);
+ }
+
+ void OnGestureEvent(ui::GestureEvent* event) override {
+ if (forward_events_ && web_contents_window())
+ web_contents_window()->delegate()->OnGestureEvent(event);
+ }
+
+ WebContentsImpl* web_contents_;
+
+ // The window is displayed both during the gesture, and after the gesture
+ // while the navigation is in progress. During the gesture, it is necessary to
+ // forward input events to the content page (e.g. when the overscroll window
+ // slides under the cursor and starts receiving scroll events). However, once
+ // the gesture is complete, and the window is being displayed as an overlay
+ // window during navigation, events should not be forwarded anymore.
+ bool forward_events_;
+
+ DISALLOW_COPY_AND_ASSIGN(OverscrollWindowDelegate);
+};
// Listens to all mouse drag events during a drag and drop and sends them to
// the renderer.
@@ -656,16 +731,17 @@
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, public:
-WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
- WebContentsViewDelegate* delegate)
+WebContentsViewAura::WebContentsViewAura(
+ WebContentsImpl* web_contents,
+ WebContentsViewDelegate* delegate)
: web_contents_(web_contents),
delegate_(delegate),
current_drag_op_(blink::WebDragOperationNone),
drag_dest_delegate_(NULL),
current_rvh_for_drag_(NULL),
+ overscroll_change_brightness_(false),
current_overscroll_gesture_(OVERSCROLL_NONE),
completed_overscroll_gesture_(OVERSCROLL_NONE),
- navigation_overlay_(nullptr),
touch_editable_(TouchEditableImplAura::Create()),
is_or_was_visible_(false) {
}
@@ -730,9 +806,86 @@
return;
}
view->overscroll_controller()->set_delegate(this);
- if (!navigation_overlay_) {
- navigation_overlay_.reset(
- new OverscrollNavigationOverlay(web_contents_, window_.get()));
+ if (!navigation_overlay_)
+ navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
+}
+
+void WebContentsViewAura::PrepareOverscrollWindow() {
+ // If there is an existing |overscroll_window_| which is in the middle of an
+ // animation, then destroying the window here causes the animation to be
+ // completed immediately, which triggers |OnImplicitAnimationsCompleted()|
+ // callback, and that tries to reset |overscroll_window_| again, causing a
+ // double-free. So use a temporary variable here.
+ if (overscroll_window_) {
+ base::AutoReset<OverscrollMode> reset_state(&current_overscroll_gesture_,
+ current_overscroll_gesture_);
+ scoped_ptr<aura::Window> reset_window(overscroll_window_.release());
+ }
+
+ OverscrollWindowDelegate* overscroll_delegate = new OverscrollWindowDelegate(
+ web_contents_,
+ current_overscroll_gesture_);
+ overscroll_window_.reset(new aura::Window(overscroll_delegate));
+ overscroll_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
+ overscroll_window_->SetTransparent(true);
+ overscroll_window_->Init(ui::LAYER_TEXTURED);
+ overscroll_window_->layer()->SetMasksToBounds(false);
+ overscroll_window_->SetName("OverscrollOverlay");
+
+ overscroll_change_brightness_ = overscroll_delegate->has_image();
+ window_->AddChild(overscroll_window_.get());
+
+ gfx::Rect bounds = gfx::Rect(window_->bounds().size());
+ if (ShouldNavigateForward(web_contents_->GetController(),
+ current_overscroll_gesture_)) {
+ // The overlay will be sliding in from the right edge towards the left in
+ // non-RTL, or sliding in from the left edge towards the right in RTL.
+ // So position the overlay window accordingly.
+ bounds.Offset(base::i18n::IsRTL() ? -bounds.width() : bounds.width(), 0);
+ }
+
+ aura::Window* animate_window = GetWindowToAnimateForOverscroll();
+ if (animate_window == overscroll_window_)
+ window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
+ else
+ window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
+
+ UpdateOverscrollWindowBrightness(0.f);
+
+ overscroll_window_->SetBounds(bounds);
+ overscroll_window_->Show();
+
+ overscroll_shadow_.reset(new ShadowLayerDelegate(animate_window->layer()));
+}
+
+void WebContentsViewAura::PrepareContentWindowForOverscroll() {
+ StopObservingImplicitAnimations();
+ aura::Window* content = GetContentNativeView();
+ content->layer()->GetAnimator()->AbortAllAnimations();
+ content->SetTransform(gfx::Transform());
+ content->layer()->SetLayerBrightness(0.f);
+}
+
+void WebContentsViewAura::ResetOverscrollTransform() {
+ if (!web_contents_->GetRenderWidgetHostView())
+ return;
+ aura::Window* target = GetWindowToAnimateForOverscroll();
+ if (!target)
+ return;
+ {
+ ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
+ settings.AddObserver(this);
+ target->SetTransform(gfx::Transform());
+ }
+ {
+ ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
+ UpdateOverscrollWindowBrightness(0.f);
}
}
@@ -740,10 +893,91 @@
if (!web_contents_->GetRenderWidgetHostView())
return;
+ // Animate out the current view first. Navigate to the requested history at
+ // the end of the animation.
+ if (current_overscroll_gesture_ == OVERSCROLL_NONE)
+ return;
+
UMA_HISTOGRAM_ENUMERATION("Overscroll.Navigated",
current_overscroll_gesture_, OVERSCROLL_COUNT);
-
- navigation_overlay_->relay_delegate()->OnOverscrollComplete(mode);
+ OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
+ overscroll_window_->delegate());
+ delegate->stop_forwarding_events();
+
+ completed_overscroll_gesture_ = mode;
+ aura::Window* target = GetWindowToAnimateForOverscroll();
+ ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(
+ ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
+ settings.SetTweenType(gfx::Tween::EASE_OUT);
+ settings.AddObserver(this);
+ gfx::Transform transform;
+ int content_width =
+ web_contents_->GetRenderWidgetHostView()->GetViewBounds().width();
+ float translate_x = static_cast<float>(mode == OVERSCROLL_WEST ?
+ -content_width : content_width);
+ transform.Translate(translate_x, 0);
+ target->SetTransform(transform);
+ UpdateOverscrollWindowBrightness(translate_x);
+}
+
+aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
+ if (current_overscroll_gesture_ == OVERSCROLL_NONE)
+ return NULL;
+
+ return ShouldNavigateForward(web_contents_->GetController(),
+ current_overscroll_gesture_) ?
+ overscroll_window_.get() : GetContentNativeView();
+}
+
+gfx::Vector2dF WebContentsViewAura::GetTranslationForOverscroll(float delta_x,
+ float delta_y) {
+ if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
+ current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
+ return gfx::Vector2dF(0, delta_y);
+ }
+ // For horizontal overscroll, scroll freely if a navigation is possible. Do a
+ // resistive scroll otherwise.
+ const NavigationControllerImpl& controller = web_contents_->GetController();
+ const gfx::Rect& bounds = GetViewBounds();
+ const float bounds_width = static_cast<float>(bounds.width());
+ if (ShouldNavigateForward(controller, current_overscroll_gesture_))
+ return gfx::Vector2dF(std::max(-bounds_width, delta_x), 0);
+ else if (ShouldNavigateBack(controller, current_overscroll_gesture_))
+ return gfx::Vector2dF(std::min(bounds_width, delta_x), 0);
+ return gfx::Vector2dF();
+}
+
+void WebContentsViewAura::PrepareOverscrollNavigationOverlay() {
+ OverscrollWindowDelegate* delegate = static_cast<OverscrollWindowDelegate*>(
+ overscroll_window_->delegate());
+ overscroll_window_->SchedulePaintInRect(
+ gfx::Rect(overscroll_window_->bounds().size()));
+ overscroll_window_->SetBounds(gfx::Rect(window_->bounds().size()));
+ overscroll_window_->SetTransform(gfx::Transform());
+ navigation_overlay_->SetOverlayWindow(overscroll_window_.Pass(),
+ delegate);
+ navigation_overlay_->StartObserving();
+}
+
+void WebContentsViewAura::UpdateOverscrollWindowBrightness(float delta_x) {
+ if (!overscroll_change_brightness_)
+ return;
+
+ const float kBrightnessMin = -.1f;
+ const float kBrightnessMax = -.01f;
+
+ float ratio = fabs(delta_x) / GetViewBounds().width();
+ ratio = std::min(1.f, ratio);
+ if (base::i18n::IsRTL())
+ ratio = 1.f - ratio;
+ float brightness = current_overscroll_gesture_ == OVERSCROLL_WEST ?
+ kBrightnessMin + ratio * (kBrightnessMax - kBrightnessMin) :
+ kBrightnessMax - ratio * (kBrightnessMax - kBrightnessMin);
+ brightness = std::max(kBrightnessMin, brightness);
+ brightness = std::min(kBrightnessMax, brightness);
+ aura::Window* window = GetWindowToAnimateForOverscroll();
+ window->layer()->SetLayerBrightness(brightness);
}
void WebContentsViewAura::AttachTouchEditableToRenderView() {
@@ -902,6 +1136,10 @@
view->InitAsChild(NULL);
GetNativeView()->AddChild(view->GetNativeView());
+ if (navigation_overlay_.get() && navigation_overlay_->has_window()) {
+ navigation_overlay_->StartObserving();
+ }
+
RenderWidgetHostImpl* host_impl =
RenderWidgetHostImpl::From(render_widget_host);
@@ -934,6 +1172,8 @@
}
void WebContentsViewAura::RenderViewSwappedIn(RenderViewHost* host) {
+ if (navigation_overlay_.get() && navigation_overlay_->has_window())
+ navigation_overlay_->StartObserving();
AttachTouchEditableToRenderView();
}
@@ -948,10 +1188,8 @@
if (!enabled)
navigation_overlay_.reset();
- if (!navigation_overlay_) {
- navigation_overlay_.reset(
- new OverscrollNavigationOverlay(web_contents_, window_.get()));
- }
+ else if (!navigation_overlay_)
+ navigation_overlay_.reset(new OverscrollNavigationOverlay(web_contents_));
}
////////////////////////////////////////////////////////////////////////////////
@@ -1077,13 +1315,21 @@
if (current_overscroll_gesture_ == OVERSCROLL_NONE)
return false;
+ aura::Window* target = GetWindowToAnimateForOverscroll();
+ gfx::Vector2dF translate = GetTranslationForOverscroll(delta_x, delta_y);
+ gfx::Transform transform;
+
if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
- OverscrollUpdateForWebContentsDelegate(delta_y);
- return delta_y != 0;
- }
- return navigation_overlay_->relay_delegate()->OnOverscrollUpdate(delta_x,
- delta_y);
+ OverscrollUpdateForWebContentsDelegate(translate.y());
+ } else {
+ // Only horizontal overscrolls participate in the navigation gesture.
+ transform.Translate(translate.x(), translate.y());
+ target->SetTransform(transform);
+ UpdateOverscrollWindowBrightness(delta_x);
+ }
+
+ return !translate.IsZero();
}
void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
@@ -1093,25 +1339,79 @@
(mode == OVERSCROLL_NORTH || mode == OVERSCROLL_SOUTH)) {
web_contents_->GetDelegate()->OverscrollComplete();
}
- CompleteOverscrollNavigation(mode);
+ NavigationControllerImpl& controller = web_contents_->GetController();
+ if (ShouldNavigateForward(controller, mode) ||
+ ShouldNavigateBack(controller, mode)) {
+ CompleteOverscrollNavigation(mode);
+ return;
+ }
+
+ ResetOverscrollTransform();
}
void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
OverscrollMode new_mode) {
+ // Reset any in-progress overscroll animation first.
+ ResetOverscrollTransform();
+
if (old_mode == OVERSCROLL_NORTH || old_mode == OVERSCROLL_SOUTH)
OverscrollUpdateForWebContentsDelegate(0);
if (new_mode != OVERSCROLL_NONE && touch_editable_)
touch_editable_->OverscrollStarted();
- if (current_overscroll_gesture_ == OVERSCROLL_NONE &&
- new_mode != OVERSCROLL_NONE) {
+ if (new_mode == OVERSCROLL_NONE ||
+ !GetContentNativeView() ||
+ ((new_mode == OVERSCROLL_EAST || new_mode == OVERSCROLL_WEST) &&
+ navigation_overlay_.get() && navigation_overlay_->has_window())) {
+ current_overscroll_gesture_ = OVERSCROLL_NONE;
+ } else {
+ aura::Window* target = GetWindowToAnimateForOverscroll();
+ if (target) {
+ StopObservingImplicitAnimations();
+ target->layer()->GetAnimator()->AbortAllAnimations();
+ }
+ // Cleanup state of the content window first, because that can reset the
+ // value of |current_overscroll_gesture_|.
+ PrepareContentWindowForOverscroll();
+
+ current_overscroll_gesture_ = new_mode;
+ if (current_overscroll_gesture_ == OVERSCROLL_EAST ||
+ current_overscroll_gesture_ == OVERSCROLL_WEST)
+ PrepareOverscrollWindow();
+
UMA_HISTOGRAM_ENUMERATION("Overscroll.Started", new_mode, OVERSCROLL_COUNT);
}
- current_overscroll_gesture_ = new_mode;
- navigation_overlay_->relay_delegate()->OnOverscrollModeChange(old_mode,
- new_mode);
completed_overscroll_gesture_ = OVERSCROLL_NONE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
+
+void WebContentsViewAura::OnImplicitAnimationsCompleted() {
+ overscroll_shadow_.reset();
+
+ if (ShouldNavigateForward(web_contents_->GetController(),
+ completed_overscroll_gesture_)) {
+ web_contents_->GetController().GoForward();
+ PrepareOverscrollNavigationOverlay();
+ } else if (ShouldNavigateBack(web_contents_->GetController(),
+ completed_overscroll_gesture_)) {
+ web_contents_->GetController().GoBack();
+ PrepareOverscrollNavigationOverlay();
+ } else {
+ if (touch_editable_)
+ touch_editable_->OverscrollCompleted();
+ }
+
+ aura::Window* content = GetContentNativeView();
+ if (content) {
+ content->SetTransform(gfx::Transform());
+ content->layer()->SetLayerBrightness(0.f);
+ }
+ current_overscroll_gesture_ = OVERSCROLL_NONE;
+ completed_overscroll_gesture_ = OVERSCROLL_NONE;
+ overscroll_window_.reset();
}
////////////////////////////////////////////////////////////////////////////////
@@ -1191,6 +1491,7 @@
// virtual functions to be called (e.g. OnImplicitAnimationsCompleted()). So
// destroy the overscroll window here.
navigation_overlay_.reset();
+ overscroll_window_.reset();
}
void WebContentsViewAura::OnWindowDestroyed(aura::Window* window) {
« no previous file with comments | « content/browser/web_contents/web_contents_view_aura.h ('k') | content/content_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698