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_; | |
simonmorris
2012/07/23 16:45:01
Drive-by: Do you need to initialise this member?
Wez
2012/07/23 17:30:16
Yes! Good spot. I wonder how the Skia folks would
Wez
2012/07/23 17:30:16
Done.
| |
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 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
379 void EventExecutorLinux::InjectMouseEvent(const MouseEvent& event) { | 381 void EventExecutorLinux::InjectMouseEvent(const MouseEvent& event) { |
380 if (!task_runner_->BelongsToCurrentThread()) { | 382 if (!task_runner_->BelongsToCurrentThread()) { |
381 task_runner_->PostTask( | 383 task_runner_->PostTask( |
382 FROM_HERE, | 384 FROM_HERE, |
383 base::Bind(&EventExecutorLinux::InjectMouseEvent, | 385 base::Bind(&EventExecutorLinux::InjectMouseEvent, |
384 base::Unretained(this), event)); | 386 base::Unretained(this), event)); |
385 return; | 387 return; |
386 } | 388 } |
387 | 389 |
388 if (event.has_x() && event.has_y()) { | 390 if (event.has_x() && event.has_y()) { |
389 VLOG(3) << "Moving mouse to " << event.x() | 391 // Injecting a motion event immediately before a button release results in |
390 << "," << event.y(); | 392 // a MotionNotify even if the mouse position hasn't changed, which confuses |
391 XTestFakeMotionEvent(display_, DefaultScreen(display_), | 393 // apps which assume MotionNotify implies movement. See crbug.com/138075. |
392 event.x(), event.y(), | 394 bool inject_motion = true; |
393 CurrentTime); | 395 if (event.has_button() && event.has_button_down() && !event.button_down()) { |
simonmorris
2012/07/23 16:45:01
Drive-by: Is there any need for these button tests
Wez
2012/07/23 17:30:16
Yes; if a local user moves the cursor and after wa
| |
396 if (SkIPoint::Make(event.x(), event.y()) == latest_mouse_position_) | |
397 inject_motion = false; | |
398 } | |
399 | |
400 latest_mouse_position_ = SkIPoint::Make(event.x(), event.y()); | |
Jamie
2012/07/23 16:44:16
Nit: It might be cleaner to declare a variable, ne
Wez
2012/07/23 17:30:16
Done.
| |
401 | |
402 if (inject_motion) { | |
403 VLOG(3) << "Moving mouse to " << event.x() | |
404 << "," << event.y(); | |
405 XTestFakeMotionEvent(display_, DefaultScreen(display_), | |
406 event.x(), event.y(), | |
407 CurrentTime); | |
408 } | |
394 } | 409 } |
395 | 410 |
396 if (event.has_button() && event.has_button_down()) { | 411 if (event.has_button() && event.has_button_down()) { |
397 int button_number = MouseButtonToX11ButtonNumber(event.button()); | 412 int button_number = MouseButtonToX11ButtonNumber(event.button()); |
398 | 413 |
399 if (button_number < 0) { | 414 if (button_number < 0) { |
400 LOG(WARNING) << "Ignoring unknown button type: " << event.button(); | 415 LOG(WARNING) << "Ignoring unknown button type: " << event.button(); |
401 return; | 416 return; |
402 } | 417 } |
403 | 418 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, | 453 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
439 VideoFrameCapturer* capturer) { | 454 VideoFrameCapturer* capturer) { |
440 scoped_ptr<EventExecutorLinux> executor( | 455 scoped_ptr<EventExecutorLinux> executor( |
441 new EventExecutorLinux(main_task_runner)); | 456 new EventExecutorLinux(main_task_runner)); |
442 if (!executor->Init()) | 457 if (!executor->Init()) |
443 return scoped_ptr<EventExecutor>(NULL); | 458 return scoped_ptr<EventExecutor>(NULL); |
444 return executor.PassAs<EventExecutor>(); | 459 return executor.PassAs<EventExecutor>(); |
445 } | 460 } |
446 | 461 |
447 } // namespace remoting | 462 } // namespace remoting |
OLD | NEW |