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..f1ffc937d5788bae12e1ef9d2e3296e86aebcee1 |
--- /dev/null |
+++ b/remoting/client/plugin/touch_input_scaler.cc |
@@ -0,0 +1,80 @@ |
+// 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 radii (size). When the output desktop and the input |
+ // desktop sizes do not match, the touch size should be scaled so that it |
+ // does not look too big or too small on the output desktop, compared to the |
Wez
2015/02/13 16:51:46
nit: The normal impact of this will not be on the
Rintaro Kuroiwa
2015/02/17 19:52:11
Done.
|
+ // input size (e.g. touch area of a finger). |
+ // TODO(rkuroiwa): Find out whether clamping should be done here or by the |
+ // host. Windows' touch injection fails when part of a touch point falls |
+ // outside the screen, but other platforms might handle it differently. |
+ // Also reduce the radii if the ellipse completely encloses the desktop. |
Wez
2015/02/13 16:51:46
Based on the Windows case, I'd suggest choosing be
Rintaro Kuroiwa
2015/02/17 19:52:11
I changed the TODO so that we can iterate on this.
Wez
2015/02/23 23:24:07
Note that we usually file bugs for improvements of
Rintaro Kuroiwa
2015/02/24 23:43:10
Done. Added a link to this todo.
|
+ 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 |