blob: 5278e94584dc80fd3351529bfa93d4a683e0b564 [file] [log] [blame]
[email protected]61f697f2013-08-15 22:02:401// 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
avi1323b9c22015-12-23 06:22:367#include <stddef.h>
8#include <stdint.h>
9
[email protected]a8399162013-09-14 21:28:1110#include "base/bind.h"
11#include "base/location.h"
12#include "base/logging.h"
avi1323b9c22015-12-23 06:22:3613#include "base/macros.h"
danakj6aaed6a2016-04-26 01:25:4414#include "base/memory/ptr_util.h"
[email protected]13fb4e972013-09-30 21:18:2015#include "base/message_loop/message_loop.h"
[email protected]a8399162013-09-14 21:28:1116#include "base/single_thread_task_runner.h"
17#include "base/strings/stringprintf.h"
18#include "base/synchronization/lock.h"
19#include "base/win/message_window.h"
20#include "media/base/keyboard_event_counter.h"
21#include "third_party/skia/include/core/SkPoint.h"
[email protected]7e9acd082013-09-17 23:31:1622#include "ui/events/keycodes/keyboard_code_conversion_win.h"
[email protected]368cd73c2013-09-14 05:16:3523
[email protected]a8399162013-09-14 21:28:1124namespace media {
25namespace {
26
27// From the HID Usage Tables specification.
28const USHORT kGenericDesktopPage = 1;
[email protected]a8399162013-09-14 21:28:1129const USHORT kKeyboardUsage = 6;
30
lethalantidotefdd566ad2017-01-21 04:20:1431std::unique_ptr<RAWINPUTDEVICE> GetRawInputDevices(HWND hwnd, DWORD flags) {
32 std::unique_ptr<RAWINPUTDEVICE> device(new RAWINPUTDEVICE());
33 device->dwFlags = flags;
34 device->usUsagePage = kGenericDesktopPage;
35 device->usUsage = kKeyboardUsage;
36 device->hwndTarget = hwnd;
37 return device;
38}
39
[email protected]a8399162013-09-14 21:28:1140// This is the actual implementation of event monitoring. It's separated from
41// UserInputMonitorWin since it needs to be deleted on the UI thread.
42class UserInputMonitorWinCore
[email protected]13fb4e972013-09-30 21:18:2043 : public base::SupportsWeakPtr<UserInputMonitorWinCore>,
44 public base::MessageLoop::DestructionObserver {
[email protected]a8399162013-09-14 21:28:1145 public:
46 enum EventBitMask {
47 MOUSE_EVENT_MASK = 1,
48 KEYBOARD_EVENT_MASK = 2,
49 };
50
51 explicit UserInputMonitorWinCore(
lethalantidotefdd566ad2017-01-21 04:20:1452 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
dchengad8e1af22015-04-21 21:01:2253 ~UserInputMonitorWinCore() override;
[email protected]a8399162013-09-14 21:28:1154
[email protected]13fb4e972013-09-30 21:18:2055 // DestructionObserver overrides.
dchengad8e1af22015-04-21 21:01:2256 void WillDestroyCurrentMessageLoop() override;
[email protected]13fb4e972013-09-30 21:18:2057
[email protected]a8399162013-09-14 21:28:1158 size_t GetKeyPressCount() const;
lethalantidotefdd566ad2017-01-21 04:20:1459 void StartMonitor();
60 void StopMonitor();
[email protected]a8399162013-09-14 21:28:1161
62 private:
63 // Handles WM_INPUT messages.
64 LRESULT OnInput(HRAWINPUT input_handle);
65 // Handles messages received by |window_|.
66 bool HandleMessage(UINT message,
67 WPARAM wparam,
68 LPARAM lparam,
69 LRESULT* result);
[email protected]a8399162013-09-14 21:28:1170
71 // Task runner on which |window_| is created.
72 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
[email protected]a8399162013-09-14 21:28:1173
74 // These members are only accessed on the UI thread.
danakj6aaed6a2016-04-26 01:25:4475 std::unique_ptr<base::win::MessageWindow> window_;
[email protected]a8399162013-09-14 21:28:1176 KeyboardEventCounter counter_;
77
78 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWinCore);
79};
80
81class UserInputMonitorWin : public UserInputMonitor {
82 public:
83 explicit UserInputMonitorWin(
84 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner);
dchengad8e1af22015-04-21 21:01:2285 ~UserInputMonitorWin() override;
[email protected]a8399162013-09-14 21:28:1186
87 // Public UserInputMonitor overrides.
dchengad8e1af22015-04-21 21:01:2288 size_t GetKeyPressCount() const override;
[email protected]a8399162013-09-14 21:28:1189
90 private:
91 // Private UserInputMonitor overrides.
dchengad8e1af22015-04-21 21:01:2292 void StartKeyboardMonitoring() override;
93 void StopKeyboardMonitoring() override;
[email protected]a8399162013-09-14 21:28:1194
95 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
96 UserInputMonitorWinCore* core_;
97
98 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWin);
99};
100
101UserInputMonitorWinCore::UserInputMonitorWinCore(
lethalantidotefdd566ad2017-01-21 04:20:14102 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
103 : ui_task_runner_(ui_task_runner) {}
[email protected]a8399162013-09-14 21:28:11104
105UserInputMonitorWinCore::~UserInputMonitorWinCore() {
106 DCHECK(!window_);
[email protected]a8399162013-09-14 21:28:11107}
108
[email protected]13fb4e972013-09-30 21:18:20109void UserInputMonitorWinCore::WillDestroyCurrentMessageLoop() {
110 DCHECK(ui_task_runner_->BelongsToCurrentThread());
lethalantidotefdd566ad2017-01-21 04:20:14111 StopMonitor();
[email protected]13fb4e972013-09-30 21:18:20112}
113
[email protected]a8399162013-09-14 21:28:11114size_t UserInputMonitorWinCore::GetKeyPressCount() const {
115 return counter_.GetKeyPressCount();
116}
117
lethalantidotefdd566ad2017-01-21 04:20:14118void UserInputMonitorWinCore::StartMonitor() {
[email protected]a8399162013-09-14 21:28:11119 DCHECK(ui_task_runner_->BelongsToCurrentThread());
120
lethalantidotefdd566ad2017-01-21 04:20:14121 if (window_)
[email protected]a8399162013-09-14 21:28:11122 return;
123
lethalantidotefdd566ad2017-01-21 04:20:14124 std::unique_ptr<base::win::MessageWindow> window =
125 base::MakeUnique<base::win::MessageWindow>();
126 if (!window->Create(base::Bind(&UserInputMonitorWinCore::HandleMessage,
127 base::Unretained(this)))) {
128 PLOG(ERROR) << "Failed to create the raw input window";
129 return;
[email protected]a8399162013-09-14 21:28:11130 }
131
lethalantidotefdd566ad2017-01-21 04:20:14132 // Register to receive raw keyboard input.
danakj6aaed6a2016-04-26 01:25:44133 std::unique_ptr<RAWINPUTDEVICE> device(
lethalantidotefdd566ad2017-01-21 04:20:14134 GetRawInputDevices(window->hwnd(), RIDEV_INPUTSINK));
[email protected]a8399162013-09-14 21:28:11135 if (!RegisterRawInputDevices(device.get(), 1, sizeof(*device))) {
[email protected]ad8cfa92014-05-21 20:06:23136 PLOG(ERROR) << "RegisterRawInputDevices() failed for RIDEV_INPUTSINK";
[email protected]a8399162013-09-14 21:28:11137 return;
138 }
[email protected]13fb4e972013-09-30 21:18:20139
lethalantidotefdd566ad2017-01-21 04:20:14140 window_ = std::move(window);
[email protected]13fb4e972013-09-30 21:18:20141 // Start observing message loop destruction if we start monitoring the first
142 // event.
lethalantidotefdd566ad2017-01-21 04:20:14143 base::MessageLoop::current()->AddDestructionObserver(this);
[email protected]a8399162013-09-14 21:28:11144}
145
lethalantidotefdd566ad2017-01-21 04:20:14146void UserInputMonitorWinCore::StopMonitor() {
[email protected]a8399162013-09-14 21:28:11147 DCHECK(ui_task_runner_->BelongsToCurrentThread());
148
lethalantidotefdd566ad2017-01-21 04:20:14149 if (!window_)
[email protected]a8399162013-09-14 21:28:11150 return;
151
152 // Stop receiving raw input.
danakj6aaed6a2016-04-26 01:25:44153 std::unique_ptr<RAWINPUTDEVICE> device(
lethalantidotefdd566ad2017-01-21 04:20:14154 GetRawInputDevices(window_->hwnd(), RIDEV_REMOVE));
[email protected]a8399162013-09-14 21:28:11155
156 if (!RegisterRawInputDevices(device.get(), 1, sizeof(*device))) {
[email protected]ad8cfa92014-05-21 20:06:23157 PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE";
[email protected]a8399162013-09-14 21:28:11158 }
159
lethalantidotefdd566ad2017-01-21 04:20:14160 window_ = nullptr;
[email protected]13fb4e972013-09-30 21:18:20161
lethalantidotefdd566ad2017-01-21 04:20:14162 // Stop observing message loop destruction if no event is being monitored.
163 base::MessageLoop::current()->RemoveDestructionObserver(this);
[email protected]a8399162013-09-14 21:28:11164}
165
166LRESULT UserInputMonitorWinCore::OnInput(HRAWINPUT input_handle) {
167 DCHECK(ui_task_runner_->BelongsToCurrentThread());
168
169 // Get the size of the input record.
170 UINT size = 0;
171 UINT result = GetRawInputData(
172 input_handle, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
thakis9230c1d2015-12-10 00:36:25173 if (result == static_cast<UINT>(-1)) {
[email protected]ad8cfa92014-05-21 20:06:23174 PLOG(ERROR) << "GetRawInputData() failed";
[email protected]a8399162013-09-14 21:28:11175 return 0;
176 }
177 DCHECK_EQ(0u, result);
178
179 // Retrieve the input record itself.
danakj6aaed6a2016-04-26 01:25:44180 std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]);
[email protected]a8399162013-09-14 21:28:11181 RAWINPUT* input = reinterpret_cast<RAWINPUT*>(buffer.get());
182 result = GetRawInputData(
183 input_handle, RID_INPUT, buffer.get(), &size, sizeof(RAWINPUTHEADER));
thakis9230c1d2015-12-10 00:36:25184 if (result == static_cast<UINT>(-1)) {
[email protected]ad8cfa92014-05-21 20:06:23185 PLOG(ERROR) << "GetRawInputData() failed";
[email protected]a8399162013-09-14 21:28:11186 return 0;
187 }
188 DCHECK_EQ(size, result);
189
190 // Notify the observer about events generated locally.
lethalantidotefdd566ad2017-01-21 04:20:14191 if (input->header.dwType == RIM_TYPEKEYBOARD &&
192 input->header.hDevice != NULL) {
[email protected]a8399162013-09-14 21:28:11193 ui::EventType event = (input->data.keyboard.Flags & RI_KEY_BREAK)
194 ? ui::ET_KEY_RELEASED
195 : ui::ET_KEY_PRESSED;
196 ui::KeyboardCode key_code =
197 ui::KeyboardCodeForWindowsKeyCode(input->data.keyboard.VKey);
198 counter_.OnKeyboardEvent(event, key_code);
199 }
200
201 return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));
202}
203
204bool UserInputMonitorWinCore::HandleMessage(UINT message,
205 WPARAM wparam,
206 LPARAM lparam,
207 LRESULT* result) {
208 DCHECK(ui_task_runner_->BelongsToCurrentThread());
209
210 switch (message) {
211 case WM_INPUT:
212 *result = OnInput(reinterpret_cast<HRAWINPUT>(lparam));
213 return true;
214
215 default:
216 return false;
217 }
218}
219
[email protected]a8399162013-09-14 21:28:11220//
221// Implementation of UserInputMonitorWin.
222//
223
224UserInputMonitorWin::UserInputMonitorWin(
225 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
226 : ui_task_runner_(ui_task_runner),
lethalantidotefdd566ad2017-01-21 04:20:14227 core_(new UserInputMonitorWinCore(ui_task_runner)) {}
[email protected]a8399162013-09-14 21:28:11228
229UserInputMonitorWin::~UserInputMonitorWin() {
230 if (!ui_task_runner_->DeleteSoon(FROM_HERE, core_))
231 delete core_;
232}
233
234size_t UserInputMonitorWin::GetKeyPressCount() const {
235 return core_->GetKeyPressCount();
236}
237
238void UserInputMonitorWin::StartKeyboardMonitoring() {
239 ui_task_runner_->PostTask(
240 FROM_HERE,
lethalantidotefdd566ad2017-01-21 04:20:14241 base::Bind(&UserInputMonitorWinCore::StartMonitor, core_->AsWeakPtr()));
[email protected]a8399162013-09-14 21:28:11242}
243
244void UserInputMonitorWin::StopKeyboardMonitoring() {
245 ui_task_runner_->PostTask(
246 FROM_HERE,
lethalantidotefdd566ad2017-01-21 04:20:14247 base::Bind(&UserInputMonitorWinCore::StopMonitor, core_->AsWeakPtr()));
[email protected]a8399162013-09-14 21:28:11248}
249
250} // namespace
251
danakj6aaed6a2016-04-26 01:25:44252std::unique_ptr<UserInputMonitor> UserInputMonitor::Create(
[email protected]a8399162013-09-14 21:28:11253 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
[email protected]61f697f2013-08-15 22:02:40254 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) {
lethalantidotefdd566ad2017-01-21 04:20:14255 return base::MakeUnique<UserInputMonitorWin>(ui_task_runner);
[email protected]61f697f2013-08-15 22:02:40256}
257
258} // namespace media