Index: remoting/host/single_window_input_injector_mac.cc |
diff --git a/remoting/host/single_window_input_injector_mac.cc b/remoting/host/single_window_input_injector_mac.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a84d2b158e9be30f0a3a8eca28bb8e94452c46c7 |
--- /dev/null |
+++ b/remoting/host/single_window_input_injector_mac.cc |
@@ -0,0 +1,175 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "remoting/host/single_window_input_injector.h" |
+ |
+#include <ApplicationServices/ApplicationServices.h> |
+#include <Carbon/Carbon.h> |
+ |
+#include "base/mac/foundation_util.h" |
+#include "base/mac/scoped_cftyperef.h" |
+#include "remoting/proto/event.pb.h" |
+#include "third_party/webrtc/modules/desktop_capture/mac/desktop_configuration.h" |
+ |
+namespace remoting { |
+ |
+using protocol::ClipboardEvent; |
+using protocol::KeyEvent; |
+using protocol::TextEvent; |
+using protocol::MouseEvent; |
+ |
+// Implements InputInjector to direct input events to a specific window. |
+// Clipboard, Key, and Text Events will all still be Global. MouseEvents |
+// will be local to the window. |
Wez
2014/08/07 23:14:33
This comment really just duplicates what is descri
ronakvora do not use
2014/08/08 17:07:14
Removed.
|
+class SingleWindowInputInjectorMac : public SingleWindowInputInjector { |
+ public: |
+ SingleWindowInputInjectorMac( |
+ webrtc::WindowId window_id, |
+ scoped_ptr<InputInjector> input_injector); |
+ virtual ~SingleWindowInputInjectorMac(); |
+ |
+ // InputInjector interface. |
+ virtual void Start( |
+ scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; |
+ virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; |
+ virtual void InjectTextEvent(const TextEvent& event) OVERRIDE; |
+ virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; |
+ virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; |
+ |
+ private: |
+ CGRect FindCGRectOfWindow(); |
+ |
+ CGWindowID window_id_; |
+ scoped_ptr<InputInjector> input_injector_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SingleWindowInputInjectorMac); |
+}; |
+ |
+SingleWindowInputInjectorMac::SingleWindowInputInjectorMac( |
+ webrtc::WindowId window_id, |
+ scoped_ptr<InputInjector> input_injector) |
+ : window_id_(static_cast<CGWindowID>(window_id)), |
+ input_injector_(input_injector.Pass()) { |
+} |
+ |
+SingleWindowInputInjectorMac::~SingleWindowInputInjectorMac() { |
+} |
+ |
+void SingleWindowInputInjectorMac::Start( |
+ scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
+ input_injector_->Start(client_clipboard.Pass()); |
+} |
+ |
+void SingleWindowInputInjectorMac::InjectKeyEvent(const KeyEvent& event) { |
+ input_injector_->InjectKeyEvent(event); |
+} |
+ |
+void SingleWindowInputInjectorMac::InjectTextEvent(const TextEvent& event) { |
+ input_injector_->InjectTextEvent(event); |
+} |
+ |
+void SingleWindowInputInjectorMac::InjectMouseEvent(const MouseEvent& event) { |
+ if (event.has_x() && event.has_y()) { |
+ CGRect windowRect = FindCGRectOfWindow(); |
+ if (CGRectIsNull(windowRect)) { |
+ LOG(ERROR) << "Window rect is null, so forwarding unmodified MouseEvent"; |
+ input_injector_->InjectMouseEvent(event); |
+ return; |
+ } |
+ |
+ webrtc::MacDesktopConfiguration desktop_config = |
+ webrtc::MacDesktopConfiguration::GetCurrent( |
+ webrtc::MacDesktopConfiguration::TopLeftOrigin); |
+ |
+ // Create a vector that has the origin of the window. |
+ webrtc::DesktopVector window_mouse_pos(windowRect.origin.x, |
+ windowRect.origin.y); |
+ |
+ // The underlying InputInjector expects coordinates relative to the |
+ // top-left of the top-left-most monitor, so translate the window origin |
+ // to that coordinate scheme. |
+ window_mouse_pos.subtract( |
+ webrtc::DesktopVector(desktop_config.pixel_bounds.left(), |
+ desktop_config.pixel_bounds.top())); |
+ |
+ // We must make sure we are taking into account the fact that when we |
+ // find the window on the host it returns its coordinates in Density |
+ // Independent coordinates. We have to convert to Density Dependent |
+ // because InputInjector assumes Density Dependent coordinates in the |
+ // MouseEvent. |
+ window_mouse_pos.set(window_mouse_pos.x() * |
+ desktop_config.dip_to_pixel_scale, |
+ window_mouse_pos.y() * |
+ desktop_config.dip_to_pixel_scale); |
+ |
+ // Create a new event with coordinates that are in respect to the window. |
+ MouseEvent modified_event(event); |
+ modified_event.set_x(event.x() + window_mouse_pos.x()); |
+ modified_event.set_y(event.y() + window_mouse_pos.y()); |
+ input_injector_->InjectMouseEvent(modified_event); |
+ } else { |
+ input_injector_->InjectMouseEvent(event); |
+ } |
+} |
+ |
+void SingleWindowInputInjectorMac::InjectClipboardEvent( |
+ const ClipboardEvent& event) { |
+ input_injector_->InjectClipboardEvent(event); |
+} |
+ |
+// This method is used if we are capturing a window instead of a screen. |
Wez
2014/08/07 23:14:33
We're always doing that if this class is used, so
ronakvora do not use
2014/08/08 17:07:13
Yeah. Removed.
|
+// It finds the rectangle of the window we are streaming using |
+// |window_id_|. The InputInjector can then use this rectangle |
+// to translate the input event to coordinates of the window rather |
+// than the screen. |
+CGRect SingleWindowInputInjectorMac::FindCGRectOfWindow() { |
+ CGRect rect; |
+ CGWindowID ids[1] = {window_id_}; |
+ base::ScopedCFTypeRef<CFArrayRef> window_id_array( |
+ CFArrayCreate(NULL, reinterpret_cast<const void **>(&ids), 1, NULL)); |
+ |
+ base::ScopedCFTypeRef<CFArrayRef> window_array( |
+ CGWindowListCreateDescriptionFromArray(window_id_array)); |
+ |
+ if (window_array == NULL || CFArrayGetCount(window_array) == 0) { |
+ // Could not find the window. It might have been closed. |
+ LOG(ERROR) << "Specified window to stream not found for id: " |
+ << window_id_; |
+ return CGRectNull; |
+ } |
+ |
+ // We don't use ScopedCFTypeRef for |window| because the |
+ // CFDictionaryRef returned by CFArrayGetValueAtIndex is owned by |
+ // window_array. The same is true of the |bounds|. |
Wez
2014/08/07 23:14:33
nit: |window_array|
ronakvora do not use
2014/08/08 17:07:13
Done.
|
+ CFDictionaryRef window = |
+ base::mac::CFCast<CFDictionaryRef>( |
+ CFArrayGetValueAtIndex(window_array, 0)); |
+ |
+ if (CFDictionaryContainsKey(window, kCGWindowBounds)) { |
+ CFDictionaryRef bounds = |
+ base::mac::GetValueFromDictionary<CFDictionaryRef>( |
+ window, kCGWindowBounds); |
+ |
+ if (bounds) { |
+ bool success = CGRectMakeWithDictionaryRepresentation(bounds, &rect); |
+ if (success) { |
Wez
2014/08/07 23:14:33
nit: if (CGRectMakeWith...()) { ?
ronakvora do not use
2014/08/08 17:07:14
Done.
|
+ return rect; |
+ } |
+ } |
+ } |
+ |
+ return CGRectNull; |
+} |
+ |
+scoped_ptr<InputInjector> SingleWindowInputInjector::Create( |
+ webrtc::WindowId window_id, |
+ scoped_ptr<InputInjector> input_injector) { |
+ scoped_ptr<SingleWindowInputInjectorMac> injector( |
+ new SingleWindowInputInjectorMac(window_id, input_injector.Pass())); |
+ return injector.PassAs<InputInjector>(); |
+} |
+ |
+ |
+ |
+} // namespace remoting |