Home | History | Annotate | Download | only in input
      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