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

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

Issue 6780014: Clean up remoting project (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix a compile glitch on Windows Created 9 years, 8 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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_linux.h" 5 #include "remoting/host/event_executor.h"
6 6
7 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #include <X11/XF86keysym.h> 8 #include <X11/XF86keysym.h>
9 #include <X11/keysym.h> 9 #include <X11/keysym.h>
10 #include <X11/extensions/XTest.h> 10 #include <X11/extensions/XTest.h>
11 11
12 #include "base/compiler_specific.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/message_loop.h" 14 #include "base/message_loop.h"
14 #include "base/task.h" 15 #include "base/task.h"
15 #include "remoting/proto/internal.pb.h" 16 #include "remoting/proto/internal.pb.h"
16 17
17 namespace remoting { 18 namespace remoting {
18 19
19 using protocol::MouseEvent; 20 using protocol::MouseEvent;
20 using protocol::KeyEvent; 21 using protocol::KeyEvent;
21 22
22 static int MouseButtonToX11ButtonNumber( 23 namespace {
23 protocol::MouseEvent::MouseButton button) { 24
25 // A class to generate events on Linux.
26 class EventExecutorLinux : public EventExecutor {
27 public:
28 EventExecutorLinux(MessageLoopForUI* message_loop, Capturer* capturer);
29 virtual ~EventExecutorLinux() {};
30
31 virtual void InjectKeyEvent(const KeyEvent* event, Task* done) OVERRIDE;
32 virtual void InjectMouseEvent(const MouseEvent* event, Task* done) OVERRIDE;
33
34 private:
35 bool Init();
36 MessageLoopForUI* message_loop_;
37 Capturer* capturer_;
38
39 // X11 graphics context.
40 Display* display_;
41 Window root_window_;
42 int width_;
43 int height_;
44
45 int test_event_base_;
46 int test_error_base_;
47
48 DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux);
49 };
50
51 int MouseButtonToX11ButtonNumber(MouseEvent::MouseButton button) {
24 switch (button) { 52 switch (button) {
25 case MouseEvent::BUTTON_LEFT: 53 case MouseEvent::BUTTON_LEFT:
26 return 1; 54 return 1;
27 55
28 case MouseEvent::BUTTON_RIGHT: 56 case MouseEvent::BUTTON_RIGHT:
29 return 3; 57 return 3;
30 58
31 case MouseEvent::BUTTON_MIDDLE: 59 case MouseEvent::BUTTON_MIDDLE:
32 return 2; 60 return 2;
33 61
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 -1, -1, -1, -1, 217 -1, -1, -1, -1,
190 // 0xF4 - 0xF7 218 // 0xF4 - 0xF7
191 -1, -1, /* VKEY_ATTN */ -1, /* VKEY_CRSEL */ -1, 219 -1, -1, /* VKEY_ATTN */ -1, /* VKEY_CRSEL */ -1,
192 // 0xF8 - 0xFB 220 // 0xF8 - 0xFB
193 /* VKEY_EXSEL */ -1, /* VKEY_EREOF */ -1, /* VKEY_PLAY */ -1, 221 /* VKEY_EXSEL */ -1, /* VKEY_EREOF */ -1, /* VKEY_PLAY */ -1,
194 /* VKEY_ZOOM */ -1, 222 /* VKEY_ZOOM */ -1,
195 // 0xFC - 0xFF 223 // 0xFC - 0xFF
196 /* VKEY_NONAME */ -1, /* VKEY_PA1 */ -1, /* VKEY_OEM_CLEAR */ -1, -1 224 /* VKEY_NONAME */ -1, /* VKEY_PA1 */ -1, /* VKEY_OEM_CLEAR */ -1, -1
197 }; 225 };
198 226
199 static int ChromotocolKeycodeToX11Keysym(int32_t keycode) { 227 int ChromotocolKeycodeToX11Keysym(int32_t keycode) {
200 if (keycode < 0 || keycode > 255) { 228 if (keycode < 0 || keycode > 255) {
201 return -1; 229 return -1;
202 } 230 }
203 231
204 return kUsVkeyToKeysym[keycode]; 232 return kUsVkeyToKeysym[keycode];
205 } 233 }
206 234
207 class EventExecutorLinuxPimpl { 235 EventExecutorLinux::EventExecutorLinux(
208 public: 236 MessageLoopForUI* message_loop, Capturer* capturer)
209 explicit EventExecutorLinuxPimpl(EventExecutorLinux* executor, 237 : message_loop_(message_loop),
210 Display* display); 238 capturer_(capturer),
211 239 display_(message_loop->GetDisplay()),
212 bool Init(); // TODO(ajwong): Do we really want this to be synchronous?
213
214 void HandleMouse(const MouseEvent* message);
215 void HandleKey(const KeyEvent* key_event);
216
217 private:
218 // Reference to containing class so we can access friend functions.
219 // Not owned.
220 EventExecutorLinux* executor_;
221
222 // X11 graphics context.
223 Display* display_;
224 Window root_window_;
225 int width_;
226 int height_;
227
228 int test_event_base_;
229 int test_error_base_;
230 };
231
232 EventExecutorLinuxPimpl::EventExecutorLinuxPimpl(EventExecutorLinux* executor,
233 Display* display)
234 : executor_(executor),
235 display_(display),
236 root_window_(BadValue), 240 root_window_(BadValue),
237 width_(0), 241 width_(0),
238 height_(0) { 242 height_(0) {
243 CHECK(Init());
239 } 244 }
240 245
241 bool EventExecutorLinuxPimpl::Init() { 246 bool EventExecutorLinux::Init() {
242 CHECK(display_); 247 CHECK(display_);
243 248
244 root_window_ = RootWindow(display_, DefaultScreen(display_)); 249 root_window_ = RootWindow(display_, DefaultScreen(display_));
245 if (root_window_ == BadValue) { 250 if (root_window_ == BadValue) {
246 LOG(ERROR) << "Unable to get the root window"; 251 LOG(ERROR) << "Unable to get the root window";
247 return false; 252 return false;
248 } 253 }
249 254
250 // TODO(ajwong): Do we want to check the major/minor version at all for XTest? 255 // TODO(ajwong): Do we want to check the major/minor version at all for XTest?
251 int major = 0; 256 int major = 0;
252 int minor = 0; 257 int minor = 0;
253 if (!XTestQueryExtension(display_, &test_event_base_, &test_error_base_, 258 if (!XTestQueryExtension(display_, &test_event_base_, &test_error_base_,
254 &major, &minor)) { 259 &major, &minor)) {
255 LOG(ERROR) << "Server does not support XTest."; 260 LOG(ERROR) << "Server does not support XTest.";
256 return false; 261 return false;
257 } 262 }
258 263
259 // Grab the width and height so we can figure out if mouse moves are out of 264 // Grab the width and height so we can figure out if mouse moves are out of
260 // range. 265 // range.
261 XWindowAttributes root_attr; 266 XWindowAttributes root_attr;
262 // TODO(ajwong): Handle resolution changes. 267 // TODO(ajwong): Handle resolution changes.
263 if (!XGetWindowAttributes(display_, root_window_, &root_attr)) { 268 if (!XGetWindowAttributes(display_, root_window_, &root_attr)) {
264 LOG(ERROR) << "Unable to get window attributes"; 269 LOG(ERROR) << "Unable to get window attributes";
265 return false; 270 return false;
266 } 271 }
267 272
268 width_ = root_attr.width; 273 width_ = root_attr.width;
269 height_ = root_attr.height; 274 height_ = root_attr.height;
270
271 return true; 275 return true;
272 } 276 }
273 277
274 void EventExecutorLinuxPimpl::HandleKey(const KeyEvent* key_event) { 278 void EventExecutorLinux::InjectKeyEvent(const KeyEvent* event, Task* done) {
279 if (MessageLoop::current() != message_loop_) {
280 message_loop_->PostTask(
281 FROM_HERE,
282 NewRunnableMethod(this, &EventExecutorLinux::InjectKeyEvent,
283 event, done));
284 return;
285 }
275 // TODO(ajwong): This will only work for QWERTY keyboards. 286 // TODO(ajwong): This will only work for QWERTY keyboards.
276 int keysym = ChromotocolKeycodeToX11Keysym(key_event->keycode()); 287 int keysym = ChromotocolKeycodeToX11Keysym(event->keycode());
277 288
278 if (keysym == -1) { 289 if (keysym == -1) {
279 LOG(WARNING) << "Ignoring unknown key: " << key_event->keycode(); 290 LOG(WARNING) << "Ignoring unknown key: " << event->keycode();
280 return; 291 return;
281 } 292 }
282 293
283 // Translate the keysym into a keycode understandable by the X display. 294 // Translate the keysym into a keycode understandable by the X display.
284 int keycode = XKeysymToKeycode(display_, keysym); 295 int keycode = XKeysymToKeycode(display_, keysym);
285 if (keycode == 0) { 296 if (keycode == 0) {
286 LOG(WARNING) << "Ignoring undefined keysym: " << keysym 297 LOG(WARNING) << "Ignoring undefined keysym: " << keysym
287 << " for key: " << key_event->keycode(); 298 << " for key: " << event->keycode();
288 return; 299 return;
289 } 300 }
290 301
291 VLOG(3) << "Got pepper key: " << key_event->keycode() 302 VLOG(3) << "Got pepper key: " << event->keycode()
292 << " sending keysym: " << keysym 303 << " sending keysym: " << keysym
293 << " to keycode: " << keycode; 304 << " to keycode: " << keycode;
294 XTestFakeKeyEvent(display_, keycode, key_event->pressed(), CurrentTime); 305 XTestFakeKeyEvent(display_, keycode, event->pressed(), CurrentTime);
306
307 done->Run();
308 delete done;
295 } 309 }
296 310
297 void EventExecutorLinuxPimpl::HandleMouse(const MouseEvent* event) { 311 void EventExecutorLinux::InjectMouseEvent(const MouseEvent* event,
312 Task* done) {
313 if (MessageLoop::current() != message_loop_) {
314 message_loop_->PostTask(
315 FROM_HERE,
316 NewRunnableMethod(this, &EventExecutorLinux::InjectMouseEvent,
317 event, done));
318 return;
319 }
298 if (event->has_x() && event->has_y()) { 320 if (event->has_x() && event->has_y()) {
299 if (event->x() < 0 || event->y() < 0 || 321 if (event->x() < 0 || event->y() < 0 ||
300 event->x() > width_ || event->y() > height_) { 322 event->x() > width_ || event->y() > height_) {
301 // A misbehaving client may send these. Drop events that are out of range. 323 // A misbehaving client may send these. Drop events that are out of range.
302 // TODO(ajwong): How can we log this sanely? We don't want to DOS the 324 // TODO(ajwong): How can we log this sanely? We don't want to DOS the
303 // server with a misbehaving client by logging like crazy. 325 // server with a misbehaving client by logging like crazy.
304 return; 326 return;
305 } 327 }
306 328
307 VLOG(3) << "Moving mouse to " << event->x() 329 VLOG(3) << "Moving mouse to " << event->x()
(...skipping 14 matching lines...) Expand all
322 344
323 VLOG(3) << "Button " << event->button() 345 VLOG(3) << "Button " << event->button()
324 << " received, sending down " << button_number; 346 << " received, sending down " << button_number;
325 XTestFakeButtonEvent(display_, button_number, event->button_down(), 347 XTestFakeButtonEvent(display_, button_number, event->button_down(),
326 CurrentTime); 348 CurrentTime);
327 } 349 }
328 350
329 if (event->has_wheel_offset_x() && event->has_wheel_offset_y()) { 351 if (event->has_wheel_offset_x() && event->has_wheel_offset_y()) {
330 NOTIMPLEMENTED() << "No scroll wheel support yet."; 352 NOTIMPLEMENTED() << "No scroll wheel support yet.";
331 } 353 }
332 }
333 354
334 EventExecutorLinux::EventExecutorLinux(
335 MessageLoopForUI* message_loop, Capturer* capturer)
336 : message_loop_(message_loop),
337 capturer_(capturer),
338 pimpl_(new EventExecutorLinuxPimpl(this, message_loop->GetDisplay())) {
339 CHECK(pimpl_->Init());
340 }
341
342 EventExecutorLinux::~EventExecutorLinux() {
343 }
344
345 void EventExecutorLinux::InjectKeyEvent(const KeyEvent* event, Task* done) {
346 if (MessageLoop::current() != message_loop_) {
347 message_loop_->PostTask(
348 FROM_HERE,
349 NewRunnableMethod(this, &EventExecutorLinux::InjectKeyEvent,
350 event, done));
351 return;
352 }
353 pimpl_->HandleKey(event);
354 done->Run(); 355 done->Run();
355 delete done; 356 delete done;
356 } 357 }
357 358
358 void EventExecutorLinux::InjectMouseEvent(const MouseEvent* event, 359 } // namespace
359 Task* done) {
360 if (MessageLoop::current() != message_loop_) {
361 message_loop_->PostTask(
362 FROM_HERE,
363 NewRunnableMethod(this, &EventExecutorLinux::InjectMouseEvent,
364 event, done));
365 return;
366 }
367 pimpl_->HandleMouse(event);
368 done->Run();
369 delete done;
370 }
371 360
372 protocol::InputStub* CreateEventExecutor(MessageLoopForUI* message_loop, 361 EventExecutor* EventExecutor::Create(MessageLoopForUI* message_loop,
373 Capturer* capturer) { 362 Capturer* capturer) {
374 return new EventExecutorLinux(message_loop, capturer); 363 return new EventExecutorLinux(message_loop, capturer);
375 } 364 }
376 365
377 } // namespace remoting 366 } // namespace remoting
367
368 DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::EventExecutorLinux);
Lambros 2011/04/01 15:54:00 Is this OK here? Do we know this object will outl
dmac 2011/04/01 21:15:07 This is how it was before. I just moved the macro.
369
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698