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/input_injector.h" | 5 #include "remoting/host/input_injector.h" |
6 | 6 |
7 #include <ApplicationServices/ApplicationServices.h> | 7 #include <ApplicationServices/ApplicationServices.h> |
8 #include <Carbon/Carbon.h> | 8 #include <Carbon/Carbon.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
53 using protocol::ClipboardEvent; | 53 using protocol::ClipboardEvent; |
54 using protocol::KeyEvent; | 54 using protocol::KeyEvent; |
55 using protocol::TextEvent; | 55 using protocol::TextEvent; |
56 using protocol::MouseEvent; | 56 using protocol::MouseEvent; |
57 | 57 |
58 // A class to generate events on Mac. | 58 // A class to generate events on Mac. |
59 class InputInjectorMac : public InputInjector { | 59 class InputInjectorMac : public InputInjector { |
60 public: | 60 public: |
61 explicit InputInjectorMac( | 61 explicit InputInjectorMac( |
62 scoped_refptr<base::SingleThreadTaskRunner> task_runner); | 62 scoped_refptr<base::SingleThreadTaskRunner> task_runner); |
63 | |
63 virtual ~InputInjectorMac(); | 64 virtual ~InputInjectorMac(); |
64 | 65 |
65 // ClipboardStub interface. | 66 // ClipboardStub interface. |
66 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; | 67 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; |
67 | 68 |
68 // InputStub interface. | 69 // InputStub interface. |
69 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; | 70 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; |
70 virtual void InjectTextEvent(const TextEvent& event) OVERRIDE; | 71 virtual void InjectTextEvent(const TextEvent& event) OVERRIDE; |
71 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; | 72 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; |
72 | 73 |
73 // InputInjector interface. | 74 // InputInjector interface. |
74 virtual void Start( | 75 virtual void Start( |
75 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; | 76 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; |
77 void EnableWindowInjection(webrtc::WindowId window_id); | |
76 | 78 |
77 private: | 79 private: |
80 CGWindowID window_id_input_injector_mac_; | |
Wez
2014/08/01 23:41:53
Members appear after type definitions (see style g
ronakvora do not use
2014/08/05 19:54:49
Got it. Removed anyhow since it was not needed, as
| |
78 // The actual implementation resides in InputInjectorMac::Core class. | 81 // The actual implementation resides in InputInjectorMac::Core class. |
79 class Core : public base::RefCountedThreadSafe<Core> { | 82 class Core : public base::RefCountedThreadSafe<Core> { |
80 public: | 83 public: |
81 explicit Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner); | 84 explicit Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner); |
82 | 85 |
83 // Mirrors the ClipboardStub interface. | 86 // Mirrors the ClipboardStub interface. |
84 void InjectClipboardEvent(const ClipboardEvent& event); | 87 void InjectClipboardEvent(const ClipboardEvent& event); |
85 | 88 |
86 // Mirrors the InputStub interface. | 89 // Mirrors the InputStub interface. |
87 void InjectKeyEvent(const KeyEvent& event); | 90 void InjectKeyEvent(const KeyEvent& event); |
88 void InjectTextEvent(const TextEvent& event); | 91 void InjectTextEvent(const TextEvent& event); |
89 void InjectMouseEvent(const MouseEvent& event); | 92 void InjectMouseEvent(const MouseEvent& event); |
90 | 93 |
91 // Mirrors the InputInjector interface. | 94 // Mirrors the InputInjector interface. |
92 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard); | 95 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard); |
96 void EnableWindowInjection(CGWindowID window_id); | |
93 | 97 |
94 void Stop(); | 98 void Stop(); |
95 | 99 |
96 private: | 100 private: |
97 friend class base::RefCountedThreadSafe<Core>; | 101 friend class base::RefCountedThreadSafe<Core>; |
98 virtual ~Core(); | 102 virtual ~Core(); |
103 CGRect FindCGRectOfWindow(webrtc::MacDesktopConfiguration desktop_config); | |
99 | 104 |
100 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 105 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
101 webrtc::DesktopVector mouse_pos_; | 106 webrtc::DesktopVector mouse_pos_; |
102 uint32 mouse_button_state_; | 107 uint32 mouse_button_state_; |
103 scoped_ptr<Clipboard> clipboard_; | 108 scoped_ptr<Clipboard> clipboard_; |
104 CGEventFlags left_modifiers_; | 109 CGEventFlags left_modifiers_; |
105 CGEventFlags right_modifiers_; | 110 CGEventFlags right_modifiers_; |
111 CGWindowID window_id_core_; | |
112 bool window_injection_enabled_; | |
106 | 113 |
107 DISALLOW_COPY_AND_ASSIGN(Core); | 114 DISALLOW_COPY_AND_ASSIGN(Core); |
108 }; | 115 }; |
109 | 116 |
110 scoped_refptr<Core> core_; | 117 scoped_refptr<Core> core_; |
111 | 118 |
112 DISALLOW_COPY_AND_ASSIGN(InputInjectorMac); | 119 DISALLOW_COPY_AND_ASSIGN(InputInjectorMac); |
113 }; | 120 }; |
114 | 121 |
115 InputInjectorMac::InputInjectorMac( | 122 InputInjectorMac::InputInjectorMac( |
(...skipping 19 matching lines...) Expand all Loading... | |
135 | 142 |
136 void InputInjectorMac::InjectMouseEvent(const MouseEvent& event) { | 143 void InputInjectorMac::InjectMouseEvent(const MouseEvent& event) { |
137 core_->InjectMouseEvent(event); | 144 core_->InjectMouseEvent(event); |
138 } | 145 } |
139 | 146 |
140 void InputInjectorMac::Start( | 147 void InputInjectorMac::Start( |
141 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 148 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
142 core_->Start(client_clipboard.Pass()); | 149 core_->Start(client_clipboard.Pass()); |
143 } | 150 } |
144 | 151 |
152 void InputInjectorMac::EnableWindowInjection(webrtc::WindowId window_id) { | |
153 window_id_input_injector_mac_ = (CGWindowID) window_id; | |
Wez
2014/08/01 23:41:53
Why do you need to store this in the InputInjector
ronakvora do not use
2014/08/05 19:54:49
Don't. Removed!
| |
154 core_->EnableWindowInjection(window_id_input_injector_mac_); | |
155 } | |
156 | |
145 InputInjectorMac::Core::Core( | 157 InputInjectorMac::Core::Core( |
146 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 158 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
147 : task_runner_(task_runner), | 159 : task_runner_(task_runner), |
148 mouse_button_state_(0), | 160 mouse_button_state_(0), |
149 clipboard_(Clipboard::Create()), | 161 clipboard_(Clipboard::Create()), |
150 left_modifiers_(0), | 162 left_modifiers_(0), |
151 right_modifiers_(0) { | 163 right_modifiers_(0) { |
152 // Ensure that local hardware events are not suppressed after injecting | 164 // Ensure that local hardware events are not suppressed after injecting |
153 // input events. This allows LocalInputMonitor to detect if the local mouse | 165 // input events. This allows LocalInputMonitor to detect if the local mouse |
154 // is being moved whilst a remote user is connected. | 166 // is being moved whilst a remote user is connected. |
155 // This API is deprecated, but it is needed when using the deprecated | 167 // This API is deprecated, but it is needed when using the deprecated |
156 // injection APIs. | 168 // injection APIs. |
157 // If the non-deprecated injection APIs were used instead, the equivalent of | 169 // If the non-deprecated injection APIs were used instead, the equivalent of |
158 // this line would not be needed, as OS X defaults to _not_ suppressing local | 170 // this line would not be needed, as OS X defaults to _not_ suppressing local |
159 // inputs in that case. | 171 // inputs in that case. |
160 #pragma clang diagnostic push | 172 #pragma clang diagnostic push |
161 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 173 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
162 CGSetLocalEventsSuppressionInterval(0.0); | 174 CGSetLocalEventsSuppressionInterval(0.0); |
163 #pragma clang diagnostic pop | 175 #pragma clang diagnostic pop |
164 } | 176 } |
165 | 177 |
178 void InputInjectorMac::Core::EnableWindowInjection(CGWindowID window_id) { | |
179 window_id_core_ = window_id; | |
180 window_injection_enabled_ = true; | |
181 } | |
182 | |
166 void InputInjectorMac::Core::InjectClipboardEvent(const ClipboardEvent& event) { | 183 void InputInjectorMac::Core::InjectClipboardEvent(const ClipboardEvent& event) { |
167 if (!task_runner_->BelongsToCurrentThread()) { | 184 if (!task_runner_->BelongsToCurrentThread()) { |
168 task_runner_->PostTask( | 185 task_runner_->PostTask( |
169 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event)); | 186 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event)); |
170 return; | 187 return; |
171 } | 188 } |
172 | 189 |
173 // |clipboard_| will ignore unknown MIME-types, and verify the data's format. | 190 // |clipboard_| will ignore unknown MIME-types, and verify the data's format. |
174 clipboard_->InjectClipboardEvent(event); | 191 clipboard_->InjectClipboardEvent(event); |
175 } | 192 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 void InputInjectorMac::Core::InjectTextEvent(const TextEvent& event) { | 238 void InputInjectorMac::Core::InjectTextEvent(const TextEvent& event) { |
222 DCHECK(event.has_text()); | 239 DCHECK(event.has_text()); |
223 base::string16 text = base::UTF8ToUTF16(event.text()); | 240 base::string16 text = base::UTF8ToUTF16(event.text()); |
224 | 241 |
225 // Applications that ignore UnicodeString field will see the text event as | 242 // Applications that ignore UnicodeString field will see the text event as |
226 // Space key. | 243 // Space key. |
227 CreateAndPostKeyEvent(kVK_Space, true, 0, text); | 244 CreateAndPostKeyEvent(kVK_Space, true, 0, text); |
228 CreateAndPostKeyEvent(kVK_Space, false, 0, text); | 245 CreateAndPostKeyEvent(kVK_Space, false, 0, text); |
229 } | 246 } |
230 | 247 |
248 // This method is used if we are capturing a window instead of a screen. | |
249 // It finds the rectangle of the window we are streaming using | |
250 // |window_id_core_|. The InputInjector can then use this rectangle | |
251 // to translate the input event to coordinates of the window rather | |
252 // than the screen. | |
253 CGRect InputInjectorMac::Core::FindCGRectOfWindow( | |
254 webrtc::MacDesktopConfiguration desktop_config) { | |
255 CGRect rect; | |
256 CGWindowID ids[1] = {window_id_core_}; | |
257 CFArrayRef window_id_array = | |
258 CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL); | |
259 CFArrayRef window_array = | |
260 CGWindowListCreateDescriptionFromArray(window_id_array); | |
261 if (window_array == NULL || 0 == CFArrayGetCount(window_array)) { | |
262 // Could not find the window. It might have been closed. | |
263 LOG(ERROR) << "Specified window to stream not found for id: " | |
264 << window_id_core_; | |
265 CFRelease(window_id_array); | |
266 CFRelease(window_array); | |
267 return CGRectNull; | |
268 } | |
269 CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>( | |
270 CFArrayGetValueAtIndex(window_array, 0)); | |
271 | |
272 if (CFDictionaryContainsKey(window, kCGWindowBounds)) { | |
273 CFDictionaryRef bounds = | |
274 reinterpret_cast<CFDictionaryRef> | |
275 (CFDictionaryGetValue(window, kCGWindowBounds)); | |
276 if (bounds) { | |
277 CGRectMakeWithDictionaryRepresentation(bounds, &rect); | |
278 } | |
279 } | |
280 | |
281 CFRelease(window_id_array); | |
282 CFRelease(window_array); | |
283 return rect; | |
284 } | |
285 | |
231 void InputInjectorMac::Core::InjectMouseEvent(const MouseEvent& event) { | 286 void InputInjectorMac::Core::InjectMouseEvent(const MouseEvent& event) { |
232 if (event.has_x() && event.has_y()) { | 287 if (event.has_x() && event.has_y()) { |
233 // On multi-monitor systems (0,0) refers to the top-left of the "main" | 288 // On multi-monitor systems (0,0) refers to the top-left of the "main" |
234 // display, whereas our coordinate scheme places (0,0) at the top-left of | 289 // display, whereas our coordinate scheme places (0,0) at the top-left of |
235 // the bounding rectangle around all the displays, so we need to translate | 290 // the bounding rectangle around all the displays, so we need to translate |
236 // accordingly. | 291 // accordingly. |
237 | 292 |
238 // Set the mouse position assuming single-monitor. | 293 // Set the mouse position assuming single-monitor. |
239 mouse_pos_.set(event.x(), event.y()); | 294 mouse_pos_.set(event.x(), event.y()); |
240 | 295 |
(...skipping 15 matching lines...) Expand all Loading... | |
256 mouse_pos_.set( | 311 mouse_pos_.set( |
257 std::max(desktop_config.pixel_bounds.left(), | 312 std::max(desktop_config.pixel_bounds.left(), |
258 std::min(desktop_config.pixel_bounds.right(), mouse_pos_.x())), | 313 std::min(desktop_config.pixel_bounds.right(), mouse_pos_.x())), |
259 std::max(desktop_config.pixel_bounds.top(), | 314 std::max(desktop_config.pixel_bounds.top(), |
260 std::min(desktop_config.pixel_bounds.bottom(), mouse_pos_.y()))); | 315 std::min(desktop_config.pixel_bounds.bottom(), mouse_pos_.y()))); |
261 | 316 |
262 // Convert from pixel to Density Independent Pixel coordinates. | 317 // Convert from pixel to Density Independent Pixel coordinates. |
263 mouse_pos_.set(mouse_pos_.x() / desktop_config.dip_to_pixel_scale, | 318 mouse_pos_.set(mouse_pos_.x() / desktop_config.dip_to_pixel_scale, |
264 mouse_pos_.y() / desktop_config.dip_to_pixel_scale); | 319 mouse_pos_.y() / desktop_config.dip_to_pixel_scale); |
265 | 320 |
321 if (window_injection_enabled_) { | |
322 CGRect windowRect = FindCGRectOfWindow(desktop_config); | |
323 if (CGRectEqualToRect(windowRect, CGRectNull)) { | |
324 LOG(ERROR) << "Can't find rectangle of window."; | |
325 return; | |
326 } | |
327 mouse_pos_ = mouse_pos_.add( | |
328 webrtc::DesktopVector(CGRectGetMinX(windowRect), | |
329 CGRectGetMinY(windowRect))); | |
Wez
2014/08/01 23:41:54
Do you mean to clamp input to the window width & h
ronakvora do not use
2014/08/05 19:54:49
I don't know what you mean by clamp input to windo
| |
330 } | |
331 | |
266 VLOG(3) << "Moving mouse to " << mouse_pos_.x() << "," << mouse_pos_.y(); | 332 VLOG(3) << "Moving mouse to " << mouse_pos_.x() << "," << mouse_pos_.y(); |
267 } | 333 } |
268 if (event.has_button() && event.has_button_down()) { | 334 if (event.has_button() && event.has_button_down()) { |
269 if (event.button() >= 1 && event.button() <= 3) { | 335 if (event.button() >= 1 && event.button() <= 3) { |
270 VLOG(2) << "Button " << event.button() | 336 VLOG(2) << "Button " << event.button() |
271 << (event.button_down() ? " down" : " up"); | 337 << (event.button_down() ? " down" : " up"); |
272 int button_change = 1 << (event.button() - 1); | 338 int button_change = 1 << (event.button() - 1); |
273 if (event.button_down()) | 339 if (event.button_down()) |
274 mouse_button_state_ |= button_change; | 340 mouse_button_state_ |= button_change; |
275 else | 341 else |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 InputInjectorMac::Core::~Core() {} | 400 InputInjectorMac::Core::~Core() {} |
335 | 401 |
336 } // namespace | 402 } // namespace |
337 | 403 |
338 scoped_ptr<InputInjector> InputInjector::Create( | 404 scoped_ptr<InputInjector> InputInjector::Create( |
339 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 405 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
340 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 406 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
341 return scoped_ptr<InputInjector>(new InputInjectorMac(main_task_runner)); | 407 return scoped_ptr<InputInjector>(new InputInjectorMac(main_task_runner)); |
342 } | 408 } |
343 | 409 |
410 scoped_ptr<InputInjector> InputInjector::CreateForWindow( | |
411 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | |
412 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | |
413 webrtc::WindowId window_id) { | |
414 scoped_ptr<InputInjectorMac>injector(new InputInjectorMac(main_task_runner)); | |
415 injector->EnableWindowInjection(window_id); | |
416 return injector.PassAs<InputInjector>(); | |
417 } | |
418 | |
344 } // namespace remoting | 419 } // namespace remoting |
OLD | NEW |