Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: remoting/host/event_executor_linux.cc

Issue 10909133: Implement clipboard for Chromoting Linux hosts. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Use desktop thread for clipboard Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698