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/protocol/mouse_input_filter.h"
6 
7 #include <algorithm>
8 
9 #include "base/logging.h"
10 #include "base/numerics/ranges.h"
11 #include "remoting/proto/event.pb.h"
12 
13 namespace remoting {
14 namespace protocol {
15 
MouseInputFilter()16 MouseInputFilter::MouseInputFilter()
17     : x_input_(0), y_input_(0), x_output_(0), y_output_(0) {}
18 
MouseInputFilter(InputStub * input_stub)19 MouseInputFilter::MouseInputFilter(InputStub* input_stub)
20     : InputFilter(input_stub),
21       x_input_(0),
22       y_input_(0),
23       x_output_(0),
24       y_output_(0) {}
25 
26 MouseInputFilter::~MouseInputFilter() = default;
27 
InjectMouseEvent(const MouseEvent & event)28 void MouseInputFilter::InjectMouseEvent(const MouseEvent& event) {
29   if (x_input_ == 0 || y_input_ == 0 || x_output_ == 0 || y_output_ == 0) {
30     return;
31   }
32 
33   // We scale based on the max input and output coordinates (which are equal
34   // to size-1), rather than the input and output sizes, so that it's possible
35   // to reach the edge of the output when up-scaling.  We also take care to
36   // round up or down correctly, which is important when down-scaling.
37   // After scaling, we offset by the output rect origin. This is normally
38   // (0,0), but may be non-zero when there are multiple displays and we are
39   // showing a single display.
40 
41   MouseEvent out_event(event);
42   if (out_event.has_x()) {
43     int x = out_event.x();
44     if (x_output_ != x_input_)
45       x = ((x * x_output_) + (x_input_ / 2)) / x_input_;
46     out_event.set_x(output_offset_.x() + base::ClampToRange(x, 0, x_output_));
47   }
48   if (out_event.has_y()) {
49     int y = out_event.y();
50     if (y_output_ != y_input_)
51       y = ((y * y_output_) + (y_input_ / 2)) / y_input_;
52     out_event.set_y(output_offset_.y() + base::ClampToRange(y, 0, y_output_));
53   }
54   InputFilter::InjectMouseEvent(out_event);
55 }
56 
set_input_size(const int32_t x,const int32_t y)57 void MouseInputFilter::set_input_size(const int32_t x, const int32_t y) {
58   x_input_ = x - 1;
59   y_input_ = y - 1;
60   LOG(INFO) << "Setting MouseInputFilter input_size to " << x_input_ << ","
61             << y_input_;
62 }
63 
set_output_size(const int32_t x,const int32_t y)64 void MouseInputFilter::set_output_size(const int32_t x, const int32_t y) {
65   x_output_ = x - 1;
66   y_output_ = y - 1;
67   LOG(INFO) << "Setting MouseInputFilter output_size to " << x_output_ << ","
68             << y_output_;
69 }
70 
set_output_offset(const webrtc::DesktopVector & v)71 void MouseInputFilter::set_output_offset(const webrtc::DesktopVector& v) {
72   output_offset_ = webrtc::DesktopVector(v.x(), v.y());
73   LOG(INFO) << "Setting MouseInputFilter output_offset to "
74             << output_offset_.x() << "," << output_offset_.y();
75 }
76 
77 }  // namespace protocol
78 }  // namespace remoting
79