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/event_executor.h" |
6 | 6 |
7 #include <ApplicationServices/ApplicationServices.h> | 7 #include <ApplicationServices/ApplicationServices.h> |
8 #include <Carbon/Carbon.h> | 8 #include <Carbon/Carbon.h> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/mac/scoped_cftyperef.h" | 12 #include "base/mac/scoped_cftyperef.h" |
13 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
14 #include "remoting/host/capturer.h" | |
15 #include "remoting/proto/internal.pb.h" | 14 #include "remoting/proto/internal.pb.h" |
16 #include "remoting/protocol/message_decoder.h" | 15 #include "remoting/protocol/message_decoder.h" |
17 | 16 |
18 namespace remoting { | 17 namespace remoting { |
19 | 18 |
20 namespace { | 19 namespace { |
21 | 20 |
22 using protocol::ClipboardEvent; | 21 using protocol::ClipboardEvent; |
23 using protocol::KeyEvent; | 22 using protocol::KeyEvent; |
24 using protocol::MouseEvent; | 23 using protocol::MouseEvent; |
25 | 24 |
26 // USB to Mac keycode mapping table. | 25 // USB to Mac keycode mapping table. |
27 #define USB_KEYMAP(usb, xkb, win, mac) {usb, mac} | 26 #define USB_KEYMAP(usb, xkb, win, mac) {usb, mac} |
28 #include "remoting/host/usb_keycode_map.h" | 27 #include "remoting/host/usb_keycode_map.h" |
29 #undef USB_KEYMAP | 28 #undef USB_KEYMAP |
30 | 29 |
31 // A class to generate events on Mac. | 30 // A class to generate events on Mac. |
32 class EventExecutorMac : public EventExecutor { | 31 class EventExecutorMac : public EventExecutor { |
33 public: | 32 public: |
34 EventExecutorMac(MessageLoop* message_loop, Capturer* capturer); | 33 EventExecutorMac(MessageLoop* message_loop); |
35 virtual ~EventExecutorMac() {} | 34 virtual ~EventExecutorMac() {} |
36 | 35 |
37 // ClipboardStub interface. | 36 // ClipboardStub interface. |
38 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; | 37 virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE; |
39 | 38 |
40 // InputStub interface. | 39 // InputStub interface. |
41 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; | 40 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; |
42 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; | 41 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; |
43 | 42 |
44 private: | 43 private: |
45 MessageLoop* message_loop_; | 44 MessageLoop* message_loop_; |
46 Capturer* capturer_; | 45 SkIPoint mouse_pos_; |
47 int last_x_, last_y_; | 46 uint32 mouse_button_state_; |
48 int mouse_buttons_; | |
49 | 47 |
50 DISALLOW_COPY_AND_ASSIGN(EventExecutorMac); | 48 DISALLOW_COPY_AND_ASSIGN(EventExecutorMac); |
51 }; | 49 }; |
52 | 50 |
53 EventExecutorMac::EventExecutorMac( | 51 EventExecutorMac::EventExecutorMac( |
54 MessageLoop* message_loop, Capturer* capturer) | 52 MessageLoop* message_loop) |
55 : message_loop_(message_loop), | 53 : message_loop_(message_loop), mouse_button_state_(0) { |
56 capturer_(capturer), last_x_(0), last_y_(0), mouse_buttons_(0) { | |
57 } | 54 } |
58 | 55 |
59 // Hard-coded mapping from Virtual Key codes to Mac KeySyms. | 56 // Hard-coded mapping from Virtual Key codes to Mac KeySyms. |
60 // This mapping is only valid if both client and host are using a | 57 // This mapping is only valid if both client and host are using a |
61 // US English keyboard layout. | 58 // US English keyboard layout. |
62 // Because we're passing VK codes on the wire, with no Scancode, | 59 // Because we're passing VK codes on the wire, with no Scancode, |
63 // "extended" flag, etc, things like distinguishing left & right | 60 // "extended" flag, etc, things like distinguishing left & right |
64 // Shift keys doesn't work. | 61 // Shift keys doesn't work. |
65 // | 62 // |
66 // TODO(wez): Replace this with something more closely tied to what | 63 // TODO(wez): Replace this with something more closely tied to what |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
267 // We use the deprecated event injection API because the new one doesn't | 264 // We use the deprecated event injection API because the new one doesn't |
268 // work with switched-out sessions (curtain mode). | 265 // work with switched-out sessions (curtain mode). |
269 CGError error = CGPostKeyboardEvent(0, keycode, event.pressed()); | 266 CGError error = CGPostKeyboardEvent(0, keycode, event.pressed()); |
270 if (error != kCGErrorSuccess) { | 267 if (error != kCGErrorSuccess) { |
271 LOG(WARNING) << "CGPostKeyboardEvent error " << error; | 268 LOG(WARNING) << "CGPostKeyboardEvent error " << error; |
272 } | 269 } |
273 } | 270 } |
274 | 271 |
275 void EventExecutorMac::InjectMouseEvent(const MouseEvent& event) { | 272 void EventExecutorMac::InjectMouseEvent(const MouseEvent& event) { |
276 if (event.has_x() && event.has_y()) { | 273 if (event.has_x() && event.has_y()) { |
277 // TODO(wez): Checking the validity of the MouseEvent should be done in core | |
278 // cross-platform code, not here! | |
279 // TODO(wez): This code assumes that MouseEvent(0,0) (top-left of client vie w) | 274 // TODO(wez): This code assumes that MouseEvent(0,0) (top-left of client vie w) |
280 // corresponds to local (0,0) (top-left of primary monitor). That won't in | 275 // corresponds to local (0,0) (top-left of primary monitor). That won't in |
281 // general be true on multi-monitor systems, though. | 276 // general be true on multi-monitor systems, though. |
282 SkISize size = capturer_->size_most_recent(); | 277 VLOG(3) << "Moving mouse to " << event.x() << "," << event.y(); |
283 if (event.x() >= 0 || event.y() >= 0 || | 278 mouse_pos_ = SkIPoint::MakeXY(event.x(), event.y()); |
284 event.x() < size.width() || event.y() < size.height()) { | |
Wez
2012/04/27 17:39:51
Ditto re CHECK()ing here, and in the Windows imple
| |
285 VLOG(3) << "Moving mouse to " << event.x() << "," << event.y(); | |
286 last_x_ = event.x(); | |
287 last_y_ = event.y(); | |
288 } else { | |
289 VLOG(1) << "Invalid mouse position " << event.x() << "," << event.y(); | |
290 } | |
291 } | 279 } |
292 if (event.has_button() && event.has_button_down()) { | 280 if (event.has_button() && event.has_button_down()) { |
293 if (event.button() >= 1 && event.button() <= 3) { | 281 if (event.button() >= 1 && event.button() <= 3) { |
294 VLOG(2) << "Button " << event.button() | 282 VLOG(2) << "Button " << event.button() |
295 << (event.button_down() ? " down" : " up"); | 283 << (event.button_down() ? " down" : " up"); |
296 int button_change = 1 << (event.button() - 1); | 284 int button_change = 1 << (event.button() - 1); |
297 if (event.button_down()) | 285 if (event.button_down()) |
298 mouse_buttons_ |= button_change; | 286 mouse_button_state_ |= button_change; |
299 else | 287 else |
300 mouse_buttons_ &= ~button_change; | 288 mouse_button_state_ &= ~button_change; |
301 } else { | 289 } else { |
302 VLOG(1) << "Unknown mouse button: " << event.button(); | 290 VLOG(1) << "Unknown mouse button: " << event.button(); |
303 } | 291 } |
304 } | 292 } |
305 // We use the deprecated CGPostMouseEvent API because we receive low-level | 293 // We use the deprecated CGPostMouseEvent API because we receive low-level |
306 // mouse events, whereas CGEventCreateMouseEvent is for injecting higher-level | 294 // mouse events, whereas CGEventCreateMouseEvent is for injecting higher-level |
307 // events. For example, the deprecated APIs will detect double-clicks or drags | 295 // events. For example, the deprecated APIs will detect double-clicks or drags |
308 // in a way that is consistent with how they would be generated using a local | 296 // in a way that is consistent with how they would be generated using a local |
309 // mouse, whereas the new APIs expect us to inject these higher-level events | 297 // mouse, whereas the new APIs expect us to inject these higher-level events |
310 // directly. | 298 // directly. |
311 CGPoint position = CGPointMake(last_x_, last_y_); | 299 CGPoint position = CGPointMake(mouse_pos_.x(), mouse_pos_.y()); |
312 enum { | 300 enum { |
313 LeftBit = 1 << (MouseEvent::BUTTON_LEFT - 1), | 301 LeftBit = 1 << (MouseEvent::BUTTON_LEFT - 1), |
314 MiddleBit = 1 << (MouseEvent::BUTTON_MIDDLE - 1), | 302 MiddleBit = 1 << (MouseEvent::BUTTON_MIDDLE - 1), |
315 RightBit = 1 << (MouseEvent::BUTTON_RIGHT - 1) | 303 RightBit = 1 << (MouseEvent::BUTTON_RIGHT - 1) |
316 }; | 304 }; |
317 CGError error = CGPostMouseEvent(position, true, 3, | 305 CGError error = CGPostMouseEvent(position, true, 3, |
318 (mouse_buttons_ & LeftBit) != 0, | 306 (mouse_button_state_ & LeftBit) != 0, |
319 (mouse_buttons_ & RightBit) != 0, | 307 (mouse_button_state_ & RightBit) != 0, |
320 (mouse_buttons_ & MiddleBit) != 0); | 308 (mouse_button_state_ & MiddleBit) != 0); |
321 if (error != kCGErrorSuccess) { | 309 if (error != kCGErrorSuccess) { |
322 LOG(WARNING) << "CGPostMouseEvent error " << error; | 310 LOG(WARNING) << "CGPostMouseEvent error " << error; |
323 } | 311 } |
324 | 312 |
325 if (event.has_wheel_offset_x() && event.has_wheel_offset_y()) { | 313 if (event.has_wheel_offset_x() && event.has_wheel_offset_y()) { |
326 int dx = event.wheel_offset_x(); | 314 int dx = event.wheel_offset_x(); |
327 int dy = event.wheel_offset_y(); | 315 int dy = event.wheel_offset_y(); |
328 // Note that |dy| (the vertical wheel) is the primary wheel. | 316 // Note that |dy| (the vertical wheel) is the primary wheel. |
329 error = CGPostScrollWheelEvent(2, dy, dx); | 317 error = CGPostScrollWheelEvent(2, dy, dx); |
330 if (error != kCGErrorSuccess) { | 318 if (error != kCGErrorSuccess) { |
331 LOG(WARNING) << "CGPostScrollWheelEvent error " << error; | 319 LOG(WARNING) << "CGPostScrollWheelEvent error " << error; |
332 } | 320 } |
333 } | 321 } |
334 } | 322 } |
335 | 323 |
336 } // namespace | 324 } // namespace |
337 | 325 |
338 scoped_ptr<protocol::HostEventStub> EventExecutor::Create( | 326 scoped_ptr<protocol::HostEventStub> EventExecutor::Create( |
339 MessageLoop* message_loop, Capturer* capturer) { | 327 MessageLoop* message_loop, Capturer* capturer) { |
340 return scoped_ptr<protocol::HostEventStub>( | 328 return scoped_ptr<protocol::HostEventStub>( |
341 new EventExecutorMac(message_loop, capturer)); | 329 new EventExecutorMac(message_loop)); |
342 } | 330 } |
343 | 331 |
344 } // namespace remoting | 332 } // namespace remoting |
OLD | NEW |