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. 4 5 #include "content/renderer/input/input_handler_manager.h" 6 7 #include "base/bind.h" 8 #include "base/debug/trace_event.h" 9 #include "base/message_loop/message_loop_proxy.h" 10 #include "cc/input/input_handler.h" 11 #include "content/renderer/input/input_event_filter.h" 12 #include "content/renderer/input/input_handler_manager_client.h" 13 #include "content/renderer/input/input_handler_wrapper.h" 14 15 using blink::WebInputEvent; 16 17 namespace content { 18 19 namespace { 20 21 InputEventAckState InputEventDispositionToAck( 22 InputHandlerProxy::EventDisposition disposition) { 23 switch (disposition) { 24 case InputHandlerProxy::DID_HANDLE: 25 return INPUT_EVENT_ACK_STATE_CONSUMED; 26 case InputHandlerProxy::DID_NOT_HANDLE: 27 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 28 case InputHandlerProxy::DROP_EVENT: 29 return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; 30 } 31 NOTREACHED(); 32 return INPUT_EVENT_ACK_STATE_UNKNOWN; 33 } 34 35 } // namespace 36 37 InputHandlerManager::InputHandlerManager( 38 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy, 39 InputHandlerManagerClient* client) 40 : message_loop_proxy_(message_loop_proxy), 41 client_(client) { 42 DCHECK(client_); 43 client_->SetBoundHandler(base::Bind(&InputHandlerManager::HandleInputEvent, 44 base::Unretained(this))); 45 } 46 47 InputHandlerManager::~InputHandlerManager() { 48 client_->SetBoundHandler(InputHandlerManagerClient::Handler()); 49 } 50 51 void InputHandlerManager::AddInputHandler( 52 int routing_id, 53 const base::WeakPtr<cc::InputHandler>& input_handler, 54 const base::WeakPtr<RenderViewImpl>& render_view_impl) { 55 if (message_loop_proxy_->BelongsToCurrentThread()) { 56 AddInputHandlerOnCompositorThread(routing_id, 57 base::MessageLoopProxy::current(), 58 input_handler, 59 render_view_impl); 60 } else { 61 message_loop_proxy_->PostTask( 62 FROM_HERE, 63 base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread, 64 base::Unretained(this), 65 routing_id, 66 base::MessageLoopProxy::current(), 67 input_handler, 68 render_view_impl)); 69 } 70 } 71 72 void InputHandlerManager::AddInputHandlerOnCompositorThread( 73 int routing_id, 74 const scoped_refptr<base::MessageLoopProxy>& main_loop, 75 const base::WeakPtr<cc::InputHandler>& input_handler, 76 const base::WeakPtr<RenderViewImpl>& render_view_impl) { 77 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 78 79 // The handler could be gone by this point if the compositor has shut down. 80 if (!input_handler) 81 return; 82 83 // The same handler may be registered for a route multiple times. 84 if (input_handlers_.count(routing_id) != 0) 85 return; 86 87 TRACE_EVENT1("input", 88 "InputHandlerManager::AddInputHandlerOnCompositorThread", 89 "result", "AddingRoute"); 90 client_->DidAddInputHandler(routing_id, input_handler.get()); 91 input_handlers_.add(routing_id, 92 make_scoped_ptr(new InputHandlerWrapper(this, 93 routing_id, main_loop, input_handler, render_view_impl))); 94 } 95 96 void InputHandlerManager::RemoveInputHandler(int routing_id) { 97 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 98 DCHECK(input_handlers_.contains(routing_id)); 99 100 TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler"); 101 102 client_->DidRemoveInputHandler(routing_id); 103 input_handlers_.erase(routing_id); 104 } 105 106 InputEventAckState InputHandlerManager::HandleInputEvent( 107 int routing_id, 108 const WebInputEvent* input_event, 109 ui::LatencyInfo* latency_info) { 110 DCHECK(message_loop_proxy_->BelongsToCurrentThread()); 111 112 InputHandlerMap::iterator it = input_handlers_.find(routing_id); 113 if (it == input_handlers_.end()) { 114 TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent", 115 "result", "NoInputHandlerFound"); 116 // Oops, we no longer have an interested input handler.. 117 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED; 118 } 119 120 InputHandlerProxy* proxy = it->second->input_handler_proxy(); 121 return InputEventDispositionToAck( 122 proxy->HandleInputEventWithLatencyInfo(*input_event, latency_info)); 123 } 124 125 void InputHandlerManager::DidOverscroll(int routing_id, 126 const DidOverscrollParams& params) { 127 client_->DidOverscroll(routing_id, params); 128 } 129 130 void InputHandlerManager::DidStopFlinging(int routing_id) { 131 client_->DidStopFlinging(routing_id); 132 } 133 134 } // namespace content 135