• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
5 #include "remoting/host/remote_input_filter.h"
6 
7 #include "base/logging.h"
8 #include "remoting/proto/event.pb.h"
9 
10 namespace {
11 
12 // The number of remote mouse events to record for the purpose of eliminating
13 // "echoes" detected by the local input detector. The value should be large
14 // enough to cope with the fact that multiple events might be injected before
15 // any echoes are detected.
16 const unsigned int kNumRemoteMousePositions = 50;
17 
18 // The number of milliseconds for which to block remote input when local input
19 // is received.
20 const int64 kRemoteBlockTimeoutMillis = 2000;
21 
22 } // namespace
23 
24 namespace remoting {
25 
RemoteInputFilter(protocol::InputEventTracker * event_tracker)26 RemoteInputFilter::RemoteInputFilter(protocol::InputEventTracker* event_tracker)
27     : event_tracker_(event_tracker),
28       expect_local_echo_(true) {
29 }
30 
~RemoteInputFilter()31 RemoteInputFilter::~RemoteInputFilter() {
32 }
33 
LocalMouseMoved(const webrtc::DesktopVector & mouse_pos)34 void RemoteInputFilter::LocalMouseMoved(
35     const webrtc::DesktopVector& mouse_pos) {
36   // If this is a genuine local input event (rather than an echo of a remote
37   // input event that we've just injected), then ignore remote inputs for a
38   // short time.
39   if (expect_local_echo_) {
40     std::list<webrtc::DesktopVector>::iterator found_position =
41         injected_mouse_positions_.begin();
42     while (found_position != injected_mouse_positions_.end() &&
43            !mouse_pos.equals(*found_position)) {
44       ++found_position;
45     }
46     if (found_position != injected_mouse_positions_.end()) {
47       // Remove it from the list, and any positions that were added before it,
48       // if any.  This is because the local input monitor is assumed to receive
49       // injected mouse position events in the order in which they were injected
50       // (if at all).  If the position is found somewhere other than the front
51       // of the queue, this would be because the earlier positions weren't
52       // successfully injected (or the local input monitor might have skipped
53       // over some positions), and not because the events were out-of-sequence.
54       // These spurious positions should therefore be discarded.
55       injected_mouse_positions_.erase(injected_mouse_positions_.begin(),
56                                       ++found_position);
57       return;
58     }
59   }
60 
61   // Release all pressed buttons or keys, disable inputs, and note the time.
62   event_tracker_->ReleaseAll();
63   latest_local_input_time_ = base::TimeTicks::Now();
64 }
65 
SetExpectLocalEcho(bool expect_local_echo)66 void RemoteInputFilter::SetExpectLocalEcho(bool expect_local_echo) {
67   expect_local_echo_ = expect_local_echo;
68   if (!expect_local_echo_)
69     injected_mouse_positions_.clear();
70 }
71 
InjectKeyEvent(const protocol::KeyEvent & event)72 void RemoteInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) {
73   if (ShouldIgnoreInput())
74     return;
75   event_tracker_->InjectKeyEvent(event);
76 }
77 
InjectMouseEvent(const protocol::MouseEvent & event)78 void RemoteInputFilter::InjectMouseEvent(const protocol::MouseEvent& event) {
79   if (ShouldIgnoreInput())
80     return;
81   if (expect_local_echo_ && event.has_x() && event.has_y()) {
82     injected_mouse_positions_.push_back(
83         webrtc::DesktopVector(event.x(), event.y()));
84     if (injected_mouse_positions_.size() > kNumRemoteMousePositions) {
85       VLOG(1) << "Injected mouse positions queue full.";
86       injected_mouse_positions_.pop_front();
87     }
88   }
89   event_tracker_->InjectMouseEvent(event);
90 }
91 
ShouldIgnoreInput() const92 bool RemoteInputFilter::ShouldIgnoreInput() const {
93   // Ignore remote events if the local mouse moved recently.
94   int64 millis =
95       (base::TimeTicks::Now() - latest_local_input_time_).InMilliseconds();
96   if (millis < kRemoteBlockTimeoutMillis)
97     return true;
98   return false;
99 }
100 
101 }  // namespace remoting
102