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