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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: media/base/user_input_monitor_mac.mm
diff --git a/media/base/user_input_monitor_mac.mm b/media/base/user_input_monitor_mac.mm
index 4ffad42a72d9b479d1611e4a10fea96ae41e0e5d..98ec79271db2b993138c7250c2d82920a420cf58 100644
--- a/media/base/user_input_monitor_mac.mm
+++ b/media/base/user_input_monitor_mac.mm
@@ -4,13 +4,207 @@
#include "media/base/user_input_monitor.h"
+#import <AppKit/AppKit.h>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/non_thread_safe.h"
+#include "third_party/skia/include/core/SkPoint.h"
+#import "third_party/GTM/AppKit/GTMCarbonEvent.h"
+
+namespace media {
+namespace {
+
+class UserInputMonitorMac : public base::NonThreadSafe,
+ public UserInputMonitor {
+ public:
+ // Invoked by UserInputMonitorManager.
+ 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.
+ public:
+ virtual ~EventHandler() {}
+
+ virtual void OnMouseMoved(const SkIPoint& position) = 0;
+ };
+
+ UserInputMonitorMac(
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
+
+ virtual ~UserInputMonitorMac();
+
+ private:
+ // The actual implementation resides in UserInputMonitorMac::Core class.
+ // Only called on the UI task runner.
+ class Core;
+ typedef const base::Callback<void(const SkIPoint&)> MouseCallback;
+
+ virtual void StartMouseMonitoring() OVERRIDE;
+ virtual void StopMouseMonitoring() OVERRIDE;
+ virtual void StartKeyboardMonitoring() OVERRIDE { NOTREACHED(); }
+ virtual void StopKeyboardMonitoring() OVERRIDE { NOTREACHED(); }
+
+ void OnMouseMoved(const SkIPoint& position);
+
+ // Task runner on which X Window events are received.
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
+ scoped_refptr<Core> core_;
+
+ DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac);
+};
+
+} // namespace
+} // namespace media
+
+@interface UserInputMonitorManager : NSObject {
+ @private
+ CFRunLoopSourceRef inputRunLoopSource_;
+ base::ScopedCFTypeRef<CFMachPortRef> inputMachPort_;
+ media::UserInputMonitorMac::EventHandler* monitor_;
+}
+
+- (id)initWithMonitor:(media::UserInputMonitorMac::EventHandler*)monitor;
+
+// Called when the local mouse moves.
+- (void)mouseMoved:(const SkIPoint&)mousePos;
+
+// 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
+// Similar to NSTimer in that more than a simple release is required.
+- (void)invalidate;
+
+@end
+
+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.
+ 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.
+ int64_t pid = CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID);
+ if (pid == 0) {
+ DCHECK(type == kCGEventMouseMoved);
+ CGPoint cgMousePos = CGEventGetLocation(event);
+ SkIPoint mousePos = SkIPoint::Make(cgMousePos.x, cgMousePos.y);
+ [static_cast<UserInputMonitorManager*>(context) mouseMoved:mousePos];
+ }
+ return NULL;
+}
+
+@implementation UserInputMonitorManager
+
+- (id)initWithMonitor:(media::UserInputMonitorMac::EventHandler*)monitor {
+ if ((self = [super init])) {
+ monitor_ = monitor;
+ inputMachPort_.reset(CGEventTapCreate(
+ kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly,
+ CGEventMaskBit(kCGEventMouseMoved), inputEvent, self));
+ if (inputMachPort_) {
+ inputRunLoopSource_ = CFMachPortCreateRunLoopSource(
+ NULL, inputMachPort_, 0);
+ CFRunLoopAddSource(
+ CFRunLoopGetMain(), inputRunLoopSource_, kCFRunLoopCommonModes);
+ } else {
+ LOG(ERROR) << "CGEventTapCreate failed.";
+ }
+ if (!inputMachPort_) {
+ [self release];
+ return nil;
+ }
+ }
+ return self;
+}
+
+- (void)mouseMoved:(const SkIPoint&)mousePos {
+ monitor_->OnMouseMoved(mousePos);
+}
+
+- (void)invalidate {
+ if (inputRunLoopSource_) {
+ CFMachPortInvalidate(inputMachPort_);
+ CFRunLoopRemoveSource(
+ CFRunLoopGetMain(), inputRunLoopSource_, kCFRunLoopCommonModes);
+ CFRelease(inputRunLoopSource_);
+ inputMachPort_.reset(0);
Sergey Ulanov 2013/08/20 00:55:41 remove 0 - it's default.
jiayl 2013/08/20 23:49:05 Done.
+ inputRunLoopSource_ = NULL;
+ }
+}
+
+@end
+
namespace media {
+namespace {
+
+class UserInputMonitorMac::Core
+ : public base::RefCountedThreadSafe<Core>,
+ public EventHandler {
+ public:
+ Core(const MouseCallback& callback);
+
+ void Start();
+ void Stop();
+
+ private:
+ friend class base::RefCountedThreadSafe<Core>;
+ virtual ~Core();
+
+ // EventHandler interface.
+ virtual void OnMouseMoved(const SkIPoint& position) OVERRIDE;
+
+ MouseCallback callback_;
+ UserInputMonitorManager* manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(Core);
+};
+
+UserInputMonitorMac::UserInputMonitorMac(
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
+ : ui_task_runner_(ui_task_runner),
+ core_(new Core(base::Bind(&UserInputMonitorMac::OnMouseMoved,
+ base::Unretained(this)))) {}
+
+UserInputMonitorMac::~UserInputMonitorMac() {}
+
+void UserInputMonitorMac::StartMouseMonitoring() {
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Core::Start, core_.get()));
+}
+
+void UserInputMonitorMac::StopMouseMonitoring() {
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Core::Stop, core_.get()));
+}
+
+void UserInputMonitorMac::OnMouseMoved(const SkIPoint& position) {
+ UserInputMonitor::OnMouseEvent(position);
+}
+
+UserInputMonitorMac::Core::Core(const MouseCallback& callback)
+ : callback_(callback), manager_(nil) {}
+
+void UserInputMonitorMac::Core::Start() {
+ manager_ = [[UserInputMonitorManager alloc] initWithMonitor:this];
+}
+
+void UserInputMonitorMac::Core::Stop() {
+ [manager_ invalidate];
+ [manager_ release];
+ manager_ = nil;
+}
+
+UserInputMonitorMac::Core::~Core() {
+ DCHECK(manager_ == nil);
+}
+
+void UserInputMonitorMac::Core::OnMouseMoved(const SkIPoint& position) {
+ callback_.Run(position);
+}
+
+} // namespace
-// TODO(jiayl): add the implementation.
scoped_ptr<UserInputMonitor> UserInputMonitor::Create(
const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) {
- return scoped_ptr<UserInputMonitor>();
+ return scoped_ptr<UserInputMonitor>(new UserInputMonitorMac(ui_task_runner));
}
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698