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

Side by Side Diff: media/base/user_input_monitor_mac.mm

Issue 22801007: Adds the UserInputMonitor implementation for Mac. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 4 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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 "media/base/user_input_monitor.h" 5 #include "media/base/user_input_monitor.h"
6 6
7 #import <AppKit/AppKit.h>
Mark Mentovai 2013/08/21 18:32:43 I can’t tell what you’ve included this for. In fac
jiayl 2013/08/21 22:58:22 removed
8 #include <ApplicationServices/ApplicationServices.h>
9
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/mac/scoped_cftyperef.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/threading/non_thread_safe.h"
16 #include "base/time/time.h"
17 #include "third_party/skia/include/core/SkPoint.h"
18 #import "third_party/GTM/AppKit/GTMCarbonEvent.h"
Mark Mentovai 2013/08/21 18:32:43 I can’t tell what you’ve included this for either.
jiayl 2013/08/21 22:58:22 removed
19
7 namespace media { 20 namespace media {
8 21 namespace {
9 // TODO(jiayl): add the implementation. 22
23 class UserInputMonitorMacCore;
24
25 class UserInputMonitorMac : public base::NonThreadSafe,
Mark Mentovai 2013/08/21 18:32:43 …so this is the implementation class?
jiayl 2013/08/21 22:58:22 Merged with *Core now.
26 public UserInputMonitor {
27 public:
28 typedef const base::Callback<void(const SkIPoint&)> MouseCallback;
29
30 UserInputMonitorMac(
31 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
32
33 virtual ~UserInputMonitorMac();
34
35 private:
36 virtual void StartMouseMonitoring() OVERRIDE;
37 virtual void StopMouseMonitoring() OVERRIDE;
38 virtual void StartKeyboardMonitoring() OVERRIDE;
39 virtual void StopKeyboardMonitoring() OVERRIDE;
40
41 void OnMouseMoved(const SkIPoint& position);
42 void OnKeyStroke();
43
44 // Task runner on which X Window events are received.
Mark Mentovai 2013/08/21 18:32:43 X Window events? Really?
jiayl 2013/08/21 22:58:22 fixed
45 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
46
47 scoped_ptr<UserInputMonitorMacCore> core_;
48
49 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac);
50 };
51
52 // The class implements the event listening. Must be called on the UI thread.
Mark Mentovai 2013/08/21 18:32:43 …no, wait, THIS is the implementation class? Why?
Mark Mentovai 2013/08/21 18:32:43 You need to assert what this comment says with DCH
jiayl 2013/08/21 22:58:22 Done.
jiayl 2013/08/21 22:58:22 Done.
Wez 2013/08/21 23:19:53 The UserInputMonitor[Mac] is owned by code on the
53 class UserInputMonitorMacCore {
54 public:
55 UserInputMonitorMacCore(
56 const UserInputMonitorMac::MouseCallback& mouse_callback,
57 const base::Closure& key_stroke_callback);
58 virtual ~UserInputMonitorMacCore();
Mark Mentovai 2013/08/21 18:32:43 This destructor doesn’t need to be virtual.
jiayl 2013/08/21 22:58:22 Done.
59
60 void StartMonitoringMouse();
61 void StopMonitoringMouse();
62 void StartPollingKeyState();
63 void StopPollingKeyState();
64
65 void OnMouseMoved(const SkIPoint& position);
66
67 base::WeakPtr<UserInputMonitorMacCore> GetAsWeakPtr();
68
69 private:
70 static CGEventRef MouseMoved(CGEventTapProxy proxy,
71 CGEventType type,
72 CGEventRef event,
73 void* context);
74 void PollKeyState();
75
76 UserInputMonitorMac::MouseCallback mouse_callback_;
77 base::Closure key_stroke_callback_;
78
79 CFRunLoopSourceRef input_run_loop_source_;
80 base::ScopedCFTypeRef<CFMachPortRef> input_mach_port_;
Mark Mentovai 2013/08/21 18:32:43 Why is this in a scoper but input_run_loop_source_
jiayl 2013/08/21 22:58:22 Done.
81
82 bool polling_key_state_;
83 // 0x5d is key "9", after that comes function keys.
Mark Mentovai 2013/08/21 18:32:43 And why don’t you care about function keys? "9" i
jiayl 2013/08/21 22:58:22 I'd be consistent with the webrtc code: https://co
84 bool prev_key_state_[0x5d];
85
86 base::WeakPtrFactory<UserInputMonitorMacCore> weak_factory_;
87
88 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMacCore);
89 };
90
91 UserInputMonitorMac::UserInputMonitorMac(
92 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
93 : ui_task_runner_(ui_task_runner),
94 core_(new UserInputMonitorMacCore(
95 base::Bind(&UserInputMonitorMac::OnMouseMoved,
96 base::Unretained(this)),
97 base::Bind(&UserInputMonitorMac::OnKeyStroke,
98 base::Unretained(this)))) {}
99
100 UserInputMonitorMac::~UserInputMonitorMac() {
101 ui_task_runner_->DeleteSoon(FROM_HERE, core_.release());
102 }
103
104 void UserInputMonitorMac::StartMouseMonitoring() {
105 ui_task_runner_->PostTask(
106 FROM_HERE, base::Bind(&UserInputMonitorMacCore::StartMonitoringMouse,
107 core_->GetAsWeakPtr()));
108 }
109
110 void UserInputMonitorMac::StopMouseMonitoring() {
111 ui_task_runner_->PostTask(
112 FROM_HERE, base::Bind(&UserInputMonitorMacCore::StopMonitoringMouse,
113 core_->GetAsWeakPtr()));
114 }
115
116 void UserInputMonitorMac::StartKeyboardMonitoring() {
117 ui_task_runner_->PostTask(
118 FROM_HERE, base::Bind(&UserInputMonitorMacCore::StartPollingKeyState,
119 core_->GetAsWeakPtr()));
120 }
121
122 void UserInputMonitorMac::StopKeyboardMonitoring() {
123 ui_task_runner_->PostTask(
124 FROM_HERE, base::Bind(&UserInputMonitorMacCore::StopPollingKeyState,
125 core_->GetAsWeakPtr()));
126 }
127
128 void UserInputMonitorMac::OnMouseMoved(const SkIPoint& position) {
129 UserInputMonitor::OnMouseEvent(position);
130 }
131
132 void UserInputMonitorMac::OnKeyStroke() {
133 UserInputMonitor::OnKeyboardEvent(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN);
134 }
135
136 UserInputMonitorMacCore::UserInputMonitorMacCore(
137 const UserInputMonitorMac::MouseCallback& mouse_callback,
138 const base::Closure& key_stroke_callback)
139 : mouse_callback_(mouse_callback),
140 key_stroke_callback_(key_stroke_callback),
141 polling_key_state_(false),
142 weak_factory_(this) {}
143
144 UserInputMonitorMacCore::~UserInputMonitorMacCore() {
145 DCHECK(!input_mach_port_);
146 DCHECK(!input_run_loop_source_);
147 DCHECK(!polling_key_state_);
148 }
149
150 void UserInputMonitorMacCore::StartMonitoringMouse() {
Mark Mentovai 2013/08/21 18:32:43 Some or all of these functions need to run on the
jiayl 2013/08/21 22:58:22 Done.
151 input_mach_port_.reset(CGEventTapCreate(
152 kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly,
153 CGEventMaskBit(kCGEventMouseMoved), MouseMoved, this));
154 if (input_mach_port_) {
155 input_run_loop_source_ = CFMachPortCreateRunLoopSource(
156 NULL, input_mach_port_, 0);
157 CFRunLoopAddSource(
158 CFRunLoopGetMain(), input_run_loop_source_, kCFRunLoopCommonModes);
159 } else {
160 LOG(ERROR) << "CGEventTapCreate failed.";
161 }
162 }
163
164 void UserInputMonitorMacCore::StopMonitoringMouse() {
165 if (input_run_loop_source_) {
166 CFMachPortInvalidate(input_mach_port_);
167 CFRunLoopRemoveSource(
168 CFRunLoopGetMain(), input_run_loop_source_, kCFRunLoopCommonModes);
169 CFRelease(input_run_loop_source_);
170 input_mach_port_.reset();
171 input_run_loop_source_ = NULL;
172 }
173 }
174
175 void UserInputMonitorMacCore::StartPollingKeyState() {
176 polling_key_state_ = true;
177 base::MessageLoop::current()->PostDelayedTask(
178 FROM_HERE,
179 base::Bind(&UserInputMonitorMacCore::PollKeyState, GetAsWeakPtr()),
180 base::TimeDelta::FromMilliseconds(10));
Mark Mentovai 2013/08/21 18:32:43 And why can’t you use an event tap for this?
jiayl 2013/08/21 22:58:22 Due to permission issues stated before.
181 }
182
183 void UserInputMonitorMacCore::StopPollingKeyState() {
184 polling_key_state_ = false;
185 }
186
187 base::WeakPtr<UserInputMonitorMacCore> UserInputMonitorMacCore::GetAsWeakPtr() {
188 return weak_factory_.GetWeakPtr();
189 }
190
191 void UserInputMonitorMacCore::OnMouseMoved(const SkIPoint& position) {
192 mouse_callback_.Run(position);
193 }
194
195 CGEventRef UserInputMonitorMacCore::MouseMoved(CGEventTapProxy proxy,
196 CGEventType type,
197 CGEventRef event,
198 void* context) {
199 int64_t pid = CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID);
200 if (pid == 0) {
Mark Mentovai 2013/08/21 18:32:43 Why? What’s 0 mean here? You need a comment to exp
jiayl 2013/08/21 22:58:22 Done.
201 DCHECK(type == kCGEventMouseMoved);
Mark Mentovai 2013/08/21 18:32:43 DCHECK_EQ
jiayl 2013/08/21 22:58:22 Done.
202 CGPoint cg_mouse_pos = CGEventGetLocation(event);
203 SkIPoint mouse_pos = SkIPoint::Make(cg_mouse_pos.x, cg_mouse_pos.y);
204 static_cast<UserInputMonitorMacCore*>(context)->OnMouseMoved(mouse_pos);
205 }
206 return NULL;
207 }
208
209 void UserInputMonitorMacCore::PollKeyState() {
210 if (!polling_key_state_)
211 return;
212
213 bool key_pressed = false;
214 for (uint key_index = 0;
Mark Mentovai 2013/08/21 18:32:43 CGKeyCode, not uint.
jiayl 2013/08/21 22:58:22 Done.
215 key_index <= sizeof(prev_key_state_)/sizeof(prev_key_state_[0]);
Mark Mentovai 2013/08/21 18:32:43 This is arraysize, you don’t need to write the cum
jiayl 2013/08/21 22:58:22 Done.
216 ++key_index) {
217 bool key_state = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState,
Mark Mentovai 2013/08/21 18:32:43 This is a lot of IPC to the window server you’re p
jiayl 2013/08/21 22:58:22 I tried both CGEventSourceCounterForEventType and
218 key_index);
219
220 // A false -> true change in keymap means a key is pressed.
221 key_pressed |= (key_state && !prev_key_state_[key_index]);
222 // Save current state.
223 prev_key_state_[key_index] = key_state;
224 }
225
226 if (key_pressed)
227 key_stroke_callback_.Run();
228
229 base::MessageLoop::current()->PostDelayedTask(
230 FROM_HERE,
231 base::Bind(&UserInputMonitorMacCore::PollKeyState, GetAsWeakPtr()),
232 base::TimeDelta::FromMilliseconds(10));
Mark Mentovai 2013/08/21 18:32:43 1. I think this business of polling is nonsense.
Wez 2013/08/21 19:45:57 Agreed. When did polling creep into this?
jiayl 2013/08/21 22:58:22 Unfortunately I don't have a better solution.
233 }
234
235 } // namespace
236
10 scoped_ptr<UserInputMonitor> UserInputMonitor::Create( 237 scoped_ptr<UserInputMonitor> UserInputMonitor::Create(
11 const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner, 238 const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner,
12 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { 239 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) {
13 return scoped_ptr<UserInputMonitor>(); 240 return scoped_ptr<UserInputMonitor>(new UserInputMonitorMac(ui_task_runner));
14 } 241 }
15 242
16 } // namespace media 243 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698