1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "media/base/user_input_monitor.h" 6 7 #include "base/bind.h" 8 #include "base/location.h" 9 #include "base/logging.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/single_thread_task_runner.h" 12 #include "base/strings/stringprintf.h" 13 #include "base/synchronization/lock.h" 14 #include "base/win/message_window.h" 15 #include "media/base/keyboard_event_counter.h" 16 #include "third_party/skia/include/core/SkPoint.h" 17 #include "ui/events/keycodes/keyboard_code_conversion_win.h" 18 19 namespace media { 20 namespace { 21 22 // From the HID Usage Tables specification. 23 const USHORT kGenericDesktopPage = 1; 24 const USHORT kMouseUsage = 2; 25 const USHORT kKeyboardUsage = 6; 26 27 // This is the actual implementation of event monitoring. It's separated from 28 // UserInputMonitorWin since it needs to be deleted on the UI thread. 29 class UserInputMonitorWinCore 30 : public base::SupportsWeakPtr<UserInputMonitorWinCore>, 31 public base::MessageLoop::DestructionObserver { 32 public: 33 enum EventBitMask { 34 MOUSE_EVENT_MASK = 1, 35 KEYBOARD_EVENT_MASK = 2, 36 }; 37 38 explicit UserInputMonitorWinCore( 39 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 40 const scoped_refptr<UserInputMonitor::MouseListenerList>& 41 mouse_listeners); 42 ~UserInputMonitorWinCore(); 43 44 // DestructionObserver overrides. 45 virtual void WillDestroyCurrentMessageLoop() OVERRIDE; 46 47 size_t GetKeyPressCount() const; 48 void StartMonitor(EventBitMask type); 49 void StopMonitor(EventBitMask type); 50 51 private: 52 // Handles WM_INPUT messages. 53 LRESULT OnInput(HRAWINPUT input_handle); 54 // Handles messages received by |window_|. 55 bool HandleMessage(UINT message, 56 WPARAM wparam, 57 LPARAM lparam, 58 LRESULT* result); 59 RAWINPUTDEVICE* GetRawInputDevices(EventBitMask event, DWORD flags); 60 61 // Task runner on which |window_| is created. 62 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; 63 scoped_refptr<ObserverListThreadSafe<UserInputMonitor::MouseEventListener> > 64 mouse_listeners_; 65 66 // These members are only accessed on the UI thread. 67 scoped_ptr<base::win::MessageWindow> window_; 68 uint8 events_monitored_; 69 KeyboardEventCounter counter_; 70 71 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWinCore); 72 }; 73 74 class UserInputMonitorWin : public UserInputMonitor { 75 public: 76 explicit UserInputMonitorWin( 77 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner); 78 virtual ~UserInputMonitorWin(); 79 80 // Public UserInputMonitor overrides. 81 virtual size_t GetKeyPressCount() const OVERRIDE; 82 83 private: 84 // Private UserInputMonitor overrides. 85 virtual void StartKeyboardMonitoring() OVERRIDE; 86 virtual void StopKeyboardMonitoring() OVERRIDE; 87 virtual void StartMouseMonitoring() OVERRIDE; 88 virtual void StopMouseMonitoring() OVERRIDE; 89 90 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; 91 UserInputMonitorWinCore* core_; 92 93 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWin); 94 }; 95 96 UserInputMonitorWinCore::UserInputMonitorWinCore( 97 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, 98 const scoped_refptr<UserInputMonitor::MouseListenerList>& mouse_listeners) 99 : ui_task_runner_(ui_task_runner), 100 mouse_listeners_(mouse_listeners), 101 events_monitored_(0) {} 102 103 UserInputMonitorWinCore::~UserInputMonitorWinCore() { 104 DCHECK(!window_); 105 DCHECK(!events_monitored_); 106 } 107 108 void UserInputMonitorWinCore::WillDestroyCurrentMessageLoop() { 109 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 110 StopMonitor(MOUSE_EVENT_MASK); 111 StopMonitor(KEYBOARD_EVENT_MASK); 112 } 113 114 size_t UserInputMonitorWinCore::GetKeyPressCount() const { 115 return counter_.GetKeyPressCount(); 116 } 117 118 void UserInputMonitorWinCore::StartMonitor(EventBitMask type) { 119 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 120 121 if (events_monitored_ & type) 122 return; 123 124 if (type == KEYBOARD_EVENT_MASK) 125 counter_.Reset(); 126 127 if (!window_) { 128 window_.reset(new base::win::MessageWindow()); 129 if (!window_->Create(base::Bind(&UserInputMonitorWinCore::HandleMessage, 130 base::Unretained(this)))) { 131 PLOG(ERROR) << "Failed to create the raw input window"; 132 window_.reset(); 133 return; 134 } 135 } 136 137 // Register to receive raw mouse and/or keyboard input. 138 scoped_ptr<RAWINPUTDEVICE> device(GetRawInputDevices(type, RIDEV_INPUTSINK)); 139 if (!RegisterRawInputDevices(device.get(), 1, sizeof(*device))) { 140 PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK"; 141 window_.reset(); 142 return; 143 } 144 145 // Start observing message loop destruction if we start monitoring the first 146 // event. 147 if (!events_monitored_) 148 base::MessageLoop::current()->AddDestructionObserver(this); 149 150 events_monitored_ |= type; 151 } 152 153 void UserInputMonitorWinCore::StopMonitor(EventBitMask type) { 154 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 155 156 if (!(events_monitored_ & type)) 157 return; 158 159 // Stop receiving raw input. 160 DCHECK(window_); 161 scoped_ptr<RAWINPUTDEVICE> device(GetRawInputDevices(type, RIDEV_REMOVE)); 162 163 if (!RegisterRawInputDevices(device.get(), 1, sizeof(*device))) { 164 PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE"; 165 } 166 167 events_monitored_ &= ~type; 168 if (events_monitored_ == 0) { 169 window_.reset(); 170 171 // Stop observing message loop destruction if no event is being monitored. 172 base::MessageLoop::current()->RemoveDestructionObserver(this); 173 } 174 } 175 176 LRESULT UserInputMonitorWinCore::OnInput(HRAWINPUT input_handle) { 177 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 178 179 // Get the size of the input record. 180 UINT size = 0; 181 UINT result = GetRawInputData( 182 input_handle, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); 183 if (result == -1) { 184 PLOG(ERROR) << "GetRawInputData() failed"; 185 return 0; 186 } 187 DCHECK_EQ(0u, result); 188 189 // Retrieve the input record itself. 190 scoped_ptr<uint8[]> buffer(new uint8[size]); 191 RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get()); 192 result = GetRawInputData( 193 input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER)); 194 if (result == -1) { 195 PLOG(ERROR) << "GetRawInputData() failed"; 196 return 0; 197 } 198 DCHECK_EQ(size, result); 199 200 // Notify the observer about events generated locally. 201 if (input->header.dwType == RIM_TYPEMOUSE && input->header.hDevice != NULL) { 202 POINT position; 203 if (!GetCursorPos(&position)) { 204 position.x = 0; 205 position.y = 0; 206 } 207 mouse_listeners_->Notify( 208 &UserInputMonitor::MouseEventListener::OnMouseMoved, 209 SkIPoint::Make(position.x, position.y)); 210 } else if (input->header.dwType == RIM_TYPEKEYBOARD && 211 input->header.hDevice != NULL) { 212 ui::EventType event = (input->data.keyboard.Flags & RI_KEY_BREAK) 213 ? ui::ET_KEY_RELEASED 214 : ui::ET_KEY_PRESSED; 215 ui::KeyboardCode key_code = 216 ui::KeyboardCodeForWindowsKeyCode(input->data.keyboard.VKey); 217 counter_.OnKeyboardEvent(event, key_code); 218 } 219 220 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER)); 221 } 222 223 bool UserInputMonitorWinCore::HandleMessage(UINT message, 224 WPARAM wparam, 225 LPARAM lparam, 226 LRESULT* result) { 227 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 228 229 switch (message) { 230 case WM_INPUT: 231 *result = OnInput(reinterpret_cast<HRAWINPUT>(lparam)); 232 return true; 233 234 default: 235 return false; 236 } 237 } 238 239 RAWINPUTDEVICE* UserInputMonitorWinCore::GetRawInputDevices(EventBitMask event, 240 DWORD flags) { 241 DCHECK(ui_task_runner_->BelongsToCurrentThread()); 242 243 scoped_ptr<RAWINPUTDEVICE> device(new RAWINPUTDEVICE()); 244 if (event == MOUSE_EVENT_MASK) { 245 device->dwFlags = flags; 246 device->usUsagePage = kGenericDesktopPage; 247 device->usUsage = kMouseUsage; 248 device->hwndTarget = window_->hwnd(); 249 } else { 250 DCHECK_EQ(KEYBOARD_EVENT_MASK, event); 251 device->dwFlags = flags; 252 device->usUsagePage = kGenericDesktopPage; 253 device->usUsage = kKeyboardUsage; 254 device->hwndTarget = window_->hwnd(); 255 } 256 return device.release(); 257 } 258 259 // 260 // Implementation of UserInputMonitorWin. 261 // 262 263 UserInputMonitorWin::UserInputMonitorWin( 264 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) 265 : ui_task_runner_(ui_task_runner), 266 core_(new UserInputMonitorWinCore(ui_task_runner, mouse_listeners())) {} 267 268 UserInputMonitorWin::~UserInputMonitorWin() { 269 if (!ui_task_runner_->DeleteSoon(FROM_HERE, core_)) 270 delete core_; 271 } 272 273 size_t UserInputMonitorWin::GetKeyPressCount() const { 274 return core_->GetKeyPressCount(); 275 } 276 277 void UserInputMonitorWin::StartKeyboardMonitoring() { 278 ui_task_runner_->PostTask( 279 FROM_HERE, 280 base::Bind(&UserInputMonitorWinCore::StartMonitor, 281 core_->AsWeakPtr(), 282 UserInputMonitorWinCore::KEYBOARD_EVENT_MASK)); 283 } 284 285 void UserInputMonitorWin::StopKeyboardMonitoring() { 286 ui_task_runner_->PostTask( 287 FROM_HERE, 288 base::Bind(&UserInputMonitorWinCore::StopMonitor, 289 core_->AsWeakPtr(), 290 UserInputMonitorWinCore::KEYBOARD_EVENT_MASK)); 291 } 292 293 void UserInputMonitorWin::StartMouseMonitoring() { 294 ui_task_runner_->PostTask( 295 FROM_HERE, 296 base::Bind(&UserInputMonitorWinCore::StartMonitor, 297 core_->AsWeakPtr(), 298 UserInputMonitorWinCore::MOUSE_EVENT_MASK)); 299 } 300 301 void UserInputMonitorWin::StopMouseMonitoring() { 302 ui_task_runner_->PostTask( 303 FROM_HERE, 304 base::Bind(&UserInputMonitorWinCore::StopMonitor, 305 core_->AsWeakPtr(), 306 UserInputMonitorWinCore::MOUSE_EVENT_MASK)); 307 } 308 309 } // namespace 310 311 scoped_ptr<UserInputMonitor> UserInputMonitor::Create( 312 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 313 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { 314 return scoped_ptr<UserInputMonitor>(new UserInputMonitorWin(ui_task_runner)); 315 } 316 317 } // namespace media 318