Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: remoting/client/plugin/chromoting_instance.cc

Issue 8985007: Refactoring of the client-side input pipeline and scaling dimension management. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/plugin/chromoting_instance.h" 5 #include "remoting/client/plugin/chromoting_instance.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/message_loop.h" 13 #include "base/message_loop.h"
14 #include "base/stringprintf.h" 14 #include "base/stringprintf.h"
15 #include "base/synchronization/lock.h" 15 #include "base/synchronization/lock.h"
16 #include "base/synchronization/waitable_event.h" 16 #include "base/synchronization/waitable_event.h"
17 #include "base/task.h" 17 #include "base/task.h"
18 #include "base/threading/thread.h" 18 #include "base/threading/thread.h"
19 #include "media/base/media.h" 19 #include "media/base/media.h"
20 #include "ppapi/cpp/completion_callback.h" 20 #include "ppapi/cpp/completion_callback.h"
21 #include "ppapi/cpp/input_event.h" 21 #include "ppapi/cpp/input_event.h"
22 #include "ppapi/cpp/rect.h" 22 #include "ppapi/cpp/rect.h"
23 // TODO(wez): Remove this when crbug.com/86353 is complete. 23 // TODO(wez): Remove this when crbug.com/86353 is complete.
24 #include "ppapi/cpp/private/var_private.h" 24 #include "ppapi/cpp/private/var_private.h"
25 #include "remoting/base/util.h" 25 #include "remoting/base/util.h"
26 #include "remoting/client/client_config.h" 26 #include "remoting/client/client_config.h"
27 #include "remoting/client/chromoting_client.h" 27 #include "remoting/client/chromoting_client.h"
28 #include "remoting/client/mouse_input_filter.h"
28 #include "remoting/client/plugin/chromoting_scriptable_object.h" 29 #include "remoting/client/plugin/chromoting_scriptable_object.h"
29 #include "remoting/client/plugin/pepper_input_handler.h" 30 #include "remoting/client/plugin/pepper_input_handler.h"
30 #include "remoting/client/plugin/pepper_view.h" 31 #include "remoting/client/plugin/pepper_view.h"
31 #include "remoting/client/plugin/pepper_view_proxy.h" 32 #include "remoting/client/plugin/pepper_view_proxy.h"
32 #include "remoting/client/plugin/pepper_xmpp_proxy.h" 33 #include "remoting/client/plugin/pepper_xmpp_proxy.h"
33 #include "remoting/client/rectangle_update_decoder.h" 34 #include "remoting/client/rectangle_update_decoder.h"
34 #include "remoting/protocol/connection_to_host.h" 35 #include "remoting/protocol/connection_to_host.h"
35 #include "remoting/protocol/host_stub.h" 36 #include "remoting/protocol/host_stub.h"
37 #include "remoting/protocol/key_event_tracker.h"
36 38
37 namespace remoting { 39 namespace remoting {
38 40
39 // This flag blocks LOGs to the UI if we're already in the middle of logging 41 // This flag blocks LOGs to the UI if we're already in the middle of logging
40 // to the UI. This prevents a potential infinite loop if we encounter an error 42 // to the UI. This prevents a potential infinite loop if we encounter an error
41 // while sending the log message to the UI. 43 // while sending the log message to the UI.
42 static bool g_logging_to_plugin = false; 44 static bool g_logging_to_plugin = false;
43 static bool g_has_logging_instance = false; 45 static bool g_has_logging_instance = false;
44 static ChromotingInstance* g_logging_instance = NULL; 46 static ChromotingInstance* g_logging_instance = NULL;
45 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL; 47 static logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 view_->SetSolidFill(0xFFCDCDCD); 128 view_->SetSolidFill(0xFFCDCDCD);
127 129
128 return true; 130 return true;
129 } 131 }
130 132
131 void ChromotingInstance::Connect(const ClientConfig& config) { 133 void ChromotingInstance::Connect(const ClientConfig& config) {
132 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 134 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
133 135
134 host_connection_.reset(new protocol::ConnectionToHost( 136 host_connection_.reset(new protocol::ConnectionToHost(
135 context_.network_message_loop(), this, true)); 137 context_.network_message_loop(), this, true));
136
137 input_handler_.reset(new PepperInputHandler(&context_,
138 host_connection_.get(),
139 view_proxy_));
140
141 client_.reset(new ChromotingClient(config, &context_, host_connection_.get(), 138 client_.reset(new ChromotingClient(config, &context_, host_connection_.get(),
142 view_proxy_, rectangle_decoder_.get(), 139 view_proxy_, rectangle_decoder_.get(),
143 input_handler_.get(), base::Closure())); 140 base::Closure()));
144 141
145 LOG(INFO) << "Connecting to " << config.host_jid 142 LOG(INFO) << "Connecting to " << config.host_jid
146 << ". Local jid: " << config.local_jid << "."; 143 << ". Local jid: " << config.local_jid << ".";
147 144
148 // Setup the XMPP Proxy. 145 // Setup the XMPP Proxy.
149 ChromotingScriptableObject* scriptable_object = GetScriptableObject(); 146 ChromotingScriptableObject* scriptable_object = GetScriptableObject();
150 scoped_refptr<PepperXmppProxy> xmpp_proxy = 147 scoped_refptr<PepperXmppProxy> xmpp_proxy =
151 new PepperXmppProxy(scriptable_object->AsWeakPtr(), 148 new PepperXmppProxy(scriptable_object->AsWeakPtr(),
152 plugin_message_loop_, 149 plugin_message_loop_,
153 context_.network_message_loop()); 150 context_.network_message_loop());
(...skipping 15 matching lines...) Expand all
169 if (client_.get()) { 166 if (client_.get()) {
170 // TODO(sergeyu): Should we disconnect asynchronously? 167 // TODO(sergeyu): Should we disconnect asynchronously?
171 base::WaitableEvent done_event(true, false); 168 base::WaitableEvent done_event(true, false);
172 client_->Stop(base::Bind(&base::WaitableEvent::Signal, 169 client_->Stop(base::Bind(&base::WaitableEvent::Signal,
173 base::Unretained(&done_event))); 170 base::Unretained(&done_event)));
174 done_event.Wait(); 171 done_event.Wait();
175 client_.reset(); 172 client_.reset();
176 } 173 }
177 174
178 input_handler_.reset(); 175 input_handler_.reset();
176 key_event_tracker_.reset();
177 mouse_input_filter_.reset();
179 host_connection_.reset(); 178 host_connection_.reset();
180 179
181 GetScriptableObject()->SetConnectionStatus( 180 GetScriptableObject()->SetConnectionStatus(
182 ChromotingScriptableObject::STATUS_CLOSED, 181 ChromotingScriptableObject::STATUS_CLOSED,
183 ChromotingScriptableObject::ERROR_NONE); 182 ChromotingScriptableObject::ERROR_NONE);
184 } 183 }
185 184
186 void ChromotingInstance::DidChangeView(const pp::Rect& position, 185 void ChromotingInstance::DidChangeView(const pp::Rect& position,
187 const pp::Rect& clip) { 186 const pp::Rect& clip) {
188 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 187 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
189 188
190 view_->SetPluginSize(SkISize::Make(position.width(), position.height())); 189 SkISize new_size = SkISize::Make(position.width(), position.height());
191 190 if (view_->GetViewDimensions() != new_size) {
192 // TODO(wez): Pass the dimensions of the plugin to the RectangleDecoder 191 view_->SetPluginSize(new_size);
193 // and let it generate the necessary refresh events. 192 if (mouse_input_filter_.get()) {
194 // If scale-to-fit is enabled then update the scaling ratios. 193 mouse_input_filter_->SetInputDimensions(new_size);
195 // We also force a full-frame refresh, in case the ratios changed. 194 }
196 if (scale_to_fit_) { 195 rectangle_decoder_->SetOutputDimensions(new_size);
197 rectangle_decoder_->SetScaleRatios(view_->GetHorizontalScaleRatio(),
198 view_->GetVerticalScaleRatio());
199 rectangle_decoder_->RefreshFullFrame();
200 } 196 }
201 197
202 // Notify the RectangleDecoder of the new clip rect.
203 rectangle_decoder_->UpdateClipRect( 198 rectangle_decoder_->UpdateClipRect(
204 SkIRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height())); 199 SkIRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height()));
205 } 200 }
206 201
207 bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) { 202 bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) {
208 DCHECK(plugin_message_loop_->BelongsToCurrentThread()); 203 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
209 if (!input_handler_.get()) { 204
205 // Never inject events if the end of the input pipeline doesn't exist.
206 // If it does exist but the pipeline doesn't, construct a pipeline.
207 // TODO(wez): This is really ugly. We should create the pipeline when
208 // the ConnectionToHost's InputStub exists.
209 if (!host_connection_.get()) {
210 return false; 210 return false;
211 } else if (!input_handler_.get()) {
212 protocol::InputStub* input_stub = host_connection_->input_stub();
213 if (!input_stub)
214 return false;
215 mouse_input_filter_.reset(new MouseInputFilter(input_stub));
216 mouse_input_filter_->SetInputDimensions(view_->GetViewDimensions());
217 key_event_tracker_.reset(
218 new protocol::KeyEventTracker(mouse_input_filter_.get()));
219 input_handler_.reset(
220 new PepperInputHandler(key_event_tracker_.get()));
211 } 221 }
212 222
213 PepperInputHandler* pih 223 // TODO(wez): When we have a good hook into Host dimensions changes, move
214 = static_cast<PepperInputHandler*>(input_handler_.get()); 224 // this there.
225 mouse_input_filter_->SetOutputDimensions(view_->GetHostDimensions());
215 226
216 switch (event.GetType()) { 227 return input_handler_->HandleInputEvent(event);
217 case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
218 pih->HandleMouseButtonEvent(true, pp::MouseInputEvent(event));
219 return true;
220 }
221
222 case PP_INPUTEVENT_TYPE_MOUSEUP: {
223 pih->HandleMouseButtonEvent(false, pp::MouseInputEvent(event));
224 return true;
225 }
226
227 case PP_INPUTEVENT_TYPE_MOUSEMOVE:
228 case PP_INPUTEVENT_TYPE_MOUSEENTER:
229 case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
230 pih->HandleMouseMoveEvent(pp::MouseInputEvent(event));
231 return true;
232 }
233
234 case PP_INPUTEVENT_TYPE_WHEEL: {
235 pih->HandleMouseWheelEvent(pp::WheelInputEvent(event));
236 return true;
237 }
238
239 case PP_INPUTEVENT_TYPE_CONTEXTMENU: {
240 // We need to return true here or else we'll get a local (plugin) context
241 // menu instead of the mouseup event for the right click.
242 return true;
243 }
244
245 case PP_INPUTEVENT_TYPE_KEYDOWN: {
246 pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event);
247 VLOG(3) << "PP_INPUTEVENT_TYPE_KEYDOWN" << " key=" << key.GetKeyCode();
248 pih->HandleKeyEvent(true, key);
249 return true;
250 }
251
252 case PP_INPUTEVENT_TYPE_KEYUP: {
253 pp::KeyboardInputEvent key = pp::KeyboardInputEvent(event);
254 VLOG(3) << "PP_INPUTEVENT_TYPE_KEYUP" << " key=" << key.GetKeyCode();
255 pih->HandleKeyEvent(false, key);
256 return true;
257 }
258
259 case PP_INPUTEVENT_TYPE_CHAR: {
260 pih->HandleCharacterEvent(pp::KeyboardInputEvent(event));
261 return true;
262 }
263
264 default: {
265 LOG(INFO) << "Unhandled input event: " << event.GetType();
266 break;
267 }
268 }
269
270 return false;
271 } 228 }
272 229
273 ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() { 230 ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() {
274 pp::VarPrivate object = GetInstanceObject(); 231 pp::VarPrivate object = GetInstanceObject();
275 if (!object.is_undefined()) { 232 if (!object.is_undefined()) {
276 pp::deprecated::ScriptableObject* so = object.AsScriptableObject(); 233 pp::deprecated::ScriptableObject* so = object.AsScriptableObject();
277 DCHECK(so != NULL); 234 DCHECK(so != NULL);
278 return static_cast<ChromotingScriptableObject*>(so); 235 return static_cast<ChromotingScriptableObject*>(so);
279 } 236 }
280 LOG(ERROR) << "Unable to get ScriptableObject for Chromoting plugin."; 237 LOG(ERROR) << "Unable to get ScriptableObject for Chromoting plugin.";
281 return NULL; 238 return NULL;
282 } 239 }
283 240
284 void ChromotingInstance::SetScaleToFit(bool scale_to_fit) {
285 DCHECK(plugin_message_loop_->BelongsToCurrentThread());
286
287 if (scale_to_fit == scale_to_fit_)
288 return;
289
290 scale_to_fit_ = scale_to_fit;
291 if (scale_to_fit) {
292 rectangle_decoder_->SetScaleRatios(view_->GetHorizontalScaleRatio(),
293 view_->GetVerticalScaleRatio());
294 } else {
295 rectangle_decoder_->SetScaleRatios(1.0, 1.0);
296 }
297
298 // TODO(wez): The RectangleDecoder should generate refresh events
299 // as necessary in response to any scaling change.
300 rectangle_decoder_->RefreshFullFrame();
301 }
302
303 // static 241 // static
304 void ChromotingInstance::RegisterLogMessageHandler() { 242 void ChromotingInstance::RegisterLogMessageHandler() {
305 base::AutoLock lock(g_logging_lock.Get()); 243 base::AutoLock lock(g_logging_lock.Get());
306 244
307 VLOG(1) << "Registering global log handler"; 245 VLOG(1) << "Registering global log handler";
308 246
309 // Record previous handler so we can call it in a chain. 247 // Record previous handler so we can call it in a chain.
310 g_logging_old_handler = logging::GetLogMessageHandler(); 248 g_logging_old_handler = logging::GetLogMessageHandler();
311 249
312 // Set up log message handler. 250 // Set up log message handler.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 return instance_object_; 335 return instance_object_;
398 } 336 }
399 337
400 ChromotingStats* ChromotingInstance::GetStats() { 338 ChromotingStats* ChromotingInstance::GetStats() {
401 if (!client_.get()) 339 if (!client_.get())
402 return NULL; 340 return NULL;
403 return client_->GetStats(); 341 return client_->GetStats();
404 } 342 }
405 343
406 void ChromotingInstance::ReleaseAllKeys() { 344 void ChromotingInstance::ReleaseAllKeys() {
407 if (!input_handler_.get()) { 345 if (key_event_tracker_.get()) {
408 return; 346 key_event_tracker_->ReleaseAllKeys();
409 } 347 }
410
411 input_handler_->ReleaseAllKeys();
412 } 348 }
413 349
414 } // namespace remoting 350 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698