Index: content/browser/renderer_host/render_widget_host_view_mac.mm |
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm |
index 86f5a774225371db85fd1cc8dbf5f64a44489c0e..a87576cea28eb693aa4979791e369aa00cb86506 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm |
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm |
@@ -75,6 +75,7 @@ |
#include "ui/gfx/geometry/point.h" |
#include "ui/gfx/geometry/rect_conversions.h" |
#include "ui/gfx/geometry/size_conversions.h" |
+#include "ui/gfx/geometry/vector2d_f.h" |
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
#include "ui/gfx/screen.h" |
#include "ui/gl/gl_switches.h" |
@@ -391,6 +392,90 @@ blink::WebScreenInfo GetWebScreenInfo(NSView* view) { |
namespace content { |
+class WheelEventRailFilterMac { |
+ public: |
+ WheelEventRailFilterMac() : |
+ mode_(MODE_UNINITIALIZED) { |
+ } |
+ |
+ ~WheelEventRailFilterMac() { |
+ } |
+ |
+ WebMouseWheelEvent FilterWheelEvent(const WebMouseWheelEvent& event) { |
+ // This number came from 0.5 feeling too big and 0.9 feeling too small. |
+ const float kDecayConstant = 0.8f; |
+ // Require a slightly-more-than-diagonal motion against the current |
+ // scroll to break the rails. |
+ const float kSinThetaToBreakRails = 0.8f; |
+ // Require a consistently-unidirectional motion to reset the rails |
+ // after they have been broken. |
+ const float kSinThetaToResetRails = 0.02f; |
+ |
+ if (event.phase == blink::WebMouseWheelEvent::PhaseBegan) { |
+ mode_ = MODE_UNINITIALIZED; |
+ decayed_delta_ = gfx::Vector2dF(); |
+ } |
+ if (event.deltaX == 0 && event.deltaY == 0) |
+ return event; |
+ |
+ decayed_delta_.Scale(kDecayConstant); |
+ decayed_delta_ += gfx::Vector2dF(fabsf(event.deltaX), fabsf(event.deltaY)); |
+ |
+ float sin_theta_horizontal = decayed_delta_.y() / decayed_delta_.Length(); |
+ float sin_theta_vertical = decayed_delta_.x() / decayed_delta_.Length(); |
+ |
+ switch (mode_) { |
+ case MODE_UNINITIALIZED: |
+ if (decayed_delta_.x() > decayed_delta_.y()) |
+ mode_ = MODE_HORIZONTAL; |
+ else |
+ mode_ = MODE_VERTICAL; |
+ break; |
+ case MODE_HORIZONTAL: |
+ if (sin_theta_horizontal > kSinThetaToBreakRails) |
+ mode_ = MODE_FREE; |
+ break; |
+ case MODE_VERTICAL: |
+ if (sin_theta_vertical > kSinThetaToBreakRails) |
+ mode_ = MODE_FREE; |
+ break; |
+ case MODE_FREE: |
+ if (sin_theta_horizontal < kSinThetaToResetRails) |
+ mode_ = MODE_HORIZONTAL; |
+ if (sin_theta_vertical < kSinThetaToResetRails) |
+ mode_ = MODE_VERTICAL; |
+ break; |
+ } |
+ |
+ WebMouseWheelEvent result = event; |
+ switch (mode_) { |
+ case MODE_HORIZONTAL: |
+ printf("mode:Horiz\n"); |
+ result.deltaY = 0; |
+ break; |
+ case MODE_VERTICAL: |
+ printf("mode:Vert\n"); |
+ result.deltaX = 0; |
+ break; |
+ default: |
+ printf("Free\n"); |
+ break; |
+ } |
+ return result; |
+ } |
+ |
+ private: |
+ enum Mode { |
+ MODE_UNINITIALIZED, |
+ MODE_HORIZONTAL, |
+ MODE_VERTICAL, |
+ MODE_FREE, |
+ }; |
+ Mode mode_; |
+ gfx::Vector2dF decayed_delta_; |
+ gfx::Vector2dF decayed_delta_other_; |
+}; |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// DelegatedFrameHost, public: |
@@ -525,7 +610,8 @@ void RenderWidgetHostViewBase::GetDefaultScreenInfo( |
RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget, |
bool is_guest_view_hack) |
- : render_widget_host_(RenderWidgetHostImpl::From(widget)), |
+ : wheel_event_rail_filter_(new WheelEventRailFilterMac), |
+ render_widget_host_(RenderWidgetHostImpl::From(widget)), |
text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
can_compose_inline_(true), |
browser_compositor_state_(BrowserCompositorDestroyed), |
@@ -2257,7 +2343,9 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged( |
bool canRubberbandRight = true; |
const WebMouseWheelEvent webEvent = WebInputEventFactory::mouseWheelEvent( |
event, self, canRubberbandLeft, canRubberbandRight); |
- renderWidgetHostView_->render_widget_host_->ForwardWheelEvent(webEvent); |
+ renderWidgetHostView_->render_widget_host_->ForwardWheelEvent( |
+ renderWidgetHostView_->wheel_event_rail_filter_->FilterWheelEvent( |
+ webEvent)); |
} |
if (endWheelMonitor_) { |
@@ -2380,7 +2468,9 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged( |
BOOL canRubberbandRight = [responderDelegate_ canRubberbandRight:self]; |
const WebMouseWheelEvent webEvent = WebInputEventFactory::mouseWheelEvent( |
event, self, canRubberbandLeft, canRubberbandRight); |
- renderWidgetHostView_->render_widget_host_->ForwardWheelEvent(webEvent); |
+ renderWidgetHostView_->render_widget_host_->ForwardWheelEvent( |
+ renderWidgetHostView_->wheel_event_rail_filter_->FilterWheelEvent( |
+ webEvent)); |
} |
} |