Chromium Code Reviews| 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 |