[email protected] | 67f92bc3 | 2012-01-26 01:56:19 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 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 "remoting/host/local_input_monitor.h" |
| 6 | |
| 7 | #import <AppKit/AppKit.h> |
avi | c5960f3 | 2015-12-22 22:49:48 | [diff] [blame] | 8 | #include <stdint.h> |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 9 | |
[email protected] | 9895e579 | 2011-10-08 01:57:06 | [diff] [blame] | 10 | #include <set> |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 11 | |
[email protected] | 1e1cb3b | 2011-11-10 02:07:41 | [diff] [blame] | 12 | #include "base/bind.h" |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 13 | #include "base/compiler_specific.h" |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 14 | #include "base/location.h" |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 15 | #include "base/logging.h" |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 16 | #include "base/mac/scoped_cftyperef.h" |
avi | c5960f3 | 2015-12-22 22:49:48 | [diff] [blame] | 17 | #include "base/macros.h" |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 18 | #include "base/memory/ptr_util.h" |
[email protected] | 0059eb96d | 2011-12-02 19:39:41 | [diff] [blame] | 19 | #include "base/memory/ref_counted.h" |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 20 | #include "base/single_thread_task_runner.h" |
[email protected] | 9895e579 | 2011-10-08 01:57:06 | [diff] [blame] | 21 | #include "base/synchronization/lock.h" |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 22 | #include "base/threading/non_thread_safe.h" |
| 23 | #include "remoting/host/client_session_control.h" |
[email protected] | a023dca | 2013-12-18 03:58:36 | [diff] [blame] | 24 | #import "third_party/google_toolbox_for_mac/src/AppKit/GTMCarbonEvent.h" |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 25 | #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 26 | |
| 27 | // Esc Key Code is 53. |
| 28 | // http://boredzo.org/blog/wp-content/uploads/2007/05/IMTx-virtual-keycodes.pdf |
| 29 | static const NSUInteger kEscKeyCode = 53; |
| 30 | |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 31 | namespace remoting { |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 32 | namespace { |
| 33 | |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 34 | class LocalInputMonitorMac : public base::NonThreadSafe, |
| 35 | public LocalInputMonitor { |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 36 | public: |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 37 | // Invoked by LocalInputMonitorManager. |
| 38 | class EventHandler { |
| 39 | public: |
| 40 | virtual ~EventHandler() {} |
| 41 | |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 42 | virtual void OnLocalMouseMoved(const webrtc::DesktopVector& position) = 0; |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 43 | virtual void OnDisconnectShortcut() = 0; |
| 44 | }; |
| 45 | |
| 46 | LocalInputMonitorMac( |
| 47 | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 48 | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
| 49 | base::WeakPtr<ClientSessionControl> client_session_control); |
dcheng | 562aba5 | 2014-10-21 12:30:14 | [diff] [blame] | 50 | ~LocalInputMonitorMac() override; |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 51 | |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 52 | private: |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 53 | // The actual implementation resides in LocalInputMonitorMac::Core class. |
| 54 | class Core; |
| 55 | scoped_refptr<Core> core_; |
| 56 | |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 57 | DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorMac); |
| 58 | }; |
| 59 | |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 60 | } // namespace |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 61 | } // namespace remoting |
| 62 | |
| 63 | @interface LocalInputMonitorManager : NSObject { |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 64 | @private |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 65 | GTMCarbonHotKey* hotKey_; |
| 66 | CFRunLoopSourceRef mouseRunLoopSource_; |
[email protected] | 3df79f4 | 2013-06-24 18:49:05 | [diff] [blame] | 67 | base::ScopedCFTypeRef<CFMachPortRef> mouseMachPort_; |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 68 | remoting::LocalInputMonitorMac::EventHandler* monitor_; |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 69 | } |
| 70 | |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 71 | - (id)initWithMonitor:(remoting::LocalInputMonitorMac::EventHandler*)monitor; |
| 72 | |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 73 | // Called when the hotKey is hit. |
| 74 | - (void)hotKeyHit:(GTMCarbonHotKey*)hotKey; |
| 75 | |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 76 | // Called when the local mouse moves |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 77 | - (void)localMouseMoved:(const webrtc::DesktopVector&)mousePos; |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 78 | |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 79 | // Must be called when the LocalInputMonitorManager is no longer to be used. |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 80 | // Similar to NSTimer in that more than a simple release is required. |
| 81 | - (void)invalidate; |
| 82 | |
| 83 | @end |
| 84 | |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 85 | static CGEventRef LocalMouseMoved(CGEventTapProxy proxy, CGEventType type, |
| 86 | CGEventRef event, void* context) { |
[email protected] | 06b39315 | 2011-10-21 03:02:41 | [diff] [blame] | 87 | int64_t pid = CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID); |
| 88 | if (pid == 0) { |
| 89 | CGPoint cgMousePos = CGEventGetLocation(event); |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 90 | webrtc::DesktopVector mousePos(cgMousePos.x, cgMousePos.y); |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 91 | [static_cast<LocalInputMonitorManager*>(context) localMouseMoved:mousePos]; |
[email protected] | 06b39315 | 2011-10-21 03:02:41 | [diff] [blame] | 92 | } |
sergeyu | c5f104b | 2015-01-09 19:33:24 | [diff] [blame] | 93 | return nullptr; |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 94 | } |
| 95 | |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 96 | @implementation LocalInputMonitorManager |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 97 | |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 98 | - (id)initWithMonitor:(remoting::LocalInputMonitorMac::EventHandler*)monitor { |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 99 | if ((self = [super init])) { |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 100 | monitor_ = monitor; |
| 101 | |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 102 | GTMCarbonEventDispatcherHandler* handler = |
| 103 | [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 104 | hotKey_ = [handler registerHotKey:kEscKeyCode |
[email protected] | f67e2a5 | 2011-10-07 18:45:37 | [diff] [blame] | 105 | modifiers:(NSAlternateKeyMask | NSControlKeyMask) |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 106 | target:self |
| 107 | action:@selector(hotKeyHit:) |
| 108 | userInfo:nil |
| 109 | whenPressed:YES]; |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 110 | if (!hotKey_) { |
| 111 | LOG(ERROR) << "registerHotKey failed."; |
| 112 | } |
[email protected] | f1e98188 | 2011-11-23 23:33:42 | [diff] [blame] | 113 | mouseMachPort_.reset(CGEventTapCreate( |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 114 | kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, |
| 115 | 1 << kCGEventMouseMoved, LocalMouseMoved, self)); |
[email protected] | f1e98188 | 2011-11-23 23:33:42 | [diff] [blame] | 116 | if (mouseMachPort_) { |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 117 | mouseRunLoopSource_ = CFMachPortCreateRunLoopSource( |
sergeyu | c5f104b | 2015-01-09 19:33:24 | [diff] [blame] | 118 | nullptr, mouseMachPort_, 0); |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 119 | CFRunLoopAddSource( |
| 120 | CFRunLoopGetMain(), mouseRunLoopSource_, kCFRunLoopCommonModes); |
| 121 | } else { |
| 122 | LOG(ERROR) << "CGEventTapCreate failed."; |
| 123 | } |
[email protected] | f1e98188 | 2011-11-23 23:33:42 | [diff] [blame] | 124 | if (!hotKey_ && !mouseMachPort_) { |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 125 | [self release]; |
| 126 | return nil; |
| 127 | } |
| 128 | } |
| 129 | return self; |
| 130 | } |
| 131 | |
| 132 | - (void)hotKeyHit:(GTMCarbonHotKey*)hotKey { |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 133 | monitor_->OnDisconnectShortcut(); |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 134 | } |
| 135 | |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 136 | - (void)localMouseMoved:(const webrtc::DesktopVector&)mousePos { |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 137 | monitor_->OnLocalMouseMoved(mousePos); |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 138 | } |
| 139 | |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 140 | - (void)invalidate { |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 141 | if (hotKey_) { |
| 142 | GTMCarbonEventDispatcherHandler* handler = |
| 143 | [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; |
| 144 | [handler unregisterHotKey:hotKey_]; |
sergeyu | c5f104b | 2015-01-09 19:33:24 | [diff] [blame] | 145 | hotKey_ = nullptr; |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 146 | } |
| 147 | if (mouseRunLoopSource_) { |
[email protected] | f1e98188 | 2011-11-23 23:33:42 | [diff] [blame] | 148 | CFMachPortInvalidate(mouseMachPort_); |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 149 | CFRunLoopRemoveSource( |
| 150 | CFRunLoopGetMain(), mouseRunLoopSource_, kCFRunLoopCommonModes); |
| 151 | CFRelease(mouseRunLoopSource_); |
[email protected] | f1e98188 | 2011-11-23 23:33:42 | [diff] [blame] | 152 | mouseMachPort_.reset(0); |
sergeyu | c5f104b | 2015-01-09 19:33:24 | [diff] [blame] | 153 | mouseRunLoopSource_ = nullptr; |
[email protected] | 3d2a904 | 2011-10-18 20:30:41 | [diff] [blame] | 154 | } |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | @end |
| 158 | |
[email protected] | 3361e1f | 2012-03-20 20:31:44 | [diff] [blame] | 159 | namespace remoting { |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 160 | namespace { |
| 161 | |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 162 | class LocalInputMonitorMac::Core |
| 163 | : public base::RefCountedThreadSafe<Core>, |
| 164 | public EventHandler { |
| 165 | public: |
| 166 | Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 167 | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
| 168 | base::WeakPtr<ClientSessionControl> client_session_control); |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 169 | |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 170 | void Start(); |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 171 | void Stop(); |
| 172 | |
| 173 | private: |
| 174 | friend class base::RefCountedThreadSafe<Core>; |
dcheng | 562aba5 | 2014-10-21 12:30:14 | [diff] [blame] | 175 | ~Core() override; |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 176 | |
| 177 | void StartOnUiThread(); |
| 178 | void StopOnUiThread(); |
| 179 | |
| 180 | // EventHandler interface. |
dcheng | 562aba5 | 2014-10-21 12:30:14 | [diff] [blame] | 181 | void OnLocalMouseMoved(const webrtc::DesktopVector& position) override; |
| 182 | void OnDisconnectShortcut() override; |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 183 | |
| 184 | // Task runner on which public methods of this class must be called. |
| 185 | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_; |
| 186 | |
| 187 | // Task runner on which |window_| is created. |
| 188 | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
| 189 | |
| 190 | LocalInputMonitorManager* manager_; |
| 191 | |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 192 | // Invoked in the |caller_task_runner_| thread to report local mouse events |
| 193 | // and session disconnect requests. |
| 194 | base::WeakPtr<ClientSessionControl> client_session_control_; |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 195 | |
[email protected] | 1bed4a2 | 2014-04-12 01:32:51 | [diff] [blame] | 196 | webrtc::DesktopVector mouse_position_; |
| 197 | |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 198 | DISALLOW_COPY_AND_ASSIGN(Core); |
| 199 | }; |
| 200 | |
| 201 | LocalInputMonitorMac::LocalInputMonitorMac( |
| 202 | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 203 | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
| 204 | base::WeakPtr<ClientSessionControl> client_session_control) |
| 205 | : core_(new Core(caller_task_runner, |
| 206 | ui_task_runner, |
| 207 | client_session_control)) { |
| 208 | core_->Start(); |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 209 | } |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 210 | |
| 211 | LocalInputMonitorMac::~LocalInputMonitorMac() { |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 212 | core_->Stop(); |
| 213 | } |
| 214 | |
| 215 | LocalInputMonitorMac::Core::Core( |
| 216 | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 217 | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
| 218 | base::WeakPtr<ClientSessionControl> client_session_control) |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 219 | : caller_task_runner_(caller_task_runner), |
| 220 | ui_task_runner_(ui_task_runner), |
| 221 | manager_(nil), |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 222 | client_session_control_(client_session_control) { |
[email protected] | fd7d379 | 2013-06-07 08:43:27 | [diff] [blame] | 223 | DCHECK(client_session_control_); |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 224 | } |
| 225 | |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 226 | void LocalInputMonitorMac::Core::Start() { |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 227 | DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 228 | |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 229 | ui_task_runner_->PostTask(FROM_HERE, |
| 230 | base::Bind(&Core::StartOnUiThread, this)); |
| 231 | } |
| 232 | |
| 233 | void LocalInputMonitorMac::Core::Stop() { |
| 234 | DCHECK(caller_task_runner_->BelongsToCurrentThread()); |
| 235 | |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 236 | ui_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::StopOnUiThread, this)); |
| 237 | } |
| 238 | |
| 239 | LocalInputMonitorMac::Core::~Core() { |
| 240 | DCHECK(manager_ == nil); |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | void LocalInputMonitorMac::Core::StartOnUiThread() { |
| 244 | DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 245 | |
| 246 | manager_ = [[LocalInputMonitorManager alloc] initWithMonitor:this]; |
| 247 | } |
| 248 | |
| 249 | void LocalInputMonitorMac::Core::StopOnUiThread() { |
| 250 | DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 251 | |
| 252 | [manager_ invalidate]; |
| 253 | [manager_ release]; |
| 254 | manager_ = nil; |
| 255 | } |
| 256 | |
[email protected] | 8c83a71c | 2013-12-16 18:02:58 | [diff] [blame] | 257 | void LocalInputMonitorMac::Core::OnLocalMouseMoved( |
| 258 | const webrtc::DesktopVector& position) { |
[email protected] | 1bed4a2 | 2014-04-12 01:32:51 | [diff] [blame] | 259 | // In some cases OS may emit bogus mouse-move events even when cursor is not |
| 260 | // actually moving. To handle this case properly verify that mouse position |
| 261 | // has changed. See crbug.com/360912 . |
| 262 | if (position.equals(mouse_position_)) { |
| 263 | return; |
| 264 | } |
| 265 | |
| 266 | mouse_position_ = position; |
| 267 | |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 268 | caller_task_runner_->PostTask( |
| 269 | FROM_HERE, base::Bind(&ClientSessionControl::OnLocalMouseMoved, |
| 270 | client_session_control_, |
| 271 | position)); |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 272 | } |
| 273 | |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 274 | void LocalInputMonitorMac::Core::OnDisconnectShortcut() { |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 275 | caller_task_runner_->PostTask( |
| 276 | FROM_HERE, base::Bind(&ClientSessionControl::DisconnectSession, |
sergeyu | ec77d854 | 2015-11-03 22:31:00 | [diff] [blame] | 277 | client_session_control_, protocol::OK)); |
[email protected] | 42dcc673 | 2012-05-29 20:35:23 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | } // namespace |
| 281 | |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 282 | std::unique_ptr<LocalInputMonitor> LocalInputMonitor::Create( |
[email protected] | ceffbde | 2013-03-14 14:54:39 | [diff] [blame] | 283 | scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner, |
| 284 | scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, |
[email protected] | b167a7b | 2013-03-25 18:34:40 | [diff] [blame] | 285 | scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
| 286 | base::WeakPtr<ClientSessionControl> client_session_control) { |
dcheng | 0765c49 | 2016-04-06 22:41:53 | [diff] [blame] | 287 | return base::WrapUnique(new LocalInputMonitorMac( |
sergeyu | 2d69088 | 2014-10-01 02:36:43 | [diff] [blame] | 288 | caller_task_runner, ui_task_runner, client_session_control)); |
[email protected] | eccefee | 2011-08-02 15:31:40 | [diff] [blame] | 289 | } |
[email protected] | 3361e1f | 2012-03-20 20:31:44 | [diff] [blame] | 290 | |
| 291 | } // namespace remoting |