diff options
21 files changed, 293 insertions, 34 deletions
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 60f9cb5..8ca4fd0 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- This comment is only here because changes to resources are not picked up +without changes to the corresponding grd file. --> <grit latest_public_release="0" current_release="1"> <outputs> <output filename="grit/browser_resources.h" type="rc_header"> diff --git a/chrome/browser/extensions/extension_view.cc b/chrome/browser/extensions/extension_view.cc index 05d310e..b55c3aa 100755 --- a/chrome/browser/extensions/extension_view.cc +++ b/chrome/browser/extensions/extension_view.cc @@ -35,17 +35,13 @@ ExtensionView::ExtensionView(Extension* extension, : HWNDHtmlView(url, this, false, instance), extension_(extension), browser_(browser) { - // Set the width initially to 0, so that the WebCore::Document can - // correctly compute the minPrefWidth which is returned in - // DidContentsChangeSize() - set_preferred_size(gfx::Size(0, 100)); SetVisible(false); } void ExtensionView::DidStopLoading(RenderViewHost* render_view_host, int32 page_id) { - SetVisible(true); render_view_host->WasResized(); + SetVisible(true); } void ExtensionView::DidContentsPreferredWidthChange(const int pref_width) { @@ -53,7 +49,7 @@ void ExtensionView::DidContentsPreferredWidthChange(const int pref_width) { // SchedulePaint first because new_width may be smaller and we want // the Parent to paint the vacated space. SchedulePaint(); - set_preferred_size(gfx::Size(pref_width, 100)); + set_preferred_size(gfx::Size(pref_width, height())); SizeToPreferredSize(); // TODO(rafaelw): This assumes that the extension view is a child of an diff --git a/chrome/browser/renderer_host/render_widget_host_unittest.cc b/chrome/browser/renderer_host/render_widget_host_unittest.cc index 0711e3d..cea36c9 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 "build/build_config.h" #include "chrome/browser/renderer_host/backing_store.h" #include "chrome/browser/renderer_host/test_render_view_host.h" +#include "chrome/common/gfx/chrome_canvas.h" #include "chrome/common/render_messages.h" #include "testing/gtest/include/gtest/gtest.h" @@ -244,6 +245,58 @@ TEST_F(RenderWidgetHostTest, Resize) { EXPECT_TRUE(process_->sink().GetUniqueMessageMatching(ViewMsg_Resize::ID)); } +// Tests setting custom background +TEST_F(RenderWidgetHostTest, Background) { +#if defined(OS_WIN) || defined(OS_LINUX) + scoped_ptr<RenderWidgetHostView> view( + RenderWidgetHostView::CreateViewForWidget(host_.get())); + host_->set_view(view.get()); + + // Create a checkerboard background to test with. + ChromeCanvas canvas(4, 4, true); + canvas.FillRectInt(SK_ColorBLACK, 0, 0, 2, 2); + canvas.FillRectInt(SK_ColorWHITE, 2, 0, 2, 2); + canvas.FillRectInt(SK_ColorWHITE, 0, 2, 2, 2); + canvas.FillRectInt(SK_ColorBLACK, 2, 2, 2, 2); + const SkBitmap& background = canvas.getDevice()->accessBitmap(false); + + // Set the background and make sure we get back a copy. + view->SetBackground(background); + EXPECT_EQ(4, view->background().width()); + EXPECT_EQ(4, view->background().height()); + EXPECT_EQ(background.getSize(), view->background().getSize()); + EXPECT_TRUE(0 == memcmp(background.getPixels(), + view->background().getPixels(), + background.getSize())); + +#if defined(OS_WIN) + // A message should have been dispatched telling the renderer about the new + // background. + const IPC::Message* set_background = + process_->sink().GetUniqueMessageMatching(ViewMsg_SetBackground::ID); + ASSERT_TRUE(set_background); + SkBitmap sent_background; + ViewMsg_SetBackground::Read(set_background, &sent_background); + EXPECT_EQ(background.getSize(), sent_background.getSize()); + EXPECT_TRUE(0 == memcmp(background.getPixels(), + sent_background.getPixels(), + background.getSize())); +#else + // TODO(port): When custom backgrounds are implemented for other ports, this + // test should work (assuming the background must still be copied into the + // renderer -- if not, then maybe the test doesn't apply?). +#endif + +#else + // TODO(port): Mac does not have ChromeCanvas. Maybe we can just change this + // test to use SkCanvas directly? +#endif + + // TODO(aa): It would be nice to factor out the painting logic so that we + // could test that, but it appears that would mean painting everything twice + // since windows HDC structures are opaque. +} + // Tests getting the backing store with the renderer not setting repaint ack // flags. TEST_F(RenderWidgetHostTest, GetBackingStore_NoRepaintAck) { diff --git a/chrome/browser/renderer_host/render_widget_host_view.h b/chrome/browser/renderer_host/render_widget_host_view.h index db894f8..beec90e 100644 --- a/chrome/browser/renderer_host/render_widget_host_view.h +++ b/chrome/browser/renderer_host/render_widget_host_view.h @@ -8,6 +8,7 @@ #include "base/gfx/native_widget_types.h" #include "base/shared_memory.h" #include "webkit/glue/webplugin.h" +#include "skia/include/SkBitmap.h" namespace gfx { class Rect; @@ -31,6 +32,8 @@ class WebCursor; // changes. class RenderWidgetHostView { public: + virtual ~RenderWidgetHostView(){}; + // Platform-specific creator. Use this to construct new RenderWidgetHostViews // rather than using RenderWidgetHostViewWin & friends. // @@ -138,14 +141,25 @@ class RenderWidgetHostView { } bool activatable() const { return activatable_; } + // Subclasses should override this method to do whatever is appropriate to set + // the custom background for their platform. + virtual void SetBackground(const SkBitmap& background) { + background_ = background; + } + const SkBitmap& background() const { return background_; } + protected: // Interface class only, do not construct. - RenderWidgetHostView() : activatable_(true) {} - + RenderWidgetHostView() : activatable_(true) {} + // Whether the window can be activated. Autocomplete popup windows for example // cannot be activated. Default is true. bool activatable_; + // A custom background to paint behind the web content. This will be tiled + // horizontally. Can be null, in which case we fall back to painting white. + SkBitmap background_; + private: DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostView); }; 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 58fbc83..d13fac4 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc @@ -31,6 +31,7 @@ // Included for views::kReflectedMessage - TODO(beng): move this to win_util.h! #include "chrome/views/widget/widget_win.h" #include "grit/webkit_resources.h" +#include "skia/ext/skia_utils_win.h" #include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h" #include "third_party/WebKit/WebKit/chromium/public/win/WebInputEventFactory.h" #include "webkit/glue/plugins/plugin_constants_win.h" @@ -641,6 +642,12 @@ BackingStore* RenderWidgetHostViewWin::AllocBackingStore( return new BackingStore(size); } +void RenderWidgetHostViewWin::SetBackground(const SkBitmap& background) { + RenderWidgetHostView::SetBackground(background); + Send(new ViewMsg_SetBackground(render_widget_host_->routing_id(), + background)); +} + /////////////////////////////////////////////////////////////////////////////// // RenderWidgetHostViewWin, private: @@ -686,10 +693,11 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) { about_to_validate_and_paint_ = false; CPaintDC paint_dc(m_hWnd); - HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); - if (backing_store) { - gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint); + gfx::Rect damaged_rect(paint_dc.m_ps.rcPaint); + if (damaged_rect.IsEmpty()) + return; + if (backing_store) { gfx::Rect bitmap_rect( 0, 0, backing_store->size().width(), backing_store->size().height()); @@ -707,14 +715,14 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) { SRCCOPY); } - // Fill the remaining portion of the damaged_rect with white + // Fill the remaining portion of the damaged_rect with the background if (damaged_rect.right() > bitmap_rect.right()) { RECT r; r.left = std::max(bitmap_rect.right(), damaged_rect.x()); r.right = damaged_rect.right(); r.top = damaged_rect.y(); r.bottom = std::min(bitmap_rect.bottom(), damaged_rect.bottom()); - paint_dc.FillRect(&r, white_brush); + DrawBackground(r, &paint_dc); } if (damaged_rect.bottom() > bitmap_rect.bottom()) { RECT r; @@ -722,7 +730,7 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) { r.right = damaged_rect.right(); r.top = std::max(bitmap_rect.bottom(), damaged_rect.y()); r.bottom = damaged_rect.bottom(); - paint_dc.FillRect(&r, white_brush); + DrawBackground(r, &paint_dc); } if (!whiteout_start_time_.is_null()) { TimeDelta whiteout_duration = TimeTicks::Now() - whiteout_start_time_; @@ -733,12 +741,33 @@ void RenderWidgetHostViewWin::OnPaint(HDC dc) { whiteout_start_time_ = TimeTicks(); } } else { - paint_dc.FillRect(&paint_dc.m_ps.rcPaint, white_brush); + DrawBackground(paint_dc.m_ps.rcPaint, &paint_dc); if (whiteout_start_time_.is_null()) whiteout_start_time_ = TimeTicks::Now(); } } +void RenderWidgetHostViewWin::DrawBackground(const RECT& dirty_rect, + CPaintDC* dc) { + const RECT& dc_rect = dc->m_ps.rcPaint; + if (!background_.empty()) { + ChromeCanvas canvas(dirty_rect.right - dirty_rect.left, + dirty_rect.bottom - dirty_rect.top, + true); // opaque + + canvas.TranslateInt(-dirty_rect.left, -dirty_rect.top); + canvas.TileImageInt(background_, 0, 0, + dc_rect.right - dc_rect.left, + dc_rect.bottom - dc_rect.top); + + canvas.getTopPlatformDevice().drawToHDC(*dc, dirty_rect.left, + dirty_rect.top, NULL); + } else { + HBRUSH white_brush = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); + dc->FillRect(&dc_rect, white_brush); + } +} + void RenderWidgetHostViewWin::OnNCPaint(HRGN update_region) { // Do nothing. This suppresses the resize corner that Windows would // otherwise draw for us. 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 3501ca1..5b80f09 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_win.h +++ b/chrome/browser/renderer_host/render_widget_host_view_win.h @@ -130,6 +130,7 @@ class RenderWidgetHostViewWin : virtual void Destroy(); virtual void SetTooltipText(const std::wstring& tooltip_text); virtual BackingStore* AllocBackingStore(const gfx::Size& size); + virtual void SetBackground(const SkBitmap& background); protected: // Windows Message Handlers @@ -210,6 +211,11 @@ class RenderWidgetHostViewWin : // given paint rect. void DrawResizeCorner(const gfx::Rect& paint_rect, HDC dc); + // Draw our background over the given HDC in the given |rect|. The background + // will be tiled such that it lines up with existing tiles starting from the + // origin of |dc|. + void DrawBackground(const RECT& rect, CPaintDC* dc); + // Create an intermediate window between the given HWND and its parent. HWND ReparentWindow(HWND window); diff --git a/chrome/browser/resources/extensions_toolstrip.css b/chrome/browser/resources/extensions_toolstrip.css index 921f97f..b709856 100755 --- a/chrome/browser/resources/extensions_toolstrip.css +++ b/chrome/browser/resources/extensions_toolstrip.css @@ -1,16 +1,13 @@ body { + display:-webkit-box; + -webkit-box-align:center; + white-space:nowrap; overflow: hidden; margin: 0; - padding: 0; + padding:0 6px; font: menu; - text-shadow: #FFFFFF 1px 1px 0px; color: #062D75; -} - -#main { - background: -webkit-gradient(linear, left top, left bottom, from(rgb(222, 234, 248)), to(rgb(237, 244, 252))); - padding-top: 3px; - height: 21px; - overflow: hidden; - white-space: nowrap; + text-shadow: #FFFFFF 1px 1px 0px; + -webkit-user-select:none; + cursor:default; } diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc index b0be7dd..b5298db 100644 --- a/chrome/browser/views/bookmark_bar_view.cc +++ b/chrome/browser/views/bookmark_bar_view.cc @@ -17,6 +17,8 @@ #include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/renderer_host/render_widget_host_view.h" #include "chrome/browser/tab_contents/page_navigator.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/view_ids.h" @@ -297,20 +299,16 @@ class BookmarkFolderButton : public views::MenuButton { // A simple container with a border for an ExtensionView. class ExtensionToolstrip : public views::View { public: - static const int kPadding = 2; - ExtensionToolstrip(Extension* extension, const GURL& url, Browser* browser) : view_(browser->profile()->GetExtensionsService()->CreateView( extension, url, browser)) { AddChildView(view_); - set_border(views::Border::CreateEmptyBorder( - kPadding, kPadding, kPadding, kPadding)); } + ExtensionView* view() { return view_; } + virtual gfx::Size GetPreferredSize() { - gfx::Size size = view_->GetPreferredSize(); - size.Enlarge(kPadding*2, kPadding*2); - return size; + return view_->GetPreferredSize(); } virtual void DidChangeBounds(const gfx::Rect& previous, @@ -689,6 +687,13 @@ void BookmarkBarView::Paint(ChromeCanvas* canvas) { canvas->drawRoundRect(rect, SkDoubleToScalar(roundness), SkDoubleToScalar(roundness), border_paint); + + SkRect toolstrip_background_rect = { + rect.fLeft + 1 + kNewtabBarRoundness, + rect.fTop + 1, + rect.fLeft + 1 + kNewtabBarRoundness + 1, + rect.fBottom - 1}; + InitToolstripBackground(canvas, toolstrip_background_rect); } else { SkPaint paint; paint.setShader(skia::CreateGradientShader(0, @@ -699,6 +704,51 @@ void BookmarkBarView::Paint(ChromeCanvas* canvas) { canvas->FillRectInt(kTopBorderColor, 0, 0, width(), 1); canvas->FillRectInt(kBottomBorderColor, 0, height() - 1, width(), 1); + + SkRect toolstrip_background_rect = { + SkIntToScalar(0), + SkIntToScalar(1), + SkIntToScalar(1), + SkIntToScalar(height() - 2)}; + InitToolstripBackground(canvas, toolstrip_background_rect); + } +} + +void BookmarkBarView::InitToolstripBackground(ChromeCanvas* canvas, + const SkRect& subset) { + if (!toolstrip_background_.empty()) + return; + + const SkBitmap& bookmarkbar_background = + canvas->getDevice()->accessBitmap(false); + + // Extract the correct subset of the toolstrip background into a bitmap. We + // must use a temporary here because extractSubset() returns a bitmap that + // references pixels in the original one and we want to actually make a copy + // that will have a long lifetime. + SkBitmap temp; + temp.setConfig(bookmarkbar_background.config(), + static_cast<int>(subset.width()), + static_cast<int>(subset.height())); + + SkRect mapped_subset = subset; + bool result = canvas->getTotalMatrix().mapRect(&mapped_subset); + DCHECK(result); + + SkIRect isubset; + mapped_subset.round(&isubset); + result = bookmarkbar_background.extractSubset(&temp, isubset); + if (!result) + return; + + temp.copyTo(&toolstrip_background_, temp.config()); + DCHECK(toolstrip_background_.readyToDraw()); + + // Tell all current toolstrips about the new background + for (int i = GetBookmarkButtonCount(); + i < GetBookmarkButtonCount() + num_extension_toolstrips_; ++i) { + static_cast<ExtensionToolstrip*>(GetChildViewAt(i))->view()->SetBackground( + toolstrip_background_); } } @@ -898,11 +948,17 @@ int BookmarkBarView::GetToolbarOverlap() { void BookmarkBarView::AnimationProgressed(const Animation* animation) { if (browser_) browser_->ToolbarSizeChanged(true); + + // Clear the toolstrip background so that we recreate it next time around the + // paint loop. + toolstrip_background_.reset(); } void BookmarkBarView::AnimationEnded(const Animation* animation) { if (browser_) browser_->ToolbarSizeChanged(false); + + toolstrip_background_.reset(); SchedulePaint(); } @@ -1379,6 +1435,7 @@ bool BookmarkBarView::AddExtensionToolstrips(const ExtensionList* extensions) { (*extension)->GetResourceURL(*toolstrip), browser_); int index = GetBookmarkButtonCount() + num_extension_toolstrips_; + view->view()->SetBackground(toolstrip_background_); AddChildView(index, view); added_toolstrip = true; ++num_extension_toolstrips_; diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h index 0726449..3963326 100644 --- a/chrome/browser/views/bookmark_bar_view.h +++ b/chrome/browser/views/bookmark_bar_view.h @@ -15,6 +15,7 @@ #include "chrome/views/controls/menu/menu.h" #include "chrome/views/controls/menu/view_menu_delegate.h" #include "chrome/views/view.h" +#include "skia/include/corecg/SkRect.h" class Browser; class PageNavigator; @@ -375,6 +376,10 @@ class BookmarkBarView : public views::View, // button. Returns true if there were any new toolstrips added. bool AddExtensionToolstrips(const ExtensionList* extensions); + // Initializes the bitmap we use for the background of extension toolstrips by + // copying a subset of the current toolstrip background. + void InitToolstripBackground(ChromeCanvas* canvas, const SkRect& subset); + Profile* profile_; // Used for opening urls. @@ -430,6 +435,9 @@ class BookmarkBarView : public views::View, // How many extension toolstrips we have showing in the toolbar. int num_extension_toolstrips_; + // Background for extension toolstrips. + SkBitmap toolstrip_background_; + DISALLOW_COPY_AND_ASSIGN(BookmarkBarView); }; diff --git a/chrome/browser/views/hwnd_html_view.cc b/chrome/browser/views/hwnd_html_view.cc index 9eb8cc4..a0174d6 100644 --- a/chrome/browser/views/hwnd_html_view.cc +++ b/chrome/browser/views/hwnd_html_view.cc @@ -32,6 +32,15 @@ HWNDHtmlView::~HWNDHtmlView() { } } +void HWNDHtmlView::SetBackground(const SkBitmap& background) { + if (initialized_) { + DCHECK(render_view_host_); + render_view_host_->view()->SetBackground(background); + } else { + pending_background_ = background; + } +} + void HWNDHtmlView::InitHidden() { // TODO(mpcomplete): make it possible to create a RenderView without an HWND. views::WidgetWin* win = new views::WidgetWin; @@ -62,6 +71,10 @@ void HWNDHtmlView::Init(HWND parent_hwnd) { rvh->AllowDOMUIBindings(); CreatingRenderer(); rvh->CreateRenderView(); + if (!pending_background_.empty()) { + rvh->view()->SetBackground(pending_background_); + pending_background_.reset(); + } rvh->NavigateToURL(content_url_); initialized_ = true; } diff --git a/chrome/browser/views/hwnd_html_view.h b/chrome/browser/views/hwnd_html_view.h index 3176551..49e2c88 100644 --- a/chrome/browser/views/hwnd_html_view.h +++ b/chrome/browser/views/hwnd_html_view.h @@ -7,6 +7,7 @@ #include "googleurl/src/gurl.h" #include "chrome/views/controls/hwnd_view.h" +#include "skia/include/SkBitmap.h" class RenderViewHost; class RenderViewHostDelegate; @@ -27,6 +28,9 @@ class HWNDHtmlView : public views::HWNDView { // don't display UI. void InitHidden(); + // Set a custom background for the view. The background will be tiled. + void SetBackground(const SkBitmap& background); + protected: // View overrides. virtual void ViewHierarchyChanged(bool is_add, View *parent, View *child); @@ -60,6 +64,10 @@ class HWNDHtmlView : public views::HWNDView { // The delegate for our render_view_host. RenderViewHostDelegate* delegate_; + // The background the view should have once it is initialized. This is set + // when the view has a custom background, but hasn't been inititalized yet. + SkBitmap pending_background_; + DISALLOW_EVIL_CONSTRUCTORS(HWNDHtmlView); }; diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 2fdf5a9..e254c4f 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -571,6 +571,11 @@ IPC_BEGIN_MESSAGES(View) // Tells the renderer to clear the focused node (if any). IPC_MESSAGE_ROUTED0(ViewMsg_ClearFocusedNode) + + // Make the RenderView transparent and render it onto a custom background. The + // background will be tiled in both directions if it is not large enough. + IPC_MESSAGE_ROUTED1(ViewMsg_SetBackground, + SkBitmap /* background */) IPC_END_MESSAGES(View) diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h index cac23ea..93a3b7d 100644 --- a/chrome/common/temp_scaffolding_stubs.h +++ b/chrome/common/temp_scaffolding_stubs.h @@ -505,6 +505,7 @@ class HWNDHtmlView { } virtual ~HWNDHtmlView() {} + int height() { NOTIMPLEMENTED(); return 0; } RenderViewHost* render_view_host() { NOTIMPLEMENTED(); return NULL; } void InitHidden() { NOTIMPLEMENTED(); } void set_preferred_size(const gfx::Size& size) { NOTIMPLEMENTED(); } diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 1893e25..e3cbc9f 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -443,6 +443,7 @@ void RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted) IPC_MESSAGE_HANDLER(ViewMsg_ExtensionResponse, OnExtensionResponse) IPC_MESSAGE_HANDLER(ViewMsg_ClearFocusedNode, OnClearFocusedNode) + IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground) // Have the super handle all other messages. IPC_MESSAGE_UNHANDLED(RenderWidget::OnMessageReceived(message)) @@ -2954,6 +2955,13 @@ void RenderView::OnClearFocusedNode() { webview()->ClearFocusedNode(); } +void RenderView::OnSetBackground(const SkBitmap& background) { + if (webview()) + webview()->SetIsTransparent(!background.empty()); + + SetBackground(background); +} + void RenderView::SendExtensionRequest(const std::string& name, const std::string& args, int callback_id, diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index eb3aa55..505dca0 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -26,6 +26,7 @@ #include "chrome/renderer/external_host_bindings.h" #include "chrome/renderer/external_js_object.h" #include "chrome/renderer/render_widget.h" +#include "skia/include/SkBitmap.h" #include "testing/gtest/include/gtest/gtest_prod.h" #include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h" #include "webkit/glue/dom_serializer_delegate.h" @@ -52,7 +53,6 @@ class FilePath; class GURL; class RenderThread; class ResourceDispatcher; -class SkBitmap; class WebAccessibilityManager; class WebError; class WebFrame; @@ -582,6 +582,10 @@ class RenderView : public RenderWidget, // Sends the selection text to the browser. void OnRequestSelectionText(); + // Handle message to make the RenderView transparent and render it on top of + // a custom background. + void OnSetBackground(const SkBitmap& background); + // Prints the page listed in |params|. void PrintPage(const ViewMsg_PrintPage_Params& params, const gfx::Size& canvas_size, diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc index 4cd54c1..23f27da 100644 --- a/chrome/renderer/render_widget.cc +++ b/chrome/renderer/render_widget.cc @@ -14,6 +14,7 @@ #include "chrome/common/transport_dib.h" #include "chrome/renderer/render_process.h" #include "skia/ext/platform_canvas.h" +#include "skia/include/SkShader.h" #include "third_party/WebKit/WebKit/chromium/public/WebRect.h" #include "third_party/WebKit/WebKit/chromium/public/WebScreenInfo.h" #include "third_party/WebKit/WebKit/chromium/public/WebSize.h" @@ -308,6 +309,25 @@ void RenderWidget::ClearFocus() { void RenderWidget::PaintRect(const gfx::Rect& rect, skia::PlatformCanvas* canvas) { + + // If there is a custom background, tile it. + if (!background_.empty()) { + canvas->save(); + + SkIRect clipRect = { rect.x(), rect.y(), rect.right(), rect.bottom() }; + canvas->setClipRegion(SkRegion(clipRect)); + + SkPaint paint; + SkShader* shader = SkShader::CreateBitmapShader(background_, + SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode); + paint.setShader(shader)->unref(); + paint.setPorterDuffXfermode(SkPorterDuff::kSrcOver_Mode); + canvas->drawPaint(paint); + + canvas->restore(); + } + // Bring the canvas into the coordinate system of the paint rect canvas->translate(static_cast<SkScalar>(-rect.x()), static_cast<SkScalar>(-rect.y())); @@ -675,6 +695,12 @@ void RenderWidget::OnSetTextDirection(int direction) { } } +void RenderWidget::SetBackground(const SkBitmap& background) { + background_ = background; + // Generate a full repaint. + DidInvalidateRect(webwidget_, gfx::Rect(size_.width(), size_.height())); +} + bool RenderWidget::next_paint_is_resize_ack() const { return ViewHostMsg_PaintRect_Flags::is_resize_ack(next_paint_flags_); } diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h index 668b4fd..62777e8 100644 --- a/chrome/renderer/render_widget.h +++ b/chrome/renderer/render_widget.h @@ -16,6 +16,7 @@ #include "chrome/common/ipc_channel.h" #include "chrome/renderer/render_process.h" #include "skia/ext/platform_canvas.h" +#include "skia/include/SkBitmap.h" #include "webkit/glue/webwidget_delegate.h" #include "webkit/glue/webcursor.h" @@ -123,6 +124,11 @@ class RenderWidget : public IPC::Channel::Listener, // corresponding paint or scroll message is send to the widget host. virtual void DidPaint() {} + // Set the background of the render widget to a bitmap. The bitmap will be + // tiled in both directions if it isn't big enough to fill the area. This is + // mainly intended to be used in conjuction with WebView::SetIsTransparent(). + virtual void SetBackground(const SkBitmap& bitmap); + // RenderWidget IPC message handlers void OnClose(); void OnCreatingNewAck(gfx::NativeViewId parent); @@ -271,6 +277,9 @@ class RenderWidget : public IPC::Channel::Listener, // Holds all the needed plugin window moves for a scroll. std::vector<WebPluginGeometry> plugin_window_moves_; + // A custom background for the widget. + SkBitmap background_; + DISALLOW_COPY_AND_ASSIGN(RenderWidget); }; diff --git a/webkit/glue/webframe_impl.cc b/webkit/glue/webframe_impl.cc index 6c55b48..1d21d0a 100644 --- a/webkit/glue/webframe_impl.cc +++ b/webkit/glue/webframe_impl.cc @@ -1532,6 +1532,9 @@ void WebFrameImpl::CreateFrameView() { frame_->setView(view); + if (webview_impl_->GetIsTransparent()) + view->setTransparent(true); + // TODO(darin): The Mac code has a comment about this possibly being // unnecessary. See installInFrame in WebCoreFrameBridge.mm if (frame_->ownerRenderer()) diff --git a/webkit/glue/webview.h b/webkit/glue/webview.h index 600338f..2a9faec 100644 --- a/webkit/glue/webview.h +++ b/webkit/glue/webview.h @@ -226,6 +226,11 @@ class WebView : public WebWidget { // Returns development tools agent instance belonging to this view. virtual WebDevToolsAgent* GetWebDevToolsAgent() = 0; + // Makes the webview transparent. Useful if you want to have some custom + // background behind it. + virtual void SetIsTransparent(bool is_transparent) = 0; + virtual bool GetIsTransparent() const = 0; + private: DISALLOW_COPY_AND_ASSIGN(WebView); }; diff --git a/webkit/glue/webview_impl.cc b/webkit/glue/webview_impl.cc index 9906a27..0155b8b 100644 --- a/webkit/glue/webview_impl.cc +++ b/webkit/glue/webview_impl.cc @@ -366,7 +366,8 @@ WebViewImpl::WebViewImpl() drag_identity_(0), drop_effect_(DROP_EFFECT_DEFAULT), drop_accept_(false), - autocomplete_popup_showing_(false) { + autocomplete_popup_showing_(false), + is_transparent_(false) { // WebKit/win/WebView.cpp does the same thing, except they call the // KJS specific wrapper around this method. We need to have threading // initialized because CollatorICU requires it. @@ -1825,6 +1826,14 @@ WebDevToolsAgentImpl* WebViewImpl::GetWebDevToolsAgentImpl() { return devtools_agent_.get(); } +void WebViewImpl::SetIsTransparent(bool is_transparent) { + is_transparent_ = is_transparent; +} + +bool WebViewImpl::GetIsTransparent() const { + return is_transparent_; +} + void WebViewImpl::DidCommitLoad(bool* is_new_navigation) { if (is_new_navigation) *is_new_navigation = observed_new_navigation_; diff --git a/webkit/glue/webview_impl.h b/webkit/glue/webview_impl.h index 71a5a86..0b8db72 100644 --- a/webkit/glue/webview_impl.h +++ b/webkit/glue/webview_impl.h @@ -125,6 +125,9 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { virtual WebDevToolsAgent* GetWebDevToolsAgent(); WebDevToolsAgentImpl* GetWebDevToolsAgentImpl(); + virtual void SetIsTransparent(bool is_transparent); + virtual bool GetIsTransparent() const; + // WebViewImpl const WebKit::WebSize& size() const { return size_; } @@ -351,6 +354,9 @@ class WebViewImpl : public WebView, public base::RefCounted<WebViewImpl> { scoped_ptr<WebDevToolsAgentImpl> devtools_agent_; + // Whether the webview is rendering transparently. + bool is_transparent_; + // HACK: current_input_event is for ChromeClientImpl::show(), until we can fix // WebKit to pass enough information up into ChromeClient::show() so we can // decide if the window.open event was caused by a middle-mouse click |