// 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/compositor_thread.h" #include "base/bind.h" #include "base/debug/trace_event.h" #include "content/renderer/gpu/input_event_filter.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebActiveWheelFlingParameters.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositorInputHandlerClient.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositorInputHandler.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" using WebKit::WebCompositorInputHandler; using WebKit::WebInputEvent; //------------------------------------------------------------------------------ class CompositorThread::InputHandlerWrapper : public WebKit::WebCompositorInputHandlerClient, public base::RefCountedThreadSafe { public: InputHandlerWrapper(CompositorThread* compositor_thread, int routing_id, WebKit::WebCompositorInputHandler* input_handler, scoped_refptr main_loop, const base::WeakPtr& render_view_impl) : compositor_thread_(compositor_thread), routing_id_(routing_id), input_handler_(input_handler), main_loop_(main_loop), render_view_impl_(render_view_impl) { input_handler_->setClient(this); } virtual void transferActiveWheelFlingAnimation( const WebKit::WebActiveWheelFlingParameters& params) { main_loop_->PostTask( FROM_HERE, base::Bind(&RenderViewImpl::TransferActiveWheelFlingAnimation, render_view_impl_, params)); } virtual ~InputHandlerWrapper() { input_handler_->setClient(NULL); } int routing_id() const { return routing_id_; } WebKit::WebCompositorInputHandler* input_handler() const { return input_handler_; } // WebCompositorInputHandlerClient methods: virtual void willShutdown() { compositor_thread_->RemoveInputHandler(routing_id_); } virtual void didHandleInputEvent() { compositor_thread_->filter_->DidHandleInputEvent(); } virtual void didNotHandleInputEvent(bool send_to_widget) { compositor_thread_->filter_->DidNotHandleInputEvent(send_to_widget); } private: CompositorThread* compositor_thread_; int routing_id_; WebKit::WebCompositorInputHandler* input_handler_; scoped_refptr main_loop_; // Can only be accessed on the main thread. base::WeakPtr render_view_impl_; DISALLOW_COPY_AND_ASSIGN(InputHandlerWrapper); }; //------------------------------------------------------------------------------ CompositorThread::CompositorThread(IPC::Channel::Listener* main_listener) : thread_("Compositor") { filter_ = new InputEventFilter(main_listener, thread_.message_loop()->message_loop_proxy(), base::Bind(&CompositorThread::HandleInputEvent, base::Unretained(this))); } CompositorThread::~CompositorThread() { } IPC::ChannelProxy::MessageFilter* CompositorThread::GetMessageFilter() const { return filter_; } void CompositorThread::AddInputHandler( int routing_id, int input_handler_id, const base::WeakPtr& render_view_impl) { DCHECK_NE(thread_.message_loop(), MessageLoop::current()); thread_.message_loop()->PostTask( FROM_HERE, base::Bind(&CompositorThread::AddInputHandlerOnCompositorThread, base::Unretained(this), routing_id, input_handler_id, base::MessageLoopProxy::current(), render_view_impl)); } void CompositorThread::AddInputHandlerOnCompositorThread( int routing_id, int input_handler_id, scoped_refptr main_loop, const base::WeakPtr& render_view_impl) { DCHECK_EQ(thread_.message_loop(), MessageLoop::current()); WebCompositorInputHandler* input_handler = WebCompositorInputHandler::fromIdentifier(input_handler_id); if (!input_handler) return; if (input_handlers_.count(routing_id) != 0) { // It's valid to call AddInputHandler() for the same routing id with the // same input_handler many times, but it's not valid to change the // input_handler for a route. DCHECK_EQ(input_handlers_[routing_id]->input_handler(), input_handler); return; } TRACE_EVENT0("CompositorThread::AddInputHandler", "AddingRoute"); filter_->AddRoute(routing_id); input_handlers_[routing_id] = make_scoped_refptr(new InputHandlerWrapper(this, routing_id, input_handler, main_loop, render_view_impl)); } void CompositorThread::RemoveInputHandler(int routing_id) { DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); TRACE_EVENT0("CompositorThread::RemoveInputHandler", "RemovingRoute"); filter_->RemoveRoute(routing_id); input_handlers_.erase(routing_id); } void CompositorThread::HandleInputEvent( int routing_id, const WebInputEvent* input_event) { DCHECK_EQ(MessageLoop::current(), thread_.message_loop()); InputHandlerMap::iterator it = input_handlers_.find(routing_id); if (it == input_handlers_.end()) { TRACE_EVENT0("CompositorThread::HandleInputEvent", "NoInputHandlerFound"); // Oops, we no longer have an interested input handler.. filter_->DidNotHandleInputEvent(true); return; } it->second->input_handler()->handleInputEvent(*input_event); }