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