Index: content/browser/renderer_host/render_widget_host_view_aura.cc |
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc |
index a59880e6a98cec1506666c278943ce2fdaa17069..a3cab6ada3b22a5fd9ac998e3978fcb248a8be08 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc |
@@ -65,9 +65,11 @@ |
#include "ui/compositor/dip_util.h" |
#include "ui/events/event.h" |
#include "ui/events/event_utils.h" |
+#include "ui/events/gestures/fling_curve.h" |
#include "ui/events/gestures/gesture_recognizer.h" |
#include "ui/gfx/canvas.h" |
#include "ui/gfx/display.h" |
+#include "ui/gfx/frame_time.h" |
#include "ui/gfx/rect_conversions.h" |
#include "ui/gfx/screen.h" |
#include "ui/gfx/size_conversions.h" |
@@ -104,6 +106,91 @@ using blink::WebTouchEvent; |
namespace content { |
+class Flinger : public ui::CompositorAnimationObserver { |
+ public: |
+ class Delegate { |
+ public: |
+ virtual ~Delegate() {} |
+ |
+ virtual void OnScroll(const gfx::Vector2dF& scroll_delta) = 0; |
+ |
+ virtual void OnScrollEnd() = 0; |
+ }; |
+ |
+ Flinger(Delegate* delegate, |
+ const gfx::Vector2dF& velocity, |
+ ui::Compositor* compositor) |
+ : delegate_(delegate), |
+ compositor_(compositor), |
+ fling_curve_(velocity, gfx::FrameTime::Now()) { |
+ CHECK(delegate_); |
+ compositor_->AddAnimationObserver(this); |
+ } |
+ |
+ virtual ~Flinger() { Done(); } |
+ |
+ private: |
+ void Done() { |
+ if (!delegate_) |
+ return; |
+ compositor_->RemoveAnimationObserver(this); |
+ Delegate* delegate = delegate_; |
+ delegate_ = NULL; |
+ delegate->OnScrollEnd(); |
+ } |
+ |
+ // ui::CompositorAnimationObserver: |
+ virtual void OnAnimationStep(base::TimeTicks timestamp) OVERRIDE { |
+ CHECK(delegate_); |
+ if (fling_curve_.start_timestamp() > timestamp) |
+ return; |
+ gfx::Vector2dF scroll = fling_curve_.GetScrollAmountAtTime(timestamp); |
+ if (scroll.IsZero()) |
+ Done(); |
+ else |
+ delegate_->OnScroll(scroll); |
+ } |
+ |
+ Delegate* delegate_; |
+ ui::Compositor* compositor_; |
+ ui::FlingCurve fling_curve_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Flinger); |
+}; |
+ |
+class FlingerDelegate : public Flinger::Delegate { |
+ public: |
+ FlingerDelegate(RenderWidgetHostView* view, |
+ const blink::WebGestureEvent& gesture_event) |
+ : view_(view), gesture_(gesture_event) {} |
+ |
+ virtual ~FlingerDelegate() {} |
+ |
+ private: |
+ // Flinger::Delegate: |
+ virtual void OnScroll(const gfx::Vector2dF& scroll_delta) OVERRIDE { |
+ blink::WebGestureEvent gesture = gesture_; |
+ gesture.type = blink::WebInputEvent::GestureScrollUpdateWithoutPropagation; |
+ gesture.data.scrollUpdate.deltaX = scroll_delta.x(); |
+ gesture.data.scrollUpdate.deltaY = scroll_delta.y(); |
+ RenderWidgetHostImpl::From(view_->GetRenderWidgetHost()) |
+ ->ForwardGestureEvent(gesture); |
+ } |
+ |
+ virtual void OnScrollEnd() OVERRIDE { |
+ blink::WebGestureEvent gesture = gesture_; |
+ gesture.type = blink::WebInputEvent::GestureScrollEnd; |
+ RenderWidgetHostImpl::From(view_->GetRenderWidgetHost()) |
+ ->ForwardGestureEvent(gesture); |
+ delete this; |
+ } |
+ |
+ RenderWidgetHostView* view_; |
+ blink::WebGestureEvent gesture_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FlingerDelegate); |
+}; |
+ |
namespace { |
// In mouse lock mode, we need to prevent the (invisible) cursor from hitting |
@@ -1965,6 +2052,11 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) { |
if (host_->IsRenderView()) |
delegate = RenderViewHost::From(host_)->GetDelegate(); |
+ // If there is an active fling, then any incoming new gesture event should |
+ // terminate the fling. |
+ if (flinger_ && event->type() == ui::ET_GESTURE_BEGIN) |
+ flinger_.reset(); |
+ |
if (delegate && event->type() == ui::ET_GESTURE_BEGIN && |
event->details().touch_points() == 1) { |
delegate->HandleGestureBegin(); |
@@ -1980,7 +2072,13 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) { |
host_->ForwardGestureEvent(fling_cancel); |
} |
- if (gesture.type != blink::WebInputEvent::Undefined) { |
+ if (gesture.type == blink::WebInputEvent::GestureFlingStart) { |
+ flinger_.reset( |
+ new Flinger(new FlingerDelegate(this, gesture), |
+ gfx::Vector2dF(gesture.data.flingStart.velocityX, |
+ gesture.data.flingStart.velocityY), |
+ window_->GetHost()->compositor())); |
+ } else if (gesture.type != blink::WebInputEvent::Undefined) { |
host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency()); |
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN || |