Chromium Code Reviews| 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 |