Index: content/browser/renderer_host/input/immediate_input_router.cc |
diff --git a/content/browser/renderer_host/input/immediate_input_router.cc b/content/browser/renderer_host/input/immediate_input_router.cc |
index 06bbc950e1d798a648fac65502f6c1c57365badc..31876bde5e022ce15a48ed80af25957db152174c 100644 |
--- a/content/browser/renderer_host/input/immediate_input_router.cc |
+++ b/content/browser/renderer_host/input/immediate_input_router.cc |
@@ -70,8 +70,73 @@ const char* GetEventAckName(InputEventAckState ack_result) { |
return ""; |
} |
+bool BrowserSideFlingEnabled() { |
+ return CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableBrowserSideFling); |
+} |
+ |
} // namespace |
+// A helper class that based on the value of the |kEnableBrowserSideFling| flag |
+// does event filtering using either |BaseGestureEventFilter| or |
+// |GestureEventFilter|. |
+class ImmediateInputRouter::EventFilteringHelper { |
+ public: |
+ // |router| must outlive us. |
+ explicit EventFilteringHelper(ImmediateInputRouter* router) { |
+ if (BrowserSideFlingEnabled()) |
+ gesture_event_filter_.reset(new BaseGestureEventFilter(router)); |
+ else |
+ gesture_event_filter_.reset(new GestureEventFilter(router, router)); |
+ } |
+ virtual ~EventFilteringHelper() {} |
+ |
+ bool ShouldDeferMouseDown(const MouseEventWithLatencyInfo& mouse_event) { |
+ if (BrowserSideFlingEnabled()) |
+ return false; |
+ |
+ return static_cast<GestureEventFilter*>(gesture_event_filter_.get())-> |
+ GetTouchpadTapSuppressionController()->ShouldDeferMouseDown( |
+ mouse_event); |
+ } |
+ |
+ bool ShouldDeferMouseUp(const MouseEventWithLatencyInfo& mouse_event) { |
+ if (BrowserSideFlingEnabled()) |
+ return false; |
+ |
+ return static_cast<GestureEventFilter*>(gesture_event_filter_.get())-> |
+ GetTouchpadTapSuppressionController()->ShouldSuppressMouseUp(); |
+ } |
+ |
+ void FlingHasBeenHalted() { |
+ if (BrowserSideFlingEnabled()) |
+ return; |
+ |
+ static_cast<GestureEventFilter*>(gesture_event_filter_.get())-> |
+ FlingHasBeenHalted(); |
+ } |
+ |
+ bool ShouldForwardGesture(const GestureEventWithLatencyInfo& gesture_event) { |
+ return gesture_event_filter_->ShouldForward(gesture_event); |
+ } |
+ |
+ bool HasQueuedGestureEvents() { |
+ return gesture_event_filter_->HasQueuedGestureEvents(); |
+ } |
+ |
+ void ProcessGestureAck(InputEventAckState ack_result, |
+ blink::WebInputEvent::Type type, |
+ const ui::LatencyInfo& latency) { |
+ gesture_event_filter_->ProcessGestureAck(ack_result, type, latency); |
+ } |
+ |
+ private: |
+ friend class ImmediateInputRouter; |
+ scoped_ptr<BaseGestureEventFilter> gesture_event_filter_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EventFilteringHelper); |
+}; |
+ |
ImmediateInputRouter::ImmediateInputRouter(IPC::Sender* sender, |
InputRouterClient* client, |
InputAckHandler* ack_handler, |
@@ -87,7 +152,8 @@ ImmediateInputRouter::ImmediateInputRouter(IPC::Sender* sender, |
has_touch_handler_(false), |
current_ack_source_(ACK_SOURCE_NONE), |
touch_event_queue_(new TouchEventQueue(this)), |
- gesture_event_filter_(new GestureEventFilter(this, this)) { |
+ flinger_(new Flinger(this)), |
+ event_filter_(new EventFilteringHelper(this)) { |
DCHECK(sender); |
DCHECK(client); |
DCHECK(ack_handler); |
@@ -126,13 +192,14 @@ void ImmediateInputRouter::SendMouseEvent( |
return; |
} |
+ if (BrowserSideFlingEnabled() && flinger_->HandleMouseEvent(mouse_event)) |
+ return; |
+ |
if (mouse_event.event.type == WebInputEvent::MouseDown && |
- gesture_event_filter_->GetTouchpadTapSuppressionController()-> |
- ShouldDeferMouseDown(mouse_event)) |
+ event_filter_->ShouldDeferMouseDown(mouse_event)) |
return; |
if (mouse_event.event.type == WebInputEvent::MouseUp && |
- gesture_event_filter_->GetTouchpadTapSuppressionController()-> |
- ShouldSuppressMouseUp()) |
+ event_filter_->ShouldDeferMouseUp(mouse_event)) |
return; |
SendMouseEventImmediately(mouse_event); |
@@ -140,6 +207,9 @@ void ImmediateInputRouter::SendMouseEvent( |
void ImmediateInputRouter::SendWheelEvent( |
const MouseWheelEventWithLatencyInfo& wheel_event) { |
+ if (BrowserSideFlingEnabled() && flinger_->HandleWheelEvent(wheel_event)) |
+ return; |
+ |
// If there's already a mouse wheel event waiting to be sent to the renderer, |
// add the new deltas to that event. Not doing so (e.g., by dropping the old |
// event, as for mouse moves) results in very slow scrolling on the Mac (on |
@@ -166,13 +236,16 @@ void ImmediateInputRouter::SendKeyboardEvent( |
const NativeWebKeyboardEvent& key_event, |
const ui::LatencyInfo& latency_info, |
bool is_keyboard_shortcut) { |
+ if (BrowserSideFlingEnabled() && flinger_->HandleKeyboardEvent()) |
+ return; |
+ |
// Put all WebKeyboardEvent objects in a queue since we can't trust the |
// renderer and we need to give something to the HandleKeyboardEvent |
// handler. |
key_queue_.push_back(key_event); |
HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
- gesture_event_filter_->FlingHasBeenHalted(); |
+ event_filter_->FlingHasBeenHalted(); |
// Only forward the non-native portions of our event. |
FilterAndSendWebInputEvent(key_event, latency_info, is_keyboard_shortcut); |
@@ -182,8 +255,11 @@ void ImmediateInputRouter::SendGestureEvent( |
const GestureEventWithLatencyInfo& gesture_event) { |
HandleGestureScroll(gesture_event); |
+ if (BrowserSideFlingEnabled() && flinger_->HandleGestureEvent(gesture_event)) |
+ return; |
+ |
if (!IsInOverscrollGesture() && |
- !gesture_event_filter_->ShouldForward(gesture_event)) { |
+ !event_filter_->ShouldForwardGesture(gesture_event)) { |
OverscrollController* controller = client_->GetOverscrollController(); |
if (controller) |
controller->DiscardingGestureEvent(gesture_event.event); |
@@ -277,6 +353,25 @@ void ImmediateInputRouter::OnGestureEventAck( |
ack_handler_->OnGestureEventAck(event, ack_result); |
} |
+void ImmediateInputRouter::SendEventForFling( |
+ const blink::WebInputEvent& event) { |
+ ui::LatencyInfo latency_info; |
+ if (Send(new InputMsg_HandleInputEvent( |
+ routing_id(), &event, latency_info, false))) |
+ in_process_messages_sources_.push(MESSAGE_SOURCE_FLING); |
+} |
+ |
+void ImmediateInputRouter::FlingFinished( |
+ blink::WebGestureEvent::SourceDevice source) { |
+ if (source == blink::WebGestureEvent::Touchscreen) { |
+ ui::LatencyInfo latency_info; |
+ blink::WebGestureEvent synthetic_gesture; |
+ synthetic_gesture.type = blink::WebInputEvent::GestureScrollEnd; |
+ synthetic_gesture.sourceDevice = blink::WebGestureEvent::Touchscreen; |
+ OfferToRenderer(synthetic_gesture, latency_info, false); |
+ } |
+} |
+ |
bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) { |
DCHECK(message->type() == InputMsg_SelectRange::ID); |
if (select_range_pending_) { |
@@ -358,7 +453,7 @@ bool ImmediateInputRouter::OfferToOverscrollController( |
const blink::WebGestureEvent& gesture_event = |
static_cast<const blink::WebGestureEvent&>(input_event); |
// An ACK is expected for the event, so mark it as consumed. |
- consumed = !gesture_event_filter_->ShouldForward( |
+ consumed = !event_filter_->ShouldForwardGesture( |
GestureEventWithLatencyInfo(gesture_event, latency_info)); |
} |
@@ -408,6 +503,7 @@ bool ImmediateInputRouter::OfferToRenderer(const WebInputEvent& input_event, |
input_event_start_time_ = TimeTicks::Now(); |
if (Send(new InputMsg_HandleInputEvent( |
routing_id(), &input_event, latency_info, is_keyboard_shortcut))) { |
+ in_process_messages_sources_.push(MESSAGE_SOURCE_REGULAR); |
client_->IncrementInFlightEventCount(); |
return true; |
} |
@@ -422,6 +518,13 @@ void ImmediateInputRouter::OnInputEventAck( |
TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); |
+ InputMessageSource source = in_process_messages_sources_.front(); |
+ in_process_messages_sources_.pop(); |
+ if (source == MESSAGE_SOURCE_FLING) { |
+ flinger_->ProcessEventAck(event_type, ack_result, latency_info); |
+ return; |
+ } |
+ |
client_->DecrementInFlightEventCount(); |
ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER); |
@@ -560,12 +663,12 @@ void ImmediateInputRouter::ProcessGestureAck(WebInputEvent::Type type, |
// If |ack_result| originated from the overscroll controller, only |
// feed |gesture_event_filter_| the ack if it was expecting one. |
if (current_ack_source_ == OVERSCROLL_CONTROLLER && |
- !gesture_event_filter_->HasQueuedGestureEvents()) { |
+ !event_filter_->HasQueuedGestureEvents()) { |
return; |
} |
// |gesture_event_filter_| will forward to OnGestureEventAck when appropriate. |
- gesture_event_filter_->ProcessGestureAck(ack_result, type, latency); |
+ event_filter_->ProcessGestureAck(ack_result, type, latency); |
} |
void ImmediateInputRouter::ProcessTouchAck( |
@@ -681,4 +784,8 @@ bool ImmediateInputRouter::IsInOverscrollGesture() const { |
return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
} |
+BaseGestureEventFilter* ImmediateInputRouter::gesture_event_filter() { |
+ return event_filter_->gesture_event_filter_.get(); |
+} |
+ |
} // namespace content |