OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/browser/renderer_host/render_widget_host.h" | 5 #include "chrome/browser/renderer_host/render_widget_host.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/histogram.h" | 8 #include "base/histogram.h" |
9 #include "base/keyboard_codes.h" | 9 #include "base/keyboard_codes.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 | 44 |
45 // How long to (synchronously) wait for the renderer to respond with a | 45 // How long to (synchronously) wait for the renderer to respond with a |
46 // PaintRect message, when our backing-store is invalid, before giving up and | 46 // PaintRect message, when our backing-store is invalid, before giving up and |
47 // returning a null or incorrectly sized backing-store from GetBackingStore. | 47 // returning a null or incorrectly sized backing-store from GetBackingStore. |
48 // This timeout impacts the "choppiness" of our window resize perf. | 48 // This timeout impacts the "choppiness" of our window resize perf. |
49 static const int kPaintMsgTimeoutMS = 40; | 49 static const int kPaintMsgTimeoutMS = 40; |
50 | 50 |
51 // How long to wait before we consider a renderer hung. | 51 // How long to wait before we consider a renderer hung. |
52 static const int kHungRendererDelayMs = 20000; | 52 static const int kHungRendererDelayMs = 20000; |
53 | 53 |
54 // How long a PaintRect_ACK message can be postponed at most, in milliseconds. | |
55 static const int kPaintACKMsgMaxPostponedDurationMS = 1000; | |
56 | |
57 /////////////////////////////////////////////////////////////////////////////// | 54 /////////////////////////////////////////////////////////////////////////////// |
58 // RenderWidgetHost | 55 // RenderWidgetHost |
59 | 56 |
60 RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, | 57 RenderWidgetHost::RenderWidgetHost(RenderProcessHost* process, |
61 int routing_id) | 58 int routing_id) |
62 : renderer_initialized_(false), | 59 : renderer_initialized_(false), |
63 view_(NULL), | 60 view_(NULL), |
64 process_(process), | 61 process_(process), |
65 painting_observer_(NULL), | 62 painting_observer_(NULL), |
66 routing_id_(routing_id), | 63 routing_id_(routing_id), |
67 is_loading_(false), | 64 is_loading_(false), |
68 is_hidden_(false), | 65 is_hidden_(false), |
69 repaint_ack_pending_(false), | 66 repaint_ack_pending_(false), |
70 resize_ack_pending_(false), | 67 resize_ack_pending_(false), |
71 mouse_move_pending_(false), | 68 mouse_move_pending_(false), |
72 needs_repainting_on_restore_(false), | 69 needs_repainting_on_restore_(false), |
73 is_unresponsive_(false), | 70 is_unresponsive_(false), |
74 in_get_backing_store_(false), | 71 in_get_backing_store_(false), |
75 view_being_painted_(false), | 72 view_being_painted_(false), |
76 text_direction_updated_(false), | 73 text_direction_updated_(false), |
77 text_direction_(WebKit::WebTextDirectionLeftToRight), | 74 text_direction_(WebKit::WebTextDirectionLeftToRight), |
78 text_direction_canceled_(false), | 75 text_direction_canceled_(false), |
79 pending_key_events_(0), | 76 suppress_next_char_events_(false) { |
80 suppress_next_char_events_(false), | |
81 paint_ack_postponed_(false), | |
82 death_flag_(NULL) { | |
83 if (routing_id_ == MSG_ROUTING_NONE) | 77 if (routing_id_ == MSG_ROUTING_NONE) |
84 routing_id_ = process_->GetNextRoutingID(); | 78 routing_id_ = process_->GetNextRoutingID(); |
85 | 79 |
86 process_->Attach(this, routing_id_); | 80 process_->Attach(this, routing_id_); |
87 // Because the widget initializes as is_hidden_ == false, | 81 // Because the widget initializes as is_hidden_ == false, |
88 // tell the process host that we're alive. | 82 // tell the process host that we're alive. |
89 process_->WidgetRestored(); | 83 process_->WidgetRestored(); |
90 } | 84 } |
91 | 85 |
92 RenderWidgetHost::~RenderWidgetHost() { | 86 RenderWidgetHost::~RenderWidgetHost() { |
93 // Force the method that destroys this object to exit immediately. | |
94 if (death_flag_) | |
95 *death_flag_ = true; | |
96 | |
97 // Clear our current or cached backing store if either remains. | 87 // Clear our current or cached backing store if either remains. |
98 BackingStoreManager::RemoveBackingStore(this); | 88 BackingStoreManager::RemoveBackingStore(this); |
99 | 89 |
100 process_->Release(routing_id_); | 90 process_->Release(routing_id_); |
101 } | 91 } |
102 | 92 |
103 gfx::NativeViewId RenderWidgetHost::GetNativeViewId() { | 93 gfx::NativeViewId RenderWidgetHost::GetNativeViewId() { |
104 if (view_) | 94 if (view_) |
105 return gfx::IdFromNativeView(view_->GetNativeView()); | 95 return gfx::IdFromNativeView(view_->GetNativeView()); |
106 return NULL; | 96 return NULL; |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 if (mouse_event.type == WebInputEvent::MouseMove) { | 358 if (mouse_event.type == WebInputEvent::MouseMove) { |
369 if (mouse_move_pending_) { | 359 if (mouse_move_pending_) { |
370 next_mouse_move_.reset(new WebMouseEvent(mouse_event)); | 360 next_mouse_move_.reset(new WebMouseEvent(mouse_event)); |
371 return; | 361 return; |
372 } | 362 } |
373 mouse_move_pending_ = true; | 363 mouse_move_pending_ = true; |
374 } else if (mouse_event.type == WebInputEvent::MouseDown) { | 364 } else if (mouse_event.type == WebInputEvent::MouseDown) { |
375 OnUserGesture(); | 365 OnUserGesture(); |
376 } | 366 } |
377 | 367 |
378 ForwardInputEvent(mouse_event, sizeof(WebMouseEvent)); | 368 ForwardInputEvent(mouse_event, sizeof(WebMouseEvent), false); |
379 } | 369 } |
380 | 370 |
381 void RenderWidgetHost::ForwardWheelEvent( | 371 void RenderWidgetHost::ForwardWheelEvent( |
382 const WebMouseWheelEvent& wheel_event) { | 372 const WebMouseWheelEvent& wheel_event) { |
383 if (process_->ignore_input_events()) | 373 if (process_->ignore_input_events()) |
384 return; | 374 return; |
385 | 375 |
386 ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent)); | 376 ForwardInputEvent(wheel_event, sizeof(WebMouseWheelEvent), false); |
387 } | 377 } |
388 | 378 |
389 void RenderWidgetHost::ForwardKeyboardEvent( | 379 void RenderWidgetHost::ForwardKeyboardEvent( |
390 const NativeWebKeyboardEvent& key_event) { | 380 const NativeWebKeyboardEvent& key_event) { |
391 if (process_->ignore_input_events()) | 381 if (process_->ignore_input_events()) |
392 return; | 382 return; |
393 | 383 |
394 if (key_event.type == WebKeyboardEvent::Char && | 384 if (key_event.type == WebKeyboardEvent::Char && |
395 (key_event.windowsKeyCode == base::VKEY_RETURN || | 385 (key_event.windowsKeyCode == base::VKEY_RETURN || |
396 key_event.windowsKeyCode == base::VKEY_SPACE)) { | 386 key_event.windowsKeyCode == base::VKEY_SPACE)) { |
397 OnUserGesture(); | 387 OnUserGesture(); |
398 } | 388 } |
399 | 389 |
400 // Double check the type to make sure caller hasn't sent us nonsense that | 390 // Double check the type to make sure caller hasn't sent us nonsense that |
401 // will mess up our key queue. | 391 // will mess up our key queue. |
402 if (WebInputEvent::isKeyboardEventType(key_event.type)) { | 392 if (WebInputEvent::isKeyboardEventType(key_event.type)) { |
403 // Don't add this key to the queue if we have no way to send the message... | |
404 if (!process_->HasConnection()) | |
405 return; | |
406 | |
407 // To help understand following logic, please refer to the comments | |
408 // explaining |pending_key_events_| and |suppress_next_char_events_| | |
409 // members. And the comments in OnMsgInputEventAck() method, which contains | |
410 // the bottom half of the logic. | |
411 // | |
412 // There are to different situations for us to handle key events: | |
413 // 1. After sending a key event to the renderer, we receive its ACK message | |
414 // from the renderer before sending the next key event. | |
415 // In this case, there is always no more than 1 key event in |key_queue_|, | |
416 // and we send the key event one by one in this method, except that a | |
417 // sequence of Char events may be suppressed directly if the preceding | |
418 // RawKeyDown event was handled as an accelerator key in the browser. | |
419 // | |
420 // 2. We get the next key event before receving the previous one's ACK | |
421 // message from the renderer. | |
422 // In this case, when we get a key event, the previous key event is still in | |
423 // |keq_queue_| waiting for being handled in OnMsgInputEventAck() method. | |
424 // Then we need handle following cases differently: | |
425 // 1) If we get a Char event, then the previous key event in |key_queue_| | |
426 // waiting for ACK must be a RawKeyDown event. Then we need keep this Char | |
427 // event in |key_queue_| rather than sending it immediately, because we | |
428 // can't determine if we should send it to the renderer or just suppress | |
429 // it, until we receive the preceding RawKeyDown event's ACK message. | |
430 // We increase the count of |pending_key_events_| to help remember this | |
431 // Char event is not sent to the renderer yet. | |
432 // 2) If there is already one or more key event pending in |key_queue_| | |
433 // (|pending_key_events_| > 0), we can not send a new key event | |
434 // immediately no matter what type it is. Otherwise the key events will be | |
435 // in wrong order. In this case we just keep them in |key_queue_| and | |
436 // increase |pending_key_events_| to remember them. | |
437 // | |
438 // Then all pending key events in |key_queue_| will be handled properly in | |
439 // OnMsgInputEventAck() method. Please refer to that method for details. | |
440 | |
441 // Tab switching/closing accelerators aren't sent to the renderer to avoid a | |
442 // hung/malicious renderer from interfering. | |
443 if (!ShouldSendToRenderer(key_event)) { | |
444 if (key_event.type == WebKeyboardEvent::RawKeyDown) | |
445 suppress_next_char_events_ = true; | |
446 UnhandledKeyboardEvent(key_event); | |
447 // We might be deleted now. | |
448 return; | |
449 } | |
450 | |
451 bool is_char = (key_event.type == WebKeyboardEvent::Char); | |
452 | |
453 // Handle the first situation mentioned above. | |
454 if (suppress_next_char_events_) { | 393 if (suppress_next_char_events_) { |
455 // If preceding RawKeyDown event was handled by the browser, then we need | 394 // If preceding RawKeyDown event was handled by the browser, then we need |
456 // suppress all Char events generated by it. Please note that, one | 395 // suppress all Char events generated by it. Please note that, one |
457 // RawKeyDown event may generate multiple Char events, so we can't reset | 396 // RawKeyDown event may generate multiple Char events, so we can't reset |
458 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown. | 397 // |suppress_next_char_events_| until we get a KeyUp or a RawKeyDown. |
459 if (is_char) | 398 if (key_event.type == WebKeyboardEvent::Char) |
460 return; | 399 return; |
461 // We get a KeyUp or a RawKeyDown event. | 400 // We get a KeyUp or a RawKeyDown event. |
462 suppress_next_char_events_ = false; | 401 suppress_next_char_events_ = false; |
463 } | 402 } |
464 | 403 |
| 404 // We need to set |suppress_next_char_events_| to true if |
| 405 // PreHandleKeyboardEvent() returns true, but |this| may already be |
| 406 // destroyed at that time. So set |suppress_next_char_events_| true here, |
| 407 // then revert it afterwards when necessary. |
| 408 if (key_event.type == WebKeyboardEvent::RawKeyDown) |
| 409 suppress_next_char_events_ = true; |
| 410 |
| 411 bool is_keyboard_shortcut = false; |
| 412 // Tab switching/closing accelerators aren't sent to the renderer to avoid a |
| 413 // hung/malicious renderer from interfering. |
| 414 if (PreHandleKeyboardEvent(key_event, &is_keyboard_shortcut)) |
| 415 return; |
| 416 |
| 417 if (key_event.type == WebKeyboardEvent::RawKeyDown) |
| 418 suppress_next_char_events_ = false; |
| 419 |
| 420 // Don't add this key to the queue if we have no way to send the message... |
| 421 if (!process_->HasConnection()) |
| 422 return; |
| 423 |
465 // Put all WebKeyboardEvent objects in a queue since we can't trust the | 424 // Put all WebKeyboardEvent objects in a queue since we can't trust the |
466 // renderer and we need to give something to the UnhandledInputEvent | 425 // renderer and we need to give something to the UnhandledInputEvent |
467 // handler. | 426 // handler. |
468 key_queue_.push_back(key_event); | 427 key_queue_.push_back(key_event); |
469 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | 428 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
470 | 429 |
471 // Handle the second situation mentioned above. | 430 // Only forward the non-native portions of our event. |
472 size_t key_queue_size = key_queue_.size(); | 431 ForwardInputEvent(key_event, sizeof(WebKeyboardEvent), |
473 if ((is_char && key_queue_size > 1) || pending_key_events_) { | 432 is_keyboard_shortcut); |
474 // The event is not send to the renderer, increase |pending_key_events_| | |
475 // to remember it. | |
476 ++pending_key_events_; | |
477 | |
478 // Some sanity checks. | |
479 // At least one key event in the front of |key_queue_| has been sent to | |
480 // the renderer, otherwise we won't be able to get any ACK back from the | |
481 // renderer. | |
482 DCHECK(key_queue_size > pending_key_events_); | |
483 // Char events must be preceded by RawKeyDown events. | |
484 // TODO(suzhe): verify it on all platforms. | |
485 DCHECK(key_queue_[key_queue_size - pending_key_events_ - 1].type == | |
486 WebKeyboardEvent::RawKeyDown); | |
487 // The first pending key event must be a Char event. Other key events must | |
488 // already be sent to the renderer at this point. | |
489 DCHECK(key_queue_[key_queue_size - pending_key_events_].type == | |
490 WebKeyboardEvent::Char); | |
491 } else { | |
492 // Fall into the first situation, so we can send the event immediately. | |
493 // Only forward the non-native portions of our event. | |
494 ForwardInputEvent(key_event, sizeof(WebKeyboardEvent)); | |
495 } | |
496 } | 433 } |
497 } | 434 } |
498 | 435 |
499 void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event, | 436 void RenderWidgetHost::ForwardInputEvent(const WebInputEvent& input_event, |
500 int event_size) { | 437 int event_size, |
| 438 bool is_keyboard_shortcut) { |
501 if (!process_->HasConnection()) | 439 if (!process_->HasConnection()) |
502 return; | 440 return; |
503 | 441 |
504 DCHECK(!process_->ignore_input_events()); | 442 DCHECK(!process_->ignore_input_events()); |
505 | 443 |
506 IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_); | 444 IPC::Message* message = new ViewMsg_HandleInputEvent(routing_id_); |
507 message->WriteData( | 445 message->WriteData( |
508 reinterpret_cast<const char*>(&input_event), event_size); | 446 reinterpret_cast<const char*>(&input_event), event_size); |
| 447 // |is_keyboard_shortcut| only makes sense for RawKeyDown events. |
| 448 if (input_event.type == WebInputEvent::RawKeyDown) |
| 449 message->WriteBool(is_keyboard_shortcut); |
509 input_event_start_time_ = TimeTicks::Now(); | 450 input_event_start_time_ = TimeTicks::Now(); |
510 Send(message); | 451 Send(message); |
511 | 452 |
512 // Any input event cancels a pending mouse move event. | 453 // Any input event cancels a pending mouse move event. |
513 next_mouse_move_.reset(); | 454 next_mouse_move_.reset(); |
514 | 455 |
515 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kHungRendererDelayMs)); | 456 StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kHungRendererDelayMs)); |
516 } | 457 } |
517 | 458 |
518 void RenderWidgetHost::ForwardEditCommand(const std::string& name, | 459 void RenderWidgetHost::ForwardEditCommand(const std::string& name, |
(...skipping 13 matching lines...) Expand all Loading... |
532 // Clearing this flag causes us to re-create the renderer when recovering | 473 // Clearing this flag causes us to re-create the renderer when recovering |
533 // from a crashed renderer. | 474 // from a crashed renderer. |
534 renderer_initialized_ = false; | 475 renderer_initialized_ = false; |
535 | 476 |
536 // Must reset these to ensure that mouse move events work with a new renderer. | 477 // Must reset these to ensure that mouse move events work with a new renderer. |
537 mouse_move_pending_ = false; | 478 mouse_move_pending_ = false; |
538 next_mouse_move_.reset(); | 479 next_mouse_move_.reset(); |
539 | 480 |
540 // Must reset these to ensure that keyboard events work with a new renderer. | 481 // Must reset these to ensure that keyboard events work with a new renderer. |
541 key_queue_.clear(); | 482 key_queue_.clear(); |
542 pending_key_events_ = 0; | |
543 suppress_next_char_events_ = false; | 483 suppress_next_char_events_ = false; |
544 | 484 |
545 // Reset some fields in preparation for recovering from a crash. | 485 // Reset some fields in preparation for recovering from a crash. |
546 resize_ack_pending_ = false; | 486 resize_ack_pending_ = false; |
547 repaint_ack_pending_ = false; | 487 repaint_ack_pending_ = false; |
548 paint_ack_postponed_ = false; | |
549 | 488 |
550 in_flight_size_.SetSize(0, 0); | 489 in_flight_size_.SetSize(0, 0); |
551 current_size_.SetSize(0, 0); | 490 current_size_.SetSize(0, 0); |
552 is_hidden_ = false; | 491 is_hidden_ = false; |
553 | 492 |
554 if (view_) { | 493 if (view_) { |
555 view_->RenderViewGone(); | 494 view_->RenderViewGone(); |
556 view_ = NULL; // The View should be deleted by RenderViewGone. | 495 view_ = NULL; // The View should be deleted by RenderViewGone. |
557 } | 496 } |
558 | 497 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
674 void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) { | 613 void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) { |
675 // Note that we ignore the position. | 614 // Note that we ignore the position. |
676 if (view_) { | 615 if (view_) { |
677 view_->SetSize(pos.size()); | 616 view_->SetSize(pos.size()); |
678 Send(new ViewMsg_Move_ACK(routing_id_)); | 617 Send(new ViewMsg_Move_ACK(routing_id_)); |
679 } | 618 } |
680 } | 619 } |
681 | 620 |
682 void RenderWidgetHost::OnMsgPaintRect( | 621 void RenderWidgetHost::OnMsgPaintRect( |
683 const ViewHostMsg_PaintRect_Params& params) { | 622 const ViewHostMsg_PaintRect_Params& params) { |
684 // We shouldn't receive PaintRect message when the last PaintRect_ACK has not | |
685 // been sent to the renderer yet. | |
686 DCHECK(!paint_ack_postponed_); | |
687 | |
688 TimeTicks paint_start = TimeTicks::Now(); | 623 TimeTicks paint_start = TimeTicks::Now(); |
689 | 624 |
690 // Update our knowledge of the RenderWidget's size. | 625 // Update our knowledge of the RenderWidget's size. |
691 current_size_ = params.view_size; | 626 current_size_ = params.view_size; |
692 | 627 |
693 bool is_resize_ack = | 628 bool is_resize_ack = |
694 ViewHostMsg_PaintRect_Flags::is_resize_ack(params.flags); | 629 ViewHostMsg_PaintRect_Flags::is_resize_ack(params.flags); |
695 | 630 |
696 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since | 631 // resize_ack_pending_ needs to be cleared before we call DidPaintRect, since |
697 // that will end up reaching GetBackingStore. | 632 // that will end up reaching GetBackingStore. |
(...skipping 27 matching lines...) Expand all Loading... |
725 // draw to the screen. | 660 // draw to the screen. |
726 PaintBackingStoreRect(dib, params.bitmap_rect, params.update_rects, | 661 PaintBackingStoreRect(dib, params.bitmap_rect, params.update_rects, |
727 params.view_size); | 662 params.view_size); |
728 } | 663 } |
729 } | 664 } |
730 | 665 |
731 // ACK early so we can prefetch the next PaintRect if there is a next one. | 666 // ACK early so we can prefetch the next PaintRect if there is a next one. |
732 // This must be done AFTER we're done painting with the bitmap supplied by the | 667 // This must be done AFTER we're done painting with the bitmap supplied by the |
733 // renderer. This ACK is a signal to the renderer that the backing store can | 668 // renderer. This ACK is a signal to the renderer that the backing store can |
734 // be re-used, so the bitmap may be invalid after this call. | 669 // be re-used, so the bitmap may be invalid after this call. |
735 // | 670 Send(new ViewMsg_PaintRect_ACK(routing_id_)); |
736 // Postpone the ACK message until all pending key events have been sent to the | |
737 // renderer, so that the renderer can process the updates caused by the key | |
738 // events in batch. | |
739 if (pending_key_events_ > 0) { | |
740 paint_ack_postponed_ = true; | |
741 paint_ack_postponed_time_ = TimeTicks::Now(); | |
742 } else { | |
743 Send(new ViewMsg_PaintRect_ACK(routing_id_)); | |
744 } | |
745 | 671 |
746 // We don't need to update the view if the view is hidden. We must do this | 672 // We don't need to update the view if the view is hidden. We must do this |
747 // early return after the ACK is sent, however, or the renderer will not send | 673 // early return after the ACK is sent, however, or the renderer will not send |
748 // us more data. | 674 // us more data. |
749 if (is_hidden_) | 675 if (is_hidden_) |
750 return; | 676 return; |
751 | 677 |
752 // Now paint the view. Watch out: it might be destroyed already. | 678 // Now paint the view. Watch out: it might be destroyed already. |
753 if (view_) { | 679 if (view_) { |
754 view_->MovePluginWindows(params.plugin_window_moves); | 680 view_->MovePluginWindows(params.plugin_window_moves); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 | 928 |
1003 void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) { | 929 void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) { |
1004 if (key_queue_.size() == 0) { | 930 if (key_queue_.size() == 0) { |
1005 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " | 931 LOG(ERROR) << "Got a KeyEvent back from the renderer but we " |
1006 << "don't seem to have sent it to the renderer!"; | 932 << "don't seem to have sent it to the renderer!"; |
1007 } else if (key_queue_.front().type != type) { | 933 } else if (key_queue_.front().type != type) { |
1008 LOG(ERROR) << "We seem to have a different key type sent from " | 934 LOG(ERROR) << "We seem to have a different key type sent from " |
1009 << "the renderer. (" << key_queue_.front().type << " vs. " | 935 << "the renderer. (" << key_queue_.front().type << " vs. " |
1010 << type << "). Ignoring event."; | 936 << type << "). Ignoring event."; |
1011 | 937 |
1012 // Something must be wrong. |key_queue_| must be cleared here to make sure | 938 // Something must be wrong. Clear the |key_queue_| and |
1013 // the feedback loop for sending upcoming keyboard events can be resumed | 939 // |suppress_next_char_events_| so that we can resume from the error. |
1014 // correctly. | |
1015 key_queue_.clear(); | 940 key_queue_.clear(); |
1016 pending_key_events_ = 0; | |
1017 suppress_next_char_events_ = false; | 941 suppress_next_char_events_ = false; |
1018 } else { | 942 } else { |
1019 // Track if |this| is destroyed or not. | |
1020 bool is_dead = false; | |
1021 death_flag_ = &is_dead; | |
1022 | |
1023 NativeWebKeyboardEvent front_item = key_queue_.front(); | 943 NativeWebKeyboardEvent front_item = key_queue_.front(); |
1024 key_queue_.pop_front(); | 944 key_queue_.pop_front(); |
1025 | 945 |
1026 bool processed_by_browser = false; | |
1027 if (!processed) { | 946 if (!processed) { |
1028 processed_by_browser = UnhandledKeyboardEvent(front_item); | 947 UnhandledKeyboardEvent(front_item); |
1029 | 948 |
1030 // WARNING: This RenderWidgetHost can be deallocated at this point | 949 // WARNING: This RenderWidgetHost can be deallocated at this point |
1031 // (i.e. in the case of Ctrl+W, where the call to | 950 // (i.e. in the case of Ctrl+W, where the call to |
1032 // UnhandledKeyboardEvent destroys this RenderWidgetHost). | 951 // UnhandledKeyboardEvent destroys this RenderWidgetHost). |
1033 } | 952 } |
1034 | |
1035 // This RenderWidgetHost was already deallocated, we can't do anything | |
1036 // from now on, including resetting |death_flag_|. So just return. | |
1037 if (is_dead) | |
1038 return; | |
1039 | |
1040 // Reset |death_flag_| to NULL, otherwise it'll point to an invalid memory | |
1041 // address after returning from this method. | |
1042 death_flag_ = NULL; | |
1043 | |
1044 // Suppress the following Char events if the RawKeyDown event was handled | |
1045 // by the browser rather than the renderer. | |
1046 if (front_item.type == WebKeyboardEvent::RawKeyDown) | |
1047 suppress_next_char_events_ = processed_by_browser; | |
1048 | |
1049 // If more than one key events in |key_queue_| were already sent to the | |
1050 // renderer but haven't got ACK messages yet, we must wait for ACK | |
1051 // messages of these key events before sending more key events to the | |
1052 // renderer. | |
1053 if (pending_key_events_ && key_queue_.size() == pending_key_events_) { | |
1054 size_t i = 0; | |
1055 if (suppress_next_char_events_) { | |
1056 // Suppress the sequence of pending Char events if preceding | |
1057 // RawKeyDown event was handled by the browser. | |
1058 while (pending_key_events_ && | |
1059 key_queue_[0].type == WebKeyboardEvent::Char) { | |
1060 --pending_key_events_; | |
1061 key_queue_.pop_front(); | |
1062 } | |
1063 } else { | |
1064 // Otherwise, send these pending Char events to the renderer. | |
1065 // Note: we can't remove them from |key_queue_|, as we still need to | |
1066 // wait for their ACK messages from the renderer. | |
1067 while (pending_key_events_ && | |
1068 key_queue_[i].type == WebKeyboardEvent::Char) { | |
1069 --pending_key_events_; | |
1070 ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent)); | |
1071 } | |
1072 } | |
1073 | |
1074 // Reset |suppress_next_char_events_| if there is still one or more | |
1075 // pending KeyUp or RawKeyDown events in the queue. | |
1076 // We can't reset it if there is no pending event anymore, because we | |
1077 // don't know if the following event is a Char event or not. | |
1078 if (pending_key_events_) | |
1079 suppress_next_char_events_ = false; | |
1080 | |
1081 // We can safely send following pending KeyUp and RawKeyDown events to | |
1082 // the renderer, until we meet another Char event. | |
1083 while (pending_key_events_ && | |
1084 key_queue_[i].type != WebKeyboardEvent::Char) { | |
1085 --pending_key_events_; | |
1086 ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent)); | |
1087 } | |
1088 } | |
1089 } | |
1090 | |
1091 // Send the pending PaintRect_ACK message after sending all pending key | |
1092 // events or after a certain duration, so that the renderer can process | |
1093 // the updates caused by the key events in batch. | |
1094 if (paint_ack_postponed_ && (pending_key_events_ == 0 || | |
1095 (TimeTicks::Now() - paint_ack_postponed_time_).InMilliseconds() > | |
1096 kPaintACKMsgMaxPostponedDurationMS)) { | |
1097 paint_ack_postponed_ = false; | |
1098 Send(new ViewMsg_PaintRect_ACK(routing_id_)); | |
1099 } | 953 } |
1100 } | 954 } |
OLD | NEW |