Index: remoting/host/remote_input_filter.cc |
diff --git a/remoting/host/remote_input_filter.cc b/remoting/host/remote_input_filter.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7863398e18a2183d7bd5a962320756dd221b68ab |
--- /dev/null |
+++ b/remoting/host/remote_input_filter.cc |
@@ -0,0 +1,88 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "remoting/host/remote_input_filter.h" |
+ |
+#include <algorithm> |
+ |
+#include "base/logging.h" |
+#include "remoting/proto/event.pb.h" |
+ |
+namespace { |
+ |
+// The number of remote mouse events to record for the purpose of eliminating |
+// "echoes" detected by the local input detector. The value should be large |
+// enough to cope with the fact that multiple events might be injected before |
+// any echoes are detected. |
+const unsigned int kNumRemoteMousePositions = 50; |
+ |
+// The number of milliseconds for which to block remote input when local input |
+// is received. |
+const int64 kRemoteBlockTimeoutMillis = 2000; |
+ |
+} // namespace |
+ |
+namespace remoting { |
+ |
+RemoteInputFilter::RemoteInputFilter(protocol::InputEventTracker* event_tracker) |
+ : event_tracker_(event_tracker) { |
+} |
+ |
+RemoteInputFilter::~RemoteInputFilter() { |
+} |
+ |
+void RemoteInputFilter::LocalMouseMoved(const SkIPoint& mouse_pos) { |
+ // If this is a genuine local input event (rather than an echo of a remote |
+ // input event that we've just injected), then ignore remote inputs for a |
+ // short time. |
+ std::list<SkIPoint>::iterator found_position = |
+ std::find(injected_mouse_positions_.begin(), |
+ injected_mouse_positions_.end(), mouse_pos); |
+ if (found_position != injected_mouse_positions_.end()) { |
+ // Remove it from the list, and any positions that were added before it, |
+ // if any. This is because the local input monitor is assumed to receive |
+ // injected mouse position events in the order in which they were injected |
+ // (if at all). If the position is found somewhere other than the front of |
+ // the queue, this would be because the earlier positions weren't |
+ // successfully injected (or the local input monitor might have skipped over |
+ // some positions), and not because the events were out-of-sequence. These |
+ // spurious positions should therefore be discarded. |
+ injected_mouse_positions_.erase(injected_mouse_positions_.begin(), |
+ ++found_position); |
+ } else { |
+ // Release all pressed buttons or keys, disable inputs, and note the time. |
+ event_tracker_->ReleaseAll(); |
+ latest_local_input_time_ = base::TimeTicks::Now(); |
+ } |
+} |
+ |
+void RemoteInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) { |
+ if (ShouldIgnoreInput()) |
+ return; |
+ event_tracker_->InjectKeyEvent(event); |
+} |
+ |
+void RemoteInputFilter::InjectMouseEvent(const protocol::MouseEvent& event) { |
+ if (ShouldIgnoreInput()) |
+ return; |
+ if (event.has_x() && event.has_y()) { |
+ injected_mouse_positions_.push_back(SkIPoint::Make(event.x(), event.y())); |
+ if (injected_mouse_positions_.size() > kNumRemoteMousePositions) { |
+ VLOG(1) << "Injected mouse positions queue full."; |
+ injected_mouse_positions_.pop_front(); |
+ } |
+ } |
+ event_tracker_->InjectMouseEvent(event); |
+} |
+ |
+bool RemoteInputFilter::ShouldIgnoreInput() const { |
+ // Ignore remote events if the local mouse moved recently. |
+ int64 millis = |
+ (base::TimeTicks::Now() - latest_local_input_time_).InMilliseconds(); |
+ if (millis < kRemoteBlockTimeoutMillis) |
+ return true; |
+ return false; |
+} |
+ |
+} // namespace remoting |