This source file includes following definitions.
- client_session_control_
- Start
- Stop
- StartOnUiThread
- StopOnUiThread
- OnInput
- HandleMessage
- Create
#include "remoting/host/local_input_monitor.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/threading/non_thread_safe.h"
#include "base/win/message_window.h"
#include "remoting/host/client_session_control.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
namespace remoting {
namespace {
const wchar_t kWindowClassFormat[] = L"Chromoting_LocalInputMonitorWin_%p";
const USHORT kGenericDesktopPage = 1;
const USHORT kMouseUsage = 2;
class LocalInputMonitorWin : public base::NonThreadSafe,
public LocalInputMonitor {
public:
LocalInputMonitorWin(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::WeakPtr<ClientSessionControl> client_session_control);
~LocalInputMonitorWin();
private:
class Core : public base::RefCountedThreadSafe<Core> {
public:
Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::WeakPtr<ClientSessionControl> client_session_control);
void Start();
void Stop();
private:
friend class base::RefCountedThreadSafe<Core>;
virtual ~Core();
void StartOnUiThread();
void StopOnUiThread();
LRESULT OnInput(HRAWINPUT input_handle);
bool HandleMessage(UINT message,
WPARAM wparam,
LPARAM lparam,
LRESULT* result);
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
scoped_ptr<base::win::MessageWindow> window_;
base::WeakPtr<ClientSessionControl> client_session_control_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
scoped_refptr<Core> core_;
DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorWin);
};
LocalInputMonitorWin::LocalInputMonitorWin(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::WeakPtr<ClientSessionControl> client_session_control)
: core_(new Core(caller_task_runner,
ui_task_runner,
client_session_control)) {
core_->Start();
}
LocalInputMonitorWin::~LocalInputMonitorWin() {
core_->Stop();
}
LocalInputMonitorWin::Core::Core(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::WeakPtr<ClientSessionControl> client_session_control)
: caller_task_runner_(caller_task_runner),
ui_task_runner_(ui_task_runner),
client_session_control_(client_session_control) {
DCHECK(client_session_control_);
}
void LocalInputMonitorWin::Core::Start() {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
ui_task_runner_->PostTask(FROM_HERE,
base::Bind(&Core::StartOnUiThread, this));
}
void LocalInputMonitorWin::Core::Stop() {
DCHECK(caller_task_runner_->BelongsToCurrentThread());
ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::StopOnUiThread, this));
}
LocalInputMonitorWin::Core::~Core() {
DCHECK(!window_);
}
void LocalInputMonitorWin::Core::StartOnUiThread() {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
window_.reset(new base::win::MessageWindow());
if (!window_->Create(base::Bind(&Core::HandleMessage,
base::Unretained(this)))) {
LOG_GETLASTERROR(ERROR) << "Failed to create the raw input window";
window_.reset();
caller_task_runner_->PostTask(
FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession,
client_session_control_));
}
}
void LocalInputMonitorWin::Core::StopOnUiThread() {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
if (window_) {
RAWINPUTDEVICE device = {0};
device.dwFlags = RIDEV_REMOVE;
device.usUsagePage = kGenericDesktopPage;
device.usUsage = kMouseUsage;
device.hwndTarget = NULL;
RegisterRawInputDevices(&device, 1, sizeof(device));
}
window_.reset();
}
LRESULT LocalInputMonitorWin::Core::OnInput(HRAWINPUT input_handle) {
DCHECK(ui_task_runner_->BelongsToCurrentThread());
UINT size = 0;
UINT result = GetRawInputData(input_handle,
RID_INPUT,
NULL,
&size,
sizeof(RAWINPUTHEADER));
if (result == -1) {
LOG_GETLASTERROR(ERROR) << "GetRawInputData() failed";
return 0;
}
scoped_ptr<uint8[]> buffer(new uint8[size]);
RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get());
result = GetRawInputData(input_handle,
RID_INPUT,
buffer.get(),
&size,
sizeof(RAWINPUTHEADER));
if (result == -1) {
LOG_GETLASTERROR(ERROR) << "GetRawInputData() failed";
return 0;
}
if (input->header.dwType == RIM_TYPEMOUSE &&
input->header.hDevice != NULL) {
POINT position;
if (!GetCursorPos(&position)) {
position.x = 0;
position.y = 0;
}
caller_task_runner_->PostTask(
FROM_HERE, base::Bind(&ClientSessionControl::OnLocalMouseMoved,
client_session_control_,
webrtc::DesktopVector(position.x, position.y)));
}
return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
}
bool LocalInputMonitorWin::Core::HandleMessage(
UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) {
switch (message) {
case WM_CREATE: {
RAWINPUTDEVICE device = {0};
device.dwFlags = RIDEV_INPUTSINK;
device.usUsagePage = kGenericDesktopPage;
device.usUsage = kMouseUsage;
device.hwndTarget = window_->hwnd();
if (RegisterRawInputDevices(&device, 1, sizeof(device))) {
*result = 0;
} else {
LOG_GETLASTERROR(ERROR) << "RegisterRawInputDevices() failed";
*result = -1;
}
return true;
}
case WM_INPUT:
*result = OnInput(reinterpret_cast<HRAWINPUT>(lparam));
return true;
default:
return false;
}
}
}
scoped_ptr<LocalInputMonitor> LocalInputMonitor::Create(
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
base::WeakPtr<ClientSessionControl> client_session_control) {
return scoped_ptr<LocalInputMonitor>(
new LocalInputMonitorWin(caller_task_runner,
ui_task_runner,
client_session_control));
}
}