| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/client/ui/gesture_interpreter.h" | 5 #include "remoting/client/ui/gesture_interpreter.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/time/time.h" | 8 #include "base/time/time.h" |
| 9 #include "remoting/client/chromoting_session.h" | 9 #include "remoting/client/chromoting_session.h" |
| 10 #include "remoting/client/ui/direct_input_strategy.h" | 10 #include "remoting/client/ui/direct_input_strategy.h" |
| 11 #include "remoting/client/ui/renderer_proxy.h" | 11 #include "remoting/client/ui/renderer_proxy.h" |
| 12 #include "remoting/client/ui/trackpad_input_strategy.h" |
| 12 | 13 |
| 13 namespace { | 14 namespace { |
| 14 | 15 |
| 15 const float kOneFingerFlingTimeConstant = 325.f; | 16 const float kOneFingerFlingTimeConstant = 325.f; |
| 16 const float kScrollFlingTimeConstant = 120.f; | 17 const float kScrollFlingTimeConstant = 120.f; |
| 17 | 18 |
| 18 } // namespace | 19 } // namespace |
| 19 | 20 |
| 20 namespace remoting { | 21 namespace remoting { |
| 21 GestureInterpreter::GestureInterpreter(RendererProxy* renderer, | 22 GestureInterpreter::GestureInterpreter(RendererProxy* renderer, |
| 22 ChromotingSession* input_stub) | 23 ChromotingSession* input_stub) |
| 23 : renderer_(renderer), | 24 : renderer_(renderer), |
| 24 input_stub_(input_stub), | 25 input_stub_(input_stub), |
| 25 pan_animation_(kOneFingerFlingTimeConstant, | 26 pan_animation_(kOneFingerFlingTimeConstant, |
| 26 base::Bind(&GestureInterpreter::PanWithoutAbortAnimations, | 27 base::Bind(&GestureInterpreter::PanWithoutAbortAnimations, |
| 27 base::Unretained(this))), | 28 base::Unretained(this))), |
| 28 scroll_animation_( | 29 scroll_animation_( |
| 29 kScrollFlingTimeConstant, | 30 kScrollFlingTimeConstant, |
| 30 base::Bind(&GestureInterpreter::ScrollWithoutAbortAnimations, | 31 base::Bind(&GestureInterpreter::ScrollWithoutAbortAnimations, |
| 31 base::Unretained(this))) { | 32 base::Unretained(this))) { |
| 32 viewport_.RegisterOnTransformationChangedCallback( | 33 viewport_.RegisterOnTransformationChangedCallback( |
| 33 base::Bind(&RendererProxy::SetTransformation, | 34 base::Bind(&RendererProxy::SetTransformation, |
| 34 base::Unretained(renderer_)), | 35 base::Unretained(renderer_)), |
| 35 true); | 36 true); |
| 36 | |
| 37 // TODO(yuweih): This should be configurable. | |
| 38 input_strategy_.reset(new DirectInputStrategy()); | |
| 39 renderer_->SetCursorVisibility(input_strategy_->IsCursorVisible()); | |
| 40 SetCursorPositionOnRenderer(); | |
| 41 } | 37 } |
| 42 | 38 |
| 43 GestureInterpreter::~GestureInterpreter() {} | 39 GestureInterpreter::~GestureInterpreter() {} |
| 44 | 40 |
| 45 void GestureInterpreter::Pinch(float pivot_x, float pivot_y, float scale) { | 41 void GestureInterpreter::SetInputMode(InputMode mode) { |
| 42 switch (mode) { |
| 43 case DIRECT_INPUT_MODE: |
| 44 input_strategy_.reset(new DirectInputStrategy()); |
| 45 break; |
| 46 case TRACKPAD_INPUT_MODE: |
| 47 input_strategy_.reset(new TrackpadInputStrategy(viewport_)); |
| 48 break; |
| 49 default: |
| 50 NOTREACHED(); |
| 51 } |
| 52 input_mode_ = mode; |
| 53 renderer_->SetCursorVisibility(input_strategy_->IsCursorVisible()); |
| 54 ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition(); |
| 55 renderer_->SetCursorPosition(cursor_position.x, cursor_position.y); |
| 56 } |
| 57 |
| 58 GestureInterpreter::InputMode GestureInterpreter::GetInputMode() const { |
| 59 return input_mode_; |
| 60 } |
| 61 |
| 62 void GestureInterpreter::Zoom(float pivot_x, |
| 63 float pivot_y, |
| 64 float scale, |
| 65 GestureState state) { |
| 46 AbortAnimations(); | 66 AbortAnimations(); |
| 47 input_strategy_->HandlePinch({pivot_x, pivot_y}, scale, &viewport_); | 67 SetGestureInProgress(InputStrategy::ZOOM, state != GESTURE_ENDED); |
| 68 input_strategy_->HandleZoom({pivot_x, pivot_y}, scale, &viewport_); |
| 48 } | 69 } |
| 49 | 70 |
| 50 void GestureInterpreter::Pan(float translation_x, float translation_y) { | 71 void GestureInterpreter::Pan(float translation_x, float translation_y) { |
| 51 AbortAnimations(); | 72 AbortAnimations(); |
| 52 PanWithoutAbortAnimations(translation_x, translation_y); | 73 PanWithoutAbortAnimations(translation_x, translation_y); |
| 53 } | 74 } |
| 54 | 75 |
| 55 void GestureInterpreter::Tap(float x, float y) { | 76 void GestureInterpreter::Tap(float x, float y) { |
| 56 AbortAnimations(); | 77 AbortAnimations(); |
| 57 | 78 |
| 58 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); | 79 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); |
| 59 StartInputFeedback(cursor_position.x, cursor_position.y, | 80 StartInputFeedback(cursor_position.x, cursor_position.y, |
| 60 InputStrategy::TAP_FEEDBACK); | 81 InputStrategy::TAP_FEEDBACK); |
| 61 InjectMouseClick(cursor_position.x, cursor_position.y, | 82 InjectMouseClick(cursor_position.x, cursor_position.y, |
| 62 protocol::MouseEvent_MouseButton_BUTTON_LEFT); | 83 protocol::MouseEvent_MouseButton_BUTTON_LEFT); |
| 63 } | 84 } |
| 64 | 85 |
| 65 void GestureInterpreter::TwoFingerTap(float x, float y) { | 86 void GestureInterpreter::TwoFingerTap(float x, float y) { |
| 66 AbortAnimations(); | 87 AbortAnimations(); |
| 67 | 88 |
| 68 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); | 89 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); |
| 69 InjectMouseClick(cursor_position.x, cursor_position.y, | 90 InjectMouseClick(cursor_position.x, cursor_position.y, |
| 70 protocol::MouseEvent_MouseButton_BUTTON_RIGHT); | 91 protocol::MouseEvent_MouseButton_BUTTON_RIGHT); |
| 71 } | 92 } |
| 72 | 93 |
| 73 void GestureInterpreter::LongPress(float x, float y, GestureState state) { | 94 void GestureInterpreter::Drag(float x, float y, GestureState state) { |
| 74 AbortAnimations(); | 95 AbortAnimations(); |
| 75 | 96 |
| 76 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); | 97 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); |
| 77 | 98 |
| 78 if (state == GESTURE_BEGAN) { | 99 if (state == GESTURE_BEGAN) { |
| 79 StartInputFeedback(cursor_position.x, cursor_position.y, | 100 StartInputFeedback(cursor_position.x, cursor_position.y, |
| 80 InputStrategy::LONG_PRESS_FEEDBACK); | 101 InputStrategy::DRAG_FEEDBACK); |
| 81 } | 102 } |
| 82 | 103 |
| 83 is_dragging_mode_ = state != GESTURE_ENDED; | 104 bool is_dragging_mode = state != GESTURE_ENDED; |
| 105 SetGestureInProgress(InputStrategy::DRAG, is_dragging_mode); |
| 84 input_stub_->SendMouseEvent(cursor_position.x, cursor_position.y, | 106 input_stub_->SendMouseEvent(cursor_position.x, cursor_position.y, |
| 85 protocol::MouseEvent_MouseButton_BUTTON_LEFT, | 107 protocol::MouseEvent_MouseButton_BUTTON_LEFT, |
| 86 is_dragging_mode_); | 108 is_dragging_mode); |
| 87 } | 109 } |
| 88 | 110 |
| 89 void GestureInterpreter::OneFingerFling(float velocity_x, float velocity_y) { | 111 void GestureInterpreter::OneFingerFling(float velocity_x, float velocity_y) { |
| 90 AbortAnimations(); | 112 AbortAnimations(); |
| 91 pan_animation_.SetVelocity(velocity_x, velocity_y); | 113 pan_animation_.SetVelocity(velocity_x, velocity_y); |
| 92 pan_animation_.Tick(); | 114 pan_animation_.Tick(); |
| 93 } | 115 } |
| 94 | 116 |
| 95 void GestureInterpreter::Scroll(float x, float y, float dx, float dy) { | 117 void GestureInterpreter::Scroll(float x, float y, float dx, float dy) { |
| 96 AbortAnimations(); | 118 AbortAnimations(); |
| 97 | 119 |
| 98 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); | 120 ViewMatrix::Point cursor_position = TrackAndGetPosition(x, y); |
| 99 | 121 |
| 100 // Inject the cursor position to the host so that scrolling can happen on the | 122 // Inject the cursor position to the host so that scrolling can happen on the |
| 101 // right place. | 123 // right place. |
| 102 input_stub_->SendMouseEvent(cursor_position.x, cursor_position.y, | 124 InjectCursorPosition(cursor_position.x, cursor_position.y); |
| 103 protocol::MouseEvent_MouseButton_BUTTON_UNDEFINED, | |
| 104 false); | |
| 105 | 125 |
| 106 ScrollWithoutAbortAnimations(dx, dy); | 126 ScrollWithoutAbortAnimations(dx, dy); |
| 107 } | 127 } |
| 108 | 128 |
| 109 void GestureInterpreter::ScrollWithVelocity(float velocity_x, | 129 void GestureInterpreter::ScrollWithVelocity(float velocity_x, |
| 110 float velocity_y) { | 130 float velocity_y) { |
| 111 AbortAnimations(); | 131 AbortAnimations(); |
| 112 | 132 |
| 113 scroll_animation_.SetVelocity(velocity_x, velocity_y); | 133 scroll_animation_.SetVelocity(velocity_x, velocity_y); |
| 114 scroll_animation_.Tick(); | 134 scroll_animation_.Tick(); |
| 115 } | 135 } |
| 116 | 136 |
| 117 void GestureInterpreter::ProcessAnimations() { | 137 void GestureInterpreter::ProcessAnimations() { |
| 118 pan_animation_.Tick(); | 138 pan_animation_.Tick(); |
| 119 scroll_animation_.Tick(); | 139 scroll_animation_.Tick(); |
| 120 } | 140 } |
| 121 | 141 |
| 122 void GestureInterpreter::OnSurfaceSizeChanged(int width, int height) { | 142 void GestureInterpreter::OnSurfaceSizeChanged(int width, int height) { |
| 123 viewport_.SetSurfaceSize(width, height); | 143 viewport_.SetSurfaceSize(width, height); |
| 124 } | 144 } |
| 125 | 145 |
| 126 void GestureInterpreter::OnDesktopSizeChanged(int width, int height) { | 146 void GestureInterpreter::OnDesktopSizeChanged(int width, int height) { |
| 127 viewport_.SetDesktopSize(width, height); | 147 viewport_.SetDesktopSize(width, height); |
| 128 } | 148 } |
| 129 | 149 |
| 130 void GestureInterpreter::PanWithoutAbortAnimations(float translation_x, | 150 void GestureInterpreter::PanWithoutAbortAnimations(float translation_x, |
| 131 float translation_y) { | 151 float translation_y) { |
| 132 input_strategy_->HandlePan({translation_x, translation_y}, is_dragging_mode_, | 152 if (input_strategy_->HandlePan({translation_x, translation_y}, |
| 133 &viewport_); | 153 gesture_in_progress_, &viewport_)) { |
| 134 SetCursorPositionOnRenderer(); | 154 // Cursor position changed. |
| 155 ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition(); |
| 156 if (gesture_in_progress_ != InputStrategy::DRAG) { |
| 157 // Drag() will inject the position so don't need to do that in that case. |
| 158 InjectCursorPosition(cursor_position.x, cursor_position.y); |
| 159 } |
| 160 renderer_->SetCursorPosition(cursor_position.x, cursor_position.y); |
| 161 } |
| 162 } |
| 163 |
| 164 void GestureInterpreter::InjectCursorPosition(float x, float y) { |
| 165 input_stub_->SendMouseEvent( |
| 166 x, y, protocol::MouseEvent_MouseButton_BUTTON_UNDEFINED, false); |
| 135 } | 167 } |
| 136 | 168 |
| 137 void GestureInterpreter::ScrollWithoutAbortAnimations(float dx, float dy) { | 169 void GestureInterpreter::ScrollWithoutAbortAnimations(float dx, float dy) { |
| 138 ViewMatrix::Point desktopDelta = | 170 ViewMatrix::Point desktopDelta = |
| 139 input_strategy_->MapScreenVectorToDesktop({dx, dy}, viewport_); | 171 input_strategy_->MapScreenVectorToDesktop({dx, dy}, viewport_); |
| 140 input_stub_->SendMouseWheelEvent(desktopDelta.x, desktopDelta.y); | 172 input_stub_->SendMouseWheelEvent(desktopDelta.x, desktopDelta.y); |
| 141 } | 173 } |
| 142 | 174 |
| 143 void GestureInterpreter::AbortAnimations() { | 175 void GestureInterpreter::AbortAnimations() { |
| 144 pan_animation_.Abort(); | 176 pan_animation_.Abort(); |
| 145 } | 177 } |
| 146 | 178 |
| 147 void GestureInterpreter::InjectMouseClick( | 179 void GestureInterpreter::InjectMouseClick( |
| 148 float x, | 180 float x, |
| 149 float y, | 181 float y, |
| 150 protocol::MouseEvent_MouseButton button) { | 182 protocol::MouseEvent_MouseButton button) { |
| 151 input_stub_->SendMouseEvent(x, y, button, true); | 183 input_stub_->SendMouseEvent(x, y, button, true); |
| 152 input_stub_->SendMouseEvent(x, y, button, false); | 184 input_stub_->SendMouseEvent(x, y, button, false); |
| 153 } | 185 } |
| 154 | 186 |
| 187 void GestureInterpreter::SetGestureInProgress(InputStrategy::Gesture gesture, |
| 188 bool is_in_progress) { |
| 189 if (!is_in_progress && gesture_in_progress_ == gesture) { |
| 190 gesture_in_progress_ = InputStrategy::NONE; |
| 191 return; |
| 192 } |
| 193 gesture_in_progress_ = gesture; |
| 194 } |
| 195 |
| 155 ViewMatrix::Point GestureInterpreter::TrackAndGetPosition(float touch_x, | 196 ViewMatrix::Point GestureInterpreter::TrackAndGetPosition(float touch_x, |
| 156 float touch_y) { | 197 float touch_y) { |
| 157 input_strategy_->TrackTouchInput({touch_x, touch_y}, viewport_); | 198 input_strategy_->TrackTouchInput({touch_x, touch_y}, viewport_); |
| 158 return input_strategy_->GetCursorPosition(); | 199 return input_strategy_->GetCursorPosition(); |
| 159 } | 200 } |
| 160 | 201 |
| 161 void GestureInterpreter::SetCursorPositionOnRenderer() { | |
| 162 if (input_strategy_->IsCursorVisible()) { | |
| 163 ViewMatrix::Point cursor_position = input_strategy_->GetCursorPosition(); | |
| 164 renderer_->SetCursorPosition(cursor_position.x, cursor_position.y); | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 void GestureInterpreter::StartInputFeedback( | 202 void GestureInterpreter::StartInputFeedback( |
| 169 float cursor_x, | 203 float cursor_x, |
| 170 float cursor_y, | 204 float cursor_y, |
| 171 InputStrategy::InputFeedbackType feedback_type) { | 205 InputStrategy::InputFeedbackType feedback_type) { |
| 172 // This radius is on the view's coordinates. Need to be converted to desktop | 206 // This radius is on the view's coordinates. Need to be converted to desktop |
| 173 // coordinate. | 207 // coordinate. |
| 174 float feedback_radius = input_strategy_->GetFeedbackRadius(feedback_type); | 208 float feedback_radius = input_strategy_->GetFeedbackRadius(feedback_type); |
| 175 if (feedback_radius > 0) { | 209 if (feedback_radius > 0) { |
| 176 // TODO(yuweih): The renderer takes diameter as parameter. Consider moving | 210 // TODO(yuweih): The renderer takes diameter as parameter. Consider moving |
| 177 // the *2 logic inside the renderer. | 211 // the *2 logic inside the renderer. |
| 178 float diameter_on_desktop = | 212 float diameter_on_desktop = |
| 179 2.f * feedback_radius / viewport_.GetTransformation().GetScale(); | 213 2.f * feedback_radius / viewport_.GetTransformation().GetScale(); |
| 180 renderer_->StartInputFeedback(cursor_x, cursor_y, diameter_on_desktop); | 214 renderer_->StartInputFeedback(cursor_x, cursor_y, diameter_on_desktop); |
| 181 } | 215 } |
| 182 } | 216 } |
| 183 | 217 |
| 184 } // namespace remoting | 218 } // namespace remoting |
| OLD | NEW |