// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_ #define CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_ #include <queue> #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "content/browser/renderer_host/input/gesture_event_queue.h" #include "content/browser/renderer_host/input/input_router.h" #include "content/browser/renderer_host/input/touch_action_filter.h" #include "content/browser/renderer_host/input/touch_event_queue.h" #include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h" #include "content/common/input/input_event_stream_validator.h" #include "content/public/browser/native_web_keyboard_event.h" struct InputHostMsg_HandleInputEvent_ACK_Params; namespace IPC { class Sender; } namespace ui { struct LatencyInfo; } namespace content { class InputAckHandler; class InputRouterClient; class OverscrollController; class RenderWidgetHostImpl; struct DidOverscrollParams; // A default implementation for browser input event routing. class CONTENT_EXPORT InputRouterImpl : public NON_EXPORTED_BASE(InputRouter), public NON_EXPORTED_BASE(GestureEventQueueClient), public NON_EXPORTED_BASE(TouchEventQueueClient), public NON_EXPORTED_BASE(TouchpadTapSuppressionControllerClient) { public: struct CONTENT_EXPORT Config { Config(); GestureEventQueue::Config gesture_config; TouchEventQueue::Config touch_config; }; InputRouterImpl(IPC::Sender* sender, InputRouterClient* client, InputAckHandler* ack_handler, int routing_id, const Config& config); virtual ~InputRouterImpl(); // InputRouter virtual void Flush() OVERRIDE; virtual bool SendInput(scoped_ptr<IPC::Message> message) OVERRIDE; virtual void SendMouseEvent( const MouseEventWithLatencyInfo& mouse_event) OVERRIDE; virtual void SendWheelEvent( const MouseWheelEventWithLatencyInfo& wheel_event) OVERRIDE; virtual void SendKeyboardEvent( const NativeWebKeyboardEvent& key_event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut) OVERRIDE; virtual void SendGestureEvent( const GestureEventWithLatencyInfo& gesture_event) OVERRIDE; virtual void SendTouchEvent( const TouchEventWithLatencyInfo& touch_event) OVERRIDE; virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const OVERRIDE; virtual bool ShouldForwardTouchEvent() const OVERRIDE; virtual void OnViewUpdated(int view_flags) OVERRIDE; // IPC::Listener virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; private: friend class InputRouterImplTest; // TouchpadTapSuppressionControllerClient virtual void SendMouseEventImmediately( const MouseEventWithLatencyInfo& mouse_event) OVERRIDE; // TouchEventQueueClient virtual void SendTouchEventImmediately( const TouchEventWithLatencyInfo& touch_event) OVERRIDE; virtual void OnTouchEventAck(const TouchEventWithLatencyInfo& event, InputEventAckState ack_result) OVERRIDE; // GetureEventFilterClient virtual void SendGestureEventImmediately( const GestureEventWithLatencyInfo& gesture_event) OVERRIDE; virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event, InputEventAckState ack_result) OVERRIDE; bool SendMoveCaret(scoped_ptr<IPC::Message> message); bool SendSelectRange(scoped_ptr<IPC::Message> message); bool Send(IPC::Message* message); // Filters and forwards |input_event| to the appropriate handler. void FilterAndSendWebInputEvent(const blink::WebInputEvent& input_event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut); // Utility routine for filtering and forwarding |input_event| to the // appropriate handler. |input_event| will be offered to the overscroll // controller, client and renderer, in that order. void OfferToHandlers(const blink::WebInputEvent& input_event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut); // Returns true if |input_event| was consumed by the overscroll controller. bool OfferToOverscrollController(const blink::WebInputEvent& input_event, const ui::LatencyInfo& latency_info); // Returns true if |input_event| was consumed by the client. bool OfferToClient(const blink::WebInputEvent& input_event, const ui::LatencyInfo& latency_info); // Returns true if |input_event| was successfully sent to the renderer // as an async IPC Message. bool OfferToRenderer(const blink::WebInputEvent& input_event, const ui::LatencyInfo& latency_info, bool is_keyboard_shortcut); // A data structure that attaches some metadata to a WebMouseWheelEvent // and its latency info. struct QueuedWheelEvent { QueuedWheelEvent(); QueuedWheelEvent(const MouseWheelEventWithLatencyInfo& event, bool synthesized_from_pinch); ~QueuedWheelEvent(); MouseWheelEventWithLatencyInfo event; bool synthesized_from_pinch; }; // Enqueue or send a mouse wheel event. void SendWheelEvent(const QueuedWheelEvent& wheel_event); // Given a Touchpad GesturePinchUpdate event, create and send a synthetic // wheel event for it. void SendSyntheticWheelEventForPinch( const GestureEventWithLatencyInfo& pinch_event); // IPC message handlers void OnInputEventAck(const InputHostMsg_HandleInputEvent_ACK_Params& ack); void OnDidOverscroll(const DidOverscrollParams& params); void OnMsgMoveCaretAck(); void OnSelectRangeAck(); void OnHasTouchEventHandlers(bool has_handlers); void OnSetTouchAction(TouchAction touch_action); // Indicates the source of an ack provided to |ProcessInputEventAck()|. // The source is tracked by |current_ack_source_|, which aids in ack routing. enum AckSource { RENDERER, CLIENT, IGNORING_DISPOSITION, ACK_SOURCE_NONE }; // Note: This function may result in |this| being deleted, and as such // should be the last method called in any internal chain of event handling. void ProcessInputEventAck(blink::WebInputEvent::Type event_type, InputEventAckState ack_result, const ui::LatencyInfo& latency_info, AckSource ack_source); // Dispatches the ack'ed event to |ack_handler_|. void ProcessKeyboardAck(blink::WebInputEvent::Type type, InputEventAckState ack_result); // Forwards a valid |next_mouse_move_| if |type| is MouseMove. void ProcessMouseAck(blink::WebInputEvent::Type type, InputEventAckState ack_result); // Dispatches the ack'ed event to |ack_handler_|, forwarding queued events // from |coalesced_mouse_wheel_events_|. void ProcessWheelAck(InputEventAckState ack_result, const ui::LatencyInfo& latency); // Forwards the event ack to |gesture_event_queue|, potentially triggering // dispatch of queued gesture events. void ProcessGestureAck(blink::WebInputEvent::Type type, InputEventAckState ack_result, const ui::LatencyInfo& latency); // Forwards the event ack to |touch_event_queue_|, potentially triggering // dispatch of queued touch events, or the creation of gesture events. void ProcessTouchAck(InputEventAckState ack_result, const ui::LatencyInfo& latency); // Called when a touch timeout-affecting bit has changed, in turn toggling the // touch ack timeout feature of the |touch_event_queue_| as appropriate. Input // to that determination includes current view properties and the allowed // touch action. Note that this will only affect platforms that have a // non-zero touch timeout configuration. void UpdateTouchAckTimeoutEnabled(); // If a flush has been requested, signals a completed flush to the client if // all events have been dispatched (i.e., |HasPendingEvents()| is false). void SignalFlushedIfNecessary(); bool HasPendingEvents() const; bool IsInOverscrollGesture() const; int routing_id() const { return routing_id_; } IPC::Sender* sender_; InputRouterClient* client_; InputAckHandler* ack_handler_; int routing_id_; // (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK. bool select_range_pending_; // (Similar to |next_mouse_move_|.) The next SelectRange to send, if any. scoped_ptr<IPC::Message> next_selection_range_; // (Similar to |mouse_move_pending_|.) True while waiting for MoveCaret_ACK. bool move_caret_pending_; // (Similar to |next_mouse_move_|.) The next MoveCaret to send, if any. scoped_ptr<IPC::Message> next_move_caret_; // True if a mouse move event was sent to the render view and we are waiting // for a corresponding InputHostMsg_HandleInputEvent_ACK message. bool mouse_move_pending_; // The next mouse move event to send (only non-null while mouse_move_pending_ // is true). scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move_; // (Similar to |mouse_move_pending_|.) True if a mouse wheel event was sent // and we are waiting for a corresponding ack. bool mouse_wheel_pending_; QueuedWheelEvent current_wheel_event_; // (Similar to |next_mouse_move_|.) The next mouse wheel events to send. // Unlike mouse moves, mouse wheel events received while one is pending are // coalesced (by accumulating deltas) if they match the previous event in // modifiers. On the Mac, in particular, mouse wheel events are received at a // high rate; not waiting for the ack results in jankiness, and using the same // mechanism as for mouse moves (just dropping old events when multiple ones // would be queued) results in very slow scrolling. typedef std::deque<QueuedWheelEvent> WheelEventQueue; WheelEventQueue coalesced_mouse_wheel_events_; // A queue of keyboard events. We can't trust data from the renderer so we // stuff key events into a queue and pop them out on ACK, feeding our copy // back to whatever unhandled handler instead of the returned version. typedef std::deque<NativeWebKeyboardEvent> KeyQueue; KeyQueue key_queue_; // The time when an input event was sent to the client. base::TimeTicks input_event_start_time_; // Cached flags from |OnViewUpdated()|, defaults to 0. int current_view_flags_; // The source of the ack within the scope of |ProcessInputEventAck()|. // Defaults to ACK_SOURCE_NONE. AckSource current_ack_source_; // Whether a call to |Flush()| has yet been accompanied by a |DidFlush()| call // to the client_ after all events have been dispatched/acked. bool flush_requested_; TouchEventQueue touch_event_queue_; GestureEventQueue gesture_event_queue_; TouchActionFilter touch_action_filter_; InputEventStreamValidator input_stream_validator_; InputEventStreamValidator output_stream_validator_; DISALLOW_COPY_AND_ASSIGN(InputRouterImpl); }; } // namespace content #endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_INPUT_ROUTER_IMPL_H_