remote_input_filter.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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
  3. // found in the LICENSE file.
  4. #include "remoting/host/remote_input_filter.h"
  5. #include <stdint.h>
  6. #include "base/logging.h"
  7. #include "remoting/proto/event.pb.h"
  8. namespace {
  9. // The number of remote mouse events to record for the purpose of eliminating
  10. // "echoes" detected by the local input detector. The value should be large
  11. // enough to cope with the fact that multiple events might be injected before
  12. // any echoes are detected.
  13. const unsigned int kNumRemoteMousePositions = 50;
  14. // The number of remote keypress events to record for the purpose of eliminating
  15. // "echoes" detected by the local input detector. The value should be large
  16. // enough to cope with the fact that multiple events might be injected before
  17. // any echoes are detected.
  18. const unsigned int kNumRemoteKeyPresses = 20;
  19. // The number of milliseconds for which to block remote input when local input
  20. // is received.
  21. const int64_t kRemoteBlockTimeoutMillis = 2000;
  22. } // namespace
  23. namespace remoting {
  24. RemoteInputFilter::RemoteInputFilter(protocol::InputEventTracker* event_tracker)
  25. : event_tracker_(event_tracker),
  26. expect_local_echo_(true) {
  27. }
  28. RemoteInputFilter::~RemoteInputFilter() = default;
  29. bool RemoteInputFilter::LocalPointerMoved(const webrtc::DesktopVector& pos,
  30. ui::EventType type) {
  31. // If this is a genuine local input event (rather than an echo of a remote
  32. // input event that we've just injected), then ignore remote inputs for a
  33. // short time.
  34. //
  35. // Note that no platforms both inject and monitor for touch events, so echo
  36. // suppression is only applied to mouse input.
  37. if (expect_local_echo_ && type == ui::ET_MOUSE_MOVED) {
  38. auto found_position = injected_mouse_positions_.begin();
  39. while (found_position != injected_mouse_positions_.end() &&
  40. !pos.equals(*found_position)) {
  41. ++found_position;
  42. }
  43. if (found_position != injected_mouse_positions_.end()) {
  44. // Remove it from the list, and any positions that were added before it,
  45. // if any. This is because the local input monitor is assumed to receive
  46. // injected mouse position events in the order in which they were injected
  47. // (if at all). If the position is found somewhere other than the front
  48. // of the queue, this would be because the earlier positions weren't
  49. // successfully injected (or the local input monitor might have skipped
  50. // over some positions), and not because the events were out-of-sequence.
  51. // These spurious positions should therefore be discarded.
  52. injected_mouse_positions_.erase(injected_mouse_positions_.begin(),
  53. ++found_position);
  54. return false;
  55. }
  56. }
  57. LocalInputDetected();
  58. return true;
  59. }
  60. bool RemoteInputFilter::LocalKeyPressed(uint32_t usb_keycode) {
  61. // If local echo is expected and |usb_keycode| is the oldest unechoed injected
  62. // keypress, then ignore it.
  63. if (expect_local_echo_ && !injected_key_presses_.empty() &&
  64. injected_key_presses_.front() == usb_keycode) {
  65. injected_key_presses_.pop_front();
  66. return false;
  67. }
  68. LocalInputDetected();
  69. return true;
  70. }
  71. void RemoteInputFilter::LocalInputDetected() {
  72. event_tracker_->ReleaseAll();
  73. latest_local_input_time_ = base::TimeTicks::Now();
  74. }
  75. void RemoteInputFilter::SetExpectLocalEcho(bool expect_local_echo) {
  76. expect_local_echo_ = expect_local_echo;
  77. if (!expect_local_echo_)
  78. injected_mouse_positions_.clear();
  79. }
  80. void RemoteInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) {
  81. if (ShouldIgnoreInput())
  82. return;
  83. if (expect_local_echo_ && event.pressed() && event.has_usb_keycode()) {
  84. injected_key_presses_.push_back(event.usb_keycode());
  85. if (injected_key_presses_.size() > kNumRemoteKeyPresses) {
  86. VLOG(1) << "Injected key press queue full.";
  87. injected_key_presses_.clear();
  88. }
  89. }
  90. event_tracker_->InjectKeyEvent(event);
  91. }
  92. void RemoteInputFilter::InjectTextEvent(const protocol::TextEvent& event) {
  93. if (ShouldIgnoreInput())
  94. return;
  95. event_tracker_->InjectTextEvent(event);
  96. }
  97. void RemoteInputFilter::InjectMouseEvent(const protocol::MouseEvent& event) {
  98. if (ShouldIgnoreInput())
  99. return;
  100. if (expect_local_echo_ && event.has_x() && event.has_y()) {
  101. injected_mouse_positions_.push_back(
  102. webrtc::DesktopVector(event.x(), event.y()));
  103. if (injected_mouse_positions_.size() > kNumRemoteMousePositions) {
  104. VLOG(1) << "Injected mouse positions queue full.";
  105. injected_mouse_positions_.pop_front();
  106. }
  107. }
  108. event_tracker_->InjectMouseEvent(event);
  109. }
  110. void RemoteInputFilter::InjectTouchEvent(const protocol::TouchEvent& event) {
  111. if (ShouldIgnoreInput())
  112. return;
  113. event_tracker_->InjectTouchEvent(event);
  114. }
  115. bool RemoteInputFilter::ShouldIgnoreInput() const {
  116. // Ignore remote events if the local mouse moved recently.
  117. int64_t millis =
  118. (base::TimeTicks::Now() - latest_local_input_time_).InMilliseconds();
  119. if (millis < kRemoteBlockTimeoutMillis)
  120. return true;
  121. return false;
  122. }
  123. } // namespace remoting