Index: remoting/client/plugin/touch_input_scaler.cc |
diff --git a/remoting/client/plugin/touch_input_scaler.cc b/remoting/client/plugin/touch_input_scaler.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6397e10e5dd77315b81da95a34b0804d2d9c410f |
--- /dev/null |
+++ b/remoting/client/plugin/touch_input_scaler.cc |
@@ -0,0 +1,77 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "remoting/client/plugin/touch_input_scaler.h" |
+ |
+#include "base/logging.h" |
+#include "remoting/proto/event.pb.h" |
+ |
+namespace remoting { |
+ |
+using protocol::TouchEvent; |
+using protocol::TouchEventPoint; |
+ |
+namespace { |
+ |
+// |value| is the number to be scaled. |output_max| is the output desktop's max |
+// height or width. |input_max| is the input desktop's max height or width. |
+float Scale(float value, int output_max, int input_max) { |
+ DCHECK_GT(output_max, 0); |
+ DCHECK_GT(input_max, 0); |
+ value *= output_max; |
+ value /= input_max; |
+ return value; |
+} |
+ |
+// Same as Scale() but |value| will be scaled and clamped using |output_max| and |
+// |input_max|. |
+float ScaleAndClamp(float value, int output_max, int input_max) { |
+ value = Scale(value, output_max, input_max); |
+ return std::max(0.0f, std::min(static_cast<float>(output_max), value)); |
+} |
+ |
+} // namespace |
+ |
+TouchInputScaler::TouchInputScaler(InputStub* input_stub) |
+ : InputFilter(input_stub) {} |
+ |
+TouchInputScaler::~TouchInputScaler() {} |
+ |
+void TouchInputScaler::InjectTouchEvent(const TouchEvent& event) { |
+ if (input_size_.is_empty() || output_size_.is_empty()) |
+ return; |
+ |
+ // We scale based on the maximum input & output coordinates, rather than the |
+ // input and output sizes, so that it's possible to reach the edge of the |
+ // output when up-scaling. We also take care to round up or down correctly, |
+ // which is important when down-scaling. |
+ TouchEvent out_event(event); |
+ for (int i = 0; i < out_event.touch_points().size(); ++i) { |
+ TouchEventPoint* point = out_event.mutable_touch_points(i); |
+ if (point->has_x() || point->has_y()) { |
+ DCHECK(point->has_x() && point->has_y()); |
+ point->set_x( |
+ ScaleAndClamp(point->x(), output_size_.width(), input_size_.width())); |
+ point->set_y(ScaleAndClamp(point->y(), output_size_.height(), |
+ input_size_.height())); |
+ } |
+ |
+ // Also scale the touch size. When the output desktop and the input desktop |
+ // sizes do not match, the touch size should be scaled for more predicatable |
Wez
2015/02/23 23:24:07
typo: predictable.
It's not clear what it means f
Rintaro Kuroiwa
2015/02/24 23:43:10
Changed description and an example where scaling i
|
+ // hit testing. |
+ // TODO(rkuroiwa): Also clamp. Note that point->angle() affects the maximum |
+ // size. |
+ if (point->has_radius_x() || point->has_radius_y()) { |
+ DCHECK(point->has_radius_x() && point->has_radius_y()); |
+ point->set_radius_x( |
+ Scale(point->radius_x(), output_size_.width(), input_size_.width())); |
+ point->set_radius_y(Scale(point->radius_y(), output_size_.height(), |
+ input_size_.height())); |
+ } |
+ } |
+ |
+ InputFilter::InjectTouchEvent(out_event); |
+} |
+ |
+} // namespace remoting |