summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/renderer_host/backing_store.h9
-rw-r--r--chrome/browser/renderer_host/backing_store_mac.mm8
-rw-r--r--chrome/browser/renderer_host/backing_store_win.cc10
-rw-r--r--chrome/browser/renderer_host/backing_store_x.cc7
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc9
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.h6
-rw-r--r--chrome/browser/renderer_host/mock_render_process_host.cc6
-rw-r--r--chrome/browser/renderer_host/mock_render_process_host.h6
-rw-r--r--chrome/browser/renderer_host/render_process_host.h10
-rw-r--r--chrome/browser/renderer_host/render_widget_helper.cc40
-rw-r--r--chrome/browser/renderer_host/render_widget_helper.h48
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc95
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h11
-rw-r--r--chrome/browser/renderer_host/render_widget_host_unittest.cc101
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h5
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.cc20
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_gtk.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h4
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm33
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc95
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h6
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc4
-rw-r--r--chrome/browser/renderer_host/test/test_render_view_host.h6
-rw-r--r--chrome/common/render_messages.h111
-rw-r--r--chrome/common/render_messages_internal.h23
-rw-r--r--chrome/renderer/render_widget.cc187
-rw-r--r--chrome/renderer/render_widget.h26
27 files changed, 510 insertions, 380 deletions
diff --git a/chrome/browser/renderer_host/backing_store.h b/chrome/browser/renderer_host/backing_store.h
index 68514e4..387a564 100644
--- a/chrome/browser/renderer_host/backing_store.h
+++ b/chrome/browser/renderer_host/backing_store.h
@@ -98,9 +98,12 @@ class BackingStore {
const gfx::Rect& bitmap_rect,
const gfx::Rect& copy_rect);
- // Scrolls the contents of clip_rect in the backing store by dx or dy (but dx
- // and dy cannot both be non-zero).
- void ScrollRect(int dx, int dy,
+ // Scrolls the given rect in the backing store, replacing the given region
+ // identified by |bitmap_rect| by the bitmap in the file identified by the
+ // given file handle.
+ void ScrollRect(base::ProcessHandle process,
+ TransportDIB* bitmap, const gfx::Rect& bitmap_rect,
+ int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size);
diff --git a/chrome/browser/renderer_host/backing_store_mac.mm b/chrome/browser/renderer_host/backing_store_mac.mm
index 0b8fa6e..1de83b2 100644
--- a/chrome/browser/renderer_host/backing_store_mac.mm
+++ b/chrome/browser/renderer_host/backing_store_mac.mm
@@ -99,7 +99,10 @@ void BackingStore::PaintRect(base::ProcessHandle process,
}
// Scroll the contents of our CGLayer
-void BackingStore::ScrollRect(int dx, int dy,
+void BackingStore::ScrollRect(base::ProcessHandle process,
+ TransportDIB* bitmap,
+ const gfx::Rect& bitmap_rect,
+ int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
DCHECK_NE(static_cast<bool>(cg_layer()), static_cast<bool>(cg_bitmap()));
@@ -155,6 +158,9 @@ void BackingStore::ScrollRect(int dx, int dy,
cg_bitmap_.swap(new_bitmap);
}
}
+ // Now paint the new bitmap data
+ PaintRect(process, bitmap, bitmap_rect, bitmap_rect);
+ return;
}
CGLayerRef BackingStore::CreateCGLayer() {
diff --git a/chrome/browser/renderer_host/backing_store_win.cc b/chrome/browser/renderer_host/backing_store_win.cc
index ae772dc..6cbaa34 100644
--- a/chrome/browser/renderer_host/backing_store_win.cc
+++ b/chrome/browser/renderer_host/backing_store_win.cc
@@ -146,7 +146,10 @@ void BackingStore::PaintRect(base::ProcessHandle process,
reinterpret_cast<BITMAPINFO*>(&hdr));
}
-void BackingStore::ScrollRect(int dx, int dy,
+void BackingStore::ScrollRect(base::ProcessHandle process,
+ TransportDIB* bitmap,
+ const gfx::Rect& bitmap_rect,
+ int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
RECT damaged_rect, r = clip_rect.ToRECT();
@@ -154,4 +157,9 @@ void BackingStore::ScrollRect(int dx, int dy,
// TODO(darin): this doesn't work if dx and dy are both non-zero!
DCHECK(dx == 0 || dy == 0);
+
+ // We expect that damaged_rect should equal bitmap_rect.
+ DCHECK(gfx::Rect(damaged_rect) == bitmap_rect);
+
+ PaintRect(process, bitmap, bitmap_rect, bitmap_rect);
}
diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc
index a1173b8..74ea8ac 100644
--- a/chrome/browser/renderer_host/backing_store_x.cc
+++ b/chrome/browser/renderer_host/backing_store_x.cc
@@ -311,7 +311,10 @@ void BackingStore::PaintRect(base::ProcessHandle process,
XFreePixmap(display_, pixmap);
}
-void BackingStore::ScrollRect(int dx, int dy,
+void BackingStore::ScrollRect(base::ProcessHandle process,
+ TransportDIB* bitmap,
+ const gfx::Rect& bitmap_rect,
+ int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
if (!display_)
@@ -343,6 +346,8 @@ void BackingStore::ScrollRect(int dx, int dy,
clip_rect.y() /* dest x */);
}
}
+
+ PaintRect(process, bitmap, bitmap_rect, bitmap_rect);
}
void BackingStore::ShowRect(const gfx::Rect& rect, XID target) {
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index 2d7d2f8..a6f02a3 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -347,16 +347,15 @@ void BrowserRenderProcessHost::CrossSiteClosePageACK(
widget_helper_->CrossSiteClosePageACK(params);
}
-bool BrowserRenderProcessHost::WaitForUpdateMsg(
- int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
+bool BrowserRenderProcessHost::WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
// The post task to this thread with the process id could be in queue, and we
// don't want to dispatch a message before then since it will need the handle.
if (child_process_.get() && child_process_->IsStarting())
return false;
- return widget_helper_->WaitForUpdateMsg(render_widget_id, max_delay, msg);
+ return widget_helper_->WaitForPaintMsg(render_widget_id, max_delay, msg);
}
void BrowserRenderProcessHost::ReceivedBadMessage(uint32 msg_type) {
diff --git a/chrome/browser/renderer_host/browser_render_process_host.h b/chrome/browser/renderer_host/browser_render_process_host.h
index 3a6e83b..cd94bf5 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.h
+++ b/chrome/browser/renderer_host/browser_render_process_host.h
@@ -63,9 +63,9 @@ class BrowserRenderProcessHost : public RenderProcessHost,
virtual int GetNextRoutingID();
virtual void CancelResourceRequests(int render_widget_id);
virtual void CrossSiteClosePageACK(const ViewMsg_ClosePage_Params& params);
- virtual bool WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ virtual bool WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
virtual void ReceivedBadMessage(uint32 msg_type);
virtual void WidgetRestored();
virtual void WidgetHidden();
diff --git a/chrome/browser/renderer_host/mock_render_process_host.cc b/chrome/browser/renderer_host/mock_render_process_host.cc
index b18cc50..8be0416 100644
--- a/chrome/browser/renderer_host/mock_render_process_host.cc
+++ b/chrome/browser/renderer_host/mock_render_process_host.cc
@@ -31,9 +31,9 @@ void MockRenderProcessHost::CrossSiteClosePageACK(
const ViewMsg_ClosePage_Params& params) {
}
-bool MockRenderProcessHost::WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
+bool MockRenderProcessHost::WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
return false;
}
diff --git a/chrome/browser/renderer_host/mock_render_process_host.h b/chrome/browser/renderer_host/mock_render_process_host.h
index 70ed985..aa04651 100644
--- a/chrome/browser/renderer_host/mock_render_process_host.h
+++ b/chrome/browser/renderer_host/mock_render_process_host.h
@@ -35,9 +35,9 @@ class MockRenderProcessHost : public RenderProcessHost {
virtual int GetNextRoutingID();
virtual void CancelResourceRequests(int render_widget_id);
virtual void CrossSiteClosePageACK(const ViewMsg_ClosePage_Params& params);
- virtual bool WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ virtual bool WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
virtual void ReceivedBadMessage(uint32 msg_type);
virtual void WidgetRestored();
virtual void WidgetHidden();
diff --git a/chrome/browser/renderer_host/render_process_host.h b/chrome/browser/renderer_host/render_process_host.h
index 7979d24..aad1f83 100644
--- a/chrome/browser/renderer_host/render_process_host.h
+++ b/chrome/browser/renderer_host/render_process_host.h
@@ -165,12 +165,12 @@ class RenderProcessHost : public IPC::Channel::Sender,
virtual void CrossSiteClosePageACK(
const ViewMsg_ClosePage_Params& params) = 0;
- // Called on the UI thread to wait for the next UpdateRect message for the
+ // Called on the UI thread to wait for the next PaintRect message for the
// specified render widget. Returns true if successful, and the msg out-
- // param will contain a copy of the received UpdateRect message.
- virtual bool WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) = 0;
+ // param will contain a copy of the received PaintRect message.
+ virtual bool WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) = 0;
// Called when a received message cannot be decoded.
virtual void ReceivedBadMessage(uint32 msg_type) = 0;
diff --git a/chrome/browser/renderer_host/render_widget_helper.cc b/chrome/browser/renderer_host/render_widget_helper.cc
index dffc9c5..8916c70 100644
--- a/chrome/browser/renderer_host/render_widget_helper.cc
+++ b/chrome/browser/renderer_host/render_widget_helper.cc
@@ -14,24 +14,24 @@
// A Task used with InvokeLater that we hold a pointer to in pending_paints_.
// Instances are deleted by MessageLoop after it calls their Run method.
-class RenderWidgetHelper::UpdateMsgProxy : public Task {
+class RenderWidgetHelper::PaintMsgProxy : public Task {
public:
- UpdateMsgProxy(RenderWidgetHelper* h, const IPC::Message& m)
+ PaintMsgProxy(RenderWidgetHelper* h, const IPC::Message& m)
: helper(h),
message(m),
cancelled(false) {
}
- ~UpdateMsgProxy() {
+ ~PaintMsgProxy() {
// If the paint message was never dispatched, then we need to let the
// helper know that we are going away.
if (!cancelled && helper)
- helper->OnDiscardUpdateMsg(this);
+ helper->OnDiscardPaintMsg(this);
}
virtual void Run() {
if (!cancelled) {
- helper->OnDispatchUpdateMsg(this);
+ helper->OnDispatchPaintMsg(this);
helper = NULL;
}
}
@@ -40,7 +40,7 @@ class RenderWidgetHelper::UpdateMsgProxy : public Task {
IPC::Message message;
bool cancelled; // If true, then the message will not be dispatched.
- DISALLOW_COPY_AND_ASSIGN(UpdateMsgProxy);
+ DISALLOW_COPY_AND_ASSIGN(PaintMsgProxy);
};
RenderWidgetHelper::RenderWidgetHelper()
@@ -94,17 +94,17 @@ void RenderWidgetHelper::CrossSiteClosePageACK(
params));
}
-bool RenderWidgetHelper::WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
+bool RenderWidgetHelper::WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
base::TimeTicks time_start = base::TimeTicks::Now();
for (;;) {
- UpdateMsgProxy* proxy = NULL;
+ PaintMsgProxy* proxy = NULL;
{
AutoLock lock(pending_paints_lock_);
- UpdateMsgProxyMap::iterator it = pending_paints_.find(render_widget_id);
+ PaintMsgProxyMap::iterator it = pending_paints_.find(render_widget_id);
if (it != pending_paints_.end()) {
proxy = it->second;
@@ -134,25 +134,25 @@ bool RenderWidgetHelper::WaitForUpdateMsg(int render_widget_id,
return false;
}
-void RenderWidgetHelper::DidReceiveUpdateMsg(const IPC::Message& msg) {
+void RenderWidgetHelper::DidReceivePaintMsg(const IPC::Message& msg) {
int render_widget_id = msg.routing_id();
- UpdateMsgProxy* proxy = NULL;
+ PaintMsgProxy* proxy = NULL;
{
AutoLock lock(pending_paints_lock_);
- UpdateMsgProxyMap::value_type new_value(render_widget_id, NULL);
+ PaintMsgProxyMap::value_type new_value(render_widget_id, NULL);
// We expect only a single PaintRect message at a time. Optimize for the
// case that we don't already have an entry by using the 'insert' method.
- std::pair<UpdateMsgProxyMap::iterator, bool> result =
+ std::pair<PaintMsgProxyMap::iterator, bool> result =
pending_paints_.insert(new_value);
if (!result.second) {
NOTREACHED() << "Unexpected PaintRect message!";
return;
}
- result.first->second = (proxy = new UpdateMsgProxy(this, msg));
+ result.first->second = (proxy = new PaintMsgProxy(this, msg));
}
// Notify anyone waiting on the UI thread that there is a new entry in the
@@ -164,14 +164,14 @@ void RenderWidgetHelper::DidReceiveUpdateMsg(const IPC::Message& msg) {
ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, proxy);
}
-void RenderWidgetHelper::OnDiscardUpdateMsg(UpdateMsgProxy* proxy) {
+void RenderWidgetHelper::OnDiscardPaintMsg(PaintMsgProxy* proxy) {
const IPC::Message& msg = proxy->message;
// Remove the proxy from the map now that we are going to handle it normally.
{
AutoLock lock(pending_paints_lock_);
- UpdateMsgProxyMap::iterator it = pending_paints_.find(msg.routing_id());
+ PaintMsgProxyMap::iterator it = pending_paints_.find(msg.routing_id());
DCHECK(it != pending_paints_.end());
DCHECK(it->second == proxy);
@@ -179,8 +179,8 @@ void RenderWidgetHelper::OnDiscardUpdateMsg(UpdateMsgProxy* proxy) {
}
}
-void RenderWidgetHelper::OnDispatchUpdateMsg(UpdateMsgProxy* proxy) {
- OnDiscardUpdateMsg(proxy);
+void RenderWidgetHelper::OnDispatchPaintMsg(PaintMsgProxy* proxy) {
+ OnDiscardPaintMsg(proxy);
// It is reasonable for the host to no longer exist.
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id_);
diff --git a/chrome/browser/renderer_host/render_widget_helper.h b/chrome/browser/renderer_host/render_widget_helper.h
index d7e863e..1220970 100644
--- a/chrome/browser/renderer_host/render_widget_helper.h
+++ b/chrome/browser/renderer_host/render_widget_helper.h
@@ -37,20 +37,20 @@ struct ViewMsg_ClosePage_Params;
// RenderWidgetHelper is used to implement optimized resize. When the
// RenderWidgetHost is resized, it sends a Resize message to its RenderWidget
// counterpart in the renderer process. The RenderWidget generates a
-// UpdateRect message in response to the Resize message, and it sets the
-// IS_RESIZE_ACK flag in the UpdateRect message to true.
+// PaintRect message in response to the Resize message, and it sets the
+// IS_RESIZE_ACK flag in the PaintRect message to true.
//
// Back in the browser process, when the RenderProcessHost's MessageFilter
-// sees a UpdateRect message, it directs it to the RenderWidgetHelper by
-// calling the DidReceiveUpdateMsg method. That method stores the data for
-// the UpdateRect message in a map, where it can be directly accessed by the
+// sees a PaintRect message, it directs it to the RenderWidgetHelper by
+// calling the DidReceivePaintMsg method. That method stores the data for
+// the PaintRect message in a map, where it can be directly accessed by the
// RenderWidgetHost on the UI thread during a call to RenderWidgetHost's
// GetBackingStore method.
//
// When the RenderWidgetHost's GetBackingStore method is called, it first
// checks to see if it is waiting for a resize ack. If it is, then it calls
-// the RenderWidgetHelper's WaitForUpdateMsg to check if there is already a
-// resulting UpdateRect message (or to wait a short amount of time for one to
+// the RenderWidgetHelper's WaitForPaintMsg to check if there is already a
+// resulting PaintRect message (or to wait a short amount of time for one to
// arrive). The main goal of this mechanism is to short-cut the usual way in
// which IPC messages are proxied over to the UI thread via InvokeLater.
// This approach is necessary since window resize is followed up immediately
@@ -60,19 +60,19 @@ struct ViewMsg_ClosePage_Params;
// OPTIMIZED TAB SWITCHING
//
// When a RenderWidgetHost is in a background tab, it is flagged as hidden.
-// This causes the corresponding RenderWidget to stop sending UpdateRect
+// This causes the corresponding RenderWidget to stop sending PaintRect
// messages. The RenderWidgetHost also discards its backingstore when it is
// hidden, which helps free up memory. As a result, when a RenderWidgetHost
// is restored, it can be momentarily without a backingstore. (Restoring a
// RenderWidgetHost results in a WasRestored message being sent to the
-// RenderWidget, which triggers a full UpdateRect message.) This can lead to
+// RenderWidget, which triggers a full PaintRect message.) This can lead to
// an observed rendering glitch as the TabContents will just have to fill
// white overtop the RenderWidgetHost until the RenderWidgetHost receives a
-// UpdateRect message to refresh its backingstore.
+// PaintRect message to refresh its backingstore.
//
// To avoid this 'white flash', the RenderWidgetHost again makes use of the
-// RenderWidgetHelper's WaitForUpdateMsg method. When the RenderWidgetHost's
-// GetBackingStore method is called, it will call WaitForUpdateMsg if it has
+// RenderWidgetHelper's WaitForPaintMsg method. When the RenderWidgetHost's
+// GetBackingStore method is called, it will call WaitForPaintMsg if it has
// no backingstore.
//
// TRANSPORT DIB CREATION
@@ -103,9 +103,9 @@ class RenderWidgetHelper
// for documentation.
void CancelResourceRequests(int render_widget_id);
void CrossSiteClosePageACK(const ViewMsg_ClosePage_Params& params);
- bool WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ bool WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
#if defined(OS_MACOSX)
// Given the id of a transport DIB, return a mapping to it or NULL on error.
@@ -115,8 +115,8 @@ class RenderWidgetHelper
// IO THREAD ONLY -----------------------------------------------------------
- // Called on the IO thread when a UpdateRect message is received.
- void DidReceiveUpdateMsg(const IPC::Message& msg);
+ // Called on the IO thread when a PaintRect message is received.
+ void DidReceivePaintMsg(const IPC::Message& msg);
void CreateNewWindow(int opener_id,
bool user_gesture,
@@ -135,20 +135,20 @@ class RenderWidgetHelper
private:
// A class used to proxy a paint message. PaintMsgProxy objects are created
// on the IO thread and destroyed on the UI thread.
- class UpdateMsgProxy;
- friend class UpdateMsgProxy;
+ class PaintMsgProxy;
+ friend class PaintMsgProxy;
friend class base::RefCountedThreadSafe<RenderWidgetHelper>;
// Map from render_widget_id to live PaintMsgProxy instance.
- typedef base::hash_map<int, UpdateMsgProxy*> UpdateMsgProxyMap;
+ typedef base::hash_map<int, PaintMsgProxy*> PaintMsgProxyMap;
~RenderWidgetHelper();
// Called on the UI thread to discard a paint message.
- void OnDiscardUpdateMsg(UpdateMsgProxy* proxy);
+ void OnDiscardPaintMsg(PaintMsgProxy* proxy);
// Called on the UI thread to dispatch a paint message if necessary.
- void OnDispatchUpdateMsg(UpdateMsgProxy* proxy);
+ void OnDispatchPaintMsg(PaintMsgProxy* proxy);
// Called on the UI thread to finish creating a window.
void OnCreateWindowOnUI(int opener_id,
@@ -179,12 +179,12 @@ class RenderWidgetHelper
// A map of live paint messages. Must hold pending_paints_lock_ to access.
// The PaintMsgProxy objects are not owned by this map. (See PaintMsgProxy
// for details about how the lifetime of instances are managed.)
- UpdateMsgProxyMap pending_paints_;
+ PaintMsgProxyMap pending_paints_;
Lock pending_paints_lock_;
int render_process_id_;
- // Event used to implement WaitForUpdateMsg.
+ // Event used to implement WaitForPaintMsg.
base::WaitableEvent event_;
// The next routing id to use.
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index ad94aa6..c40bbf8 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -124,7 +124,8 @@ void RenderWidgetHost::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewGone, OnMsgRenderViewGone)
IPC_MESSAGE_HANDLER(ViewHostMsg_Close, OnMsgClose)
IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnMsgRequestMove)
- IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnMsgUpdateRect)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_PaintRect, OnMsgPaintRect)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ScrollRect, OnMsgScrollRect)
IPC_MESSAGE_HANDLER(ViewHostMsg_HandleInputEvent_ACK, OnMsgInputEventAck)
IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnMsgFocus)
IPC_MESSAGE_HANDLER(ViewHostMsg_Blur, OnMsgBlur)
@@ -298,9 +299,9 @@ BackingStore* RenderWidgetHost::GetBackingStore(bool force_create) {
if (resize_ack_pending_ || !backing_store) {
IPC::Message msg;
TimeDelta max_delay = TimeDelta::FromMilliseconds(kPaintMsgTimeoutMS);
- if (process_->WaitForUpdateMsg(routing_id_, max_delay, &msg)) {
- ViewHostMsg_UpdateRect::Dispatch(
- &msg, this, &RenderWidgetHost::OnMsgUpdateRect);
+ if (process_->WaitForPaintMsg(routing_id_, max_delay, &msg)) {
+ ViewHostMsg_PaintRect::Dispatch(
+ &msg, this, &RenderWidgetHost::OnMsgPaintRect);
backing_store = BackingStoreManager::GetBackingStore(this, current_size_);
}
}
@@ -617,15 +618,15 @@ void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) {
}
}
-void RenderWidgetHost::OnMsgUpdateRect(
- const ViewHostMsg_UpdateRect_Params& params) {
+void RenderWidgetHost::OnMsgPaintRect(
+ const ViewHostMsg_PaintRect_Params& params) {
TimeTicks paint_start = TimeTicks::Now();
// Update our knowledge of the RenderWidget's size.
current_size_ = params.view_size;
bool is_resize_ack =
- ViewHostMsg_UpdateRect_Flags::is_resize_ack(params.flags);
+ ViewHostMsg_PaintRect_Flags::is_resize_ack(params.flags);
// resize_ack_pending_ needs to be cleared before we call DidPaintRect, since
// that will end up reaching GetBackingStore.
@@ -636,7 +637,7 @@ void RenderWidgetHost::OnMsgUpdateRect(
}
bool is_repaint_ack =
- ViewHostMsg_UpdateRect_Flags::is_repaint_ack(params.flags);
+ ViewHostMsg_PaintRect_Flags::is_repaint_ack(params.flags);
if (is_repaint_ack) {
repaint_ack_pending_ = false;
TimeDelta delta = TimeTicks::Now() - repaint_start_time_;
@@ -652,19 +653,12 @@ void RenderWidgetHost::OnMsgUpdateRect(
if (dib) {
if (dib->size() < size) {
DLOG(WARNING) << "Transport DIB too small for given rectangle";
- process()->ReceivedBadMessage(ViewHostMsg_UpdateRect__ID);
+ process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID);
} else {
- // Scroll the backing store.
- if (!params.scroll_rect.IsEmpty()) {
- ScrollBackingStoreRect(params.dx, params.dy,
- params.scroll_rect,
- params.view_size);
- }
-
// Paint the backing store. This will update it with the renderer-supplied
// bits. The view will read out of the backing store later to actually
// draw to the screen.
- PaintBackingStoreRect(dib, params.bitmap_rect, params.copy_rects,
+ PaintBackingStoreRect(dib, params.bitmap_rect, params.update_rects,
params.view_size);
}
}
@@ -673,7 +667,7 @@ void RenderWidgetHost::OnMsgUpdateRect(
// 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_UpdateRect_ACK(routing_id_));
+ 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
@@ -685,12 +679,7 @@ void RenderWidgetHost::OnMsgUpdateRect(
if (view_) {
view_->MovePluginWindows(params.plugin_window_moves);
view_being_painted_ = true;
- if (!params.scroll_rect.IsEmpty()) {
- view_->DidScrollBackingStoreRect(params.scroll_rect,
- params.dx,
- params.dy);
- }
- view_->DidPaintBackingStoreRects(params.copy_rects);
+ view_->DidPaintRect(params.bitmap_rect);
view_being_painted_ = false;
}
@@ -711,7 +700,56 @@ void RenderWidgetHost::OnMsgUpdateRect(
// Log the time delta for processing a paint message.
TimeDelta delta = TimeTicks::Now() - paint_start;
- UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgUpdateRect", delta);
+ UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgPaintRect", delta);
+}
+
+void RenderWidgetHost::OnMsgScrollRect(
+ const ViewHostMsg_ScrollRect_Params& params) {
+ TimeTicks scroll_start = TimeTicks::Now();
+
+ DCHECK(!params.view_size.IsEmpty());
+
+ const size_t size = params.bitmap_rect.height() *
+ params.bitmap_rect.width() * 4;
+ TransportDIB* dib = process_->GetTransportDIB(params.bitmap);
+ if (dib) {
+ if (dib->size() < size) {
+ LOG(WARNING) << "Transport DIB too small for given rectangle";
+ process()->ReceivedBadMessage(ViewHostMsg_PaintRect__ID);
+ } else {
+ // Scroll the backing store.
+ ScrollBackingStoreRect(dib, params.bitmap_rect,
+ params.dx, params.dy,
+ params.clip_rect, params.view_size);
+ }
+ }
+
+ // ACK early so we can prefetch the next ScrollRect if there is a next one.
+ // 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_ScrollRect_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
+ // is more data.
+ if (is_hidden_)
+ return;
+
+ // Paint the view. Watch out: it might be destroyed already.
+ if (view_) {
+ view_being_painted_ = true;
+ view_->MovePluginWindows(params.plugin_window_moves);
+ view_->DidScrollRect(params.clip_rect, params.dx, params.dy);
+ view_being_painted_ = false;
+ }
+
+ if (painting_observer_)
+ painting_observer_->WidgetDidUpdateBackingStore(this);
+
+ // Log the time delta for processing a scroll message.
+ TimeDelta delta = TimeTicks::Now() - scroll_start;
+ UMA_HISTOGRAM_TIMES("MPArch.RWH_OnMsgScrollRect", delta);
}
void RenderWidgetHost::OnMsgInputEventAck(const IPC::Message& message) {
@@ -853,7 +891,9 @@ void RenderWidgetHost::PaintBackingStoreRect(
}
}
-void RenderWidgetHost::ScrollBackingStoreRect(int dx, int dy,
+void RenderWidgetHost::ScrollBackingStoreRect(TransportDIB* bitmap,
+ const gfx::Rect& bitmap_rect,
+ int dx, int dy,
const gfx::Rect& clip_rect,
const gfx::Size& view_size) {
if (is_hidden_) {
@@ -870,7 +910,8 @@ void RenderWidgetHost::ScrollBackingStoreRect(int dx, int dy,
BackingStore* backing_store = BackingStoreManager::Lookup(this);
if (!backing_store || (backing_store->size() != view_size))
return;
- backing_store->ScrollRect(dx, dy, clip_rect, view_size);
+ backing_store->ScrollRect(process_->GetHandle(), bitmap, bitmap_rect,
+ dx, dy, clip_rect, view_size);
}
void RenderWidgetHost::ToggleSpellPanel(bool is_currently_visible) {
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index d59fc4e..dc425b0 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -38,8 +38,9 @@ class RenderWidgetHostView;
class RenderWidgetHostPaintingObserver;
class TransportDIB;
class WebCursor;
+struct ViewHostMsg_PaintRect_Params;
+struct ViewHostMsg_ScrollRect_Params;
struct ViewHostMsg_ShowPopup_Params;
-struct ViewHostMsg_UpdateRect_Params;
// This class manages the browser side of a browser<->renderer HWND connection.
// The HWND lives in the browser process, and windows events are sent over
@@ -412,7 +413,8 @@ class RenderWidgetHost : public IPC::Channel::Listener,
void OnMsgRenderViewGone();
void OnMsgClose();
void OnMsgRequestMove(const gfx::Rect& pos);
- void OnMsgUpdateRect(const ViewHostMsg_UpdateRect_Params& params);
+ void OnMsgPaintRect(const ViewHostMsg_PaintRect_Params& params);
+ void OnMsgScrollRect(const ViewHostMsg_ScrollRect_Params& params);
void OnMsgInputEventAck(const IPC::Message& message);
void OnMsgFocus();
void OnMsgBlur();
@@ -442,7 +444,10 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// Scrolls the given |clip_rect| in the backing by the given dx/dy amount. The
// |dib| and its corresponding location |bitmap_rect| in the backing store
// is the newly painted pixels by the renderer.
- void ScrollBackingStoreRect(int dx, int dy, const gfx::Rect& clip_rect,
+ void ScrollBackingStoreRect(TransportDIB* dib,
+ const gfx::Rect& bitmap_rect,
+ int dx, int dy,
+ const gfx::Rect& clip_rect,
const gfx::Size& view_size);
// Called by OnMsgInputEventAck() to process a keyboard event ack message.
diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc
index ba191fc..e3f4517 100644
--- a/chrome/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc
@@ -21,9 +21,9 @@ class RenderWidgetHostProcess : public MockRenderProcessHost {
public:
explicit RenderWidgetHostProcess(Profile* profile)
: MockRenderProcessHost(profile),
- current_update_buf_(NULL),
- update_msg_should_reply_(false),
- update_msg_reply_flags_(0) {
+ current_paint_buf_(NULL),
+ paint_msg_should_reply_(false),
+ paint_msg_reply_flags_(0) {
// DANGER! This is a hack. The RenderWidgetHost checks the channel to see
// if the process is still alive, but it doesn't actually dereference it.
// An IPC::SyncChannel is nontrivial, so we just fake it here. If you end up
@@ -34,65 +34,64 @@ class RenderWidgetHostProcess : public MockRenderProcessHost {
// We don't want to actually delete the channel, since it's not a real
// pointer.
channel_.release();
- delete current_update_buf_;
+ if (current_paint_buf_)
+ delete current_paint_buf_;
}
- void set_update_msg_should_reply(bool reply) {
- update_msg_should_reply_ = reply;
+ void set_paint_msg_should_reply(bool reply) {
+ paint_msg_should_reply_ = reply;
}
- void set_update_msg_reply_flags(int flags) {
- update_msg_reply_flags_ = flags;
+ void set_paint_msg_reply_flags(int flags) {
+ paint_msg_reply_flags_ = flags;
}
// Fills the given paint parameters with resonable default values.
- void InitUpdateRectParams(ViewHostMsg_UpdateRect_Params* params);
+ void InitPaintRectParams(ViewHostMsg_PaintRect_Params* params);
protected:
- virtual bool WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg);
+ virtual bool WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg);
- TransportDIB* current_update_buf_;
+ TransportDIB* current_paint_buf_;
// Set to true when WaitForPaintMsg should return a successful paint messaage
// reply. False implies timeout.
- bool update_msg_should_reply_;
+ bool paint_msg_should_reply_;
// Indicates the flags that should be sent with a the repaint request. This
// only has an effect when paint_msg_should_reply_ is true.
- int update_msg_reply_flags_;
+ int paint_msg_reply_flags_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostProcess);
};
-void RenderWidgetHostProcess::InitUpdateRectParams(
- ViewHostMsg_UpdateRect_Params* params) {
+void RenderWidgetHostProcess::InitPaintRectParams(
+ ViewHostMsg_PaintRect_Params* params) {
// Create the shared backing store.
const int w = 100, h = 100;
const size_t pixel_size = w * h * 4;
- if (!current_update_buf_)
- current_update_buf_ = TransportDIB::Create(pixel_size, 0);
- params->bitmap = current_update_buf_->id();
+ if (!current_paint_buf_)
+ current_paint_buf_ = TransportDIB::Create(pixel_size, 0);
+ params->bitmap = current_paint_buf_->id();
params->bitmap_rect = gfx::Rect(0, 0, w, h);
- params->dx = 0;
- params->dy = 0;
- params->copy_rects.push_back(params->bitmap_rect);
+ params->update_rects.push_back(params->bitmap_rect);
params->view_size = gfx::Size(w, h);
- params->flags = update_msg_reply_flags_;
+ params->flags = paint_msg_reply_flags_;
}
-bool RenderWidgetHostProcess::WaitForUpdateMsg(int render_widget_id,
- const base::TimeDelta& max_delay,
- IPC::Message* msg) {
- if (!update_msg_should_reply_)
+bool RenderWidgetHostProcess::WaitForPaintMsg(int render_widget_id,
+ const base::TimeDelta& max_delay,
+ IPC::Message* msg) {
+ if (!paint_msg_should_reply_)
return false;
// Construct a fake paint reply.
- ViewHostMsg_UpdateRect_Params params;
- InitUpdateRectParams(&params);
+ ViewHostMsg_PaintRect_Params params;
+ InitPaintRectParams(&params);
- ViewHostMsg_UpdateRect message(render_widget_id, params);
+ ViewHostMsg_PaintRect message(render_widget_id, params);
*msg = message;
return true;
}
@@ -252,9 +251,9 @@ TEST_F(RenderWidgetHostTest, Resize) {
// Send out a paint that's not a resize ack. This should not clean the
// resize ack pending flag.
- ViewHostMsg_UpdateRect_Params params;
- process_->InitUpdateRectParams(&params);
- host_->OnMsgUpdateRect(params);
+ ViewHostMsg_PaintRect_Params params;
+ process_->InitPaintRectParams(&params);
+ host_->OnMsgPaintRect(params);
EXPECT_TRUE(host_->resize_ack_pending_);
EXPECT_EQ(original_size.size(), host_->in_flight_size_);
@@ -272,9 +271,9 @@ TEST_F(RenderWidgetHostTest, Resize) {
// this isn't the second_size, the message handler should immediately send
// a new resize message for the new size to the renderer.
process_->sink().ClearMessages();
- params.flags = ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
+ params.flags = ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK;
params.view_size = original_size.size();
- host_->OnMsgUpdateRect(params);
+ host_->OnMsgPaintRect(params);
EXPECT_TRUE(host_->resize_ack_pending_);
EXPECT_EQ(second_size.size(), host_->in_flight_size_);
ASSERT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID));
@@ -282,7 +281,7 @@ TEST_F(RenderWidgetHostTest, Resize) {
// Send the resize ack for the latest size.
process_->sink().ClearMessages();
params.view_size = second_size.size();
- host_->OnMsgUpdateRect(params);
+ host_->OnMsgPaintRect(params);
EXPECT_FALSE(host_->resize_ack_pending_);
EXPECT_EQ(gfx::Size(), host_->in_flight_size_);
ASSERT_FALSE(process_->sink().GetFirstMessageMatching(ViewMsg_Resize::ID));
@@ -399,42 +398,42 @@ TEST_F(RenderWidgetHostTest, Background) {
TEST_F(RenderWidgetHostTest, GetBackingStore_NoRepaintAck) {
// We don't currently have a backing store, and if the renderer doesn't send
// one in time, we should get nothing.
- process_->set_update_msg_should_reply(false);
+ process_->set_paint_msg_should_reply(false);
BackingStore* backing = host_->GetBackingStore(true);
EXPECT_FALSE(backing);
// The widget host should have sent a request for a repaint, and there should
// be no paint ACK.
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
+ ViewMsg_PaintRect_ACK::ID));
// Allowing the renderer to reply in time should give is a backing store.
process_->sink().ClearMessages();
- process_->set_update_msg_should_reply(true);
- process_->set_update_msg_reply_flags(0);
+ process_->set_paint_msg_should_reply(true);
+ process_->set_paint_msg_reply_flags(0);
backing = host_->GetBackingStore(true);
EXPECT_TRUE(backing);
// The widget host should NOT have sent a request for a repaint, since there
// was an ACK already pending.
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
+ ViewMsg_PaintRect_ACK::ID));
}
// Tests getting the backing store with the renderer sending a repaint ack.
TEST_F(RenderWidgetHostTest, GetBackingStore_RepaintAck) {
// Doing a request request with the paint message allowed should work and
// the repaint ack should work.
- process_->set_update_msg_should_reply(true);
- process_->set_update_msg_reply_flags(
- ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK);
+ process_->set_paint_msg_should_reply(true);
+ process_->set_paint_msg_reply_flags(
+ ViewHostMsg_PaintRect_Flags::IS_REPAINT_ACK);
BackingStore* backing = host_->GetBackingStore(true);
EXPECT_TRUE(backing);
// We still should not have sent out a repaint request since the last flags
// didn't have the repaint ack set, and the pending flag will still be set.
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
+ ViewMsg_PaintRect_ACK::ID));
// Asking again for the backing store should just re-use the existing one
// and not send any messagse.
@@ -443,7 +442,7 @@ TEST_F(RenderWidgetHostTest, GetBackingStore_RepaintAck) {
EXPECT_TRUE(backing);
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(ViewMsg_Repaint::ID));
EXPECT_FALSE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
+ ViewMsg_PaintRect_ACK::ID));
}
// Test that we don't paint when we're hidden, but we still send the ACK. Most
@@ -457,13 +456,13 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) {
// Send it a paint as from the renderer.
process_->sink().ClearMessages();
- ViewHostMsg_UpdateRect_Params params;
- process_->InitUpdateRectParams(&params);
- host_->OnMsgUpdateRect(params);
+ ViewHostMsg_PaintRect_Params params;
+ process_->InitPaintRectParams(&params);
+ host_->OnMsgPaintRect(params);
// It should have sent out the ACK.
EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(
- ViewMsg_UpdateRect_ACK::ID));
+ ViewMsg_PaintRect_ACK::ID));
// Now unhide.
process_->sink().ClearMessages();
diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h
index 2a87291..3a71011 100644
--- a/chrome/browser/renderer_host/render_widget_host_view.h
+++ b/chrome/browser/renderer_host/render_widget_host_view.h
@@ -110,14 +110,13 @@ class RenderWidgetHostView {
// (Worse, we might recursively call RenderWidgetHost::GetBackingStore().)
// Thus implementers should generally paint as much of |rect| as possible
// synchronously with as little overpainting as possible.
- virtual void DidPaintBackingStoreRects(
- const std::vector<gfx::Rect>& rects) = 0;
+ virtual void DidPaintRect(const gfx::Rect& rect) = 0;
// Informs the view that a portion of the widget's backing store was scrolled
// by dx pixels horizontally and dy pixels vertically. The view should copy
// the exposed pixels from the backing store of the render widget (which has
// already been scrolled) onto the screen.
- virtual void DidScrollBackingStoreRect(
+ virtual void DidScrollRect(
const gfx::Rect& rect, int dx, int dy) = 0;
// Notifies the View that the renderer has ceased to exist.
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
index 8ce8747..cd38ec8 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc
@@ -505,27 +505,21 @@ void RenderWidgetHostViewGtk::IMEUpdateStatus(int control,
key_bindings_handler_->set_enabled(control != IME_DISABLE);
}
-void RenderWidgetHostViewGtk::DidPaintBackingStoreRects(
- const std::vector<gfx::Rect>& rects) {
+void RenderWidgetHostViewGtk::DidPaintRect(const gfx::Rect& rect) {
if (is_hidden_)
return;
- for (size_t i = 0; i < rects.size(); ++i) {
- if (about_to_validate_and_paint_) {
- invalid_rect_ = invalid_rect_.Union(rects[i]);
- } else {
- Paint(rects[i]);
- }
- }
+ if (about_to_validate_and_paint_)
+ invalid_rect_ = invalid_rect_.Union(rect);
+ else
+ Paint(rect);
}
-void RenderWidgetHostViewGtk::DidScrollBackingStoreRect(const gfx::Rect& rect,
- int dx, int dy) {
+void RenderWidgetHostViewGtk::DidScrollRect(const gfx::Rect& rect, int dx,
+ int dy) {
if (is_hidden_)
return;
- // TODO(darin): Implement the equivalent of Win32's ScrollWindowEX. Can that
- // be done using XCopyArea? Perhaps similar to BackingStore::ScrollRect?
Paint(rect);
}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.h b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
index 5c05094..94f4f1a 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.h
@@ -60,8 +60,8 @@ class RenderWidgetHostViewGtk : public RenderWidgetHostView {
virtual void UpdateCursor(const WebCursor& cursor);
virtual void SetIsLoading(bool is_loading);
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect);
- virtual void DidPaintBackingStoreRects(const std::vector<gfx::Rect>& rects);
- virtual void DidScrollBackingStoreRect(const gfx::Rect& rect, int dx, int dy);
+ virtual void DidPaintRect(const gfx::Rect& rect);
+ virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy);
virtual void RenderViewGone();
virtual void Destroy();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {}
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h
index 3dc07b2..c661578 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h
@@ -95,8 +95,8 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView {
virtual void UpdateCursor(const WebCursor& cursor);
virtual void SetIsLoading(bool is_loading);
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect);
- virtual void DidPaintBackingStoreRects(const std::vector<gfx::Rect>& rects);
- virtual void DidScrollBackingStoreRect(const gfx::Rect& rect, int dx, int dy);
+ virtual void DidPaintRect(const gfx::Rect& rect);
+ virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy);
virtual void RenderViewGone();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) {};
virtual void Destroy();
diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
index 55cfaef..78d2736 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm
@@ -275,31 +275,26 @@ void RenderWidgetHostViewMac::IMEUpdateStatus(int control,
caret_rect.width(), caret_rect.height());
}
-void RenderWidgetHostViewMac::DidPaintBackingStoreRects(
- const std::vector<gfx::Rect>& rects) {
+void RenderWidgetHostViewMac::DidPaintRect(const gfx::Rect& rect) {
if (is_hidden_)
return;
- for (size_t i = 0; i < rects.size(); ++i) {
- NSRect ns_rect = [cocoa_view_ RectToNSRect:rects[i]];
-
- if (about_to_validate_and_paint_) {
- // As much as we'd like to use -setNeedsDisplayInRect: here, we can't.
- // We're in the middle of executing a -drawRect:, and as soon as it
- // returns Cocoa will clear its record of what needs display. If we want
- // to handle the recursive drawing, we need to do it ourselves.
- invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect);
- } else {
- [cocoa_view_ setNeedsDisplayInRect:ns_rect];
- }
- }
+ NSRect ns_rect = [cocoa_view_ RectToNSRect:rect];
- if (!about_to_validate_and_paint_)
+ if (about_to_validate_and_paint_) {
+ // As much as we'd like to use -setNeedsDisplayInRect: here, we can't. We're
+ // in the middle of executing a -drawRect:, and as soon as it returns Cocoa
+ // will clear its record of what needs display. If we want to handle the
+ // recursive drawing, we need to do it ourselves.
+ invalid_rect_ = NSUnionRect(invalid_rect_, ns_rect);
+ } else {
+ [cocoa_view_ setNeedsDisplayInRect:ns_rect];
[cocoa_view_ displayIfNeeded];
+ }
}
-void RenderWidgetHostViewMac::DidScrollBackingStoreRect(const gfx::Rect& rect,
- int dx, int dy) {
+void RenderWidgetHostViewMac::DidScrollRect(
+ const gfx::Rect& rect, int dx, int dy) {
if (is_hidden_)
return;
@@ -310,7 +305,7 @@ void RenderWidgetHostViewMac::DidScrollBackingStoreRect(const gfx::Rect& rect,
// TODO(rohitrao): Evaluate how slow this full redraw is. If it
// turns out to be a problem, consider scrolling only a portion of
// the view, based on where the findbar and blocked popups are.
- DidPaintBackingStoreRects(std::vector<gfx::Rect>(1, rect));
+ DidPaintRect(rect);
}
void RenderWidgetHostViewMac::RenderViewGone() {
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index 8be4df5..e0b3832 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -568,13 +568,7 @@ BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lparam) {
return TRUE;
}
-void RenderWidgetHostViewWin::Redraw() {
- RECT damage_bounds;
- GetUpdateRect(&damage_bounds, FALSE);
-
- ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
- GetUpdateRgn(damage_region, FALSE);
-
+void RenderWidgetHostViewWin::Redraw(const gfx::Rect& rect) {
// Paint the invalid region synchronously. Our caller will not paint again
// until we return, so by painting to the screen here, we ensure effective
// rate-limiting of backing store updates. This helps a lot on pages that
@@ -585,11 +579,12 @@ void RenderWidgetHostViewWin::Redraw() {
// message dispatching we allow scrolling to be smooth, and also avoid the
// browser process locking up if the plugin process is hung.
//
- RedrawWindow(NULL, damage_region, RDW_UPDATENOW | RDW_NOCHILDREN);
+ RedrawWindow(
+ &rect.ToRECT(), NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOCHILDREN);
// Send the invalid rect in screen coordinates.
gfx::Rect screen_rect = GetViewBounds();
- gfx::Rect invalid_screen_rect(damage_bounds);
+ gfx::Rect invalid_screen_rect = rect;
invalid_screen_rect.Offset(screen_rect.x(), screen_rect.y());
LPARAM lparam = reinterpret_cast<LPARAM>(&invalid_screen_rect);
@@ -624,29 +619,31 @@ void RenderWidgetHostViewWin::DrawResizeCorner(const gfx::Rect& paint_rect,
}
}
-void RenderWidgetHostViewWin::DidPaintBackingStoreRects(
- const std::vector<gfx::Rect>& rects) {
+void RenderWidgetHostViewWin::DidPaintRect(const gfx::Rect& rect) {
if (is_hidden_)
return;
- for (size_t i = 0; i < rects.size(); ++i)
- InvalidateRect(&rects[i].ToRECT(), false);
-
- if (!about_to_validate_and_paint_)
- Redraw();
+ if (about_to_validate_and_paint_)
+ InvalidateRect(&rect.ToRECT(), false);
+ else
+ Redraw(rect);
}
-void RenderWidgetHostViewWin::DidScrollBackingStoreRect(
+void RenderWidgetHostViewWin::DidScrollRect(
const gfx::Rect& rect, int dx, int dy) {
if (is_hidden_)
return;
- // We need to pass in SW_INVALIDATE to ScrollWindowEx. The documentation on
- // MSDN states that it only applies to the HRGN argument, which is wrong.
- // Not passing in this flag does not invalidate the region which was scrolled
- // from, thus causing painting issues.
+ // We need to pass in SW_INVALIDATE to ScrollWindowEx. The MSDN
+ // documentation states that it only applies to the HRGN argument, which is
+ // wrong. Not passing in this flag does not invalidate the region which was
+ // scrolled from, thus causing painting issues.
RECT clip_rect = rect.ToRECT();
ScrollWindowEx(dx, dy, NULL, &clip_rect, NULL, NULL, SW_INVALIDATE);
+
+ RECT invalid_rect = {0};
+ GetUpdateRect(&invalid_rect);
+ Redraw(gfx::Rect(invalid_rect));
}
void RenderWidgetHostViewWin::RenderViewGone() {
@@ -768,12 +765,6 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) {
// GetBackingStore(), so that if it updates the invalid rect we'll catch the
// changes and repaint them.
about_to_validate_and_paint_ = false;
-
- // Grab the region to paint before creation of paint_dc since it clears the
- // damage region.
- ScopedGDIObject<HRGN> damage_region(CreateRectRgn(0, 0, 0, 0));
- GetUpdateRgn(damage_region, FALSE);
-
CPaintDC paint_dc(m_hWnd);
gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint);
@@ -781,38 +772,28 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) {
return;
if (backing_store) {
- gfx::Rect bitmap_rect(gfx::Point(), backing_store->size());
-
- bool manage_colors = BackingStore::ColorManagementEnabled();
- if (manage_colors)
- SetICMMode(paint_dc.m_hDC, ICM_ON);
-
- // Blit only the damaged regions from the backing store.
- DWORD data_size = GetRegionData(damage_region, 0, NULL);
- scoped_array<char> region_data_buf(new char[data_size]);
- RGNDATA* region_data = reinterpret_cast<RGNDATA*>(region_data_buf.get());
- GetRegionData(damage_region, data_size, region_data);
-
- RECT* region_rects = reinterpret_cast<RECT*>(region_data->Buffer);
- for (DWORD i = 0; i < region_data->rdh.nCount; ++i) {
- gfx::Rect paint_rect = bitmap_rect.Intersect(gfx::Rect(region_rects[i]));
- if (!paint_rect.IsEmpty()) {
- DrawResizeCorner(paint_rect, backing_store->hdc());
- BitBlt(paint_dc.m_hDC,
- paint_rect.x(),
- paint_rect.y(),
- paint_rect.width(),
- paint_rect.height(),
- backing_store->hdc(),
- paint_rect.x(),
- paint_rect.y(),
- SRCCOPY);
- }
+ gfx::Rect bitmap_rect(
+ 0, 0, backing_store->size().width(), backing_store->size().height());
+
+ gfx::Rect paint_rect = bitmap_rect.Intersect(damaged_rect);
+ if (!paint_rect.IsEmpty()) {
+ DrawResizeCorner(paint_rect, backing_store->hdc());
+ bool manage_colors = BackingStore::ColorManagementEnabled();
+ if (manage_colors)
+ SetICMMode(paint_dc.m_hDC, ICM_ON);
+ BitBlt(paint_dc.m_hDC,
+ paint_rect.x(),
+ paint_rect.y(),
+ paint_rect.width(),
+ paint_rect.height(),
+ backing_store->hdc(),
+ paint_rect.x(),
+ paint_rect.y(),
+ SRCCOPY);
+ if (manage_colors)
+ SetICMMode(paint_dc.m_hDC, ICM_OFF);
}
- if (manage_colors)
- SetICMMode(paint_dc.m_hDC, ICM_OFF);
-
// Fill the remaining portion of the damaged_rect with the background
if (damaged_rect.right() > bitmap_rect.right()) {
RECT r;
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 3b54064..57b220b 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -125,8 +125,8 @@ class RenderWidgetHostViewWin
virtual void UpdateCursor(const WebCursor& cursor);
virtual void SetIsLoading(bool is_loading);
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect);
- virtual void DidPaintBackingStoreRects(const std::vector<gfx::Rect>& rects);
- virtual void DidScrollBackingStoreRect(const gfx::Rect& rect, int dx, int dy);
+ virtual void DidPaintRect(const gfx::Rect& rect);
+ virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy);
virtual void RenderViewGone();
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh);
virtual void Destroy();
@@ -207,7 +207,7 @@ class RenderWidgetHostViewWin
// Redraws the window synchronously, and any child windows (i.e. plugins)
// asynchronously.
- void Redraw();
+ void Redraw(const gfx::Rect& invalid_rect);
// Draw the resize corner bitmap on top of the given HDC, if it intersects the
// given paint rect.
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index c0cc742..2bcccb2 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -326,8 +326,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DnsPrefetch, OnDnsPrefetch)
IPC_MESSAGE_HANDLER(ViewHostMsg_RendererHistograms,
OnRendererHistograms)
- IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_UpdateRect,
- render_widget_helper_->DidReceiveUpdateMsg(msg))
+ IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_PaintRect,
+ render_widget_helper_->DidReceivePaintMsg(msg))
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsAsync,
OnClipboardWriteObjects)
IPC_MESSAGE_HANDLER(ViewHostMsg_ClipboardWriteObjectsSync,
diff --git a/chrome/browser/renderer_host/test/test_render_view_host.h b/chrome/browser/renderer_host/test/test_render_view_host.h
index 9990fab..b1458a1 100644
--- a/chrome/browser/renderer_host/test/test_render_view_host.h
+++ b/chrome/browser/renderer_host/test/test_render_view_host.h
@@ -64,10 +64,8 @@ class TestRenderWidgetHostView : public RenderWidgetHostView {
virtual void UpdateCursor(const WebCursor& cursor) {}
virtual void UpdateCursorIfOverSelf() {}
virtual void IMEUpdateStatus(int control, const gfx::Rect& caret_rect) {}
- virtual void DidPaintBackingStoreRects(
- const std::vector<gfx::Rect>& rects) {}
- virtual void DidScrollBackingStoreRect(
- const gfx::Rect& rect, int dx, int dy) {}
+ virtual void DidPaintRect(const gfx::Rect& rect) {}
+ virtual void DidScrollRect(const gfx::Rect& rect, int dx, int dy) {}
virtual void RenderViewGone() { delete this; }
virtual void WillDestroyRenderWidget(RenderWidgetHost* rwh) { }
virtual void Destroy() {}
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index c886522..9e2e6fc 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -176,8 +176,8 @@ struct ViewHostMsg_FrameNavigate_Params {
};
// Values that may be OR'd together to form the 'flags' parameter of a
-// ViewHostMsg_UpdateRect_Params structure.
-struct ViewHostMsg_UpdateRect_Flags {
+// ViewHostMsg_PaintRect message.
+struct ViewHostMsg_PaintRect_Flags {
enum {
IS_RESIZE_ACK = 1 << 0,
IS_RESTORE_ACK = 1 << 1,
@@ -189,12 +189,13 @@ struct ViewHostMsg_UpdateRect_Flags {
static bool is_restore_ack(int flags) {
return (flags & IS_RESTORE_ACK) != 0;
}
+
static bool is_repaint_ack(int flags) {
return (flags & IS_REPAINT_ACK) != 0;
}
};
-struct ViewHostMsg_UpdateRect_Params {
+struct ViewHostMsg_PaintRect_Params {
// The bitmap to be painted into the view at the locations specified by
// update_rects.
TransportDIB::Id bitmap;
@@ -202,18 +203,8 @@ struct ViewHostMsg_UpdateRect_Params {
// The position and size of the bitmap.
gfx::Rect bitmap_rect;
- // The scroll offset. Only one of these can be non-zero, and if they are
- // both zero, then it means there is no scrolling and the scroll_rect is
- // ignored.
- int dx;
- int dy;
-
- // The rectangular region to scroll.
- gfx::Rect scroll_rect;
-
// The regions of the bitmap (in view coords) that contain updated pixels.
- // In the case of scrolling, this includes the scroll damage rect.
- std::vector<gfx::Rect> copy_rects;
+ std::vector<gfx::Rect> update_rects;
// The size of the RenderView when this message was generated. This is
// included so the host knows how large the view is from the perspective of
@@ -226,22 +217,42 @@ struct ViewHostMsg_UpdateRect_Params {
// The following describes the various bits that may be set in flags:
//
- // ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK
+ // ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK
// Indicates that this is a response to a ViewMsg_Resize message.
//
- // ViewHostMsg_UpdateRect_Flags::IS_RESTORE_ACK
+ // ViewHostMsg_PaintRect_Flags::IS_RESTORE_ACK
// Indicates that this is a response to a ViewMsg_WasRestored message.
//
- // ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK
- // Indicates that this is a response to a ViewMsg_Repaint message.
- //
// If flags is zero, then this message corresponds to an unsoliticed paint
- // request by the render view. Any of the above bits may be set in flags,
+ // request by the render view. Both of the above bits may be set in flags,
// which would indicate that this paint message is an ACK for multiple
// request messages.
int flags;
};
+// Parameters structure for ViewHostMsg_ScrollRect, which has too many data
+// parameters to be reasonably put in a predefined IPC message.
+struct ViewHostMsg_ScrollRect_Params {
+ // The bitmap to be painted into the rect exposed by scrolling.
+ TransportDIB::Id bitmap;
+
+ // The position and size of the bitmap.
+ gfx::Rect bitmap_rect;
+
+ // The scroll offset. Only one of these can be non-zero.
+ int dx;
+ int dy;
+
+ // The rectangular region to scroll.
+ gfx::Rect clip_rect;
+
+ // The size of the RenderView when this message was generated.
+ gfx::Size view_size;
+
+ // New window locations for plugin child windows.
+ std::vector<webkit_glue::WebPluginGeometry> plugin_window_moves;
+};
+
// Information on closing a tab. This is used both for ViewMsg_ClosePage, and
// the corresponding ViewHostMsg_ClosePage_ACK.
struct ViewMsg_ClosePage_Params {
@@ -967,20 +978,56 @@ struct ParamTraits<ContextMenuParams> {
}
};
-// Traits for ViewHostMsg_UpdateRect_Params structure to pack/unpack.
+// Traits for ViewHostMsg_PaintRect_Params structure to pack/unpack.
template <>
-struct ParamTraits<ViewHostMsg_UpdateRect_Params> {
- typedef ViewHostMsg_UpdateRect_Params param_type;
+struct ParamTraits<ViewHostMsg_PaintRect_Params> {
+ typedef ViewHostMsg_PaintRect_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.bitmap);
+ WriteParam(m, p.bitmap_rect);
+ WriteParam(m, p.update_rects);
+ WriteParam(m, p.view_size);
+ WriteParam(m, p.plugin_window_moves);
+ WriteParam(m, p.flags);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->bitmap) &&
+ ReadParam(m, iter, &p->bitmap_rect) &&
+ ReadParam(m, iter, &p->update_rects) &&
+ ReadParam(m, iter, &p->view_size) &&
+ ReadParam(m, iter, &p->plugin_window_moves) &&
+ ReadParam(m, iter, &p->flags);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.bitmap, l);
+ l->append(L", ");
+ LogParam(p.bitmap_rect, l);
+ l->append(L", ");
+ LogParam(p.update_rects, l);
+ l->append(L", ");
+ LogParam(p.view_size, l);
+ l->append(L", ");
+ LogParam(p.plugin_window_moves, l);
+ l->append(L", ");
+ LogParam(p.flags, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_ScrollRect_Params structure to pack/unpack.
+template <>
+struct ParamTraits<ViewHostMsg_ScrollRect_Params> {
+ typedef ViewHostMsg_ScrollRect_Params param_type;
static void Write(Message* m, const param_type& p) {
WriteParam(m, p.bitmap);
WriteParam(m, p.bitmap_rect);
WriteParam(m, p.dx);
WriteParam(m, p.dy);
- WriteParam(m, p.scroll_rect);
- WriteParam(m, p.copy_rects);
+ WriteParam(m, p.clip_rect);
WriteParam(m, p.view_size);
WriteParam(m, p.plugin_window_moves);
- WriteParam(m, p.flags);
}
static bool Read(const Message* m, void** iter, param_type* p) {
return
@@ -988,11 +1035,9 @@ struct ParamTraits<ViewHostMsg_UpdateRect_Params> {
ReadParam(m, iter, &p->bitmap_rect) &&
ReadParam(m, iter, &p->dx) &&
ReadParam(m, iter, &p->dy) &&
- ReadParam(m, iter, &p->scroll_rect) &&
- ReadParam(m, iter, &p->copy_rects) &&
+ ReadParam(m, iter, &p->clip_rect) &&
ReadParam(m, iter, &p->view_size) &&
- ReadParam(m, iter, &p->plugin_window_moves) &&
- ReadParam(m, iter, &p->flags);
+ ReadParam(m, iter, &p->plugin_window_moves);
}
static void Log(const param_type& p, std::wstring* l) {
l->append(L"(");
@@ -1004,15 +1049,11 @@ struct ParamTraits<ViewHostMsg_UpdateRect_Params> {
l->append(L", ");
LogParam(p.dy, l);
l->append(L", ");
- LogParam(p.scroll_rect, l);
- l->append(L", ");
- LogParam(p.copy_rects, l);
+ LogParam(p.clip_rect, l);
l->append(L", ");
LogParam(p.view_size, l);
l->append(L", ");
LogParam(p.plugin_window_moves, l);
- l->append(L", ");
- LogParam(p.flags, l);
l->append(L")");
}
};
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index ca3e80b..3f9a1f1 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -128,6 +128,10 @@ IPC_BEGIN_MESSAGES(View)
// render view responds with a ViewHostMsg_Thumbnail.
IPC_MESSAGE_ROUTED0(ViewMsg_CaptureThumbnail)
+ // Tells the render view that a ViewHostMsg_PaintRect message was processed.
+ // This signals the render view that it can send another PaintRect message.
+ IPC_MESSAGE_ROUTED0(ViewMsg_PaintRect_ACK)
+
// Tells the render view to switch the CSS to print media type, renders every
// requested pages and switch back the CSS to display media type.
IPC_MESSAGE_ROUTED0(ViewMsg_PrintPages)
@@ -143,9 +147,9 @@ IPC_BEGIN_MESSAGES(View)
// JS garbage, not in purging irreplaceable objects.
IPC_MESSAGE_CONTROL0(ViewMsg_PurgeMemory)
- // Tells the render view that a ViewHostMsg_UpdateRect message was processed.
- // This signals the render view that it can send another UpdateRect message.
- IPC_MESSAGE_ROUTED0(ViewMsg_UpdateRect_ACK)
+ // Tells the render view that a ViewHostMsg_ScrollRect message was processed.
+ // This signals the render view that it can send another ScrollRect message.
+ IPC_MESSAGE_ROUTED0(ViewMsg_ScrollRect_ACK)
// Message payload includes:
// 1. A blob that should be cast to WebInputEvent
@@ -989,10 +993,15 @@ IPC_BEGIN_MESSAGES(ViewHost)
navigating to a POST again and we're going to
show the POST interstitial */ )
- // Sent to update part of the view. In response to this message, the host
- // generates a ViewMsg_UpdateRect_ACK message.
- IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateRect,
- ViewHostMsg_UpdateRect_Params)
+ // Sent to paint part of the view. In response to this message, the host
+ // generates a ViewMsg_PaintRect_ACK message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_PaintRect,
+ ViewHostMsg_PaintRect_Params)
+
+ // Sent to scroll part of the view. In response to this message, the host
+ // generates a ViewMsg_ScrollRect_ACK message.
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ScrollRect,
+ ViewHostMsg_ScrollRect_Params)
// Acknowledges receipt of a ViewMsg_HandleInputEvent message.
// Payload is a WebInputEvent::Type which is the type of the event, followed
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc
index 8a3513c..27955bb 100644
--- a/chrome/renderer/render_widget.cc
+++ b/chrome/renderer/render_widget.cc
@@ -50,8 +50,9 @@ RenderWidget::RenderWidget(RenderThreadBase* render_thread, bool activatable)
render_thread_(render_thread),
host_window_(0),
current_paint_buf_(NULL),
+ current_scroll_buf_(NULL),
next_paint_flags_(0),
- update_reply_pending_(false),
+ paint_reply_pending_(false),
did_show_(false),
is_hidden_(false),
needs_repainting_on_restore_(false),
@@ -78,6 +79,10 @@ RenderWidget::~RenderWidget() {
RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
current_paint_buf_ = NULL;
}
+ if (current_scroll_buf_) {
+ RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_);
+ current_scroll_buf_ = NULL;
+ }
RenderProcess::current()->ReleaseProcess();
}
@@ -137,7 +142,8 @@ IPC_DEFINE_MESSAGE_MAP(RenderWidget)
IPC_MESSAGE_HANDLER(ViewMsg_Resize, OnResize)
IPC_MESSAGE_HANDLER(ViewMsg_WasHidden, OnWasHidden)
IPC_MESSAGE_HANDLER(ViewMsg_WasRestored, OnWasRestored)
- IPC_MESSAGE_HANDLER(ViewMsg_UpdateRect_ACK, OnUpdateRectAck)
+ IPC_MESSAGE_HANDLER(ViewMsg_PaintRect_ACK, OnPaintRectAck)
+ IPC_MESSAGE_HANDLER(ViewMsg_ScrollRect_ACK, OnScrollRectAck)
IPC_MESSAGE_HANDLER(ViewMsg_HandleInputEvent, OnHandleInputEvent)
IPC_MESSAGE_HANDLER(ViewMsg_MouseCaptureLost, OnMouseCaptureLost)
IPC_MESSAGE_HANDLER(ViewMsg_SetFocus, OnSetFocus)
@@ -252,17 +258,11 @@ void RenderWidget::OnWasRestored(bool needs_repainting) {
didInvalidateRect(gfx::Rect(size_.width(), size_.height()));
}
-void RenderWidget::OnRequestMoveAck() {
- DCHECK(pending_window_rect_count_);
- pending_window_rect_count_--;
-}
-
-void RenderWidget::OnUpdateRectAck() {
- DCHECK(update_reply_pending());
- update_reply_pending_ = false;
-
- // If we sent an UpdateRect message with a zero-sized bitmap, then we should
- // have no current update buf.
+void RenderWidget::OnPaintRectAck() {
+ DCHECK(paint_reply_pending());
+ paint_reply_pending_ = false;
+ // If we sent a PaintRect message with a zero-sized bitmap, then
+ // we should have no current paint buf.
if (current_paint_buf_) {
RenderProcess::current()->ReleaseTransportDIB(current_paint_buf_);
current_paint_buf_ = NULL;
@@ -275,6 +275,23 @@ void RenderWidget::OnUpdateRectAck() {
CallDoDeferredUpdate();
}
+void RenderWidget::OnRequestMoveAck() {
+ DCHECK(pending_window_rect_count_);
+ pending_window_rect_count_--;
+}
+
+void RenderWidget::OnScrollRectAck() {
+ DCHECK(scroll_reply_pending());
+
+ if (current_scroll_buf_) {
+ RenderProcess::current()->ReleaseTransportDIB(current_scroll_buf_);
+ current_scroll_buf_ = NULL;
+ }
+
+ // Continue scrolling if necessary...
+ CallDoDeferredUpdate();
+}
+
void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
void* iter = NULL;
@@ -388,17 +405,9 @@ void RenderWidget::PaintDebugBorder(const gfx::Rect& rect,
if (!kPaintBorder)
return;
- // Cycle through these colors to help distinguish new paint rects.
- const SkColor colors[] = {
- SkColorSetARGB(0x3F, 0xFF, 0, 0),
- SkColorSetARGB(0x3F, 0xFF, 0, 0xFF),
- SkColorSetARGB(0x3F, 0, 0, 0xFF),
- };
- static int color_selector = 0;
-
SkPaint paint;
paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(colors[color_selector++ % arraysize(colors)]);
+ paint.setColor(SkColorSetARGB(0x3F, 0xFF, 0, 0));
paint.setStrokeWidth(1);
SkIRect irect;
@@ -417,7 +426,7 @@ void RenderWidget::CallDoDeferredUpdate() {
void RenderWidget::DoDeferredUpdate() {
if (!webwidget_ || !paint_aggregator_.HasPendingUpdate() ||
- update_reply_pending())
+ paint_reply_pending() || scroll_reply_pending())
return;
// Suppress updating when we are hidden.
@@ -435,56 +444,86 @@ void RenderWidget::DoDeferredUpdate() {
PaintAggregator::PendingUpdate update = paint_aggregator_.GetPendingUpdate();
paint_aggregator_.ClearPendingUpdate();
- gfx::Rect scroll_damage = update.GetScrollDamage();
- gfx::Rect bounds = update.GetPaintBounds().Union(scroll_damage);
+ if (!update.scroll_rect.IsEmpty()) {
+ // Optmized scrolling
- // Compute a buffer for painting and cache it.
- scoped_ptr<skia::PlatformCanvas> canvas(
- RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_, bounds));
- if (!canvas.get()) {
- NOTREACHED();
- return;
- }
+ // Compute the region we will expose by scrolling, and paint that into a
+ // shared memory section.
+ gfx::Rect damaged_rect = update.GetScrollDamage();
- // We may get back a smaller canvas than we asked for.
- // TODO(darin): This seems like it could cause painting problems!
- DCHECK_EQ(bounds.width(), canvas->getDevice()->width());
- DCHECK_EQ(bounds.height(), canvas->getDevice()->height());
- bounds.set_width(canvas->getDevice()->width());
- bounds.set_height(canvas->getDevice()->height());
-
- HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size());
-
- // The scroll damage is just another rectangle to paint and copy.
- std::vector<gfx::Rect> copy_rects;
- copy_rects.swap(update.paint_rects);
- if (!scroll_damage.IsEmpty())
- copy_rects.push_back(scroll_damage);
-
- // TODO(darin): Re-enable painting multiple damage rects once the
- // page-cycler regressions are resolved. See bug 29589.
- if (update.scroll_rect.IsEmpty()) {
- update.paint_rects.clear();
- update.paint_rects.push_back(bounds);
+ scoped_ptr<skia::PlatformCanvas> canvas(
+ RenderProcess::current()->GetDrawingCanvas(&current_scroll_buf_,
+ damaged_rect));
+ if (!canvas.get()) {
+ NOTREACHED();
+ return;
+ }
+
+ // We may get back a smaller canvas than we asked for.
+ damaged_rect.set_width(canvas->getDevice()->width());
+ damaged_rect.set_height(canvas->getDevice()->height());
+
+ // Set these parameters before calling Paint, since that could result in
+ // further invalidates (uncommon).
+ ViewHostMsg_ScrollRect_Params params;
+ params.bitmap_rect = damaged_rect;
+ params.dx = update.scroll_delta.x();
+ params.dy = update.scroll_delta.y();
+ params.clip_rect = update.scroll_rect;
+ params.view_size = size_;
+ params.plugin_window_moves = plugin_window_moves_;
+ params.bitmap = current_scroll_buf_->id();
+
+ plugin_window_moves_.clear();
+
+ PaintRect(damaged_rect, damaged_rect.origin(), canvas.get());
+ Send(new ViewHostMsg_ScrollRect(routing_id_, params));
}
- for (size_t i = 0; i < copy_rects.size(); ++i)
- PaintRect(copy_rects[i], bounds.origin(), canvas.get());
+ if (!update.paint_rects.empty()) {
+ // Normal painting
+
+ gfx::Rect bounds = update.GetPaintBounds();
+
+ // Compute a buffer for painting and cache it.
+ scoped_ptr<skia::PlatformCanvas> canvas(
+ RenderProcess::current()->GetDrawingCanvas(&current_paint_buf_,
+ bounds));
+ if (!canvas.get()) {
+ NOTREACHED();
+ return;
+ }
+
+ // We may get back a smaller canvas than we asked for.
+ bounds.set_width(canvas->getDevice()->width());
+ bounds.set_height(canvas->getDevice()->height());
+
+ HISTOGRAM_COUNTS_100("MPArch.RW_PaintRectCount", update.paint_rects.size());
+
+ // TODO(darin): Re-enable painting multiple damage rects once the
+ // page-cycler regressions are resolved. See bug 29589.
+ if (update.scroll_rect.IsEmpty()) {
+ update.paint_rects.clear();
+ update.paint_rects.push_back(bounds);
+ }
+
+ for (size_t i = 0; i < update.paint_rects.size(); ++i)
+ PaintRect(update.paint_rects[i], bounds.origin(), canvas.get());
- ViewHostMsg_UpdateRect_Params params;
- params.bitmap = current_paint_buf_->id();
- params.bitmap_rect = bounds;
- params.dx = update.scroll_delta.x();
- params.dy = update.scroll_delta.y();
- params.scroll_rect = update.scroll_rect;
- params.copy_rects.swap(copy_rects); // TODO(darin): clip to bounds?
- params.view_size = size_;
- params.plugin_window_moves.swap(plugin_window_moves_);
- params.flags = next_paint_flags_;
+ ViewHostMsg_PaintRect_Params params;
+ params.bitmap_rect = bounds;
+ params.update_rects = update.paint_rects; // TODO(darin): clip to bounds?
+ params.view_size = size_;
+ params.plugin_window_moves = plugin_window_moves_;
+ params.flags = next_paint_flags_;
+ params.bitmap = current_paint_buf_->id();
- update_reply_pending_ = true;
- Send(new ViewHostMsg_UpdateRect(routing_id_, params));
- next_paint_flags_ = 0;
+ plugin_window_moves_.clear();
+
+ paint_reply_pending_ = true;
+ Send(new ViewHostMsg_PaintRect(routing_id_, params));
+ next_paint_flags_ = 0;
+ }
UpdateIME();
}
@@ -509,7 +548,7 @@ void RenderWidget::didInvalidateRect(const WebRect& rect) {
return;
if (!paint_aggregator_.HasPendingUpdate())
return;
- if (update_reply_pending())
+ if (paint_reply_pending() || scroll_reply_pending())
return;
// Perform updating asynchronously. This serves two purposes:
@@ -538,7 +577,7 @@ void RenderWidget::didScrollRect(int dx, int dy, const WebRect& clip_rect) {
return;
if (!paint_aggregator_.HasPendingUpdate())
return;
- if (update_reply_pending())
+ if (paint_reply_pending() || scroll_reply_pending())
return;
// Perform updating asynchronously. This serves two purposes:
@@ -734,23 +773,23 @@ void RenderWidget::SetBackground(const SkBitmap& background) {
}
bool RenderWidget::next_paint_is_resize_ack() const {
- return ViewHostMsg_UpdateRect_Flags::is_resize_ack(next_paint_flags_);
+ return ViewHostMsg_PaintRect_Flags::is_resize_ack(next_paint_flags_);
}
bool RenderWidget::next_paint_is_restore_ack() const {
- return ViewHostMsg_UpdateRect_Flags::is_restore_ack(next_paint_flags_);
+ return ViewHostMsg_PaintRect_Flags::is_restore_ack(next_paint_flags_);
}
void RenderWidget::set_next_paint_is_resize_ack() {
- next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK;
+ next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_RESIZE_ACK;
}
void RenderWidget::set_next_paint_is_restore_ack() {
- next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_RESTORE_ACK;
+ next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_RESTORE_ACK;
}
void RenderWidget::set_next_paint_is_repaint_ack() {
- next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK;
+ next_paint_flags_ |= ViewHostMsg_PaintRect_Flags::IS_REPAINT_ACK;
}
void RenderWidget::UpdateIME() {
diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h
index 4cf033e..c25c99a 100644
--- a/chrome/renderer/render_widget.h
+++ b/chrome/renderer/render_widget.h
@@ -142,7 +142,8 @@ class RenderWidget : public IPC::Channel::Listener,
const gfx::Rect& resizer_rect);
void OnWasHidden();
void OnWasRestored(bool needs_repainting);
- void OnUpdateRectAck();
+ void OnPaintRectAck();
+ void OnScrollRectAck();
void OnRequestMoveAck();
void OnHandleInputEvent(const IPC::Message& message);
void OnMouseCaptureLost();
@@ -166,9 +167,14 @@ class RenderWidget : public IPC::Channel::Listener,
bool is_hidden() const { return is_hidden_; }
- // True if an UpdateRect_ACK message is pending.
- bool update_reply_pending() const {
- return update_reply_pending_;
+ // True if a PaintRect_ACK message is pending.
+ bool paint_reply_pending() const {
+ return paint_reply_pending_;
+ }
+
+ // True if a ScrollRect_ACK message is pending.
+ bool scroll_reply_pending() const {
+ return current_scroll_buf_ != NULL;
}
bool next_paint_is_resize_ack() const;
@@ -232,20 +238,22 @@ class RenderWidget : public IPC::Channel::Listener,
// The size of the RenderWidget.
gfx::Size size_;
- // The TransportDIB that is being used to transfer an image to the browser.
+ // Transport DIBs that are currently in use to transfer an image to the
+ // browser.
TransportDIB* current_paint_buf_;
+ TransportDIB* current_scroll_buf_;
PaintAggregator paint_aggregator_;
// The area that must be reserved for drawing the resize corner.
gfx::Rect resizer_rect_;
- // Flags for the next ViewHostMsg_UpdateRect message.
+ // Flags for the next ViewHostMsg_PaintRect message.
int next_paint_flags_;
- // True if we are expecting an UpdateRect_ACK message (i.e., that a
- // UpdateRect message has been sent).
- bool update_reply_pending_;
+ // True if we are expecting a PaintRect_ACK message (i.e., that a PaintRect
+ // message has been sent).
+ bool paint_reply_pending_;
// Set to true if we should ignore RenderWidget::Show calls.
bool did_show_;