| 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 |