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/XF86keysym.h> | 10 #include <X11/XF86keysym.h> |
11 #include <X11/keysym.h> | 11 #include <X11/keysym.h> |
12 #include <X11/extensions/XTest.h> | 12 #include <X11/extensions/XTest.h> |
13 | 13 |
14 #include "base/basictypes.h" | 14 #include "base/basictypes.h" |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/compiler_specific.h" | 16 #include "base/compiler_specific.h" |
17 #include "base/location.h" | 17 #include "base/location.h" |
18 #include "base/logging.h" | 18 #include "base/logging.h" |
19 #include "base/single_thread_task_runner.h" | 19 #include "base/single_thread_task_runner.h" |
20 #include "remoting/proto/internal.pb.h" | 20 #include "remoting/proto/internal.pb.h" |
| 21 #include "third_party/skia/include/core/SkPoint.h" |
21 | 22 |
22 namespace remoting { | 23 namespace remoting { |
23 | 24 |
24 namespace { | 25 namespace { |
25 | 26 |
26 using protocol::ClipboardEvent; | 27 using protocol::ClipboardEvent; |
27 using protocol::KeyEvent; | 28 using protocol::KeyEvent; |
28 using protocol::MouseEvent; | 29 using protocol::MouseEvent; |
29 | 30 |
30 // USB to XKB keycode map table. | 31 // USB to XKB keycode map table. |
(...skipping 25 matching lines...) Expand all Loading... |
56 private: | 57 private: |
57 // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff, | 58 // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff, |
58 // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl() | 59 // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl() |
59 // API. | 60 // API. |
60 void SetAutoRepeatForKey(int keycode, int mode); | 61 void SetAutoRepeatForKey(int keycode, int mode); |
61 void InjectScrollWheelClicks(int button, int count); | 62 void InjectScrollWheelClicks(int button, int count); |
62 | 63 |
63 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | 64 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
64 | 65 |
65 std::set<int> pressed_keys_; | 66 std::set<int> pressed_keys_; |
| 67 SkIPoint latest_mouse_position_; |
66 | 68 |
67 // X11 graphics context. | 69 // X11 graphics context. |
68 Display* display_; | 70 Display* display_; |
69 Window root_window_; | 71 Window root_window_; |
70 | 72 |
71 int test_event_base_; | 73 int test_event_base_; |
72 int test_error_base_; | 74 int test_error_base_; |
73 | 75 |
74 DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux); | 76 DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux); |
75 }; | 77 }; |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 int ChromotocolKeycodeToX11Keysym(int32_t keycode) { | 266 int ChromotocolKeycodeToX11Keysym(int32_t keycode) { |
265 if (keycode < 0 || keycode > 255) | 267 if (keycode < 0 || keycode > 255) |
266 return kInvalidKeycode; | 268 return kInvalidKeycode; |
267 | 269 |
268 return kUsVkeyToKeysym[keycode]; | 270 return kUsVkeyToKeysym[keycode]; |
269 } | 271 } |
270 | 272 |
271 EventExecutorLinux::EventExecutorLinux( | 273 EventExecutorLinux::EventExecutorLinux( |
272 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 274 scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
273 : task_runner_(task_runner), | 275 : task_runner_(task_runner), |
| 276 latest_mouse_position_(SkIPoint::Make(-1, -1)), |
274 display_(XOpenDisplay(NULL)), | 277 display_(XOpenDisplay(NULL)), |
275 root_window_(BadValue) { | 278 root_window_(BadValue) { |
276 } | 279 } |
277 | 280 |
278 EventExecutorLinux::~EventExecutorLinux() { | 281 EventExecutorLinux::~EventExecutorLinux() { |
279 CHECK(pressed_keys_.empty()); | 282 CHECK(pressed_keys_.empty()); |
280 } | 283 } |
281 | 284 |
282 bool EventExecutorLinux::Init() { | 285 bool EventExecutorLinux::Init() { |
283 CHECK(display_); | 286 CHECK(display_); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 void EventExecutorLinux::InjectMouseEvent(const MouseEvent& event) { | 382 void EventExecutorLinux::InjectMouseEvent(const MouseEvent& event) { |
380 if (!task_runner_->BelongsToCurrentThread()) { | 383 if (!task_runner_->BelongsToCurrentThread()) { |
381 task_runner_->PostTask( | 384 task_runner_->PostTask( |
382 FROM_HERE, | 385 FROM_HERE, |
383 base::Bind(&EventExecutorLinux::InjectMouseEvent, | 386 base::Bind(&EventExecutorLinux::InjectMouseEvent, |
384 base::Unretained(this), event)); | 387 base::Unretained(this), event)); |
385 return; | 388 return; |
386 } | 389 } |
387 | 390 |
388 if (event.has_x() && event.has_y()) { | 391 if (event.has_x() && event.has_y()) { |
389 VLOG(3) << "Moving mouse to " << event.x() | 392 // Injecting a motion event immediately before a button release results in |
390 << "," << event.y(); | 393 // a MotionNotify even if the mouse position hasn't changed, which confuses |
391 XTestFakeMotionEvent(display_, DefaultScreen(display_), | 394 // apps which assume MotionNotify implies movement. See crbug.com/138075. |
392 event.x(), event.y(), | 395 bool inject_motion = true; |
393 CurrentTime); | 396 SkIPoint new_mouse_position(SkIPoint::Make(event.x(), event.y())); |
| 397 if (event.has_button() && event.has_button_down() && !event.button_down()) { |
| 398 if (new_mouse_position == latest_mouse_position_) |
| 399 inject_motion = false; |
| 400 } |
| 401 |
| 402 latest_mouse_position_ = new_mouse_position; |
| 403 |
| 404 if (inject_motion) { |
| 405 VLOG(3) << "Moving mouse to " << event.x() |
| 406 << "," << event.y(); |
| 407 XTestFakeMotionEvent(display_, DefaultScreen(display_), |
| 408 event.x(), event.y(), |
| 409 CurrentTime); |
| 410 } |
394 } | 411 } |
395 | 412 |
396 if (event.has_button() && event.has_button_down()) { | 413 if (event.has_button() && event.has_button_down()) { |
397 int button_number = MouseButtonToX11ButtonNumber(event.button()); | 414 int button_number = MouseButtonToX11ButtonNumber(event.button()); |
398 | 415 |
399 if (button_number < 0) { | 416 if (button_number < 0) { |
400 LOG(WARNING) << "Ignoring unknown button type: " << event.button(); | 417 LOG(WARNING) << "Ignoring unknown button type: " << event.button(); |
401 return; | 418 return; |
402 } | 419 } |
403 | 420 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
438 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | 455 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
439 VideoFrameCapturer* capturer) { | 456 VideoFrameCapturer* capturer) { |
440 scoped_ptr<EventExecutorLinux> executor( | 457 scoped_ptr<EventExecutorLinux> executor( |
441 new EventExecutorLinux(main_task_runner)); | 458 new EventExecutorLinux(main_task_runner)); |
442 if (!executor->Init()) | 459 if (!executor->Init()) |
443 return scoped_ptr<EventExecutor>(NULL); | 460 return scoped_ptr<EventExecutor>(NULL); |
444 return executor.PassAs<EventExecutor>(); | 461 return executor.PassAs<EventExecutor>(); |
445 } | 462 } |
446 | 463 |
447 } // namespace remoting | 464 } // namespace remoting |
OLD | NEW |