| 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..11396ab931cce35003e79f87962b8b0d3abeb0c3
|
| --- /dev/null
|
| +++ b/remoting/client/plugin/touch_input_scaler.cc
|
| @@ -0,0 +1,86 @@
|
| +// 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. Without scaling, the size on the host will not
|
| + // be right.
|
| + // For example
|
| + // Suppose:
|
| + // - No size scaling.
|
| + // - Client is a HiDPI Chromebook device.
|
| + // - Host is running on a HiDPI Windows device.
|
| + // With the configuration above, the client will send the logical touch
|
| + // size to the host, therefore it will be smaller on the host.
|
| + // This is because a HiDPI Chromebook device (e.g. Pixel) has 2 by 2
|
| + // physical pixel mapped to a logical pixel.
|
| + // With scaling, the size would be the same.
|
| + // TODO(rkuroiwa): Also clamp. Note that point->angle() affects the maximum
|
| + // size (crbug.com/461526).
|
| + 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
|
|
|