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/event_executor.h" | 5 #include "remoting/host/input_injector.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <ApplicationServices/ApplicationServices.h> | 8 #include <ApplicationServices/ApplicationServices.h> |
9 #include <Carbon/Carbon.h> | 9 #include <Carbon/Carbon.h> |
10 | 10 |
11 #include "base/basictypes.h" | 11 #include "base/basictypes.h" |
12 #include "base/bind.h" | 12 #include "base/bind.h" |
13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/mac/scoped_cftyperef.h" | 15 #include "base/mac/scoped_cftyperef.h" |
(...skipping 21 matching lines...) Expand all Loading... |
37 #undef USB_KEYMAP | 37 #undef USB_KEYMAP |
38 | 38 |
39 // skia/ext/skia_utils_mac.h only defines CGRectToSkRect(). | 39 // skia/ext/skia_utils_mac.h only defines CGRectToSkRect(). |
40 SkIRect CGRectToSkIRect(const CGRect& rect) { | 40 SkIRect CGRectToSkIRect(const CGRect& rect) { |
41 SkIRect result; | 41 SkIRect result; |
42 gfx::CGRectToSkRect(rect).round(&result); | 42 gfx::CGRectToSkRect(rect).round(&result); |
43 return result; | 43 return result; |
44 } | 44 } |
45 | 45 |
46 // A class to generate events on Mac. | 46 // A class to generate events on Mac. |
47 class EventExecutorMac : public EventExecutor { | 47 class InputInjectorMac : public InputInjector { |
48 public: | 48 public: |
49 explicit EventExecutorMac( | 49 explicit InputInjectorMac( |
50 scoped_refptr<base::SingleThreadTaskRunner> task_runner); | 50 scoped_refptr<base::SingleThreadTaskRunner> task_runner); |
51 virtual ~EventExecutorMac(); | 51 virtual ~InputInjectorMac(); |
52 | 52 |
53 // ClipboardStub interface. | 53 // ClipboardStub interface. |
54 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; | 54 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; |
55 | 55 |
56 // InputStub interface. | 56 // InputStub interface. |
57 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; | 57 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; |
58 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; | 58 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; |
59 | 59 |
60 // EventExecutor interface. | 60 // InputInjector interface. |
61 virtual void Start( | 61 virtual void Start( |
62 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; | 62 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; |
63 | 63 |
64 private: | 64 private: |
65 // The actual implementation resides in EventExecutorMac::Core class. | 65 // The actual implementation resides in InputInjectorMac::Core class. |
66 class Core : public base::RefCountedThreadSafe<Core> { | 66 class Core : public base::RefCountedThreadSafe<Core> { |
67 public: | 67 public: |
68 explicit Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner); | 68 explicit Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner); |
69 | 69 |
70 // Mirrors the ClipboardStub interface. | 70 // Mirrors the ClipboardStub interface. |
71 void InjectClipboardEvent(const ClipboardEvent& event); | 71 void InjectClipboardEvent(const ClipboardEvent& event); |
72 | 72 |
73 // Mirrors the InputStub interface. | 73 // Mirrors the InputStub interface. |
74 void InjectKeyEvent(const KeyEvent& event); | 74 void InjectKeyEvent(const KeyEvent& event); |
75 void InjectMouseEvent(const MouseEvent& event); | 75 void InjectMouseEvent(const MouseEvent& event); |
76 | 76 |
77 // Mirrors the EventExecutor interface. | 77 // Mirrors the InputInjector interface. |
78 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard); | 78 void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard); |
79 | 79 |
80 void Stop(); | 80 void Stop(); |
81 | 81 |
82 private: | 82 private: |
83 friend class base::RefCountedThreadSafe<Core>; | 83 friend class base::RefCountedThreadSafe<Core>; |
84 virtual ~Core(); | 84 virtual ~Core(); |
85 | 85 |
86 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 86 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
87 SkIPoint mouse_pos_; | 87 SkIPoint mouse_pos_; |
88 uint32 mouse_button_state_; | 88 uint32 mouse_button_state_; |
89 scoped_ptr<Clipboard> clipboard_; | 89 scoped_ptr<Clipboard> clipboard_; |
90 | 90 |
91 DISALLOW_COPY_AND_ASSIGN(Core); | 91 DISALLOW_COPY_AND_ASSIGN(Core); |
92 }; | 92 }; |
93 | 93 |
94 scoped_refptr<Core> core_; | 94 scoped_refptr<Core> core_; |
95 | 95 |
96 DISALLOW_COPY_AND_ASSIGN(EventExecutorMac); | 96 DISALLOW_COPY_AND_ASSIGN(InputInjectorMac); |
97 }; | 97 }; |
98 | 98 |
99 EventExecutorMac::EventExecutorMac( | 99 InputInjectorMac::InputInjectorMac( |
100 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { | 100 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { |
101 core_ = new Core(task_runner); | 101 core_ = new Core(task_runner); |
102 } | 102 } |
103 | 103 |
104 EventExecutorMac::~EventExecutorMac() { | 104 InputInjectorMac::~InputInjectorMac() { |
105 core_->Stop(); | 105 core_->Stop(); |
106 } | 106 } |
107 | 107 |
108 void EventExecutorMac::InjectClipboardEvent(const ClipboardEvent& event) { | 108 void InputInjectorMac::InjectClipboardEvent(const ClipboardEvent& event) { |
109 core_->InjectClipboardEvent(event); | 109 core_->InjectClipboardEvent(event); |
110 } | 110 } |
111 | 111 |
112 void EventExecutorMac::InjectKeyEvent(const KeyEvent& event) { | 112 void InputInjectorMac::InjectKeyEvent(const KeyEvent& event) { |
113 core_->InjectKeyEvent(event); | 113 core_->InjectKeyEvent(event); |
114 } | 114 } |
115 | 115 |
116 void EventExecutorMac::InjectMouseEvent(const MouseEvent& event) { | 116 void InputInjectorMac::InjectMouseEvent(const MouseEvent& event) { |
117 core_->InjectMouseEvent(event); | 117 core_->InjectMouseEvent(event); |
118 } | 118 } |
119 | 119 |
120 void EventExecutorMac::Start( | 120 void InputInjectorMac::Start( |
121 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 121 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
122 core_->Start(client_clipboard.Pass()); | 122 core_->Start(client_clipboard.Pass()); |
123 } | 123 } |
124 | 124 |
125 EventExecutorMac::Core::Core( | 125 InputInjectorMac::Core::Core( |
126 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 126 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
127 : task_runner_(task_runner), | 127 : task_runner_(task_runner), |
128 mouse_button_state_(0), | 128 mouse_button_state_(0), |
129 clipboard_(Clipboard::Create()) { | 129 clipboard_(Clipboard::Create()) { |
130 // Ensure that local hardware events are not suppressed after injecting | 130 // Ensure that local hardware events are not suppressed after injecting |
131 // input events. This allows LocalInputMonitor to detect if the local mouse | 131 // input events. This allows LocalInputMonitor to detect if the local mouse |
132 // is being moved whilst a remote user is connected. | 132 // is being moved whilst a remote user is connected. |
133 // This API is deprecated, but it is needed when using the deprecated | 133 // This API is deprecated, but it is needed when using the deprecated |
134 // injection APIs. | 134 // injection APIs. |
135 // If the non-deprecated injection APIs were used instead, the equivalent of | 135 // If the non-deprecated injection APIs were used instead, the equivalent of |
136 // this line would not be needed, as OS X defaults to _not_ suppressing local | 136 // this line would not be needed, as OS X defaults to _not_ suppressing local |
137 // inputs in that case. | 137 // inputs in that case. |
138 #pragma clang diagnostic push | 138 #pragma clang diagnostic push |
139 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 139 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
140 CGSetLocalEventsSuppressionInterval(0.0); | 140 CGSetLocalEventsSuppressionInterval(0.0); |
141 #pragma clang diagnostic pop | 141 #pragma clang diagnostic pop |
142 } | 142 } |
143 | 143 |
144 void EventExecutorMac::Core::InjectClipboardEvent(const ClipboardEvent& event) { | 144 void InputInjectorMac::Core::InjectClipboardEvent(const ClipboardEvent& event) { |
145 if (!task_runner_->BelongsToCurrentThread()) { | 145 if (!task_runner_->BelongsToCurrentThread()) { |
146 task_runner_->PostTask( | 146 task_runner_->PostTask( |
147 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event)); | 147 FROM_HERE, base::Bind(&Core::InjectClipboardEvent, this, event)); |
148 return; | 148 return; |
149 } | 149 } |
150 | 150 |
151 // |clipboard_| will ignore unknown MIME-types, and verify the data's format. | 151 // |clipboard_| will ignore unknown MIME-types, and verify the data's format. |
152 clipboard_->InjectClipboardEvent(event); | 152 clipboard_->InjectClipboardEvent(event); |
153 } | 153 } |
154 | 154 |
155 void EventExecutorMac::Core::InjectKeyEvent(const KeyEvent& event) { | 155 void InputInjectorMac::Core::InjectKeyEvent(const KeyEvent& event) { |
156 // HostEventDispatcher should filter events missing the pressed field. | 156 // HostEventDispatcher should filter events missing the pressed field. |
157 if (!event.has_pressed() || !event.has_usb_keycode()) | 157 if (!event.has_pressed() || !event.has_usb_keycode()) |
158 return; | 158 return; |
159 | 159 |
160 int keycode = UsbKeycodeToNativeKeycode(event.usb_keycode()); | 160 int keycode = UsbKeycodeToNativeKeycode(event.usb_keycode()); |
161 | 161 |
162 VLOG(3) << "Converting USB keycode: " << std::hex << event.usb_keycode() | 162 VLOG(3) << "Converting USB keycode: " << std::hex << event.usb_keycode() |
163 << " to keycode: " << keycode << std::dec; | 163 << " to keycode: " << keycode << std::dec; |
164 | 164 |
165 // If we couldn't determine the Mac virtual key code then ignore the event. | 165 // If we couldn't determine the Mac virtual key code then ignore the event. |
166 if (keycode == InvalidNativeKeycode()) | 166 if (keycode == InvalidNativeKeycode()) |
167 return; | 167 return; |
168 | 168 |
169 // We use the deprecated event injection API because the new one doesn't | 169 // We use the deprecated event injection API because the new one doesn't |
170 // work with switched-out sessions (curtain mode). | 170 // work with switched-out sessions (curtain mode). |
171 #pragma clang diagnostic push | 171 #pragma clang diagnostic push |
172 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 172 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
173 CGError error = CGPostKeyboardEvent(0, keycode, event.pressed()); | 173 CGError error = CGPostKeyboardEvent(0, keycode, event.pressed()); |
174 #pragma clang diagnostic pop | 174 #pragma clang diagnostic pop |
175 if (error != kCGErrorSuccess) | 175 if (error != kCGErrorSuccess) |
176 LOG(WARNING) << "CGPostKeyboardEvent error " << error; | 176 LOG(WARNING) << "CGPostKeyboardEvent error " << error; |
177 } | 177 } |
178 | 178 |
179 void EventExecutorMac::Core::InjectMouseEvent(const MouseEvent& event) { | 179 void InputInjectorMac::Core::InjectMouseEvent(const MouseEvent& event) { |
180 if (event.has_x() && event.has_y()) { | 180 if (event.has_x() && event.has_y()) { |
181 // On multi-monitor systems (0,0) refers to the top-left of the "main" | 181 // On multi-monitor systems (0,0) refers to the top-left of the "main" |
182 // display, whereas our coordinate scheme places (0,0) at the top-left of | 182 // display, whereas our coordinate scheme places (0,0) at the top-left of |
183 // the bounding rectangle around all the displays, so we need to translate | 183 // the bounding rectangle around all the displays, so we need to translate |
184 // accordingly. | 184 // accordingly. |
185 | 185 |
186 // Set the mouse position assuming single-monitor. | 186 // Set the mouse position assuming single-monitor. |
187 mouse_pos_ = SkIPoint::Make(event.x(), event.y()); | 187 mouse_pos_ = SkIPoint::Make(event.x(), event.y()); |
188 | 188 |
189 // Fetch the desktop configuration. | 189 // Fetch the desktop configuration. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 int delta_x = static_cast<int>(event.wheel_delta_x()); | 252 int delta_x = static_cast<int>(event.wheel_delta_x()); |
253 int delta_y = static_cast<int>(event.wheel_delta_y()); | 253 int delta_y = static_cast<int>(event.wheel_delta_y()); |
254 base::mac::ScopedCFTypeRef<CGEventRef> event( | 254 base::mac::ScopedCFTypeRef<CGEventRef> event( |
255 CGEventCreateScrollWheelEvent( | 255 CGEventCreateScrollWheelEvent( |
256 NULL, kCGScrollEventUnitPixel, 2, delta_y, delta_x)); | 256 NULL, kCGScrollEventUnitPixel, 2, delta_y, delta_x)); |
257 if (event) | 257 if (event) |
258 CGEventPost(kCGSessionEventTap, event); | 258 CGEventPost(kCGSessionEventTap, event); |
259 } | 259 } |
260 } | 260 } |
261 | 261 |
262 void EventExecutorMac::Core::Start( | 262 void InputInjectorMac::Core::Start( |
263 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 263 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
264 if (!task_runner_->BelongsToCurrentThread()) { | 264 if (!task_runner_->BelongsToCurrentThread()) { |
265 task_runner_->PostTask( | 265 task_runner_->PostTask( |
266 FROM_HERE, | 266 FROM_HERE, |
267 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); | 267 base::Bind(&Core::Start, this, base::Passed(&client_clipboard))); |
268 return; | 268 return; |
269 } | 269 } |
270 | 270 |
271 clipboard_->Start(client_clipboard.Pass()); | 271 clipboard_->Start(client_clipboard.Pass()); |
272 } | 272 } |
273 | 273 |
274 void EventExecutorMac::Core::Stop() { | 274 void InputInjectorMac::Core::Stop() { |
275 if (!task_runner_->BelongsToCurrentThread()) { | 275 if (!task_runner_->BelongsToCurrentThread()) { |
276 task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); | 276 task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Stop, this)); |
277 return; | 277 return; |
278 } | 278 } |
279 | 279 |
280 clipboard_->Stop(); | 280 clipboard_->Stop(); |
281 } | 281 } |
282 | 282 |
283 EventExecutorMac::Core::~Core() { | 283 InputInjectorMac::Core::~Core() { |
284 } | 284 } |
285 | 285 |
286 } // namespace | 286 } // namespace |
287 | 287 |
288 scoped_ptr<EventExecutor> EventExecutor::Create( | 288 scoped_ptr<InputInjector> InputInjector::Create( |
289 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 289 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
290 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 290 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
291 return scoped_ptr<EventExecutor>(new EventExecutorMac(main_task_runner)); | 291 return scoped_ptr<InputInjector>(new InputInjectorMac(main_task_runner)); |
292 } | 292 } |
293 | 293 |
294 } // namespace remoting | 294 } // namespace remoting |
OLD | NEW |