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

Side by Side Diff: chrome/browser/renderer_host/render_widget_host.cc

Issue 400012: Refactor the keyboard events handling code related to RenderViewHostDelegate:... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 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) 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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host.h ('k') | chrome/browser/renderer_host/render_widget_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698