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

Side by Side Diff: remoting/host/input_injector_mac.cc

Issue 422503004: Adding ability to stream windows and inject events to them (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: uploaded to remove lint errors Created 6 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
OLDNEW
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
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 // TODO(sidj, sskhandp) Remove these methods and use
78 // WindowInputInjectorMac instead.
79 virtual void SetWindowId(webrtc::WindowId windowId);
Lambros 2014/07/30 00:14:48 Do these need to be virtual?
ronakvora do not use 2014/07/30 20:55:36 Nope, changed.
80 virtual void SetEnableWindowCapture(bool enable_window_capture);
Lambros 2014/07/30 00:14:48 Don't say "Capture" here. Maybe replace these meth
ronakvora do not use 2014/07/30 20:55:36 Done.
76 81
77 private: 82 private:
83 // TODO(sidj, sskhandp) put these inside of WindowInputInjectorMac.
Lambros 2014/07/30 00:14:49 Remove TODO - I don't think it's worth defining a
ronakvora do not use 2014/07/30 20:55:36 Done.
84 CGWindowID windowId_input_injector_mac_;
Lambros 2014/07/30 00:14:49 nit: window_id_
ronakvora do not use 2014/07/30 20:55:36 Done.
85 bool enable_window_capture_injector_mac_;
Lambros 2014/07/30 00:14:48 nit: window_injection_enabled_ - don't use "captur
ronakvora do not use 2014/07/30 20:55:36 Done.
78 // The actual implementation resides in InputInjectorMac::Core class. 86 // The actual implementation resides in InputInjectorMac::Core class.
79 class Core : public base::RefCountedThreadSafe<Core> { 87 class Core : public base::RefCountedThreadSafe<Core> {
80 public: 88 public:
81 explicit Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner); 89 explicit Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
82 90
83 // Mirrors the ClipboardStub interface. 91 // Mirrors the ClipboardStub interface.
84 void InjectClipboardEvent(const ClipboardEvent& event); 92 void InjectClipboardEvent(const ClipboardEvent& event);
85 93
86 // Mirrors the InputStub interface. 94 // Mirrors the InputStub interface.
87 void InjectKeyEvent(const KeyEvent& event); 95 void InjectKeyEvent(const KeyEvent& event);
88 void InjectTextEvent(const TextEvent& event); 96 void InjectTextEvent(const TextEvent& event);
89 void InjectMouseEvent(const MouseEvent& event); 97 void InjectMouseEvent(const MouseEvent& event);
90 98
91 // Mirrors the InputInjector interface. 99 // Mirrors the InputInjector interface.
92 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard); 100 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard);
93 101
102 // TODO(sidj, sskhandp) Remove these methods and use
Lambros 2014/07/30 00:14:48 Remove TODO.
ronakvora do not use 2014/07/30 20:55:36 Done.
103 // WindowInputInjectorMac instead.
104 void SetWindowId(CGWindowID windowId);
105 void SetEnableWindowCapture(bool enable_window_capture);
106
94 void Stop(); 107 void Stop();
95 108
96 private: 109 private:
97 friend class base::RefCountedThreadSafe<Core>; 110 friend class base::RefCountedThreadSafe<Core>;
98 virtual ~Core(); 111 virtual ~Core();
112 CGRect FindCGRectOfWindow(webrtc::MacDesktopConfiguration desktop_config);
99 113
100 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 114 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
101 webrtc::DesktopVector mouse_pos_; 115 webrtc::DesktopVector mouse_pos_;
102 uint32 mouse_button_state_; 116 uint32 mouse_button_state_;
103 scoped_ptr<Clipboard> clipboard_; 117 scoped_ptr<Clipboard> clipboard_;
104 CGEventFlags left_modifiers_; 118 CGEventFlags left_modifiers_;
105 CGEventFlags right_modifiers_; 119 CGEventFlags right_modifiers_;
120 // TODO(sidj, sskhandp) put these inside of WindowInputInjectorMac.
Lambros 2014/07/30 00:14:48 Remove TODO.
ronakvora do not use 2014/07/30 20:55:36 Done.
121 CGWindowID windowId_core_;
122 bool enable_window_capture_core_;
106 123
107 DISALLOW_COPY_AND_ASSIGN(Core); 124 DISALLOW_COPY_AND_ASSIGN(Core);
108 }; 125 };
109 126
110 scoped_refptr<Core> core_; 127 scoped_refptr<Core> core_;
111 128
112 DISALLOW_COPY_AND_ASSIGN(InputInjectorMac); 129 DISALLOW_COPY_AND_ASSIGN(InputInjectorMac);
113 }; 130 };
114 131
115 InputInjectorMac::InputInjectorMac( 132 InputInjectorMac::InputInjectorMac(
(...skipping 19 matching lines...) Expand all
135 152
136 void InputInjectorMac::InjectMouseEvent(const MouseEvent& event) { 153 void InputInjectorMac::InjectMouseEvent(const MouseEvent& event) {
137 core_->InjectMouseEvent(event); 154 core_->InjectMouseEvent(event);
138 } 155 }
139 156
140 void InputInjectorMac::Start( 157 void InputInjectorMac::Start(
141 scoped_ptr<protocol::ClipboardStub> client_clipboard) { 158 scoped_ptr<protocol::ClipboardStub> client_clipboard) {
142 core_->Start(client_clipboard.Pass()); 159 core_->Start(client_clipboard.Pass());
143 } 160 }
144 161
162 void InputInjectorMac::SetWindowId(webrtc::WindowId windowId) {
163 windowId_input_injector_mac_ = (CGWindowID) windowId;
164 core_->SetWindowId(windowId_input_injector_mac_);
165 }
166
167 void InputInjectorMac::SetEnableWindowCapture(bool enable_window_capture) {
168 enable_window_capture_injector_mac_ = enable_window_capture;
169 core_->SetEnableWindowCapture(enable_window_capture_injector_mac_);
170 }
171
145 InputInjectorMac::Core::Core( 172 InputInjectorMac::Core::Core(
146 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 173 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
147 : task_runner_(task_runner), 174 : task_runner_(task_runner),
148 mouse_button_state_(0), 175 mouse_button_state_(0),
149 clipboard_(Clipboard::Create()), 176 clipboard_(Clipboard::Create()),
150 left_modifiers_(0), 177 left_modifiers_(0),
151 right_modifiers_(0) { 178 right_modifiers_(0) {
152 // Ensure that local hardware events are not suppressed after injecting 179 // Ensure that local hardware events are not suppressed after injecting
153 // input events. This allows LocalInputMonitor to detect if the local mouse 180 // input events. This allows LocalInputMonitor to detect if the local mouse
154 // is being moved whilst a remote user is connected. 181 // is being moved whilst a remote user is connected.
155 // This API is deprecated, but it is needed when using the deprecated 182 // This API is deprecated, but it is needed when using the deprecated
156 // injection APIs. 183 // injection APIs.
157 // If the non-deprecated injection APIs were used instead, the equivalent of 184 // 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 185 // this line would not be needed, as OS X defaults to _not_ suppressing local
159 // inputs in that case. 186 // inputs in that case.
160 #pragma clang diagnostic push 187 #pragma clang diagnostic push
161 #pragma clang diagnostic ignored "-Wdeprecated-declarations" 188 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
162 CGSetLocalEventsSuppressionInterval(0.0); 189 CGSetLocalEventsSuppressionInterval(0.0);
163 #pragma clang diagnostic pop 190 #pragma clang diagnostic pop
164 } 191 }
165 192
193 void InputInjectorMac::Core::SetWindowId(CGWindowID windowId) {
194 windowId_core_ = windowId;
195 }
196 void InputInjectorMac::Core::SetEnableWindowCapture
197 (bool enable_window_capture) {
198 enable_window_capture_core_ = enable_window_capture;
199 }
166 void InputInjectorMac::Core::InjectClipboardEvent(const ClipboardEvent& event) { 200 void InputInjectorMac::Core::InjectClipboardEvent(const ClipboardEvent& event) {
167 if (!task_runner_->BelongsToCurrentThread()) { 201 if (!task_runner_->BelongsToCurrentThread()) {
168 task_runner_->PostTask( 202 task_runner_->PostTask(
169 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event)); 203 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event));
170 return; 204 return;
171 } 205 }
172 206
173 // |clipboard_| will ignore unknown MIME-types, and verify the data's format. 207 // |clipboard_| will ignore unknown MIME-types, and verify the data's format.
174 clipboard_->InjectClipboardEvent(event); 208 clipboard_->InjectClipboardEvent(event);
175 } 209 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 void InputInjectorMac::Core::InjectTextEvent(const TextEvent& event) { 255 void InputInjectorMac::Core::InjectTextEvent(const TextEvent& event) {
222 DCHECK(event.has_text()); 256 DCHECK(event.has_text());
223 base::string16 text = base::UTF8ToUTF16(event.text()); 257 base::string16 text = base::UTF8ToUTF16(event.text());
224 258
225 // Applications that ignore UnicodeString field will see the text event as 259 // Applications that ignore UnicodeString field will see the text event as
226 // Space key. 260 // Space key.
227 CreateAndPostKeyEvent(kVK_Space, true, 0, text); 261 CreateAndPostKeyEvent(kVK_Space, true, 0, text);
228 CreateAndPostKeyEvent(kVK_Space, false, 0, text); 262 CreateAndPostKeyEvent(kVK_Space, false, 0, text);
229 } 263 }
230 264
265 CGRect InputInjectorMac::Core::FindCGRectOfWindow(
266 webrtc::MacDesktopConfiguration desktop_config) {
267 CGRect rect;
268 CGWindowID ids[1] = {windowId_core_};
269 CFArrayRef window_id_array =
270 CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL);
271 CFArrayRef window_array =
272 CGWindowListCreateDescriptionFromArray(window_id_array);
273 if (window_array == NULL || 0 == CFArrayGetCount(window_array)) {
274 // Could not find the window. It might have been closed.
275 LOG(ERROR) << "Specified window to stream not found for id: "
276 << windowId_core_;
277 CFRelease(window_id_array);
Lambros 2014/07/30 00:14:49 Use ScopedCFTypeRef from base/mac/scoped_cftyperef
ronakvora do not use 2014/07/30 20:55:36 I've been a bit confused on the scoped_X types. Do
278 CFRelease(window_array);
279 return CGRectNull;
280 }
281 CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
282 CFArrayGetValueAtIndex(window_array, 0));
283
284 if (CFDictionaryContainsKey(window, kCGWindowBounds)) {
285 CFDictionaryRef bounds =
286 reinterpret_cast<CFDictionaryRef>
287 (CFDictionaryGetValue(window, kCGWindowBounds));
288 if (bounds) {
289 CGRectMakeWithDictionaryRepresentation(bounds, &rect);
290 }
291 }
292
293 CFRelease(window_id_array);
294 CFRelease(window_array);
295 return rect;
296 }
297
231 void InputInjectorMac::Core::InjectMouseEvent(const MouseEvent& event) { 298 void InputInjectorMac::Core::InjectMouseEvent(const MouseEvent& event) {
232 if (event.has_x() && event.has_y()) { 299 if (event.has_x() && event.has_y()) {
233 // On multi-monitor systems (0,0) refers to the top-left of the "main" 300 // 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 301 // 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 302 // the bounding rectangle around all the displays, so we need to translate
236 // accordingly. 303 // accordingly.
237 304
238 // Set the mouse position assuming single-monitor. 305 // Set the mouse position assuming single-monitor.
239 mouse_pos_.set(event.x(), event.y()); 306 mouse_pos_.set(event.x(), event.y());
240 307
(...skipping 15 matching lines...) Expand all
256 mouse_pos_.set( 323 mouse_pos_.set(
257 std::max(desktop_config.pixel_bounds.left(), 324 std::max(desktop_config.pixel_bounds.left(),
258 std::min(desktop_config.pixel_bounds.right(), mouse_pos_.x())), 325 std::min(desktop_config.pixel_bounds.right(), mouse_pos_.x())),
259 std::max(desktop_config.pixel_bounds.top(), 326 std::max(desktop_config.pixel_bounds.top(),
260 std::min(desktop_config.pixel_bounds.bottom(), mouse_pos_.y()))); 327 std::min(desktop_config.pixel_bounds.bottom(), mouse_pos_.y())));
261 328
262 // Convert from pixel to Density Independent Pixel coordinates. 329 // Convert from pixel to Density Independent Pixel coordinates.
263 mouse_pos_.set(mouse_pos_.x() / desktop_config.dip_to_pixel_scale, 330 mouse_pos_.set(mouse_pos_.x() / desktop_config.dip_to_pixel_scale,
264 mouse_pos_.y() / desktop_config.dip_to_pixel_scale); 331 mouse_pos_.y() / desktop_config.dip_to_pixel_scale);
265 332
333 // Translate the mouse position into window coordinates.
334 // TODO(sskhandp, sidj) Remove this if clause and implement
335 // functionality in WindowInputInjectorMac.
336 if (enable_window_capture_core_) {
337 CGRect windowRect = FindCGRectOfWindow(desktop_config);
338 if (CGRectEqualToRect(windowRect, CGRectNull)) {
339 LOG(ERROR) << "Can't find rectangle of window.";
340 return;
341 }
342 mouse_pos_ = mouse_pos_.add(
343 webrtc::DesktopVector(CGRectGetMinX(windowRect),
344 CGRectGetMinY(windowRect)));
345 }
346
266 VLOG(3) << "Moving mouse to " << mouse_pos_.x() << "," << mouse_pos_.y(); 347 VLOG(3) << "Moving mouse to " << mouse_pos_.x() << "," << mouse_pos_.y();
267 } 348 }
268 if (event.has_button() && event.has_button_down()) { 349 if (event.has_button() && event.has_button_down()) {
269 if (event.button() >= 1 && event.button() <= 3) { 350 if (event.button() >= 1 && event.button() <= 3) {
270 VLOG(2) << "Button " << event.button() 351 VLOG(2) << "Button " << event.button()
271 << (event.button_down() ? " down" : " up"); 352 << (event.button_down() ? " down" : " up");
272 int button_change = 1 << (event.button() - 1); 353 int button_change = 1 << (event.button() - 1);
273 if (event.button_down()) 354 if (event.button_down())
274 mouse_button_state_ |= button_change; 355 mouse_button_state_ |= button_change;
275 else 356 else
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 InputInjectorMac::Core::~Core() {} 415 InputInjectorMac::Core::~Core() {}
335 416
336 } // namespace 417 } // namespace
337 418
338 scoped_ptr<InputInjector> InputInjector::Create( 419 scoped_ptr<InputInjector> InputInjector::Create(
339 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 420 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
340 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { 421 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
341 return scoped_ptr<InputInjector>(new InputInjectorMac(main_task_runner)); 422 return scoped_ptr<InputInjector>(new InputInjectorMac(main_task_runner));
342 } 423 }
343 424
425 // TODO(sskhandp, sidj) remove this method and make WindowInputInjector
Lambros 2014/07/30 00:14:48 Remove TODO.
ronakvora do not use 2014/07/30 20:55:36 Done.
426 scoped_ptr<InputInjector> InputInjector::Create(
427 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
428 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
429 webrtc::WindowId windowId,
430 bool enable_window_capture) {
431 InputInjectorMac* injector = new InputInjectorMac(main_task_runner);
Lambros 2014/07/30 00:14:49 nit: Declare |injector| as scoped_ptr instead of r
ronakvora do not use 2014/07/30 20:55:36 Done.
432 injector->SetWindowId(windowId);
433 injector->SetEnableWindowCapture(enable_window_capture);
434 return scoped_ptr<InputInjector>(injector);
435 }
436
344 } // namespace remoting 437 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698