15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/remote_input_filter.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/proto/event.pb.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of remote mouse events to record for the purpose of eliminating
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "echoes" detected by the local input detector. The value should be large
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enough to cope with the fact that multiple events might be injected before
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// any echoes are detected.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned int kNumRemoteMousePositions = 50;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The number of milliseconds for which to block remote input when local input
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is received.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int64 kRemoteBlockTimeoutMillis = 2000;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RemoteInputFilter::RemoteInputFilter(protocol::InputEventTracker* event_tracker)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : event_tracker_(event_tracker),
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expect_local_echo_(true) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RemoteInputFilter::~RemoteInputFilter() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RemoteInputFilter::LocalMouseMoved(const SkIPoint& mouse_pos) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this is a genuine local input event (rather than an echo of a remote
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // input event that we've just injected), then ignore remote inputs for a
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // short time.
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (expect_local_echo_) {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::list<SkIPoint>::iterator found_position =
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::find(injected_mouse_positions_.begin(),
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  injected_mouse_positions_.end(), mouse_pos);
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (found_position != injected_mouse_positions_.end()) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Remove it from the list, and any positions that were added before it,
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // if any.  This is because the local input monitor is assumed to receive
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // injected mouse position events in the order in which they were injected
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // (if at all).  If the position is found somewhere other than the front
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // of the queue, this would be because the earlier positions weren't
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // successfully injected (or the local input monitor might have skipped
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // over some positions), and not because the events were out-of-sequence.
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // These spurious positions should therefore be discarded.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      injected_mouse_positions_.erase(injected_mouse_positions_.begin(),
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      ++found_position);
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Release all pressed buttons or keys, disable inputs, and note the time.
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_tracker_->ReleaseAll();
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  latest_local_input_time_ = base::TimeTicks::Now();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void RemoteInputFilter::SetExpectLocalEcho(bool expect_local_echo) {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expect_local_echo_ = expect_local_echo;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!expect_local_echo_)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    injected_mouse_positions_.clear();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RemoteInputFilter::InjectKeyEvent(const protocol::KeyEvent& event) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldIgnoreInput())
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_tracker_->InjectKeyEvent(event);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RemoteInputFilter::InjectMouseEvent(const protocol::MouseEvent& event) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ShouldIgnoreInput())
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (expect_local_echo_ && event.has_x() && event.has_y()) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    injected_mouse_positions_.push_back(SkIPoint::Make(event.x(), event.y()));
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (injected_mouse_positions_.size() > kNumRemoteMousePositions) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(1) << "Injected mouse positions queue full.";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      injected_mouse_positions_.pop_front();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_tracker_->InjectMouseEvent(event);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RemoteInputFilter::ShouldIgnoreInput() const {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore remote events if the local mouse moved recently.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 millis =
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (base::TimeTicks::Now() - latest_local_input_time_).InMilliseconds();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (millis < kRemoteBlockTimeoutMillis)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
99