OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "remoting/host/local_input_monitor.h" | 5 #include "remoting/host/local_input_monitor.h" |
6 | 6 |
7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/mac/scoped_cftyperef.h" | 14 #include "base/mac/scoped_cftyperef.h" |
15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
17 #include "remoting/host/chromoting_host.h" | 17 #include "remoting/host/mouse_move_observer.h" |
| 18 #include "third_party/skia/include/core/SkPoint.h" |
18 #import "third_party/GTM/AppKit/GTMCarbonEvent.h" | 19 #import "third_party/GTM/AppKit/GTMCarbonEvent.h" |
19 | 20 |
20 // Esc Key Code is 53. | 21 // Esc Key Code is 53. |
21 // http://boredzo.org/blog/wp-content/uploads/2007/05/IMTx-virtual-keycodes.pdf | 22 // http://boredzo.org/blog/wp-content/uploads/2007/05/IMTx-virtual-keycodes.pdf |
22 static const NSUInteger kEscKeyCode = 53; | 23 static const NSUInteger kEscKeyCode = 53; |
23 | 24 |
| 25 namespace remoting { |
| 26 |
24 namespace { | 27 namespace { |
25 typedef std::set<scoped_refptr<remoting::ChromotingHost> > Hosts; | |
26 } | |
27 | 28 |
28 @interface LocalInputMonitorImpl : NSObject { | 29 class LocalInputMonitorMac : public LocalInputMonitor { |
| 30 public: |
| 31 LocalInputMonitorMac() : mouse_move_observer_(NULL) {} |
| 32 virtual ~LocalInputMonitorMac(); |
| 33 virtual void Start(MouseMoveObserver* mouse_move_observer, |
| 34 const base::Closure& disconnect_callback) OVERRIDE; |
| 35 virtual void Stop() OVERRIDE; |
| 36 |
| 37 void OnLocalMouseMoved(const SkIPoint& new_pos); |
| 38 void OnDisconnectShortcut(); |
| 39 |
| 40 private: |
| 41 MouseMoveObserver* mouse_move_observer_; |
| 42 base::Closure disconnect_callback_; |
| 43 DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorMac); |
| 44 }; |
| 45 |
| 46 typedef std::set<remoting::LocalInputMonitorMac*> LocalInputMonitors; |
| 47 |
| 48 } // namespace |
| 49 |
| 50 } // namespace remoting |
| 51 |
| 52 @interface LocalInputMonitorManager : NSObject { |
29 @private | 53 @private |
30 GTMCarbonHotKey* hotKey_; | 54 GTMCarbonHotKey* hotKey_; |
31 CFRunLoopSourceRef mouseRunLoopSource_; | 55 CFRunLoopSourceRef mouseRunLoopSource_; |
32 base::mac::ScopedCFTypeRef<CFMachPortRef> mouseMachPort_; | 56 base::mac::ScopedCFTypeRef<CFMachPortRef> mouseMachPort_; |
33 base::Lock hostsLock_; | 57 base::Lock lock_; |
34 Hosts hosts_; | 58 remoting::LocalInputMonitors monitors_; |
35 } | 59 } |
36 | 60 |
37 // Called when the hotKey is hit. | 61 // Called when the hotKey is hit. |
38 - (void)hotKeyHit:(GTMCarbonHotKey*)hotKey; | 62 - (void)hotKeyHit:(GTMCarbonHotKey*)hotKey; |
39 | 63 |
40 // Called when the local mouse moves | 64 // Called when the local mouse moves |
41 - (void)localMouseMoved:(const SkIPoint&)mousePos; | 65 - (void)localMouseMoved:(const SkIPoint&)mousePos; |
42 | 66 |
43 // Must be called when the LocalInputMonitorImpl is no longer to be used. | 67 // Must be called when the LocalInputMonitorManager is no longer to be used. |
44 // Similar to NSTimer in that more than a simple release is required. | 68 // Similar to NSTimer in that more than a simple release is required. |
45 - (void)invalidate; | 69 - (void)invalidate; |
46 | 70 |
47 // Called to add a host to the list of those to be Shutdown() when the hotkey | 71 // Called to add a monitor. |
48 // is pressed. | 72 - (void)addMonitor:(remoting::LocalInputMonitorMac*)monitor; |
49 - (void)addHost:(remoting::ChromotingHost*)host; | |
50 | 73 |
51 // Called to remove a host. Returns true if it was the last host being | 74 // Called to remove a monitor. Returns true if it was the last |
52 // monitored, in which case the object should be destroyed. | 75 // monitor, in which case the object should be destroyed. |
53 - (bool)removeHost:(remoting::ChromotingHost*)host; | 76 - (bool)removeMonitor:(remoting::LocalInputMonitorMac*)monitor; |
54 | |
55 // Disabled disconnection keyboard shortcut. | |
56 - (void)disableShortcut; | |
57 | 77 |
58 @end | 78 @end |
59 | 79 |
60 static CGEventRef LocalMouseMoved(CGEventTapProxy proxy, CGEventType type, | 80 static CGEventRef LocalMouseMoved(CGEventTapProxy proxy, CGEventType type, |
61 CGEventRef event, void* context) { | 81 CGEventRef event, void* context) { |
62 int64_t pid = CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID); | 82 int64_t pid = CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID); |
63 if (pid == 0) { | 83 if (pid == 0) { |
64 CGPoint cgMousePos = CGEventGetLocation(event); | 84 CGPoint cgMousePos = CGEventGetLocation(event); |
65 SkIPoint mousePos = SkIPoint::Make(cgMousePos.x, cgMousePos.y); | 85 SkIPoint mousePos = SkIPoint::Make(cgMousePos.x, cgMousePos.y); |
66 [static_cast<LocalInputMonitorImpl*>(context) localMouseMoved:mousePos]; | 86 [static_cast<LocalInputMonitorManager*>(context) localMouseMoved:mousePos]; |
67 } | 87 } |
68 return NULL; | 88 return NULL; |
69 } | 89 } |
70 | 90 |
71 @implementation LocalInputMonitorImpl | 91 @implementation LocalInputMonitorManager |
72 | 92 |
73 - (id)init { | 93 - (id)init { |
74 if ((self = [super init])) { | 94 if ((self = [super init])) { |
75 GTMCarbonEventDispatcherHandler* handler = | 95 GTMCarbonEventDispatcherHandler* handler = |
76 [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; | 96 [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; |
77 hotKey_ = [handler registerHotKey:kEscKeyCode | 97 hotKey_ = [handler registerHotKey:kEscKeyCode |
78 modifiers:(NSAlternateKeyMask | NSControlKeyMask) | 98 modifiers:(NSAlternateKeyMask | NSControlKeyMask) |
79 target:self | 99 target:self |
80 action:@selector(hotKeyHit:) | 100 action:@selector(hotKeyHit:) |
81 userInfo:nil | 101 userInfo:nil |
(...skipping 14 matching lines...) Expand all Loading... |
96 } | 116 } |
97 if (!hotKey_ && !mouseMachPort_) { | 117 if (!hotKey_ && !mouseMachPort_) { |
98 [self release]; | 118 [self release]; |
99 return nil; | 119 return nil; |
100 } | 120 } |
101 } | 121 } |
102 return self; | 122 return self; |
103 } | 123 } |
104 | 124 |
105 - (void)hotKeyHit:(GTMCarbonHotKey*)hotKey { | 125 - (void)hotKeyHit:(GTMCarbonHotKey*)hotKey { |
106 base::AutoLock lock(hostsLock_); | 126 base::AutoLock lock(lock_); |
107 for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i) { | 127 for (remoting::LocalInputMonitors::const_iterator i = monitors_.begin(); |
108 (*i)->Shutdown(base::Closure()); | 128 i != monitors_.end(); ++i) { |
| 129 (*i)->OnDisconnectShortcut(); |
109 } | 130 } |
110 } | 131 } |
111 | 132 |
112 - (void)localMouseMoved:(const SkIPoint&)mousePos { | 133 - (void)localMouseMoved:(const SkIPoint&)mousePos { |
113 base::AutoLock lock(hostsLock_); | 134 base::AutoLock lock(lock_); |
114 for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i) { | 135 for (remoting::LocalInputMonitors::const_iterator i = monitors_.begin(); |
115 (*i)->LocalMouseMoved(mousePos); | 136 i != monitors_.end(); ++i) { |
| 137 (*i)->OnLocalMouseMoved(mousePos); |
116 } | 138 } |
117 } | 139 } |
118 | 140 |
119 - (void)invalidate { | 141 - (void)invalidate { |
120 if (hotKey_) { | 142 if (hotKey_) { |
121 GTMCarbonEventDispatcherHandler* handler = | 143 GTMCarbonEventDispatcherHandler* handler = |
122 [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; | 144 [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; |
123 [handler unregisterHotKey:hotKey_]; | 145 [handler unregisterHotKey:hotKey_]; |
124 hotKey_ = NULL; | 146 hotKey_ = NULL; |
125 } | 147 } |
126 if (mouseRunLoopSource_) { | 148 if (mouseRunLoopSource_) { |
127 CFMachPortInvalidate(mouseMachPort_); | 149 CFMachPortInvalidate(mouseMachPort_); |
128 CFRunLoopRemoveSource( | 150 CFRunLoopRemoveSource( |
129 CFRunLoopGetMain(), mouseRunLoopSource_, kCFRunLoopCommonModes); | 151 CFRunLoopGetMain(), mouseRunLoopSource_, kCFRunLoopCommonModes); |
130 CFRelease(mouseRunLoopSource_); | 152 CFRelease(mouseRunLoopSource_); |
131 mouseMachPort_.reset(0); | 153 mouseMachPort_.reset(0); |
132 mouseRunLoopSource_ = NULL; | 154 mouseRunLoopSource_ = NULL; |
133 } | 155 } |
134 } | 156 } |
135 | 157 |
136 - (void)addHost:(remoting::ChromotingHost*)host { | 158 - (void)addMonitor:(remoting::LocalInputMonitorMac*)monitor { |
137 base::AutoLock lock(hostsLock_); | 159 base::AutoLock lock(lock_); |
138 hosts_.insert(host); | 160 monitors_.insert(monitor); |
139 } | 161 } |
140 | 162 |
141 - (bool)removeHost:(remoting::ChromotingHost*)host { | 163 - (bool)removeMonitor:(remoting::LocalInputMonitorMac*)monitor { |
142 base::AutoLock lock(hostsLock_); | 164 base::AutoLock lock(lock_); |
143 hosts_.erase(host); | 165 monitors_.erase(monitor); |
144 return hosts_.empty(); | 166 return monitors_.empty(); |
145 } | |
146 | |
147 - (void)disableShortcut { | |
148 if (hotKey_) { | |
149 GTMCarbonEventDispatcherHandler* handler = | |
150 [GTMCarbonEventDispatcherHandler sharedEventDispatcherHandler]; | |
151 [handler unregisterHotKey:hotKey_]; | |
152 hotKey_ = NULL; | |
153 } | |
154 } | 167 } |
155 | 168 |
156 @end | 169 @end |
157 | 170 |
158 namespace remoting { | 171 namespace remoting { |
159 | 172 |
160 namespace { | 173 namespace { |
161 | 174 |
162 class LocalInputMonitorMac : public LocalInputMonitor { | 175 base::LazyInstance<base::Lock>::Leaky g_monitor_lock = |
163 public: | 176 LAZY_INSTANCE_INITIALIZER; |
164 LocalInputMonitorMac() : host_(NULL) {} | 177 LocalInputMonitorManager* g_local_input_monitor_manager = NULL; |
165 virtual ~LocalInputMonitorMac(); | |
166 virtual void Start(ChromotingHost* host) OVERRIDE; | |
167 virtual void Stop() OVERRIDE; | |
168 virtual void DisableShortcutOnMac() OVERRIDE; | |
169 | |
170 private: | |
171 ChromotingHost* host_; | |
172 DISALLOW_COPY_AND_ASSIGN(LocalInputMonitorMac); | |
173 }; | |
174 | |
175 base::LazyInstance<base::Lock>::Leaky monitor_lock = LAZY_INSTANCE_INITIALIZER; | |
176 LocalInputMonitorImpl* local_input_monitor = NULL; | |
177 | |
178 } // namespace | |
179 | 178 |
180 LocalInputMonitorMac::~LocalInputMonitorMac() { | 179 LocalInputMonitorMac::~LocalInputMonitorMac() { |
181 Stop(); | 180 Stop(); |
182 } | 181 } |
183 | 182 |
184 void LocalInputMonitorMac::Start(ChromotingHost* host) { | 183 void LocalInputMonitorMac::Start(MouseMoveObserver* mouse_move_observer, |
185 base::AutoLock lock(monitor_lock.Get()); | 184 const base::Closure& disconnect_callback) { |
186 if (!local_input_monitor) | 185 base::AutoLock lock(g_monitor_lock.Get()); |
187 local_input_monitor = [[LocalInputMonitorImpl alloc] init]; | 186 if (!g_local_input_monitor_manager) |
188 CHECK(local_input_monitor); | 187 g_local_input_monitor_manager = [[LocalInputMonitorManager alloc] init]; |
189 [local_input_monitor addHost:host]; | 188 CHECK(g_local_input_monitor_manager); |
190 host_ = host; | 189 mouse_move_observer_ = mouse_move_observer; |
| 190 disconnect_callback_ = disconnect_callback; |
| 191 [g_local_input_monitor_manager addMonitor:this]; |
191 } | 192 } |
192 | 193 |
193 void LocalInputMonitorMac::Stop() { | 194 void LocalInputMonitorMac::Stop() { |
194 base::AutoLock lock(monitor_lock.Get()); | 195 base::AutoLock lock(g_monitor_lock.Get()); |
195 if ([local_input_monitor removeHost:host_]) { | 196 if ([g_local_input_monitor_manager removeMonitor:this]) { |
196 [local_input_monitor invalidate]; | 197 [g_local_input_monitor_manager invalidate]; |
197 [local_input_monitor release]; | 198 [g_local_input_monitor_manager release]; |
198 local_input_monitor = nil; | 199 g_local_input_monitor_manager = nil; |
199 } | 200 } |
200 } | 201 } |
201 | 202 |
202 void LocalInputMonitorMac::DisableShortcutOnMac() { | 203 void LocalInputMonitorMac::OnLocalMouseMoved(const SkIPoint& new_pos) { |
203 [local_input_monitor disableShortcut]; | 204 mouse_move_observer_->OnLocalMouseMoved(new_pos); |
204 } | 205 } |
205 | 206 |
| 207 void LocalInputMonitorMac::OnDisconnectShortcut() { |
| 208 disconnect_callback_.Run(); |
| 209 } |
| 210 |
| 211 } // namespace |
| 212 |
206 scoped_ptr<LocalInputMonitor> LocalInputMonitor::Create() { | 213 scoped_ptr<LocalInputMonitor> LocalInputMonitor::Create() { |
207 return scoped_ptr<LocalInputMonitor>(new LocalInputMonitorMac()); | 214 return scoped_ptr<LocalInputMonitor>(new LocalInputMonitorMac()); |
208 } | 215 } |
209 | 216 |
210 } // namespace remoting | 217 } // namespace remoting |
OLD | NEW |