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

Unified Diff: chrome/browser/renderer_host/render_widget_host.cc

Issue 435002: Optimize the rendering when there are pending key events.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/renderer_host/render_widget_host.cc
===================================================================
--- chrome/browser/renderer_host/render_widget_host.cc (revision 33056)
+++ chrome/browser/renderer_host/render_widget_host.cc (working copy)
@@ -51,6 +51,9 @@
// How long to wait before we consider a renderer hung.
static const int kHungRendererDelayMs = 20000;
+// How long a PaintRect_ACK message can be postponed at most, in milliseconds.
+static const int kPaintACKMsgMaxPostponedDurationMS = 1000;
+
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHost
@@ -73,8 +76,9 @@
text_direction_updated_(false),
text_direction_(WebKit::WebTextDirectionLeftToRight),
text_direction_canceled_(false),
- pending_key_events_(false),
+ pending_key_events_(0),
suppress_next_char_events_(false),
+ paint_ack_postponed_(false),
death_flag_(NULL) {
if (routing_id_ == MSG_ROUTING_NONE)
routing_id_ = process_->GetNextRoutingID();
@@ -533,8 +537,16 @@
mouse_move_pending_ = false;
next_mouse_move_.reset();
+ // Must reset these to ensure that keyboard events work with a new renderer.
+ key_queue_.clear();
+ pending_key_events_ = 0;
+ suppress_next_char_events_ = false;
+
// Reset some fields in preparation for recovering from a crash.
resize_ack_pending_ = false;
+ repaint_ack_pending_ = false;
+ paint_ack_postponed_ = false;
+
in_flight_size_.SetSize(0, 0);
current_size_.SetSize(0, 0);
is_hidden_ = false;
@@ -669,6 +681,10 @@
void RenderWidgetHost::OnMsgPaintRect(
const ViewHostMsg_PaintRect_Params& params) {
+ // We shouldn't receive PaintRect message when the last PaintRect_ACK has not
+ // been sent to the renderer yet.
+ DCHECK(!paint_ack_postponed_);
+
TimeTicks paint_start = TimeTicks::Now();
// Update our knowledge of the RenderWidget's size.
@@ -715,7 +731,16 @@
// This must be done AFTER we're done painting with the bitmap supplied by the
// renderer. This ACK is a signal to the renderer that the backing store can
// be re-used, so the bitmap may be invalid after this call.
- Send(new ViewMsg_PaintRect_ACK(routing_id_));
+ //
+ // Postpone the ACK message until all pending key events have been sent to the
+ // renderer, so that the renderer can process the updates caused by the key
+ // events in batch.
+ if (pending_key_events_ > 0) {
+ paint_ack_postponed_ = true;
+ paint_ack_postponed_time_ = TimeTicks::Now();
+ } else {
+ Send(new ViewMsg_PaintRect_ACK(routing_id_));
+ }
// We don't need to update the view if the view is hidden. We must do this
// early return after the ACK is sent, however, or the renderer will not send
@@ -801,10 +826,6 @@
}
void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
- // Track if |this| is destroyed or not.
- bool is_dead = false;
- death_flag_ = &is_dead;
-
// Log the time delta for processing an input event.
TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
UMA_HISTOGRAM_TIMES("MPArch.RWH_InputEventDelta", delta);
@@ -814,10 +835,9 @@
void* iter = NULL;
int type = 0;
- if (!message.ReadInt(&iter, &type) || (type < WebInputEvent::Undefined))
+ if (!message.ReadInt(&iter, &type) || (type < WebInputEvent::Undefined)) {
process()->ReceivedBadMessage(message.type());
-
- if (type == WebInputEvent::MouseMove) {
+ } else if (type == WebInputEvent::MouseMove) {
mouse_move_pending_ = false;
// now, we can send the next mouse move event
@@ -825,96 +845,13 @@
DCHECK(next_mouse_move_->type == WebInputEvent::MouseMove);
ForwardMouseEvent(*next_mouse_move_);
}
- }
+ } else if (WebInputEvent::isKeyboardEventType(type)) {
+ bool processed = false;
+ if (!message.ReadBool(&iter, &processed))
+ process()->ReceivedBadMessage(message.type());
- if (WebInputEvent::isKeyboardEventType(type)) {
- if (key_queue_.size() == 0) {
- LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
- << "don't seem to have sent it to the renderer!";
- } else if (key_queue_.front().type != type) {
- LOG(ERROR) << "We seem to have a different key type sent from "
- << "the renderer. (" << key_queue_.front().type << " vs. "
- << type << "). Ignoring event.";
-
- // Something must be wrong. |key_queue_| must be cleared here to make sure
- // the feedback loop for sending upcoming keyboard events can be resumed
- // correctly.
- key_queue_.clear();
- pending_key_events_ = 0;
- suppress_next_char_events_ = false;
- } else {
- bool processed = false;
- if (!message.ReadBool(&iter, &processed))
- process()->ReceivedBadMessage(message.type());
-
- NativeWebKeyboardEvent front_item = key_queue_.front();
- key_queue_.pop_front();
-
- bool processed_by_browser = false;
- if (!processed) {
- processed_by_browser = UnhandledKeyboardEvent(front_item);
-
- // WARNING: This RenderWidgetHost can be deallocated at this point
- // (i.e. in the case of Ctrl+W, where the call to
- // UnhandledKeyboardEvent destroys this RenderWidgetHost).
- }
-
- // This RenderWidgetHost was already deallocated, we can't do anything
- // from now on, including resetting |death_flag_|. So just return.
- if (is_dead)
- return;
-
- // Suppress the following Char events if the RawKeyDown event was handled
- // by the browser rather than the renderer.
- if (front_item.type == WebKeyboardEvent::RawKeyDown)
- suppress_next_char_events_ = processed_by_browser;
-
- // If more than one key events in |key_queue_| were already sent to the
- // renderer but haven't got ACK messages yet, we must wait for ACK
- // messages of these key events before sending more key events to the
- // renderer.
- if (pending_key_events_ && key_queue_.size() == pending_key_events_) {
- size_t i = 0;
- if (suppress_next_char_events_) {
- // Suppress the sequence of pending Char events if preceding
- // RawKeyDown event was handled by the browser.
- while (pending_key_events_ &&
- key_queue_[0].type == WebKeyboardEvent::Char) {
- --pending_key_events_;
- key_queue_.pop_front();
- }
- } else {
- // Otherwise, send these pending Char events to the renderer.
- // Note: we can't remove them from |key_queue_|, as we still need to
- // wait for their ACK messages from the renderer.
- while (pending_key_events_ &&
- key_queue_[i].type == WebKeyboardEvent::Char) {
- --pending_key_events_;
- ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent));
- }
- }
-
- // Reset |suppress_next_char_events_| if there is still one or more
- // pending KeyUp or RawKeyDown events in the queue.
- // We can't reset it if there is no pending event anymore, because we
- // don't know if the following event is a Char event or not.
- if (pending_key_events_)
- suppress_next_char_events_ = false;
-
- // We can safely send following pending KeyUp and RawKeyDown events to
- // the renderer, until we meet another Char event.
- while (pending_key_events_ &&
- key_queue_[i].type != WebKeyboardEvent::Char) {
- --pending_key_events_;
- ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent));
- }
- }
- }
+ ProcessKeyboardEventAck(type, processed);
}
-
- // Reset |death_flag_| to NULL, otherwise it'll point to an invalid memory
- // address after returning from this method.
- death_flag_ = NULL;
}
void RenderWidgetHost::OnMsgFocus() {
@@ -1048,3 +985,102 @@
void RenderWidgetHost::AdvanceToNextMisspelling() {
Send(new ViewMsg_AdvanceToNextMisspelling(routing_id_));
}
+
+void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) {
+ if (key_queue_.size() == 0) {
+ LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
+ << "don't seem to have sent it to the renderer!";
+ } else if (key_queue_.front().type != type) {
+ LOG(ERROR) << "We seem to have a different key type sent from "
+ << "the renderer. (" << key_queue_.front().type << " vs. "
+ << type << "). Ignoring event.";
+
+ // Something must be wrong. |key_queue_| must be cleared here to make sure
+ // the feedback loop for sending upcoming keyboard events can be resumed
+ // correctly.
+ key_queue_.clear();
+ pending_key_events_ = 0;
+ suppress_next_char_events_ = false;
+ } else {
+ // Track if |this| is destroyed or not.
+ bool is_dead = false;
+ death_flag_ = &is_dead;
+
+ NativeWebKeyboardEvent front_item = key_queue_.front();
+ key_queue_.pop_front();
+
+ bool processed_by_browser = false;
+ if (!processed) {
+ processed_by_browser = UnhandledKeyboardEvent(front_item);
+
+ // WARNING: This RenderWidgetHost can be deallocated at this point
+ // (i.e. in the case of Ctrl+W, where the call to
+ // UnhandledKeyboardEvent destroys this RenderWidgetHost).
+ }
+
+ // This RenderWidgetHost was already deallocated, we can't do anything
+ // from now on, including resetting |death_flag_|. So just return.
+ if (is_dead)
+ return;
+
+ // Reset |death_flag_| to NULL, otherwise it'll point to an invalid memory
+ // address after returning from this method.
+ death_flag_ = NULL;
+
+ // Suppress the following Char events if the RawKeyDown event was handled
+ // by the browser rather than the renderer.
+ if (front_item.type == WebKeyboardEvent::RawKeyDown)
+ suppress_next_char_events_ = processed_by_browser;
+
+ // If more than one key events in |key_queue_| were already sent to the
+ // renderer but haven't got ACK messages yet, we must wait for ACK
+ // messages of these key events before sending more key events to the
+ // renderer.
+ if (pending_key_events_ && key_queue_.size() == pending_key_events_) {
+ size_t i = 0;
+ if (suppress_next_char_events_) {
+ // Suppress the sequence of pending Char events if preceding
+ // RawKeyDown event was handled by the browser.
+ while (pending_key_events_ &&
+ key_queue_[0].type == WebKeyboardEvent::Char) {
+ --pending_key_events_;
+ key_queue_.pop_front();
+ }
+ } else {
+ // Otherwise, send these pending Char events to the renderer.
+ // Note: we can't remove them from |key_queue_|, as we still need to
+ // wait for their ACK messages from the renderer.
+ while (pending_key_events_ &&
+ key_queue_[i].type == WebKeyboardEvent::Char) {
+ --pending_key_events_;
+ ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent));
+ }
+ }
+
+ // Reset |suppress_next_char_events_| if there is still one or more
+ // pending KeyUp or RawKeyDown events in the queue.
+ // We can't reset it if there is no pending event anymore, because we
+ // don't know if the following event is a Char event or not.
+ if (pending_key_events_)
+ suppress_next_char_events_ = false;
+
+ // We can safely send following pending KeyUp and RawKeyDown events to
+ // the renderer, until we meet another Char event.
+ while (pending_key_events_ &&
+ key_queue_[i].type != WebKeyboardEvent::Char) {
+ --pending_key_events_;
+ ForwardInputEvent(key_queue_[i++], sizeof(WebKeyboardEvent));
+ }
+ }
+ }
+
+ // Send the pending PaintRect_ACK message after sending all pending key
+ // events or after a certain duration, so that the renderer can process
+ // the updates caused by the key events in batch.
+ if (paint_ack_postponed_ && (pending_key_events_ == 0 ||
+ (TimeTicks::Now() - paint_ack_postponed_time_).InMilliseconds() >
+ kPaintACKMsgMaxPostponedDurationMS)) {
+ paint_ack_postponed_ = false;
+ Send(new ViewMsg_PaintRect_ACK(routing_id_));
+ }
+}
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698