Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: remoting/host/local_input_monitor_win.cc

Issue 13142002: Moved code implementing message-only windows to a dedicated class (Windows only). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/host/local_input_monitor.h" 5 #include "remoting/host/local_input_monitor.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/single_thread_task_runner.h" 11 #include "base/single_thread_task_runner.h"
12 #include "base/stringprintf.h" 12 #include "base/stringprintf.h"
13 #include "base/threading/non_thread_safe.h" 13 #include "base/threading/non_thread_safe.h"
14 #include "base/win/wrapped_window_proc.h"
15 #include "remoting/host/client_session_control.h" 14 #include "remoting/host/client_session_control.h"
15 #include "remoting/host/win/message_window.h"
16 #include "third_party/skia/include/core/SkPoint.h" 16 #include "third_party/skia/include/core/SkPoint.h"
17 17
18 namespace remoting { 18 namespace remoting {
19 19
20 namespace { 20 namespace {
21 21
22 const wchar_t kWindowClassFormat[] = L"Chromoting_LocalInputMonitorWin_%p"; 22 const wchar_t kWindowClassFormat[] = L"Chromoting_LocalInputMonitorWin_%p";
23 23
24 // From the HID Usage Tables specification. 24 // From the HID Usage Tables specification.
25 const USHORT kGenericDesktopPage = 1; 25 const USHORT kGenericDesktopPage = 1;
26 const USHORT kMouseUsage = 2; 26 const USHORT kMouseUsage = 2;
27 27
28 class LocalInputMonitorWin : public base::NonThreadSafe, 28 class LocalInputMonitorWin : public base::NonThreadSafe,
29 public LocalInputMonitor { 29 public LocalInputMonitor {
30 public: 30 public:
31 LocalInputMonitorWin( 31 LocalInputMonitorWin(
32 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 32 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
33 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 33 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
34 base::WeakPtr<ClientSessionControl> client_session_control); 34 base::WeakPtr<ClientSessionControl> client_session_control);
35 ~LocalInputMonitorWin(); 35 ~LocalInputMonitorWin();
36 36
37 private: 37 private:
38 // The actual implementation resides in LocalInputMonitorWin::Core class. 38 // The actual implementation resides in LocalInputMonitorWin::Core class.
39 class Core : public base::RefCountedThreadSafe<Core> { 39 class Core : public base::RefCountedThreadSafe<Core>,
40 public win::MessageWindow::Delegate {
40 public: 41 public:
41 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 42 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
42 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 43 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
43 base::WeakPtr<ClientSessionControl> client_session_control); 44 base::WeakPtr<ClientSessionControl> client_session_control);
44 45
45 void Start(); 46 void Start();
46 void Stop(); 47 void Stop();
47 48
48 private: 49 private:
49 friend class base::RefCountedThreadSafe<Core>; 50 friend class base::RefCountedThreadSafe<Core>;
50 virtual ~Core(); 51 virtual ~Core();
51 52
52 void StartOnUiThread(); 53 void StartOnUiThread();
53 void StopOnUiThread(); 54 void StopOnUiThread();
54 55
55 // Handles WM_CREATE messages. 56 // Enables |window_| to receive the raw input.
56 LRESULT OnCreate(HWND hwnd); 57 void EnableRawInput();
57 58
58 // Handles WM_INPUT messages. 59 // Handles WM_INPUT messages.
59 LRESULT OnInput(HRAWINPUT input_handle); 60 LRESULT OnInput(HRAWINPUT input_handle);
60 61
61 // Window procedure invoked by the OS to process window messages. 62 // win::MessageWindow::Delegate interface.
62 static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, 63 virtual bool HandleMessage(UINT message, WPARAM wparam, LPARAM lparam,
63 WPARAM wparam, LPARAM lparam); 64 LRESULT* result) OVERRIDE;
64 65
65 // Task runner on which public methods of this class must be called. 66 // Task runner on which public methods of this class must be called.
66 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; 67 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
67 68
68 // Task runner on which |window_| is created. 69 // Task runner on which |window_| is created.
69 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; 70 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
70 71
71 // Atom representing the input window class. 72 // Used to receive raw input.
72 ATOM atom_; 73 scoped_ptr<win::MessageWindow> window_;
73
74 // Instance of the module containing the window procedure.
75 HINSTANCE instance_;
76
77 // Handle of the input window.
78 HWND window_;
79 74
80 // Points to the object receiving mouse event notifications. 75 // Points to the object receiving mouse event notifications.
81 base::WeakPtr<ClientSessionControl> client_session_control_; 76 base::WeakPtr<ClientSessionControl> client_session_control_;
82 77
83 DISALLOW_COPY_AND_ASSIGN(Core); 78 DISALLOW_COPY_AND_ASSIGN(Core);
84 }; 79 };
85 80
86 scoped_refptr<Core> core_; 81 scoped_refptr<Core> core_;
87 82
88 DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorWin); 83 DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorWin);
(...skipping 12 matching lines...) Expand all
101 LocalInputMonitorWin::~LocalInputMonitorWin() { 96 LocalInputMonitorWin::~LocalInputMonitorWin() {
102 core_->Stop(); 97 core_->Stop();
103 } 98 }
104 99
105 LocalInputMonitorWin::Core::Core( 100 LocalInputMonitorWin::Core::Core(
106 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 101 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
107 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 102 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
108 base::WeakPtr<ClientSessionControl> client_session_control) 103 base::WeakPtr<ClientSessionControl> client_session_control)
109 : caller_task_runner_(caller_task_runner), 104 : caller_task_runner_(caller_task_runner),
110 ui_task_runner_(ui_task_runner), 105 ui_task_runner_(ui_task_runner),
111 atom_(0),
112 instance_(NULL),
113 window_(NULL),
114 client_session_control_(client_session_control) { 106 client_session_control_(client_session_control) {
115 DCHECK(client_session_control_); 107 DCHECK(client_session_control_);
116 } 108 }
117 109
118 void LocalInputMonitorWin::Core::Start() { 110 void LocalInputMonitorWin::Core::Start() {
119 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 111 DCHECK(caller_task_runner_->BelongsToCurrentThread());
120 112
121 ui_task_runner_->PostTask(FROM_HERE, 113 ui_task_runner_->PostTask(FROM_HERE,
122 base::Bind(&Core::StartOnUiThread, this)); 114 base::Bind(&Core::StartOnUiThread, this));
123 } 115 }
124 116
125 void LocalInputMonitorWin::Core::Stop() { 117 void LocalInputMonitorWin::Core::Stop() {
126 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 118 DCHECK(caller_task_runner_->BelongsToCurrentThread());
127 119
128 ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::StopOnUiThread, this)); 120 ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::StopOnUiThread, this));
129 } 121 }
130 122
131 LocalInputMonitorWin::Core::~Core() { 123 LocalInputMonitorWin::Core::~Core() {
132 DCHECK(!atom_);
133 DCHECK(!instance_);
134 DCHECK(!window_); 124 DCHECK(!window_);
135 } 125 }
136 126
137 void LocalInputMonitorWin::Core::StartOnUiThread() { 127 void LocalInputMonitorWin::Core::StartOnUiThread() {
138 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 128 DCHECK(ui_task_runner_->BelongsToCurrentThread());
139 129
140 // Create a window for receiving raw input. 130 window_.reset(new win::MessageWindow());
141 string16 window_class_name = base::StringPrintf(kWindowClassFormat, this); 131 if (!window_->Create(this)) {
142 WNDCLASSEX window_class; 132 LOG_GETLASTERROR(ERROR) << "Failed to create the raw input window";
143 base::win::InitializeWindowClass(
144 window_class_name.c_str(),
145 &base::win::WrappedWindowProc<WindowProc>,
146 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
147 &window_class);
148 instance_ = window_class.hInstance;
149 atom_ = RegisterClassEx(&window_class);
150 if (atom_ == 0) {
151 LOG_GETLASTERROR(ERROR)
152 << "Failed to register the window class '" << window_class_name << "'";
153 return;
154 }
155 133
156 window_ = CreateWindow(MAKEINTATOM(atom_), 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 134 // If the local input cannot be monitored, the remote user can take over
157 instance_, this); 135 // the session. Disconnect the session now to prevent this.
158 if (window_ == NULL) { 136 caller_task_runner_->PostTask(
159 LOG_GETLASTERROR(ERROR) << "Failed to create the raw input window"; 137 FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession,
160 return; 138 client_session_control_));
161 } 139 }
162 } 140 }
163 141
164 void LocalInputMonitorWin::Core::StopOnUiThread() { 142 void LocalInputMonitorWin::Core::StopOnUiThread() {
165 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 143 DCHECK(ui_task_runner_->BelongsToCurrentThread());
166 144
167 if (window_ != NULL) { 145 // Stop receiving raw mouse input.
168 DestroyWindow(window_); 146 if (window_ && window_->hwnd()) {
169 window_ = NULL; 147 RAWINPUTDEVICE device = {0};
148 device.dwFlags = RIDEV_REMOVE;
149 device.usUsagePage = kGenericDesktopPage;
150 device.usUsage = kMouseUsage;
151 device.hwndTarget = window_->hwnd();
152
153 // The error is harmless, ignore it.
154 RegisterRawInputDevices(&device, 1, sizeof(device));
170 } 155 }
171 156
172 if (atom_ != 0) { 157 window_.reset();
173 UnregisterClass(MAKEINTATOM(atom_), instance_);
174 atom_ = 0;
175 instance_ = NULL;
176 }
177 } 158 }
178 159
179 LRESULT LocalInputMonitorWin::Core::OnCreate(HWND hwnd) { 160 void LocalInputMonitorWin::Core::EnableRawInput() {
180 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 161 DCHECK(ui_task_runner_->BelongsToCurrentThread());
181 162
182 // Register to receive raw mouse input. 163 if (window_ && window_->hwnd()) {
183 RAWINPUTDEVICE device = {0}; 164 // Register to receive raw mouse input.
184 device.dwFlags = RIDEV_INPUTSINK; 165 RAWINPUTDEVICE device = {0};
185 device.usUsagePage = kGenericDesktopPage; 166 device.dwFlags = RIDEV_INPUTSINK;
186 device.usUsage = kMouseUsage; 167 device.usUsagePage = kGenericDesktopPage;
187 device.hwndTarget = hwnd; 168 device.usUsage = kMouseUsage;
188 if (!RegisterRawInputDevices(&device, 1, sizeof(device))) { 169 device.hwndTarget = window_->hwnd();
170 if (RegisterRawInputDevices(&device, 1, sizeof(device)))
171 return;
172
189 LOG_GETLASTERROR(ERROR) << "RegisterRawInputDevices() failed"; 173 LOG_GETLASTERROR(ERROR) << "RegisterRawInputDevices() failed";
190 return -1;
191 } 174 }
192 175
193 return 0; 176 // If the local input cannot be monitored, the remote user can take over
177 // the session. Disconnect the session now to prevent this.
178 caller_task_runner_->PostTask(
179 FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession,
180 client_session_control_));
194 } 181 }
195 182
196 LRESULT LocalInputMonitorWin::Core::OnInput(HRAWINPUT input_handle) { 183 LRESULT LocalInputMonitorWin::Core::OnInput(HRAWINPUT input_handle) {
197 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 184 DCHECK(ui_task_runner_->BelongsToCurrentThread());
198 185
199 // Get the size of the input record. 186 // Get the size of the input record.
200 UINT size = 0; 187 UINT size = 0;
201 UINT result = GetRawInputData(input_handle, 188 UINT result = GetRawInputData(input_handle,
202 RID_INPUT, 189 RID_INPUT,
203 NULL, 190 NULL,
(...skipping 29 matching lines...) Expand all
233 220
234 caller_task_runner_->PostTask( 221 caller_task_runner_->PostTask(
235 FROM_HERE, base::Bind(&ClientSessionControl::OnLocalMouseMoved, 222 FROM_HERE, base::Bind(&ClientSessionControl::OnLocalMouseMoved,
236 client_session_control_, 223 client_session_control_,
237 SkIPoint::Make(position.x, position.y))); 224 SkIPoint::Make(position.x, position.y)));
238 } 225 }
239 226
240 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); 227 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
241 } 228 }
242 229
243 // static 230 bool LocalInputMonitorWin::Core::HandleMessage(
244 LRESULT CALLBACK LocalInputMonitorWin::Core::WindowProc( 231 UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) {
245 HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
246 // Store |this| to the window's user data.
247 if (message == WM_CREATE) {
248 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lparam);
249 SetLastError(ERROR_SUCCESS);
250 LONG_PTR result = SetWindowLongPtr(
251 hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(cs->lpCreateParams));
252 CHECK(result != 0 || GetLastError() == ERROR_SUCCESS);
253 }
254
255 Core* self = reinterpret_cast<Core*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
256 switch (message) { 232 switch (message) {
257 case WM_CREATE: 233 case WM_CREATE:
258 return self->OnCreate(hwnd); 234 // |window_->hwnd()| is not available yet. Enable raw mouse input once
dcaiafa 2013/03/28 23:25:35 Refer to my comment on MessageWindow. I think hwnd
alexeypa (please no reviews) 2013/03/29 16:57:01 Done.
235 // the window is fully created.
236 ui_task_runner_->PostTask(FROM_HERE,
237 base::Bind(&Core::EnableRawInput, this));
238 *result = 0;
239 return true;
259 240
260 case WM_INPUT: 241 case WM_INPUT:
261 return self->OnInput(reinterpret_cast<HRAWINPUT>(lparam)); 242 *result = OnInput(reinterpret_cast<HRAWINPUT>(lparam));
243 return true;
262 244
263 default: 245 default:
264 return DefWindowProc(hwnd, message, wparam, lparam); 246 return false;
265 } 247 }
266 } 248 }
267 249
268 } // namespace 250 } // namespace
269 251
270 scoped_ptr<LocalInputMonitor> LocalInputMonitor::Create( 252 scoped_ptr<LocalInputMonitor> LocalInputMonitor::Create(
271 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, 253 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
272 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, 254 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
273 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 255 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
274 base::WeakPtr<ClientSessionControl> client_session_control) { 256 base::WeakPtr<ClientSessionControl> client_session_control) {
275 return scoped_ptr<LocalInputMonitor>( 257 return scoped_ptr<LocalInputMonitor>(
276 new LocalInputMonitorWin(caller_task_runner, 258 new LocalInputMonitorWin(caller_task_runner,
277 ui_task_runner, 259 ui_task_runner,
278 client_session_control)); 260 client_session_control));
279 } 261 }
280 262
281 } // namespace remoting 263 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698