Home | History | Annotate | Download | only in host
      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