// Copyright 2014 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 "remoting/host/local_input_monitor.h" #include "base/bind.h" #include "base/callback.h" #include "base/location.h" #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "base/threading/non_thread_safe.h" #include "remoting/host/chromeos/point_transformer.h" #include "remoting/host/client_session_control.h" #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/platform/platform_event_observer.h" #include "ui/events/platform/platform_event_source.h" namespace remoting { namespace { class LocalInputMonitorChromeos : public LocalInputMonitor { public: LocalInputMonitorChromeos( scoped_refptr caller_task_runner, scoped_refptr input_task_runner, base::WeakPtr client_session_control); ~LocalInputMonitorChromeos() override; private: class Core : ui::PlatformEventObserver { public: Core(scoped_refptr caller_task_runner, base::WeakPtr client_session_control); ~Core() override; void Start(); // ui::PlatformEventObserver interface. void WillProcessEvent(const ui::PlatformEvent& event) override; void DidProcessEvent(const ui::PlatformEvent& event) override; private: void HandleMouseMove(const ui::PlatformEvent& event); void HandleKeyPressed(const ui::PlatformEvent& event); scoped_refptr caller_task_runner_; // Points to the object receiving mouse event notifications and session // disconnect requests. Must be called on the |caller_task_runner_|. base::WeakPtr client_session_control_; // Used to rotate the local mouse positions appropriately based on the // current display rotation settings. scoped_ptr point_transformer_; DISALLOW_COPY_AND_ASSIGN(Core); }; // Task runner on which ui::events are received. scoped_refptr input_task_runner_; scoped_ptr core_; DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorChromeos); }; LocalInputMonitorChromeos::LocalInputMonitorChromeos( scoped_refptr caller_task_runner, scoped_refptr input_task_runner, base::WeakPtr client_session_control) : input_task_runner_(input_task_runner), core_(new Core(caller_task_runner, client_session_control)) { input_task_runner_->PostTask( FROM_HERE, base::Bind(&Core::Start, base::Unretained(core_.get()))); } LocalInputMonitorChromeos::~LocalInputMonitorChromeos() { input_task_runner_->DeleteSoon(FROM_HERE, core_.release()); } LocalInputMonitorChromeos::Core::Core( scoped_refptr caller_task_runner, base::WeakPtr client_session_control) : caller_task_runner_(caller_task_runner), client_session_control_(client_session_control) { DCHECK(client_session_control_.get()); } void LocalInputMonitorChromeos::Core::Start() { ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); point_transformer_.reset(new PointTransformer()); } LocalInputMonitorChromeos::Core::~Core() { ui::PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this); } void LocalInputMonitorChromeos::Core::WillProcessEvent( const ui::PlatformEvent& event) { // No need to handle this callback. } void LocalInputMonitorChromeos::Core::DidProcessEvent( const ui::PlatformEvent& event) { ui::EventType type = ui::EventTypeFromNative(event); if (type == ui::ET_MOUSE_MOVED) { HandleMouseMove(event); } else if (type == ui::ET_KEY_PRESSED) { HandleKeyPressed(event); } } void LocalInputMonitorChromeos::Core::HandleMouseMove( const ui::PlatformEvent& event) { auto mouse_position = gfx::PointF(ui::EventLocationFromNative(event)); mouse_position = point_transformer_->FromScreenCoordinates(mouse_position); caller_task_runner_->PostTask( FROM_HERE, base::Bind( &ClientSessionControl::OnLocalMouseMoved, client_session_control_, webrtc::DesktopVector(mouse_position.x(), mouse_position.y()))); } void LocalInputMonitorChromeos::Core::HandleKeyPressed( const ui::PlatformEvent& event) { ui::KeyEvent key_event(event); DCHECK(key_event.is_char()); if (key_event.IsControlDown() && key_event.IsAltDown() && key_event.key_code() == ui::VKEY_ESCAPE) { caller_task_runner_->PostTask( FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession, client_session_control_, protocol::OK)); } } } // namespace scoped_ptr LocalInputMonitor::Create( scoped_refptr caller_task_runner, scoped_refptr input_task_runner, scoped_refptr ui_task_runner, base::WeakPtr client_session_control) { return make_scoped_ptr(new LocalInputMonitorChromeos( caller_task_runner, input_task_runner, client_session_control)); } } // namespace remoting