diff options
author | gspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-28 17:26:49 +0000 |
---|---|---|
committer | gspencer@chromium.org <gspencer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-28 17:26:49 +0000 |
commit | d65adb173f09a837c96f96fc24a258f439e46e58 (patch) | |
tree | 43605ab367e97389930c518c4e94bd3da5f20080 /chrome/browser/renderer_host | |
parent | 7cea56d943924d0c2196bdf4049f592b6182992c (diff) | |
download | chromium_src-d65adb173f09a837c96f96fc24a258f439e46e58.zip chromium_src-d65adb173f09a837c96f96fc24a258f439e46e58.tar.gz chromium_src-d65adb173f09a837c96f96fc24a258f439e46e58.tar.bz2 |
This adds in the ability for Chrome to generate windows with snapshots
of all currently open tabs in all browsers.
This is needed for overview mode on ChromeOS.
BUG=http://code.google.com/p/chromium-os/issues/detail?id=1170
TEST=Ran Chrome under ChromeOS with updated window manager.
Review URL: http://codereview.chromium.org/661237
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45824 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/renderer_host')
6 files changed, 105 insertions, 9 deletions
diff --git a/chrome/browser/renderer_host/backing_store_x.cc b/chrome/browser/renderer_host/backing_store_x.cc index d88dca7..f10e589 100644 --- a/chrome/browser/renderer_host/backing_store_x.cc +++ b/chrome/browser/renderer_host/backing_store_x.cc @@ -326,6 +326,7 @@ bool BackingStoreX::CopyFromBackingStore(const gfx::Rect& rect, // TODO(jhawkins): Need to convert the image data if the image bits per pixel // is not 32. + // Note that this also initializes the output bitmap as opaque. if (!output->initialize(width, height, true) || image->bits_per_pixel != 32) { if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) @@ -335,15 +336,19 @@ bool BackingStoreX::CopyFromBackingStore(const gfx::Rect& rect, return false; } - // The X image might have a different row stride, so iterate through it and - // copy each row out, only up to the pixels we're actually using. - // This code assumes a visual mode where a pixel is represented using - // a byte for each component. + // The X image might have a different row stride, so iterate through + // it and copy each row out, only up to the pixels we're actually + // using. This code assumes a visual mode where a pixel is + // represented using a 32-bit unsigned int, with a byte per component. SkBitmap bitmap = output->getTopPlatformDevice().accessBitmap(true); for (int y = 0; y < height; y++) { + const uint32* src_row = reinterpret_cast<uint32*>( + &image->data[image->bytes_per_line * y]); uint32* dest_row = bitmap.getAddr32(0, y); - const char* src_row = &image->data[image->bytes_per_line * y]; - memcpy(dest_row, src_row, width * 4); + for (int x = 0; x < width; ++x, ++dest_row) { + // Force alpha to be 0xff, because otherwise it causes rendering problems. + *dest_row = src_row[x] | 0xff000000; + } } if (shared_memory_support_ != x11_util::SHARED_MEMORY_NONE) diff --git a/chrome/browser/renderer_host/render_widget_helper.h b/chrome/browser/renderer_host/render_widget_helper.h index 53b336c..33ca744 100644 --- a/chrome/browser/renderer_host/render_widget_helper.h +++ b/chrome/browser/renderer_host/render_widget_helper.h @@ -188,7 +188,7 @@ class RenderWidgetHelper #endif // A map of live paint messages. Must hold pending_paints_lock_ to access. - // The PaintMsgProxy objects are not owned by this map. (See PaintMsgProxy + // The UpdateMsgProxy objects are not owned by this map. (See UpdateMsgProxy // for details about how the lifetime of instances are managed.) UpdateMsgProxyMap pending_paints_; Lock pending_paints_lock_; diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc index 6b20935..59b2231 100644 --- a/chrome/browser/renderer_host/render_widget_host.cc +++ b/chrome/browser/renderer_host/render_widget_host.cc @@ -127,6 +127,7 @@ 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_PaintAtSize_ACK, OnMsgPaintAtSizeAck) IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateRect, OnMsgUpdateRect) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateVideo, OnMsgCreateVideo) IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateVideo, OnMsgUpdateVideo) @@ -280,6 +281,14 @@ void RenderWidgetHost::SetIsLoading(bool is_loading) { view_->SetIsLoading(is_loading); } +void RenderWidgetHost::PaintAtSize(TransportDIB::Handle dib_handle, + const gfx::Size& size) { + // Ask the renderer to create a bitmap regardless of whether it's + // hidden, being resized, redrawn, etc., and to scale it by the + // scale factor given. + Send(new ViewMsg_PaintAtSize(routing_id_, dib_handle, size)); +} + BackingStore* RenderWidgetHost::GetBackingStore(bool force_create) { // We should not be asked to paint while we are hidden. If we are hidden, // then it means that our consumer failed to call WasRestored. If we're not @@ -676,6 +685,13 @@ void RenderWidgetHost::OnMsgRequestMove(const gfx::Rect& pos) { } } +void RenderWidgetHost::OnMsgPaintAtSizeAck( + const TransportDIB::Handle& dib_handle, const gfx::Size& size) { + if (painting_observer_) { + painting_observer_->WidgetDidReceivePaintAtSizeAck(this, dib_handle, size); + } +} + void RenderWidgetHost::OnMsgUpdateRect( const ViewHostMsg_UpdateRect_Params& params) { TimeTicks paint_start = TimeTicks::Now(); diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h index d57d8bc..7b87d13 100644 --- a/chrome/browser/renderer_host/render_widget_host.h +++ b/chrome/browser/renderer_host/render_widget_host.h @@ -205,6 +205,16 @@ class RenderWidgetHost : public IPC::Channel::Listener, // Indicates if the page has finished loading. void SetIsLoading(bool is_loading); + // This tells the renderer to paint into a bitmap and return it, + // regardless of whether the tab is hidden or not. It returns the + // bitmap scaled so it matches the requested size, so that the + // scaling happens on the rendering thread. When the bitmap is + // ready, the renderer sends a PaintAtSizeACK to this host, and the + // painting observer is notified. Note that this bypasses most of + // the update logic that is normally invoked, and doesn't put the + // results into the backing store. + void PaintAtSize(TransportDIB::Handle dib_handle, const gfx::Size& size); + // Get access to the widget's backing store. If a resize is in progress, // then the current size of the backing store may be less than the size of // the widget's view. If you pass |force_create| as true, then the backing @@ -413,6 +423,7 @@ class RenderWidgetHost : public IPC::Channel::Listener, FRIEND_TEST(RenderWidgetHostTest, Resize); FRIEND_TEST(RenderWidgetHostTest, ResizeThenCrash); FRIEND_TEST(RenderWidgetHostTest, HiddenPaint); + FRIEND_TEST(RenderWidgetHostTest, PaintAtSize); // Tell this object to destroy itself. void Destroy(); @@ -421,7 +432,7 @@ class RenderWidgetHost : public IPC::Channel::Listener, // if it is. void CheckRendererIsUnresponsive(); - // Called if we know the renderer is responsive. When we currently thing the + // Called if we know the renderer is responsive. When we currently think the // renderer is unresponsive, this will clear that state and call // NotifyRendererResponsive. void RendererIsResponsive(); @@ -431,6 +442,8 @@ class RenderWidgetHost : public IPC::Channel::Listener, void OnMsgRenderViewGone(); void OnMsgClose(); void OnMsgRequestMove(const gfx::Rect& pos); + void OnMsgPaintAtSizeAck(const TransportDIB::Handle& dib_handle, + const gfx::Size& size); void OnMsgUpdateRect(const ViewHostMsg_UpdateRect_Params& params); void OnMsgCreateVideo(const gfx::Size& size); void OnMsgUpdateVideo(TransportDIB::Id bitmap, const gfx::Rect& bitmap_rect); diff --git a/chrome/browser/renderer_host/render_widget_host_painting_observer.h b/chrome/browser/renderer_host/render_widget_host_painting_observer.h index d24b61a..332e446 100644 --- a/chrome/browser/renderer_host/render_widget_host_painting_observer.h +++ b/chrome/browser/renderer_host/render_widget_host_painting_observer.h @@ -5,8 +5,15 @@ #ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_PAINTING_OBSERVER_H_ #define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_PAINTING_OBSERVER_H_ +#include "app/surface/transport_dib.h" + class BackingStore; class RenderWidgetHost; +class SkBitmap; + +namespace gfx { +class Size; +} // This class can be used to observe painting events for a RenderWidgetHost. // Its primary goal in Chrome is to allow thumbnails to be generated. @@ -19,6 +26,13 @@ class RenderWidgetHostPaintingObserver { // Indicates that the RenderWidgetHost just updated the backing store. virtual void WidgetDidUpdateBackingStore(RenderWidgetHost* widget) = 0; + + // This notifies the painting observer that a PaintAtSizeACK was + // received. + virtual void WidgetDidReceivePaintAtSizeAck( + RenderWidgetHost* widget, + const TransportDIB::Handle& dib_handle, + const gfx::Size& size) = 0; }; #endif // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_PAINTING_OBSERVER_H_ diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc index e0ffe1a..28be917 100644 --- a/chrome/browser/renderer_host/render_widget_host_unittest.cc +++ b/chrome/browser/renderer_host/render_widget_host_unittest.cc @@ -9,6 +9,7 @@ #include "base/timer.h" #include "build/build_config.h" #include "chrome/browser/renderer_host/backing_store.h" +#include "chrome/browser/renderer_host/render_widget_host_painting_observer.h" #include "chrome/browser/renderer_host/test/test_render_view_host.h" #include "chrome/common/render_messages.h" #include "gfx/canvas.h" @@ -19,6 +20,10 @@ using base::TimeDelta; using WebKit::WebInputEvent; using WebKit::WebMouseWheelEvent; +namespace gfx { +class Size; +} + // RenderWidgetHostProcess ----------------------------------------------------- class RenderWidgetHostProcess : public MockRenderProcessHost { @@ -191,6 +196,32 @@ class MockRenderWidgetHost : public RenderWidgetHost { bool unresponsive_timer_fired_; }; +// MockPaintingObserver -------------------------------------------------------- + +class MockPaintingObserver : public RenderWidgetHostPaintingObserver { + public: + void WidgetWillDestroyBackingStore(RenderWidgetHost* widget, + BackingStore* backing_store) {} + void WidgetDidUpdateBackingStore(RenderWidgetHost* widget) {} + void WidgetDidReceivePaintAtSizeAck(RenderWidgetHost* host, + const TransportDIB::Handle& dib_handle, + const gfx::Size& size) { + host_ = reinterpret_cast<MockRenderWidgetHost*>(host); + dib_handle_ = dib_handle; + size_ = size; + } + + MockRenderWidgetHost* host() const { return host_; } + TransportDIB::Handle dib_handle() const { return dib_handle_; } + gfx::Size size() const { return size_; } + + private: + MockRenderWidgetHost* host_; + TransportDIB::Handle dib_handle_; + gfx::Size size_; +}; + + // RenderWidgetHostTest -------------------------------------------------------- class RenderWidgetHostTest : public testing::Test { @@ -504,6 +535,24 @@ TEST_F(RenderWidgetHostTest, HiddenPaint) { EXPECT_TRUE(needs_repaint.a); } +TEST_F(RenderWidgetHostTest, PaintAtSize) { + host_->PaintAtSize(TransportDIB::GetFakeHandleForTest(), gfx::Size(20, 30)); + EXPECT_TRUE( + process_->sink().GetUniqueMessageMatching(ViewMsg_PaintAtSize::ID)); + + MockPaintingObserver observer; + host_->set_painting_observer(&observer); + + // Need to generate a fake handle value on all platforms. + TransportDIB::Handle handle = TransportDIB::GetFakeHandleForTest(); + host_->OnMsgPaintAtSizeAck(handle, gfx::Size(20, 30)); + EXPECT_TRUE(host_ == observer.host()); + EXPECT_TRUE(handle == observer.dib_handle()); + EXPECT_EQ(20, observer.size().width()); + EXPECT_EQ(30, observer.size().height()); + host_->set_painting_observer(NULL); +} + TEST_F(RenderWidgetHostTest, HandleKeyEventsWeSent) { // Simulate a keyboard event. SimulateKeyboardEvent(WebInputEvent::RawKeyDown); @@ -649,4 +698,3 @@ TEST_F(RenderWidgetHostTest, StopAndStartHangMonitorTimeout) { MessageLoop::current()->Run(); EXPECT_TRUE(host_->unresponsive_timer_fired()); } - |