summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-23 23:19:14 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-04-23 23:19:14 +0000
commit699ab0da64a44444bc99108592004d1354f5f89f (patch)
tree05dd618d341567e26dc303b56baac155e5fe2d1a /chrome
parentb547fd44ca39e90e6416da8a5ffc040fa9d2446c (diff)
downloadchromium_src-699ab0da64a44444bc99108592004d1354f5f89f.zip
chromium_src-699ab0da64a44444bc99108592004d1354f5f89f.tar.gz
chromium_src-699ab0da64a44444bc99108592004d1354f5f89f.tar.bz2
Add transparency support to RenderWidgetHostView.
This is used to make the background behind toolstrips 'shine through' them. It isn't possible to make them really transparent due to cleartype (cleartype must know the pixels behind the text to work), so instead we paint the background we want behind the transparent webview. Review URL: http://codereview.chromium.org/88076 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14378 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser_resources.grd2
-rwxr-xr-xchrome/browser/extensions/extension_view.cc8
-rw-r--r--chrome/browser/renderer_host/render_widget_host_unittest.cc53
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view.h18
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc43
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h6
-rwxr-xr-xchrome/browser/resources/extensions_toolstrip.css17
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc71
-rw-r--r--chrome/browser/views/bookmark_bar_view.h8
-rw-r--r--chrome/browser/views/hwnd_html_view.cc13
-rw-r--r--chrome/browser/views/hwnd_html_view.h8
-rw-r--r--chrome/common/render_messages_internal.h5
-rw-r--r--chrome/common/temp_scaffolding_stubs.h1
-rw-r--r--chrome/renderer/render_view.cc8
-rw-r--r--chrome/renderer/render_view.h6
-rw-r--r--chrome/renderer/render_widget.cc26
-rw-r--r--chrome/renderer/render_widget.h9
17 files changed, 269 insertions, 33 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);
};