diff options
-rw-r--r-- | chrome/app/generated_resources.grd | 6 | ||||
-rw-r--r-- | chrome/browser/about_flags.cc | 9 | ||||
-rw-r--r-- | content/browser/renderer_host/overscroll_controller.cc | 10 | ||||
-rw-r--r-- | content/browser/renderer_host/overscroll_controller_delegate.h | 1 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_impl.cc | 11 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_impl.h | 4 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_view_aura.cc | 203 | ||||
-rw-r--r-- | content/browser/web_contents/web_contents_view_aura.h | 48 | ||||
-rw-r--r-- | content/public/common/content_switches.cc | 4 | ||||
-rw-r--r-- | content/public/common/content_switches.h | 2 |
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_ |