// Copyright 2015 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/mus/compositor_mus_connection.h" #include "base/single_thread_task_runner.h" #include "content/common/input/web_input_event_traits.h" #include "content/renderer/input/input_handler_manager.h" #include "content/renderer/mus/render_widget_mus_connection.h" #include "mojo/converters/blink/blink_input_events_type_converters.h" #include "mojo/converters/input_events/input_events_type_converters.h" #include "ui/events/latency_info.h" namespace { void DoNothingBool(bool result) {} } // namespace namespace content { CompositorMusConnection::CompositorMusConnection( int routing_id, const scoped_refptr& main_task_runner, const scoped_refptr& compositor_task_runner, mojo::InterfaceRequest request, InputHandlerManager* input_handler_manager) : routing_id_(routing_id), root_(nullptr), main_task_runner_(main_task_runner), compositor_task_runner_(compositor_task_runner), input_handler_manager_(input_handler_manager) { DCHECK(main_task_runner_->BelongsToCurrentThread()); compositor_task_runner_->PostTask( FROM_HERE, base::Bind(&CompositorMusConnection:: CreateWindowTreeConnectionOnCompositorThread, this, base::Passed(std::move(request)))); } void CompositorMusConnection::AttachSurfaceOnMainThread( scoped_ptr surface_binding) { DCHECK(main_task_runner_->BelongsToCurrentThread()); compositor_task_runner_->PostTask( FROM_HERE, base::Bind(&CompositorMusConnection::AttachSurfaceOnCompositorThread, this, base::Passed(std::move(surface_binding)))); } CompositorMusConnection::~CompositorMusConnection() {} void CompositorMusConnection::AttachSurfaceOnCompositorThread( scoped_ptr surface_binding) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); window_surface_binding_ = std::move(surface_binding); if (root_) { root_->AttachSurface(mus::mojom::SurfaceType::DEFAULT, std::move(window_surface_binding_)); } } void CompositorMusConnection::CreateWindowTreeConnectionOnCompositorThread( mojo::InterfaceRequest request) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); mus::WindowTreeConnection::Create( this, std::move(request), mus::WindowTreeConnection::CreateType::DONT_WAIT_FOR_EMBED); } void CompositorMusConnection::OnConnectionLostOnMainThread() { DCHECK(main_task_runner_->BelongsToCurrentThread()); RenderWidgetMusConnection* connection = RenderWidgetMusConnection::Get(routing_id_); if (!connection) return; connection->OnConnectionLost(); } void CompositorMusConnection::OnWindowInputEventOnMainThread( scoped_ptr web_event, const base::Callback& ack) { DCHECK(main_task_runner_->BelongsToCurrentThread()); RenderWidgetMusConnection* connection = RenderWidgetMusConnection::Get(routing_id_); if (!connection) { ack.Run(false); return; } connection->OnWindowInputEvent(std::move(web_event), ack); } void CompositorMusConnection::OnWindowInputEventAckOnMainThread( const base::Callback& ack, bool handled) { DCHECK(main_task_runner_->BelongsToCurrentThread()); compositor_task_runner_->PostTask(FROM_HERE, base::Bind(ack, handled)); } void CompositorMusConnection::OnConnectionLost( mus::WindowTreeConnection* connection) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); main_task_runner_->PostTask( FROM_HERE, base::Bind(&CompositorMusConnection::OnConnectionLostOnMainThread, this)); } void CompositorMusConnection::OnEmbed(mus::Window* root) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); root_ = root; root_->set_input_event_handler(this); if (window_surface_binding_) { root->AttachSurface(mus::mojom::SurfaceType::DEFAULT, std::move(window_surface_binding_)); } } void CompositorMusConnection::OnWindowInputEvent( mus::Window* window, const ui::Event& event, scoped_ptr>* ack_callback) { DCHECK(compositor_task_runner_->BelongsToCurrentThread()); // TODO(moshayedi): Convert ui::Event directly to blink::WebInputEvent. scoped_ptr web_event( mus::mojom::Event::From(event).To>()); // TODO(sad): We probably need to plumb LatencyInfo through Mus. ui::LatencyInfo info; InputEventAckState ack_state = input_handler_manager_->HandleInputEvent( routing_id_, web_event.get(), &info); // TODO(jonross): We probably need to ack the event based on the consumed // state. if (ack_state != INPUT_EVENT_ACK_STATE_NOT_CONSUMED) return; base::Callback ack = base::Bind(&::DoNothingBool); const bool send_ack = WebInputEventTraits::ShouldBlockEventStream(*web_event); if (send_ack) { // Ultimately, this ACK needs to go back to the Mus client lib which is not // thread-safe and lives on the compositor thread. For ACKs that are passed // to the main thread we pass them back to the compositor thread via // OnWindowInputEventAckOnMainThread. ack = base::Bind(&CompositorMusConnection::OnWindowInputEventAckOnMainThread, this, *ack_callback->get()); ack_callback->reset(); } main_task_runner_->PostTask( FROM_HERE, base::Bind(&CompositorMusConnection::OnWindowInputEventOnMainThread, this, base::Passed(std::move(web_event)), ack)); } } // namespace content