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

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>
8
9 #include "base/bind.h"
10 #include "base/compiler_specific.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/mac/scoped_cftyperef.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/threading/non_thread_safe.h"
17 #include "third_party/skia/include/core/SkPoint.h"
18 #import "third_party/GTM/AppKit/GTMCarbonEvent.h"
19
7 namespace media { 20 namespace media {
8 21 namespace {
9 // TODO(jiayl): add the implementation. 22
23 class UserInputMonitorMac : public base::NonThreadSafe,
24 public UserInputMonitor {
25 public:
26 // Invoked by UserInputMonitorManager.
27 class EventHandler {
Sergey Ulanov 2013/08/20 00:55:41 Do you need this interface? Can you just reference
jiayl 2013/08/20 23:49:05 I rearranged the code to get rid of the interface.
28 public:
29 virtual ~EventHandler() {}
30
31 virtual void OnMouseMoved(const SkIPoint& position) = 0;
32 };
33
34 UserInputMonitorMac(
35 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
36
37 virtual ~UserInputMonitorMac();
38
39 private:
40 // The actual implementation resides in UserInputMonitorMac::Core class.
41 // Only called on the UI task runner.
42 class Core;
43 typedef const base::Callback<void(const SkIPoint&)> MouseCallback;
44
45 virtual void StartMouseMonitoring() OVERRIDE;
46 virtual void StopMouseMonitoring() OVERRIDE;
47 virtual void StartKeyboardMonitoring() OVERRIDE { NOTREACHED(); }
48 virtual void StopKeyboardMonitoring() OVERRIDE { NOTREACHED(); }
49
50 void OnMouseMoved(const SkIPoint& position);
51
52 // Task runner on which X Window events are received.
53 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
54
55 scoped_refptr<Core> core_;
56
57 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac);
58 };
59
60 } // namespace
61 } // namespace media
62
63 @interface UserInputMonitorManager : NSObject {
64 @private
65 CFRunLoopSourceRef inputRunLoopSource_;
66 base::ScopedCFTypeRef<CFMachPortRef> inputMachPort_;
67 media::UserInputMonitorMac::EventHandler* monitor_;
68 }
69
70 - (id)initWithMonitor:(media::UserInputMonitorMac::EventHandler*)monitor;
71
72 // Called when the local mouse moves.
73 - (void)mouseMoved:(const SkIPoint&)mousePos;
74
75 // Must be called when the UserInputMonitorManager is no longer to be used.
DaleCurtis 2013/08/19 23:49:00 UserInputMonitorManager?
jiayl 2013/08/20 00:21:15 Renamed
76 // Similar to NSTimer in that more than a simple release is required.
77 - (void)invalidate;
78
79 @end
80
81 static CGEventRef inputEvent(CGEventTapProxy proxy, CGEventType type,
Sergey Ulanov 2013/08/20 00:55:41 nit: one argument per line please.
jiayl 2013/08/20 23:49:05 Done.
82 CGEventRef event, void* context) {
Sergey Ulanov 2013/08/20 00:55:41 why is it void*?
jiayl 2013/08/20 23:49:05 This is required by the CGEventTapCreate API.
83 int64_t pid = CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID);
84 if (pid == 0) {
85 DCHECK(type == kCGEventMouseMoved);
86 CGPoint cgMousePos = CGEventGetLocation(event);
87 SkIPoint mousePos = SkIPoint::Make(cgMousePos.x, cgMousePos.y);
88 [static_cast<UserInputMonitorManager*>(context) mouseMoved:mousePos];
89 }
90 return NULL;
91 }
92
93 @implementation UserInputMonitorManager
94
95 - (id)initWithMonitor:(media::UserInputMonitorMac::EventHandler*)monitor {
96 if ((self = [super init])) {
97 monitor_ = monitor;
98 inputMachPort_.reset(CGEventTapCreate(
99 kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly,
100 CGEventMaskBit(kCGEventMouseMoved), inputEvent, self));
101 if (inputMachPort_) {
102 inputRunLoopSource_ = CFMachPortCreateRunLoopSource(
103 NULL, inputMachPort_, 0);
104 CFRunLoopAddSource(
105 CFRunLoopGetMain(), inputRunLoopSource_, kCFRunLoopCommonModes);
106 } else {
107 LOG(ERROR) << "CGEventTapCreate failed.";
108 }
109 if (!inputMachPort_) {
110 [self release];
111 return nil;
112 }
113 }
114 return self;
115 }
116
117 - (void)mouseMoved:(const SkIPoint&)mousePos {
118 monitor_->OnMouseMoved(mousePos);
119 }
120
121 - (void)invalidate {
122 if (inputRunLoopSource_) {
123 CFMachPortInvalidate(inputMachPort_);
124 CFRunLoopRemoveSource(
125 CFRunLoopGetMain(), inputRunLoopSource_, kCFRunLoopCommonModes);
126 CFRelease(inputRunLoopSource_);
127 inputMachPort_.reset(0);
Sergey Ulanov 2013/08/20 00:55:41 remove 0 - it's default.
jiayl 2013/08/20 23:49:05 Done.
128 inputRunLoopSource_ = NULL;
129 }
130 }
131
132 @end
133
134 namespace media {
135 namespace {
136
137 class UserInputMonitorMac::Core
138 : public base::RefCountedThreadSafe<Core>,
139 public EventHandler {
140 public:
141 Core(const MouseCallback& callback);
142
143 void Start();
144 void Stop();
145
146 private:
147 friend class base::RefCountedThreadSafe<Core>;
148 virtual ~Core();
149
150 // EventHandler interface.
151 virtual void OnMouseMoved(const SkIPoint& position) OVERRIDE;
152
153 MouseCallback callback_;
154 UserInputMonitorManager* manager_;
155
156 DISALLOW_COPY_AND_ASSIGN(Core);
157 };
158
159 UserInputMonitorMac::UserInputMonitorMac(
160 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
161 : ui_task_runner_(ui_task_runner),
162 core_(new Core(base::Bind(&UserInputMonitorMac::OnMouseMoved,
163 base::Unretained(this)))) {}
164
165 UserInputMonitorMac::~UserInputMonitorMac() {}
166
167 void UserInputMonitorMac::StartMouseMonitoring() {
168 ui_task_runner_->PostTask(
169 FROM_HERE, base::Bind(&Core::Start, core_.get()));
170 }
171
172 void UserInputMonitorMac::StopMouseMonitoring() {
173 ui_task_runner_->PostTask(
174 FROM_HERE, base::Bind(&Core::Stop, core_.get()));
175 }
176
177 void UserInputMonitorMac::OnMouseMoved(const SkIPoint& position) {
178 UserInputMonitor::OnMouseEvent(position);
179 }
180
181 UserInputMonitorMac::Core::Core(const MouseCallback& callback)
182 : callback_(callback), manager_(nil) {}
183
184 void UserInputMonitorMac::Core::Start() {
185 manager_ = [[UserInputMonitorManager alloc] initWithMonitor:this];
186 }
187
188 void UserInputMonitorMac::Core::Stop() {
189 [manager_ invalidate];
190 [manager_ release];
191 manager_ = nil;
192 }
193
194 UserInputMonitorMac::Core::~Core() {
195 DCHECK(manager_ == nil);
196 }
197
198 void UserInputMonitorMac::Core::OnMouseMoved(const SkIPoint& position) {
199 callback_.Run(position);
200 }
201
202 } // namespace
203
10 scoped_ptr<UserInputMonitor> UserInputMonitor::Create( 204 scoped_ptr<UserInputMonitor> UserInputMonitor::Create(
11 const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner, 205 const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner,
12 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) { 206 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) {
13 return scoped_ptr<UserInputMonitor>(); 207 return scoped_ptr<UserInputMonitor>(new UserInputMonitorMac(ui_task_runner));
14 } 208 }
15 209
16 } // namespace media 210 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698