blob: bf04859821faeddf19391018b48ded015d0c0e3c [file] [log] [blame]
// Copyright (c) 2012 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.
#include "content/renderer/gpu/input_handler_manager.h"
#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop_proxy.h"
#include "cc/input/input_handler.h"
#include "content/renderer/gpu/input_event_filter.h"
#include "content/renderer/gpu/input_handler_manager_client.h"
#include "content/renderer/gpu/input_handler_wrapper.h"
using blink::WebInputEvent;
namespace content {
namespace {
InputEventAckState InputEventDispositionToAck(
InputHandlerProxy::EventDisposition disposition) {
switch (disposition) {
case InputHandlerProxy::DID_HANDLE:
return INPUT_EVENT_ACK_STATE_CONSUMED;
case InputHandlerProxy::DID_NOT_HANDLE:
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
case InputHandlerProxy::DROP_EVENT:
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
}
NOTREACHED();
return INPUT_EVENT_ACK_STATE_UNKNOWN;
}
} // namespace
InputHandlerManager::InputHandlerManager(
const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
InputHandlerManagerClient* client)
: message_loop_proxy_(message_loop_proxy),
client_(client) {
DCHECK(client_);
client_->SetBoundHandler(base::Bind(&InputHandlerManager::HandleInputEvent,
base::Unretained(this)));
}
InputHandlerManager::~InputHandlerManager() {
client_->SetBoundHandler(InputHandlerManagerClient::Handler());
}
void InputHandlerManager::AddInputHandler(
int routing_id,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl) {
if (message_loop_proxy_->BelongsToCurrentThread()) {
AddInputHandlerOnCompositorThread(routing_id,
base::MessageLoopProxy::current(),
input_handler,
render_view_impl);
} else {
message_loop_proxy_->PostTask(
FROM_HERE,
base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread,
base::Unretained(this),
routing_id,
base::MessageLoopProxy::current(),
input_handler,
render_view_impl));
}
}
void InputHandlerManager::AddInputHandlerOnCompositorThread(
int routing_id,
const scoped_refptr<base::MessageLoopProxy>& main_loop,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl) {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
// The handler could be gone by this point if the compositor has shut down.
if (!input_handler)
return;
// The same handler may be registered for a route multiple times.
if (input_handlers_.count(routing_id) != 0)
return;
TRACE_EVENT1("input",
"InputHandlerManager::AddInputHandlerOnCompositorThread",
"result", "AddingRoute");
client_->DidAddInputHandler(routing_id, input_handler.get());
input_handlers_.add(routing_id,
make_scoped_ptr(new InputHandlerWrapper(this,
routing_id, main_loop, input_handler, render_view_impl)));
}
void InputHandlerManager::RemoveInputHandler(int routing_id) {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
DCHECK(input_handlers_.contains(routing_id));
TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler");
client_->DidRemoveInputHandler(routing_id);
input_handlers_.erase(routing_id);
}
InputEventAckState InputHandlerManager::HandleInputEvent(
int routing_id,
const WebInputEvent* input_event,
ui::LatencyInfo* latency_info) {
DCHECK(message_loop_proxy_->BelongsToCurrentThread());
InputHandlerMap::iterator it = input_handlers_.find(routing_id);
if (it == input_handlers_.end()) {
TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent",
"result", "NoInputHandlerFound");
// Oops, we no longer have an interested input handler..
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
InputHandlerProxy* proxy = it->second->input_handler_proxy();
return InputEventDispositionToAck(
proxy->HandleInputEventWithLatencyInfo(*input_event, latency_info));
}
void InputHandlerManager::DidOverscroll(int routing_id,
const cc::DidOverscrollParams& params) {
client_->DidOverscroll(routing_id, params);
}
} // namespace content