OLD | NEW |
---|---|
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 |
OLD | NEW |