blob: e06113b3e5819b433aa80ccf59b533bd4b17fbfc [file] [log] [blame]
// 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;
virtual bool HasPendingEvents() const 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 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_