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

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

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
« no previous file with comments | « media/base/user_input_monitor.cc ('k') | media/base/user_input_monitor_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "media/base/user_input_monitor.h"
6
7 #include <ApplicationServices/ApplicationServices.h>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/mac/scoped_cftyperef.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/time/time.h"
15 #include "base/timer/timer.h"
16 #include "third_party/skia/include/core/SkPoint.h"
17
18 namespace media {
19 namespace {
20
21 class UserInputMonitorMac : public UserInputMonitor {
22 public:
23 explicit UserInputMonitorMac(
24 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
25 virtual ~UserInputMonitorMac();
26
27 private:
28 static CGEventRef MouseMoved(CGEventTapProxy proxy,
29 CGEventType type,
30 CGEventRef event,
31 void* context);
32
33 virtual void StartMouseMonitoring() OVERRIDE;
34 virtual void StopMouseMonitoring() OVERRIDE;
35 virtual void StartKeyboardMonitoring() OVERRIDE;
36 virtual void StopKeyboardMonitoring() OVERRIDE;
37
38 void PollKeyState();
39
40 // Task runner on which input events are received.
41 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
42
43 // These members should only be accessed on the UI thread.
44 base::ScopedCFTypeRef<CFRunLoopSourceRef> input_run_loop_source_;
45 base::ScopedCFTypeRef<CFMachPortRef> input_mach_port_;
46 base::Timer polling_timer_;
47 // 0x5c is key "9", after that comes function keys.
48 bool prev_key_state_[0x5d];
49
50 DISALLOW_COPY_AND_ASSIGN(UserInputMonitorMac);
51 };
52
53 UserInputMonitorMac::UserInputMonitorMac(
54 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
55 : ui_task_runner_(ui_task_runner),
56 polling_timer_(false, true) {}
57
58 UserInputMonitorMac::~UserInputMonitorMac() {
59 DCHECK(!input_mach_port_);
60 DCHECK(!input_run_loop_source_);
61 DCHECK(!polling_timer_.IsRunning());
62 }
63
64 CGEventRef UserInputMonitorMac::MouseMoved(CGEventTapProxy proxy,
65 CGEventType type,
66 CGEventRef event,
67 void* context) {
68 DCHECK_EQ(base::MessageLoop::TYPE_UI, base::MessageLoop::current()->type());
69
70 int64_t pid = CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID);
71 // |pid| 0 means the event is generated by hardware.
72 if (pid == 0) {
73 DCHECK_EQ(kCGEventMouseMoved, type);
74 CGPoint cg_mouse_pos = CGEventGetLocation(event);
75 SkIPoint mouse_pos = SkIPoint::Make(cg_mouse_pos.x, cg_mouse_pos.y);
76 static_cast<UserInputMonitorMac*>(context)->OnMouseEvent(mouse_pos);
77 }
78 return NULL;
79 }
80
81 void UserInputMonitorMac::StartMouseMonitoring() {
82 if (!ui_task_runner_->BelongsToCurrentThread()) {
83 ui_task_runner_->PostTask(
84 FROM_HERE,
85 base::Bind(&UserInputMonitorMac::StartMouseMonitoring,
86 base::Unretained(this)));
Wez 2013/08/21 23:19:53 This code will now crash if the calling thread e.g
jiayl 2013/08/21 23:32:59 UserInputMonitor should always outlive the UI/IO t
Wez 2013/08/21 23:43:54 That's specific to the BrowserMainLoop caller - I
87 return;
88 }
89 input_mach_port_.reset(CGEventTapCreate(kCGSessionEventTap,
90 kCGHeadInsertEventTap,
91 kCGEventTapOptionListenOnly,
92 CGEventMaskBit(kCGEventMouseMoved),
93 MouseMoved,
94 this));
95 if (input_mach_port_) {
96 input_run_loop_source_.reset(
97 CFMachPortCreateRunLoopSource(NULL, input_mach_port_, 0));
98 CFRunLoopAddSource(
99 CFRunLoopGetMain(), input_run_loop_source_, kCFRunLoopCommonModes);
100 } else {
101 LOG(ERROR) << "CGEventTapCreate failed.";
102 }
103 }
104
105 void UserInputMonitorMac::StopMouseMonitoring() {
106 if (!ui_task_runner_->BelongsToCurrentThread()) {
107 ui_task_runner_->PostTask(
108 FROM_HERE,
109 base::Bind(&UserInputMonitorMac::StopMouseMonitoring,
110 base::Unretained(this)));
111 return;
112 }
113 if (input_run_loop_source_) {
114 CFMachPortInvalidate(input_mach_port_);
115 CFRunLoopRemoveSource(
116 CFRunLoopGetMain(), input_run_loop_source_, kCFRunLoopCommonModes);
117 input_run_loop_source_.reset();
118 input_mach_port_.reset();
119 }
120 }
121
122 void UserInputMonitorMac::StartKeyboardMonitoring() {
123 if (!ui_task_runner_->BelongsToCurrentThread()) {
124 ui_task_runner_->PostTask(
125 FROM_HERE,
126 base::Bind(&UserInputMonitorMac::StartKeyboardMonitoring,
127 base::Unretained(this)));
128 return;
129 }
130 polling_timer_.Start(
131 FROM_HERE,
132 base::TimeDelta::FromMilliseconds(30),
133 base::Bind(&UserInputMonitorMac::PollKeyState, base::Unretained(this)));
134 }
135
136 void UserInputMonitorMac::StopKeyboardMonitoring() {
137 if (!ui_task_runner_->BelongsToCurrentThread()) {
138 ui_task_runner_->PostTask(
139 FROM_HERE,
140 base::Bind(&UserInputMonitorMac::StopKeyboardMonitoring,
141 base::Unretained(this)));
142 return;
143 }
144 polling_timer_.Stop();
145 }
146
147 void UserInputMonitorMac::PollKeyState() {
148 DCHECK(ui_task_runner_->BelongsToCurrentThread());
149
150 bool key_pressed = false;
151 for (CGKeyCode key_index = 0; key_index < arraysize(prev_key_state_);
152 ++key_index) {
153 bool key_state =
154 CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, key_index);
155 // A false -> true change in keymap means a key is pressed.
156 key_pressed |= (key_state && !prev_key_state_[key_index]);
157 // Save current state.
158 prev_key_state_[key_index] = key_state;
159 }
160
161 if (key_pressed)
162 OnKeyboardEvent(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN);
163 }
164
165 } // namespace
166
167 scoped_ptr<UserInputMonitor> UserInputMonitor::Create(
168 const scoped_refptr<base::SingleThreadTaskRunner>& input_task_runner,
169 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) {
170 return scoped_ptr<UserInputMonitor>(new UserInputMonitorMac(ui_task_runner));
171 }
172
173 } // namespace media
OLDNEW
« no previous file with comments | « media/base/user_input_monitor.cc ('k') | media/base/user_input_monitor_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698