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