1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/input/input_handler_manager.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/trace_event/trace_event.h"
12 #include "cc/input/input_handler.h"
13 #include "components/scheduler/renderer/renderer_scheduler.h"
14 #include "content/renderer/input/input_event_filter.h"
15 #include "content/renderer/input/input_handler_manager_client.h"
16 #include "content/renderer/input/input_handler_wrapper.h"
17 #include "content/renderer/input/input_scroll_elasticity_controller.h"
19 using blink::WebInputEvent
;
20 using scheduler::RendererScheduler
;
26 InputEventAckState
InputEventDispositionToAck(
27 InputHandlerProxy::EventDisposition disposition
) {
28 switch (disposition
) {
29 case InputHandlerProxy::DID_HANDLE
:
30 return INPUT_EVENT_ACK_STATE_CONSUMED
;
31 case InputHandlerProxy::DID_NOT_HANDLE
:
32 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
33 case InputHandlerProxy::DROP_EVENT
:
34 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
;
37 return INPUT_EVENT_ACK_STATE_UNKNOWN
;
42 InputHandlerManager::InputHandlerManager(
43 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
44 InputHandlerManagerClient
* client
,
45 scheduler::RendererScheduler
* renderer_scheduler
)
46 : task_runner_(task_runner
),
48 renderer_scheduler_(renderer_scheduler
) {
50 client_
->SetBoundHandler(base::Bind(&InputHandlerManager::HandleInputEvent
,
51 base::Unretained(this)));
54 InputHandlerManager::~InputHandlerManager() {
55 client_
->SetBoundHandler(InputHandlerManagerClient::Handler());
58 void InputHandlerManager::AddInputHandler(
60 const base::WeakPtr
<cc::InputHandler
>& input_handler
,
61 const base::WeakPtr
<RenderViewImpl
>& render_view_impl
) {
62 if (task_runner_
->BelongsToCurrentThread()) {
63 AddInputHandlerOnCompositorThread(routing_id
,
64 base::ThreadTaskRunnerHandle::Get(),
65 input_handler
, render_view_impl
);
67 task_runner_
->PostTask(
69 base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread
,
70 base::Unretained(this), routing_id
,
71 base::ThreadTaskRunnerHandle::Get(), input_handler
,
76 void InputHandlerManager::AddInputHandlerOnCompositorThread(
78 const scoped_refptr
<base::SingleThreadTaskRunner
>& main_task_runner
,
79 const base::WeakPtr
<cc::InputHandler
>& input_handler
,
80 const base::WeakPtr
<RenderViewImpl
>& render_view_impl
) {
81 DCHECK(task_runner_
->BelongsToCurrentThread());
83 // The handler could be gone by this point if the compositor has shut down.
87 // The same handler may be registered for a route multiple times.
88 if (input_handlers_
.count(routing_id
) != 0)
92 "InputHandlerManager::AddInputHandlerOnCompositorThread",
93 "result", "AddingRoute");
94 scoped_ptr
<InputHandlerWrapper
> wrapper(new InputHandlerWrapper(
95 this, routing_id
, main_task_runner
, input_handler
, render_view_impl
));
96 client_
->DidAddInputHandler(routing_id
, input_handler
.get(),
97 wrapper
->input_handler_proxy());
98 input_handlers_
.add(routing_id
, wrapper
.Pass());
101 void InputHandlerManager::RemoveInputHandler(int routing_id
) {
102 DCHECK(task_runner_
->BelongsToCurrentThread());
103 DCHECK(input_handlers_
.contains(routing_id
));
105 TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler");
107 client_
->DidRemoveInputHandler(routing_id
);
108 input_handlers_
.erase(routing_id
);
111 void InputHandlerManager::ObserveWheelEventAndResultOnMainThread(
113 const blink::WebMouseWheelEvent
& wheel_event
,
114 const cc::InputHandlerScrollResult
& scroll_result
) {
115 task_runner_
->PostTask(
118 &InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread
,
119 base::Unretained(this), routing_id
, wheel_event
, scroll_result
));
122 void InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread(
124 const blink::WebMouseWheelEvent
& wheel_event
,
125 const cc::InputHandlerScrollResult
& scroll_result
) {
126 auto it
= input_handlers_
.find(routing_id
);
127 if (it
== input_handlers_
.end())
130 InputHandlerProxy
* proxy
= it
->second
->input_handler_proxy();
131 DCHECK(proxy
->scroll_elasticity_controller());
132 proxy
->scroll_elasticity_controller()->ObserveWheelEventAndResult(
133 wheel_event
, scroll_result
);
136 InputEventAckState
InputHandlerManager::HandleInputEvent(
138 const WebInputEvent
* input_event
,
139 ui::LatencyInfo
* latency_info
) {
140 DCHECK(task_runner_
->BelongsToCurrentThread());
142 auto it
= input_handlers_
.find(routing_id
);
143 if (it
== input_handlers_
.end()) {
144 TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent",
145 "result", "NoInputHandlerFound");
146 // Oops, we no longer have an interested input handler..
147 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED
;
150 InputHandlerProxy
* proxy
= it
->second
->input_handler_proxy();
151 InputEventAckState input_event_ack_state
= InputEventDispositionToAck(
152 proxy
->HandleInputEventWithLatencyInfo(*input_event
, latency_info
));
153 switch (input_event_ack_state
) {
154 case INPUT_EVENT_ACK_STATE_CONSUMED
:
155 renderer_scheduler_
->DidHandleInputEventOnCompositorThread(
157 RendererScheduler::InputEventState::EVENT_CONSUMED_BY_COMPOSITOR
);
159 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED
:
160 renderer_scheduler_
->DidHandleInputEventOnCompositorThread(
162 RendererScheduler::InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD
);
167 return input_event_ack_state
;
170 void InputHandlerManager::DidOverscroll(int routing_id
,
171 const DidOverscrollParams
& params
) {
172 client_
->DidOverscroll(routing_id
, params
);
175 void InputHandlerManager::DidStopFlinging(int routing_id
) {
176 client_
->DidStopFlinging(routing_id
);
179 void InputHandlerManager::DidAnimateForInput() {
180 renderer_scheduler_
->DidAnimateForInputOnCompositorThread();
183 } // namespace content