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 26 RemoteInputFilter::RemoteInputFilter(protocol::InputEventTracker* event_tracker) 27 : event_tracker_(event_tracker), 28 expect_local_echo_(true) { 29 } 30 31 RemoteInputFilter::~RemoteInputFilter() { 32 } 33 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 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 72 void RemoteInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) { 73 if (ShouldIgnoreInput()) 74 return; 75 event_tracker_->InjectKeyEvent(event); 76 } 77 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 92 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