123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- // Copyright 2017 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/gesture_interpreter.h"
- #include <memory>
- #include "base/bind.h"
- #include "base/time/time.h"
- #include "remoting/client/chromoting_session.h"
- #include "remoting/client/display/renderer_proxy.h"
- #include "remoting/client/input/direct_touch_input_strategy.h"
- #include "remoting/client/input/trackpad_input_strategy.h"
- namespace {
- const float kOneFingerFlingTimeConstant = 180.f;
- const float kScrollFlingTimeConstant = 250.f;
- } // namespace
- namespace remoting {
- GestureInterpreter::GestureInterpreter()
- // TODO(yuweih): These animations are better to take GetWeakPtr().
- : pan_animation_(
- kOneFingerFlingTimeConstant,
- base::BindRepeating(&GestureInterpreter::PanWithoutAbortAnimations,
- base::Unretained(this))),
- scroll_animation_(
- kScrollFlingTimeConstant,
- base::BindRepeating(&GestureInterpreter::ScrollWithoutAbortAnimations,
- base::Unretained(this))) {}
- GestureInterpreter::~GestureInterpreter() = default;
- void GestureInterpreter::SetContext(RendererProxy* renderer,
- ChromotingSession* input_stub) {
- renderer_ = renderer;
- input_stub_ = input_stub;
- auto transformation_callback =
- renderer_ ? base::BindRepeating(&RendererProxy::SetTransformation,
- base::Unretained(renderer_))
- : DesktopViewport::TransformationCallback();
- viewport_.RegisterOnTransformationChangedCallback(transformation_callback,
- true);
- }
- void GestureInterpreter::SetInputMode(InputMode mode) {
- switch (mode) {
- case DIRECT_INPUT_MODE:
- input_strategy_ = std::make_unique<DirectTouchInputStrategy>();
- break;
- case TRACKPAD_INPUT_MODE:
- input_strategy_ = std::make_unique<TrackpadInputStrategy>(viewport_);
- break;
- default:
- NOTREACHED();
- }
- input_mode_ = mode;
- if (!renderer_) {
- return;
- }
- renderer_->SetCursorVisibility(input_strategy_->IsCursorVisible());
- ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
- renderer_->SetCursorPosition(cursor_position.x, cursor_position.y);
- }
- GestureInterpreter::InputMode GestureInterpreter::GetInputMode() const {
- return input_mode_;
- }
- void GestureInterpreter::Zoom(float pivot_x,
- float pivot_y,
- float scale,
- GestureState state) {
- AbortAnimations();
- SetGestureInProgress(TouchInputStrategy::ZOOM, state != GESTURE_ENDED);
- if (viewport_.IsViewportReady()) {
- input_strategy_->HandleZoom({pivot_x, pivot_y}, scale, &viewport_);
- }
- }
- void GestureInterpreter::Pan(float translation_x, float translation_y) {
- AbortAnimations();
- PanWithoutAbortAnimations(translation_x, translation_y);
- }
- void GestureInterpreter::Tap(float x, float y) {
- AbortAnimations();
- InjectMouseClick(x, y, protocol::MouseEvent_MouseButton_BUTTON_LEFT);
- }
- void GestureInterpreter::TwoFingerTap(float x, float y) {
- AbortAnimations();
- InjectMouseClick(x, y, protocol::MouseEvent_MouseButton_BUTTON_RIGHT);
- }
- void GestureInterpreter::ThreeFingerTap(float x, float y) {
- AbortAnimations();
- InjectMouseClick(x, y, protocol::MouseEvent_MouseButton_BUTTON_MIDDLE);
- }
- void GestureInterpreter::Drag(float x, float y, GestureState state) {
- AbortAnimations();
- bool is_dragging_mode = state != GESTURE_ENDED;
- SetGestureInProgress(TouchInputStrategy::DRAG, is_dragging_mode);
- if (!input_stub_ || !viewport_.IsViewportReady() ||
- !input_strategy_->TrackTouchInput({x, y}, viewport_)) {
- return;
- }
- ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
- switch (state) {
- case GESTURE_BEGAN:
- StartInputFeedback(cursor_position.x, cursor_position.y,
- TouchInputStrategy::DRAG_FEEDBACK);
- input_stub_->SendMouseEvent(cursor_position.x, cursor_position.y,
- protocol::MouseEvent_MouseButton_BUTTON_LEFT,
- true);
- break;
- case GESTURE_CHANGED:
- InjectCursorPosition(cursor_position.x, cursor_position.y);
- break;
- case GESTURE_ENDED:
- input_stub_->SendMouseEvent(cursor_position.x, cursor_position.y,
- protocol::MouseEvent_MouseButton_BUTTON_LEFT,
- false);
- break;
- default:
- NOTREACHED();
- }
- }
- void GestureInterpreter::OneFingerFling(float velocity_x, float velocity_y) {
- AbortAnimations();
- pan_animation_.SetVelocity(velocity_x, velocity_y);
- pan_animation_.Tick();
- }
- void GestureInterpreter::Scroll(float x, float y, float dx, float dy) {
- AbortAnimations();
- if (!viewport_.IsViewportReady() ||
- !input_strategy_->TrackTouchInput({x, y}, viewport_)) {
- return;
- }
- ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
- // Inject the cursor position to the host so that scrolling can happen on the
- // right place.
- InjectCursorPosition(cursor_position.x, cursor_position.y);
- ScrollWithoutAbortAnimations(dx, dy);
- }
- void GestureInterpreter::ScrollWithVelocity(float velocity_x,
- float velocity_y) {
- AbortAnimations();
- scroll_animation_.SetVelocity(velocity_x, velocity_y);
- scroll_animation_.Tick();
- }
- void GestureInterpreter::ProcessAnimations() {
- pan_animation_.Tick();
- // TODO(yuweih): It's probably not right to handle host side virtual scroll
- // momentum in the renderer's callback.
- scroll_animation_.Tick();
- }
- void GestureInterpreter::OnSurfaceSizeChanged(int width, int height) {
- viewport_.SetSurfaceSize(width, height);
- if (viewport_.IsViewportReady()) {
- input_strategy_->FocusViewportOnCursor(&viewport_);
- }
- }
- void GestureInterpreter::OnDesktopSizeChanged(int width, int height) {
- viewport_.SetDesktopSize(width, height);
- if (viewport_.IsViewportReady()) {
- input_strategy_->FocusViewportOnCursor(&viewport_);
- }
- }
- void GestureInterpreter::OnSafeInsetsChanged(int left,
- int top,
- int right,
- int bottom) {
- viewport_.SetSafeInsets(left, top, right, bottom);
- if (viewport_.IsViewportReady()) {
- input_strategy_->FocusViewportOnCursor(&viewport_);
- }
- }
- base::WeakPtr<GestureInterpreter> GestureInterpreter::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
- void GestureInterpreter::PanWithoutAbortAnimations(float translation_x,
- float translation_y) {
- if (viewport_.IsViewportReady() &&
- input_strategy_->HandlePan({translation_x, translation_y},
- gesture_in_progress_, &viewport_)) {
- // Cursor position changed.
- ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
- if (gesture_in_progress_ != TouchInputStrategy::DRAG) {
- // Drag() will inject the position so don't need to do that in that case.
- InjectCursorPosition(cursor_position.x, cursor_position.y);
- }
- if (renderer_) {
- renderer_->SetCursorPosition(cursor_position.x, cursor_position.y);
- }
- }
- }
- void GestureInterpreter::InjectCursorPosition(float x, float y) {
- if (!input_stub_) {
- return;
- }
- input_stub_->SendMouseEvent(
- x, y, protocol::MouseEvent_MouseButton_BUTTON_UNDEFINED, false);
- }
- void GestureInterpreter::ScrollWithoutAbortAnimations(float dx, float dy) {
- if (!input_stub_ || !viewport_.IsViewportReady()) {
- return;
- }
- ViewMatrix::Point desktopDelta =
- input_strategy_->MapScreenVectorToDesktop({dx, dy}, viewport_);
- input_stub_->SendMouseWheelEvent(desktopDelta.x, desktopDelta.y);
- }
- void GestureInterpreter::AbortAnimations() {
- pan_animation_.Abort();
- scroll_animation_.Abort();
- }
- void GestureInterpreter::InjectMouseClick(
- float touch_x,
- float touch_y,
- protocol::MouseEvent_MouseButton button) {
- if (!input_stub_ || !viewport_.IsViewportReady() ||
- !input_strategy_->TrackTouchInput({touch_x, touch_y}, viewport_)) {
- return;
- }
- ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition();
- StartInputFeedback(cursor_position.x, cursor_position.y,
- TouchInputStrategy::TAP_FEEDBACK);
- input_stub_->SendMouseEvent(cursor_position.x, cursor_position.y, button,
- true);
- input_stub_->SendMouseEvent(cursor_position.x, cursor_position.y, button,
- false);
- }
- void GestureInterpreter::SetGestureInProgress(
- TouchInputStrategy::Gesture gesture,
- bool is_in_progress) {
- if (!is_in_progress && gesture_in_progress_ == gesture) {
- gesture_in_progress_ = TouchInputStrategy::NONE;
- return;
- }
- gesture_in_progress_ = gesture;
- }
- void GestureInterpreter::StartInputFeedback(
- float cursor_x,
- float cursor_y,
- TouchInputStrategy::TouchFeedbackType feedback_type) {
- // This radius is on the view's coordinates. Need to be converted to desktop
- // coordinate.
- float feedback_radius = input_strategy_->GetFeedbackRadius(feedback_type);
- if (feedback_radius > 0) {
- // TODO(yuweih): The renderer takes diameter as parameter. Consider moving
- // the *2 logic inside the renderer.
- float diameter_on_desktop =
- 2.f * feedback_radius / viewport_.GetTransformation().GetScale();
- if (renderer_) {
- renderer_->StartInputFeedback(cursor_x, cursor_y, diameter_on_desktop);
- }
- }
- }
- } // namespace remoting
|