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 <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include <X11/Xlib.h> | 9 #include <X11/Xlib.h> |
| 10 #include <X11/extensions/XTest.h> | 10 #include <X11/extensions/XTest.h> |
| 11 | 11 |
| 12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
| 15 #include "base/location.h" | 15 #include "base/location.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
| 18 #include "remoting/host/clipboard.h" | |
| 18 #include "remoting/proto/internal.pb.h" | 19 #include "remoting/proto/internal.pb.h" |
| 19 #include "third_party/skia/include/core/SkPoint.h" | 20 #include "third_party/skia/include/core/SkPoint.h" |
| 20 | 21 |
| 21 namespace remoting { | 22 namespace remoting { |
| 22 | 23 |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 using protocol::ClipboardEvent; | 26 using protocol::ClipboardEvent; |
| 26 using protocol::KeyEvent; | 27 using protocol::KeyEvent; |
| 27 using protocol::MouseEvent; | 28 using protocol::MouseEvent; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 46 // InputStub interface. | 47 // InputStub interface. |
| 47 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; | 48 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; |
| 48 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; | 49 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; |
| 49 | 50 |
| 50 // EventExecutor interface. | 51 // EventExecutor interface. |
| 51 virtual void Start( | 52 virtual void Start( |
| 52 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; | 53 scoped_ptr<protocol::ClipboardStub> client_clipboard) OVERRIDE; |
| 53 virtual void StopAndDelete() OVERRIDE; | 54 virtual void StopAndDelete() OVERRIDE; |
| 54 | 55 |
| 55 private: | 56 private: |
| 57 void InitClipboard(); | |
| 58 | |
| 56 // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff, | 59 // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff, |
| 57 // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl() | 60 // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl() |
| 58 // API. | 61 // API. |
| 59 void SetAutoRepeatForKey(int keycode, int mode); | 62 void SetAutoRepeatForKey(int keycode, int mode); |
| 60 void InjectScrollWheelClicks(int button, int count); | 63 void InjectScrollWheelClicks(int button, int count); |
| 61 | 64 |
| 62 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 65 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| 63 | 66 |
| 64 std::set<int> pressed_keys_; | 67 std::set<int> pressed_keys_; |
| 65 SkIPoint latest_mouse_position_; | 68 SkIPoint latest_mouse_position_; |
| 66 | 69 |
| 67 // X11 graphics context. | 70 // X11 graphics context. |
| 68 Display* display_; | 71 Display* display_; |
| 69 Window root_window_; | 72 Window root_window_; |
| 70 | 73 |
| 71 int test_event_base_; | 74 int test_event_base_; |
| 72 int test_error_base_; | 75 int test_error_base_; |
| 73 | 76 |
| 77 scoped_ptr<Clipboard> clipboard_; | |
| 78 | |
| 74 DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux); | 79 DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux); |
| 75 }; | 80 }; |
| 76 | 81 |
| 77 int MouseButtonToX11ButtonNumber(MouseEvent::MouseButton button) { | 82 int MouseButtonToX11ButtonNumber(MouseEvent::MouseButton button) { |
| 78 switch (button) { | 83 switch (button) { |
| 79 case MouseEvent::BUTTON_LEFT: | 84 case MouseEvent::BUTTON_LEFT: |
| 80 return 1; | 85 return 1; |
| 81 | 86 |
| 82 case MouseEvent::BUTTON_RIGHT: | 87 case MouseEvent::BUTTON_RIGHT: |
| 83 return 3; | 88 return 3; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 101 // are wheel scroll-down events (button 5). | 106 // are wheel scroll-down events (button 5). |
| 102 return (dy > 0 ? 4 : 5); | 107 return (dy > 0 ? 4 : 5); |
| 103 } | 108 } |
| 104 | 109 |
| 105 EventExecutorLinux::EventExecutorLinux( | 110 EventExecutorLinux::EventExecutorLinux( |
| 106 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 111 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
| 107 : task_runner_(task_runner), | 112 : task_runner_(task_runner), |
| 108 latest_mouse_position_(SkIPoint::Make(-1, -1)), | 113 latest_mouse_position_(SkIPoint::Make(-1, -1)), |
| 109 display_(XOpenDisplay(NULL)), | 114 display_(XOpenDisplay(NULL)), |
| 110 root_window_(BadValue) { | 115 root_window_(BadValue) { |
| 116 if (!task_runner_->BelongsToCurrentThread()) { | |
| 117 task_runner_->PostTask( | |
| 118 FROM_HERE, | |
| 119 base::Bind(&EventExecutorLinux::InitClipboard, base::Unretained(this))); | |
| 120 } | |
| 111 } | 121 } |
| 112 | 122 |
| 113 EventExecutorLinux::~EventExecutorLinux() { | 123 EventExecutorLinux::~EventExecutorLinux() { |
| 114 CHECK(pressed_keys_.empty()); | 124 CHECK(pressed_keys_.empty()); |
| 115 } | 125 } |
| 116 | 126 |
| 117 bool EventExecutorLinux::Init() { | 127 bool EventExecutorLinux::Init() { |
| 118 CHECK(display_); | 128 CHECK(display_); |
| 119 | 129 |
| 120 root_window_ = RootWindow(display_, DefaultScreen(display_)); | 130 root_window_ = RootWindow(display_, DefaultScreen(display_)); |
| 121 if (root_window_ == BadValue) { | 131 if (root_window_ == BadValue) { |
| 122 LOG(ERROR) << "Unable to get the root window"; | 132 LOG(ERROR) << "Unable to get the root window"; |
| 123 return false; | 133 return false; |
| 124 } | 134 } |
| 125 | 135 |
| 126 // TODO(ajwong): Do we want to check the major/minor version at all for XTest? | 136 // TODO(ajwong): Do we want to check the major/minor version at all for XTest? |
| 127 int major = 0; | 137 int major = 0; |
| 128 int minor = 0; | 138 int minor = 0; |
| 129 if (!XTestQueryExtension(display_, &test_event_base_, &test_error_base_, | 139 if (!XTestQueryExtension(display_, &test_event_base_, &test_error_base_, |
| 130 &major, &minor)) { | 140 &major, &minor)) { |
| 131 LOG(ERROR) << "Server does not support XTest."; | 141 LOG(ERROR) << "Server does not support XTest."; |
| 132 return false; | 142 return false; |
| 133 } | 143 } |
| 134 | 144 |
| 135 return true; | 145 return true; |
| 136 } | 146 } |
| 137 | 147 |
| 138 void EventExecutorLinux::InjectClipboardEvent(const ClipboardEvent& event) { | 148 void EventExecutorLinux::InjectClipboardEvent(const ClipboardEvent& event) { |
| 139 // TODO(simonmorris): Implement clipboard injection. | 149 if (!task_runner_->BelongsToCurrentThread()) { |
| 150 task_runner_->PostTask( | |
| 151 FROM_HERE, | |
| 152 base::Bind(&EventExecutorLinux::InjectClipboardEvent, | |
| 153 base::Unretained(this), event)); | |
| 154 return; | |
| 155 } | |
| 156 | |
| 157 clipboard_->InjectClipboardEvent(event); | |
| 140 } | 158 } |
| 141 | 159 |
| 142 void EventExecutorLinux::InjectKeyEvent(const KeyEvent& event) { | 160 void EventExecutorLinux::InjectKeyEvent(const KeyEvent& event) { |
| 143 // HostEventDispatcher should filter events missing the pressed field. | 161 // HostEventDispatcher should filter events missing the pressed field. |
| 144 DCHECK(event.has_pressed()); | 162 DCHECK(event.has_pressed()); |
| 145 DCHECK(event.has_usb_keycode()); | 163 DCHECK(event.has_usb_keycode()); |
| 146 | 164 |
| 147 if (!task_runner_->BelongsToCurrentThread()) { | 165 if (!task_runner_->BelongsToCurrentThread()) { |
| 148 task_runner_->PostTask( | 166 task_runner_->PostTask( |
| 149 FROM_HERE, | 167 FROM_HERE, |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 179 // case, this ensures that key-repeating will continue to work normally | 197 // case, this ensures that key-repeating will continue to work normally |
| 180 // for the local user of the host machine. "ModeDefault" is used instead | 198 // for the local user of the host machine. "ModeDefault" is used instead |
| 181 // of "ModeOn", since some keys (such as Shift) should not auto-repeat. | 199 // of "ModeOn", since some keys (such as Shift) should not auto-repeat. |
| 182 SetAutoRepeatForKey(keycode, AutoRepeatModeDefault); | 200 SetAutoRepeatForKey(keycode, AutoRepeatModeDefault); |
| 183 } | 201 } |
| 184 | 202 |
| 185 XTestFakeKeyEvent(display_, keycode, event.pressed(), CurrentTime); | 203 XTestFakeKeyEvent(display_, keycode, event.pressed(), CurrentTime); |
| 186 XFlush(display_); | 204 XFlush(display_); |
| 187 } | 205 } |
| 188 | 206 |
| 207 void EventExecutorLinux::InitClipboard() { | |
| 208 clipboard_ = Clipboard::Create(); | |
|
Sergey Ulanov
2012/09/14 19:35:01
thread DCHECK please.
Lambros
2012/09/14 21:35:13
Done.
| |
| 209 } | |
| 210 | |
| 189 void EventExecutorLinux::SetAutoRepeatForKey(int keycode, int mode) { | 211 void EventExecutorLinux::SetAutoRepeatForKey(int keycode, int mode) { |
| 190 XKeyboardControl control; | 212 XKeyboardControl control; |
| 191 control.key = keycode; | 213 control.key = keycode; |
| 192 control.auto_repeat_mode = mode; | 214 control.auto_repeat_mode = mode; |
| 193 XChangeKeyboardControl(display_, KBKey | KBAutoRepeatMode, &control); | 215 XChangeKeyboardControl(display_, KBKey | KBAutoRepeatMode, &control); |
| 194 } | 216 } |
| 195 | 217 |
| 196 void EventExecutorLinux::InjectScrollWheelClicks(int button, int count) { | 218 void EventExecutorLinux::InjectScrollWheelClicks(int button, int count) { |
| 197 for (int i = 0; i < count; i++) { | 219 for (int i = 0; i < count; i++) { |
| 198 // Generate a button-down and a button-up to simulate a wheel click. | 220 // Generate a button-down and a button-up to simulate a wheel click. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 int dx = event.wheel_offset_x(); | 278 int dx = event.wheel_offset_x(); |
| 257 InjectScrollWheelClicks(HorizontalScrollWheelToX11ButtonNumber(dx), | 279 InjectScrollWheelClicks(HorizontalScrollWheelToX11ButtonNumber(dx), |
| 258 abs(dx)); | 280 abs(dx)); |
| 259 } | 281 } |
| 260 | 282 |
| 261 XFlush(display_); | 283 XFlush(display_); |
| 262 } | 284 } |
| 263 | 285 |
| 264 void EventExecutorLinux::Start( | 286 void EventExecutorLinux::Start( |
| 265 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | 287 scoped_ptr<protocol::ClipboardStub> client_clipboard) { |
| 266 return; | 288 if (!task_runner_->BelongsToCurrentThread()) { |
| 289 task_runner_->PostTask( | |
| 290 FROM_HERE, | |
| 291 base::Bind(&EventExecutorLinux::Start, base::Unretained(this), | |
| 292 base::Passed(client_clipboard.Pass()))); | |
|
Sergey Ulanov
2012/09/14 19:35:01
FYI: alternative, slightly shorter syntax is base:
Lambros
2012/09/14 21:35:13
This got changed to the shorter syntax when I reba
| |
| 293 return; | |
| 294 } | |
| 295 | |
| 296 clipboard_->Start(client_clipboard.Pass()); | |
| 267 } | 297 } |
| 268 | 298 |
| 269 void EventExecutorLinux::StopAndDelete() { | 299 void EventExecutorLinux::StopAndDelete() { |
| 270 delete this; | 300 delete this; |
| 271 } | 301 } |
| 272 | 302 |
| 273 } // namespace | 303 } // namespace |
| 274 | 304 |
| 275 scoped_ptr<EventExecutor> EventExecutor::Create( | 305 scoped_ptr<EventExecutor> EventExecutor::Create( |
| 276 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | 306 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, |
| 277 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { | 307 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { |
| 278 scoped_ptr<EventExecutorLinux> executor( | 308 scoped_ptr<EventExecutorLinux> executor( |
| 279 new EventExecutorLinux(main_task_runner)); | 309 new EventExecutorLinux(main_task_runner)); |
| 280 if (!executor->Init()) | 310 if (!executor->Init()) |
| 281 return scoped_ptr<EventExecutor>(NULL); | 311 return scoped_ptr<EventExecutor>(NULL); |
| 282 return executor.PassAs<EventExecutor>(); | 312 return executor.PassAs<EventExecutor>(); |
| 283 } | 313 } |
| 284 | 314 |
| 285 } // namespace remoting | 315 } // namespace remoting |
| OLD | NEW |