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

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

Issue 10255007: Clamp events before they are sent to EventExecutors. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix typo. Created 8 years, 7 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
« no previous file with comments | « remoting/host/client_session.cc ('k') | remoting/host/event_executor_mac.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/XF86keysym.h> 10 #include <X11/XF86keysym.h>
(...skipping 16 matching lines...) Expand all
27 using protocol::MouseEvent; 27 using protocol::MouseEvent;
28 28
29 // USB to XKB keycode map table. 29 // USB to XKB keycode map table.
30 #define USB_KEYMAP(usb, xkb, win, mac) {usb, xkb} 30 #define USB_KEYMAP(usb, xkb, win, mac) {usb, xkb}
31 #include "remoting/host/usb_keycode_map.h" 31 #include "remoting/host/usb_keycode_map.h"
32 #undef USB_KEYMAP 32 #undef USB_KEYMAP
33 33
34 // A class to generate events on Linux. 34 // A class to generate events on Linux.
35 class EventExecutorLinux : public EventExecutor { 35 class EventExecutorLinux : public EventExecutor {
36 public: 36 public:
37 EventExecutorLinux(MessageLoop* message_loop, Capturer* capturer); 37 EventExecutorLinux(MessageLoop* message_loop);
38 virtual ~EventExecutorLinux(); 38 virtual ~EventExecutorLinux();
39 39
40 bool Init(); 40 bool Init();
41 41
42 // Clipboard stub interface. 42 // Clipboard stub interface.
43 virtual void InjectClipboardEvent(const ClipboardEvent& event) 43 virtual void InjectClipboardEvent(const ClipboardEvent& event)
44 OVERRIDE; 44 OVERRIDE;
45 45
46 // InputStub interface. 46 // InputStub interface.
47 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; 47 virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
48 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; 48 virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
49 49
50 private: 50 private:
51 // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff, 51 // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff,
52 // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl() 52 // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl()
53 // API. 53 // API.
54 void SetAutoRepeatForKey(int keycode, int mode); 54 void SetAutoRepeatForKey(int keycode, int mode);
55 void InjectScrollWheelClicks(int button, int count); 55 void InjectScrollWheelClicks(int button, int count);
56 56
57 MessageLoop* message_loop_; 57 MessageLoop* message_loop_;
58 58
59 std::set<int> pressed_keys_; 59 std::set<int> pressed_keys_;
60 60
61 // X11 graphics context. 61 // X11 graphics context.
62 Display* display_; 62 Display* display_;
63 Window root_window_; 63 Window root_window_;
64 int width_;
65 int height_;
66 64
67 int test_event_base_; 65 int test_event_base_;
68 int test_error_base_; 66 int test_error_base_;
69 67
70 DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux); 68 DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux);
71 }; 69 };
72 70
73 int MouseButtonToX11ButtonNumber(MouseEvent::MouseButton button) { 71 int MouseButtonToX11ButtonNumber(MouseEvent::MouseButton button) {
74 switch (button) { 72 switch (button) {
75 case MouseEvent::BUTTON_LEFT: 73 case MouseEvent::BUTTON_LEFT:
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 /* VKEY_NONAME */ -1, /* VKEY_PA1 */ -1, /* VKEY_OEM_CLEAR */ -1, -1 255 /* VKEY_NONAME */ -1, /* VKEY_PA1 */ -1, /* VKEY_OEM_CLEAR */ -1, -1
258 }; 256 };
259 257
260 int ChromotocolKeycodeToX11Keysym(int32_t keycode) { 258 int ChromotocolKeycodeToX11Keysym(int32_t keycode) {
261 if (keycode < 0 || keycode > 255) 259 if (keycode < 0 || keycode > 255)
262 return kInvalidKeycode; 260 return kInvalidKeycode;
263 261
264 return kUsVkeyToKeysym[keycode]; 262 return kUsVkeyToKeysym[keycode];
265 } 263 }
266 264
267 EventExecutorLinux::EventExecutorLinux(MessageLoop* message_loop, 265 EventExecutorLinux::EventExecutorLinux(MessageLoop* message_loop)
268 Capturer* capturer)
269 : message_loop_(message_loop), 266 : message_loop_(message_loop),
270 display_(XOpenDisplay(NULL)), 267 display_(XOpenDisplay(NULL)),
271 root_window_(BadValue), 268 root_window_(BadValue) {
272 width_(0),
273 height_(0) {
274 } 269 }
275 270
276 EventExecutorLinux::~EventExecutorLinux() { 271 EventExecutorLinux::~EventExecutorLinux() {
277 CHECK(pressed_keys_.empty()); 272 CHECK(pressed_keys_.empty());
278 } 273 }
279 274
280 bool EventExecutorLinux::Init() { 275 bool EventExecutorLinux::Init() {
281 CHECK(display_); 276 CHECK(display_);
282 277
283 root_window_ = RootWindow(display_, DefaultScreen(display_)); 278 root_window_ = RootWindow(display_, DefaultScreen(display_));
284 if (root_window_ == BadValue) { 279 if (root_window_ == BadValue) {
285 LOG(ERROR) << "Unable to get the root window"; 280 LOG(ERROR) << "Unable to get the root window";
286 return false; 281 return false;
287 } 282 }
288 283
289 // TODO(ajwong): Do we want to check the major/minor version at all for XTest? 284 // TODO(ajwong): Do we want to check the major/minor version at all for XTest?
290 int major = 0; 285 int major = 0;
291 int minor = 0; 286 int minor = 0;
292 if (!XTestQueryExtension(display_, &test_event_base_, &test_error_base_, 287 if (!XTestQueryExtension(display_, &test_event_base_, &test_error_base_,
293 &major, &minor)) { 288 &major, &minor)) {
294 LOG(ERROR) << "Server does not support XTest."; 289 LOG(ERROR) << "Server does not support XTest.";
295 return false; 290 return false;
296 } 291 }
297 292
298 // Grab the width and height so we can figure out if mouse moves are out of
299 // range.
300 XWindowAttributes root_attr;
301 // TODO(ajwong): Handle resolution changes.
302 if (!XGetWindowAttributes(display_, root_window_, &root_attr)) {
303 LOG(ERROR) << "Unable to get window attributes";
304 return false;
305 }
306
307 width_ = root_attr.width;
308 height_ = root_attr.height;
309 return true; 293 return true;
310 } 294 }
311 295
312 void EventExecutorLinux::InjectClipboardEvent(const ClipboardEvent& event) { 296 void EventExecutorLinux::InjectClipboardEvent(const ClipboardEvent& event) {
313 // TODO(simonmorris): Implement clipboard injection. 297 // TODO(simonmorris): Implement clipboard injection.
314 } 298 }
315 299
316 void EventExecutorLinux::InjectKeyEvent(const KeyEvent& event) { 300 void EventExecutorLinux::InjectKeyEvent(const KeyEvent& event) {
317 // HostEventDispatcher should filter events missing the pressed field. 301 // HostEventDispatcher should filter events missing the pressed field.
318 DCHECK(event.has_pressed()); 302 DCHECK(event.has_pressed());
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 control.auto_repeat_mode = mode; 360 control.auto_repeat_mode = mode;
377 XChangeKeyboardControl(display_, KBKey | KBAutoRepeatMode, &control); 361 XChangeKeyboardControl(display_, KBKey | KBAutoRepeatMode, &control);
378 } 362 }
379 363
380 void EventExecutorLinux::InjectScrollWheelClicks(int button, int count) { 364 void EventExecutorLinux::InjectScrollWheelClicks(int button, int count) {
381 for (int i = 0; i < count; i++) { 365 for (int i = 0; i < count; i++) {
382 // Generate a button-down and a button-up to simulate a wheel click. 366 // Generate a button-down and a button-up to simulate a wheel click.
383 XTestFakeButtonEvent(display_, button, true, CurrentTime); 367 XTestFakeButtonEvent(display_, button, true, CurrentTime);
384 XTestFakeButtonEvent(display_, button, false, CurrentTime); 368 XTestFakeButtonEvent(display_, button, false, CurrentTime);
385 } 369 }
386 XFlush(display_);
387 } 370 }
388 371
389 void EventExecutorLinux::InjectMouseEvent(const MouseEvent& event) { 372 void EventExecutorLinux::InjectMouseEvent(const MouseEvent& event) {
390 if (MessageLoop::current() != message_loop_) { 373 if (MessageLoop::current() != message_loop_) {
391 message_loop_->PostTask( 374 message_loop_->PostTask(
392 FROM_HERE, 375 FROM_HERE,
393 base::Bind(&EventExecutorLinux::InjectMouseEvent, 376 base::Bind(&EventExecutorLinux::InjectMouseEvent,
394 base::Unretained(this), event)); 377 base::Unretained(this), event));
395 return; 378 return;
396 } 379 }
397 380
398 if (event.has_x() && event.has_y()) { 381 if (event.has_x() && event.has_y()) {
399 if (event.x() < 0 || event.y() < 0 ||
400 event.x() > width_ || event.y() > height_) {
401 // A misbehaving client may send these. Drop events that are out of range.
402 // TODO(ajwong): How can we log this sanely? We don't want to DOS the
403 // server with a misbehaving client by logging like crazy.
404 return;
405 }
406
407 VLOG(3) << "Moving mouse to " << event.x() 382 VLOG(3) << "Moving mouse to " << event.x()
408 << "," << event.y(); 383 << "," << event.y();
409 XTestFakeMotionEvent(display_, DefaultScreen(display_), 384 XTestFakeMotionEvent(display_, DefaultScreen(display_),
410 event.x(), event.y(), 385 event.x(), event.y(),
411 CurrentTime); 386 CurrentTime);
412 XFlush(display_);
413 } 387 }
414 388
415 if (event.has_button() && event.has_button_down()) { 389 if (event.has_button() && event.has_button_down()) {
416 int button_number = MouseButtonToX11ButtonNumber(event.button()); 390 int button_number = MouseButtonToX11ButtonNumber(event.button());
417 391
418 if (button_number < 0) { 392 if (button_number < 0) {
419 LOG(WARNING) << "Ignoring unknown button type: " << event.button(); 393 LOG(WARNING) << "Ignoring unknown button type: " << event.button();
420 return; 394 return;
421 } 395 }
422 396
423 VLOG(3) << "Button " << event.button() 397 VLOG(3) << "Button " << event.button()
424 << " received, sending " 398 << " received, sending "
425 << (event.button_down() ? "down " : "up ") 399 << (event.button_down() ? "down " : "up ")
426 << button_number; 400 << button_number;
427 XTestFakeButtonEvent(display_, button_number, event.button_down(), 401 XTestFakeButtonEvent(display_, button_number, event.button_down(),
428 CurrentTime); 402 CurrentTime);
429 XFlush(display_);
430 } 403 }
431 404
432 if (event.has_wheel_offset_y() && event.wheel_offset_y() != 0) { 405 if (event.has_wheel_offset_y() && event.wheel_offset_y() != 0) {
433 int dy = event.wheel_offset_y(); 406 int dy = event.wheel_offset_y();
434 InjectScrollWheelClicks(VerticalScrollWheelToX11ButtonNumber(dy), abs(dy)); 407 InjectScrollWheelClicks(VerticalScrollWheelToX11ButtonNumber(dy), abs(dy));
435 } 408 }
436 if (event.has_wheel_offset_x() && event.wheel_offset_x() != 0) { 409 if (event.has_wheel_offset_x() && event.wheel_offset_x() != 0) {
437 int dx = event.wheel_offset_x(); 410 int dx = event.wheel_offset_x();
438 InjectScrollWheelClicks(HorizontalScrollWheelToX11ButtonNumber(dx), 411 InjectScrollWheelClicks(HorizontalScrollWheelToX11ButtonNumber(dx),
439 abs(dx)); 412 abs(dx));
440 } 413 }
414
415 XFlush(display_);
441 } 416 }
442 417
443 } // namespace 418 } // namespace
444 419
445 scoped_ptr<protocol::HostEventStub> EventExecutor::Create( 420 scoped_ptr<protocol::HostEventStub> EventExecutor::Create(
446 MessageLoop* message_loop, Capturer* capturer) { 421 MessageLoop* message_loop, Capturer* capturer) {
447 scoped_ptr<EventExecutorLinux> executor( 422 scoped_ptr<EventExecutorLinux> executor(
448 new EventExecutorLinux(message_loop, capturer)); 423 new EventExecutorLinux(message_loop));
449 if (!executor->Init()) { 424 if (!executor->Init())
450 executor.reset(NULL); 425 return scoped_ptr<protocol::HostEventStub>(NULL);
451 }
452 return executor.PassAs<protocol::HostEventStub>(); 426 return executor.PassAs<protocol::HostEventStub>();
453 } 427 }
454 428
455 } // namespace remoting 429 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/client_session.cc ('k') | remoting/host/event_executor_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698