summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd6
-rw-r--r--chrome/browser/about_flags.cc9
-rw-r--r--content/browser/renderer_host/overscroll_controller.cc10
-rw-r--r--content/browser/renderer_host/overscroll_controller_delegate.h1
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.cc11
-rw-r--r--content/browser/renderer_host/render_widget_host_impl.h4
-rw-r--r--content/browser/web_contents/web_contents_view_aura.cc203
-rw-r--r--content/browser/web_contents/web_contents_view_aura.h48
-rw-r--r--content/public/common/content_switches.cc4
-rw-r--r--content/public/common/content_switches.h2
10 files changed, 291 insertions, 7 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 8dd4f8c..9649556 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -6362,6 +6362,12 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_FLAGS_ENABLE_EXPERIMENTAL_FORM_FILLING_DESCRIPTION" desc="Description for the flag to enable experimantal form filling feature">
Enable experimental form filling. Enables a collection of experimental features that make form filling easier.
</message>
+ <message name="IDS_FLAGS_ENABLE_OVERSCROLL_HISTORY_NAVIGATION_NAME" desc="Title for the flag to enable history navigation from horizontal overscroll.">
+ Enable overscroll history navigation
+ </message>
+ <message name="IDS_FLAGS_ENABLE_OVERSCROLL_HISTORY_NAVIGATION_DESCRIPTION" desc="Description for the flag to enable history navigation from horizontal overscroll.">
+ Enables experimental history navigation in response to horizontal overscroll.
+ </message>
<message name="IDS_FLAGS_SYNC_SEARCH_ENGINES_NAME" desc="Title for the flag to enable syncing the Search Engines datatype">
Enable syncing search engines
</message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 2fe7ca8..08bee24 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1116,6 +1116,15 @@ const Experiment kExperiments[] = {
kOsWin | kOsCrOS,
SINGLE_VALUE_TYPE(switches::kEnableInteractiveAutocomplete)
},
+#if defined(USE_AURA)
+ {
+ "enable-overscroll-history-navigation",
+ IDS_FLAGS_ENABLE_OVERSCROLL_HISTORY_NAVIGATION_NAME,
+ IDS_FLAGS_ENABLE_OVERSCROLL_HISTORY_NAVIGATION_DESCRIPTION,
+ kOsAll,
+ SINGLE_VALUE_TYPE(switches::kEnableOverscrollHistoryNavigation)
+ },
+#endif
};
const Experiment* experiments = kExperiments;
diff --git a/content/browser/renderer_host/overscroll_controller.cc b/content/browser/renderer_host/overscroll_controller.cc
index 906a270..ce23b17d 100644
--- a/content/browser/renderer_host/overscroll_controller.cc
+++ b/content/browser/renderer_host/overscroll_controller.cc
@@ -95,11 +95,11 @@ bool OverscrollController::DispatchEventCompletesAction (
const float kOverscrollVerticalThreshold = 0.20f;
float ratio, threshold;
if (overscroll_mode_ == OVERSCROLL_WEST ||
- overscroll_mode_ == OVERSCROLL_WEST) {
- ratio = overscroll_delta_x_ / bounds.width();
+ overscroll_mode_ == OVERSCROLL_EAST) {
+ ratio = fabs(overscroll_delta_x_) / bounds.width();
threshold = kOverscrollHorizontalThreshold;
} else {
- ratio = overscroll_delta_y_ / bounds.height();
+ ratio = fabs(overscroll_delta_y_) / bounds.height();
threshold = kOverscrollVerticalThreshold;
}
return ratio >= threshold;
@@ -160,7 +160,7 @@ void OverscrollController::ProcessEventForOverscroll(
}
default:
- NOTREACHED();
+ DCHECK(WebKit::WebInputEvent::isGestureEventType(event.type));
}
}
@@ -194,6 +194,8 @@ void OverscrollController::ProcessOverscroll(float delta_x, float delta_y) {
void OverscrollController::CompleteAction() {
if (delegate_)
delegate_->OnOverscrollComplete(overscroll_mode_);
+ overscroll_mode_ = OVERSCROLL_NONE;
+ overscroll_delta_x_ = overscroll_delta_y_ = 0.f;
}
void OverscrollController::SetOverscrollMode(OverscrollMode mode) {
diff --git a/content/browser/renderer_host/overscroll_controller_delegate.h b/content/browser/renderer_host/overscroll_controller_delegate.h
index b9cd7d9..6d40ed1 100644
--- a/content/browser/renderer_host/overscroll_controller_delegate.h
+++ b/content/browser/renderer_host/overscroll_controller_delegate.h
@@ -15,6 +15,7 @@ namespace content {
// should perform appropriate actions.
class OverscrollControllerDelegate {
public:
+ OverscrollControllerDelegate() {}
virtual ~OverscrollControllerDelegate() {}
// This is called for each update in the overscroll amount.
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 02a5ee5..a9dd74e 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -182,6 +182,13 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
// Because the widget initializes as is_hidden_ == false,
// tell the process host that we're alive.
process_->WidgetRestored();
+
+#if defined(USE_AURA)
+ bool overscroll_enabled = CommandLine::ForCurrentProcess()->
+ HasSwitch(switches::kEnableOverscrollHistoryNavigation);
+ if (overscroll_enabled)
+ InitializeOverscrollController();
+#endif
}
RenderWidgetHostImpl::~RenderWidgetHostImpl() {
@@ -1070,8 +1077,6 @@ void RenderWidgetHostImpl::ForwardInputEvent(const WebInputEvent& input_event,
DCHECK(!process_->IgnoreInputEvents());
- in_process_event_types_.push(input_event.type);
-
if (overscroll_controller_.get() &&
!overscroll_controller_->WillDispatchEvent(input_event)) {
// Reset the wheel-event state when appropriate.
@@ -1089,6 +1094,8 @@ void RenderWidgetHostImpl::ForwardInputEvent(const WebInputEvent& input_event,
return;
}
+ in_process_event_types_.push(input_event.type);
+
IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_);
message->WriteData(
reinterpret_cast<const char*>(&input_event), event_size);
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index c3f2ff8..00e8bab 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -444,6 +444,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl : virtual public RenderWidgetHost,
return gesture_event_filter_.get();
}
+ OverscrollController* overscroll_controller() {
+ return overscroll_controller_.get();
+ }
+
protected:
virtual RenderWidgetHostImpl* AsRenderWidgetHostImpl() OVERRIDE;
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index a18411e..7d55ce2 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -6,7 +6,9 @@
#include "base/utf_string_conversions.h"
#include "content/browser/renderer_host/dip_util.h"
+#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/interstitial_page_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/notification_observer.h"
@@ -33,6 +35,7 @@
#include "ui/base/events/event_utils.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/screen.h"
#include "webkit/glue/webdropdata.h"
@@ -243,7 +246,9 @@ WebContentsViewAura::WebContentsViewAura(
delegate_(delegate),
current_drag_op_(WebKit::WebDragOperationNone),
drag_dest_delegate_(NULL),
- current_rvh_for_drag_(NULL) {
+ current_rvh_for_drag_(NULL),
+ current_overscroll_gesture_(OVERSCROLL_NONE),
+ completed_overscroll_gesture_(OVERSCROLL_NONE) {
}
////////////////////////////////////////////////////////////////////////////////
@@ -276,6 +281,128 @@ void WebContentsViewAura::EndDrag(WebKit::WebDragOperationsMask ops) {
screen_loc.y(), ops);
}
+void WebContentsViewAura::PrepareOverscrollWindow() {
+ overscroll_window_.reset(new aura::Window(NULL));
+ overscroll_window_->SetType(aura::client::WINDOW_TYPE_CONTROL);
+ overscroll_window_->SetTransparent(false);
+ overscroll_window_->Init(ui::LAYER_SOLID_COLOR);
+ overscroll_window_->layer()->SetMasksToBounds(true);
+ overscroll_window_->layer()->SetColor(SK_ColorGRAY);
+ overscroll_window_->SetName("OverscrollOverlay");
+
+ window_->AddChild(overscroll_window_.get());
+
+ gfx::Rect bounds = gfx::Rect(window_->bounds().size());
+ if (current_overscroll_gesture_ == OVERSCROLL_WEST &&
+ web_contents_->GetController().CanGoForward()) {
+ // The overlay will be sliding in from the right edge towards the left.
+ // So position the overlay window on the right of the window.
+ bounds.Offset(bounds.width(), 0);
+ }
+
+ if (GetWindowToAnimateForOverscroll() == overscroll_window_.get())
+ window_->StackChildAbove(overscroll_window_.get(), GetContentNativeView());
+ else
+ window_->StackChildBelow(overscroll_window_.get(), GetContentNativeView());
+
+ overscroll_window_->SetBounds(bounds);
+ overscroll_window_->Show();
+}
+
+void WebContentsViewAura::PrepareContentWindowForOverscroll() {
+ aura::Window* content = GetContentNativeView();
+ if (!content)
+ return;
+
+ ui::ScopedLayerAnimationSettings settings(content->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(ui::LayerAnimator::IMMEDIATELY_SET_NEW_TARGET);
+ content->SetTransform(gfx::Transform());
+}
+
+void WebContentsViewAura::ResetOverscrollTransform() {
+ if (!view_)
+ return;
+ aura::Window* target = GetWindowToAnimateForOverscroll();
+ ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
+ settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.AddObserver(this);
+ target->SetTransform(gfx::Transform());
+}
+
+void WebContentsViewAura::CompleteOverscrollNavigation(OverscrollMode mode) {
+ // Animate out the current view first. Navigate to the requested history at
+ // the end of the animation.
+ if (current_overscroll_gesture_ == OVERSCROLL_NONE)
+ return;
+
+ if (!view_)
+ return;
+
+ completed_overscroll_gesture_ = mode;
+ aura::Window* target = GetWindowToAnimateForOverscroll();
+ ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
+ settings.SetTweenType(ui::Tween::EASE_OUT);
+ settings.AddObserver(this);
+ gfx::Transform transform;
+ int content_width = view_->GetViewBounds().width();
+ transform.SetTranslateX(mode == OVERSCROLL_WEST ? -content_width :
+ content_width);
+ target->SetTransform(transform);
+}
+
+aura::Window* WebContentsViewAura::GetWindowToAnimateForOverscroll() {
+ if (current_overscroll_gesture_ == OVERSCROLL_NONE)
+ return NULL;
+
+ if (current_overscroll_gesture_ == OVERSCROLL_WEST &&
+ web_contents_->GetController().CanGoForward()) {
+ return overscroll_window_.get();
+ }
+ return GetContentNativeView();
+}
+
+gfx::Vector2d WebContentsViewAura::GetTranslationForOverscroll(int delta_x,
+ int delta_y) {
+ if (current_overscroll_gesture_ == OVERSCROLL_NORTH ||
+ current_overscroll_gesture_ == OVERSCROLL_SOUTH) {
+ // For vertical overscroll, always do a resisted drag.
+ const int kVerticalOverscrollAmount = 40;
+ if (abs(delta_y) <= kVerticalOverscrollAmount)
+ return gfx::Vector2d(0, delta_y);
+
+ // Start resisting after the threshold.
+ int scroll = kVerticalOverscrollAmount;
+ int resist = abs(delta_y) - scroll;
+ while (resist /= 2)
+ scroll += 3;
+ return gfx::Vector2d(0, delta_y < 0 ? -scroll : scroll);
+ }
+
+ // For horizontal overscroll, scroll freely if a navigation is possible. Do a
+ // resistive scroll otherwise.
+ const NavigationControllerImpl& controller = web_contents_->GetController();
+ if (current_overscroll_gesture_ == OVERSCROLL_WEST) {
+ if (controller.CanGoForward())
+ return gfx::Vector2d(delta_x, 0);
+ } else if (current_overscroll_gesture_ == OVERSCROLL_EAST) {
+ if (controller.CanGoBack())
+ return gfx::Vector2d(delta_x, 0);
+ }
+
+ const int kHorizontalOverscrollAmount = 60;
+ if (abs(delta_x) < kHorizontalOverscrollAmount)
+ return gfx::Vector2d(delta_x, 0);
+
+ // Start resisting after the threshold.
+ int scroll = kHorizontalOverscrollAmount;
+ int resist = abs(delta_x) - scroll;
+ while (resist /= 2)
+ scroll += 3;
+ return gfx::Vector2d(delta_x < 0 ? -scroll : scroll, 0);
+}
+
////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, WebContentsView implementation:
@@ -320,6 +447,12 @@ RenderWidgetHostView* WebContentsViewAura::CreateViewForWidget(
// We listen to drag drop events in the newly created view's window.
aura::client::SetDragDropDelegate(view_->GetNativeView(), this);
+
+ RenderWidgetHostImpl* host_impl =
+ RenderWidgetHostImpl::From(render_widget_host);
+ if (host_impl->overscroll_controller())
+ host_impl->overscroll_controller()->set_delegate(this);
+
return view_;
}
@@ -496,6 +629,74 @@ void WebContentsViewAura::TakeFocus(bool reverse) {
}
////////////////////////////////////////////////////////////////////////////////
+// WebContentsViewAura, OverscrollControllerDelegate implementation:
+
+void WebContentsViewAura::OnOverscrollUpdate(float delta_x, float delta_y) {
+ if (current_overscroll_gesture_ == OVERSCROLL_NONE)
+ return;
+
+ aura::Window* target = GetWindowToAnimateForOverscroll();
+ gfx::Vector2d translate = GetTranslationForOverscroll(delta_x, delta_y);
+ ui::ScopedLayerAnimationSettings settings(target->layer()->GetAnimator());
+ settings.SetPreemptionStrategy(ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS);
+ gfx::Transform transform;
+ transform.SetTranslate(translate.x(), translate.y());
+ target->SetTransform(transform);
+}
+
+void WebContentsViewAura::OnOverscrollComplete(OverscrollMode mode) {
+ if (mode == OVERSCROLL_WEST) {
+ NavigationControllerImpl& controller = web_contents_->GetController();
+ if (controller.CanGoForward()) {
+ CompleteOverscrollNavigation(mode);
+ return;
+ }
+ } else if (mode == OVERSCROLL_EAST) {
+ NavigationControllerImpl& controller = web_contents_->GetController();
+ if (controller.CanGoBack()) {
+ CompleteOverscrollNavigation(mode);
+ return;
+ }
+ }
+
+ ResetOverscrollTransform();
+}
+
+void WebContentsViewAura::OnOverscrollModeChange(OverscrollMode old_mode,
+ OverscrollMode new_mode) {
+ if (new_mode == OVERSCROLL_NONE) {
+ // Reset any in-progress overscroll animation first.
+ ResetOverscrollTransform();
+ current_overscroll_gesture_ = new_mode;
+ } else {
+ // Cleanup state of the content window first, because that can reset the
+ // value of |current_overscroll_gesture_|.
+ PrepareContentWindowForOverscroll();
+
+ current_overscroll_gesture_ = new_mode;
+ PrepareOverscrollWindow();
+ }
+ completed_overscroll_gesture_ = OVERSCROLL_NONE;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// WebContentsViewAura, ui::ImplicitAnimationObserver implementation:
+
+void WebContentsViewAura::OnImplicitAnimationsCompleted() {
+ if (completed_overscroll_gesture_ == OVERSCROLL_WEST) {
+ web_contents_->GetController().GoForward();
+ } else if (completed_overscroll_gesture_ == OVERSCROLL_EAST) {
+ web_contents_->GetController().GoBack();
+ }
+
+ if (GetContentNativeView())
+ GetContentNativeView()->SetTransform(gfx::Transform());
+ current_overscroll_gesture_ = OVERSCROLL_NONE;
+ completed_overscroll_gesture_ = OVERSCROLL_NONE;
+ overscroll_window_.reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
// WebContentsViewAura, aura::WindowDelegate implementation:
gfx::Size WebContentsViewAura::GetMinimumSize() const {
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index 6fc2ae3..2c4aa9d 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -9,11 +9,13 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "content/browser/renderer_host/overscroll_controller_delegate.h"
#include "content/common/content_export.h"
#include "content/port/browser/render_view_host_delegate_view.h"
#include "content/public/browser/web_contents_view.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window_delegate.h"
+#include "ui/compositor/layer_animation_observer.h"
namespace aura {
class Window;
@@ -31,6 +33,8 @@ class WebDragDestDelegate;
class CONTENT_EXPORT WebContentsViewAura
: public WebContentsView,
public RenderViewHostDelegateView,
+ NON_EXPORTED_BASE(public OverscrollControllerDelegate),
+ public ui::ImplicitAnimationObserver,
public aura::WindowDelegate,
public aura::client::DragDropDelegate {
public:
@@ -44,6 +48,33 @@ class CONTENT_EXPORT WebContentsViewAura
void EndDrag(WebKit::WebDragOperationsMask ops);
+ // Creates and sets up the overlay window that will be displayed during the
+ // overscroll gesture.
+ void PrepareOverscrollWindow();
+
+ // Sets up the content window in preparation for starting an overscroll
+ // gesture.
+ void PrepareContentWindowForOverscroll();
+
+ // Resets any in-progress animation for the overscroll gesture. Note that this
+ // doesn't immediately reset the internal states; that happens after an
+ // animation.
+ void ResetOverscrollTransform();
+
+ // Completes the navigation in response to a completed overscroll gesture.
+ // The navigation happens after an animation (either the overlay window
+ // animates in, or the content window animates out).
+ void CompleteOverscrollNavigation(OverscrollMode mode);
+
+ // Returns the window that should be animated for the overscroll gesture.
+ // (note that during the overscroll gesture, either the overlay window or the
+ // content window can be animated).
+ aura::Window* GetWindowToAnimateForOverscroll();
+
+ // Returns the amount the animating window should be translated in response to
+ // the overscroll gesture.
+ gfx::Vector2d GetTranslationForOverscroll(int delta_x, int delta_y);
+
// Overridden from WebContentsView:
virtual void CreateView(const gfx::Size& initial_size) OVERRIDE;
virtual RenderWidgetHostView* CreateViewForWidget(
@@ -86,6 +117,15 @@ class CONTENT_EXPORT WebContentsViewAura
virtual void GotFocus() OVERRIDE;
virtual void TakeFocus(bool reverse) OVERRIDE;
+ // Overridden from OverscrollControllerDelegate:
+ virtual void OnOverscrollUpdate(float delta_x, float delta_y) OVERRIDE;
+ virtual void OnOverscrollComplete(OverscrollMode overscroll_mode) OVERRIDE;
+ virtual void OnOverscrollModeChange(OverscrollMode old_mode,
+ OverscrollMode new_mode) OVERRIDE;
+
+ // Overridden from ui::ImplicitAnimationObserver:
+ virtual void OnImplicitAnimationsCompleted() OVERRIDE;
+
// Overridden from aura::WindowDelegate:
virtual gfx::Size GetMinimumSize() const OVERRIDE;
virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
@@ -121,6 +161,7 @@ class CONTENT_EXPORT WebContentsViewAura
virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
scoped_ptr<aura::Window> window_;
+ scoped_ptr<aura::Window> overscroll_window_;
// The WebContentsImpl whose contents we display.
WebContentsImpl* web_contents_;
@@ -141,6 +182,13 @@ class CONTENT_EXPORT WebContentsViewAura
// pointers.
void* current_rvh_for_drag_;
+ // The overscroll gesture currently in progress.
+ OverscrollMode current_overscroll_gesture_;
+
+ // This is the completed overscroll gesture. This is used for the animation
+ // callback that happens in response to a completed overscroll gesture.
+ OverscrollMode completed_overscroll_gesture_;
+
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
};
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 45d6870..689e39e 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -748,4 +748,8 @@ const char kDisableFixedPositionCreatesStackingContext[]
// Defer image decoding in WebKit until painting.
const char kEnableDeferredImageDecoding[] = "enable-deferred-image-decoding";
+// Enables history navigation in response to horizontal overscroll.
+const char kEnableOverscrollHistoryNavigation[] =
+ "enable-overscroll-history-navigation";
+
} // namespace switches
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index e59d15b..2f8bceb 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -238,6 +238,8 @@ CONTENT_EXPORT extern const char kFlingTapSuppressMaxGap[];
CONTENT_EXPORT extern const char kTestCompositor[];
#endif
+CONTENT_EXPORT extern const char kEnableOverscrollHistoryNavigation[];
+
} // namespace switches
#endif // CONTENT_PUBLIC_COMMON_CONTENT_SWITCHES_H_