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

Unified Diff: chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc

Issue 2543473005: Draw omnibox shadow with a ninebox layer.
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index 04bb74bcb783ba4cd6281b2a1d5d38b63aed88aa..57e080010e84f0130efe12cfae389386eb034609 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -22,6 +22,7 @@
#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
+#include "ui/gfx/image/canvas_image_source.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/path.h"
@@ -33,10 +34,38 @@
namespace {
-// Cache the shadow images so that potentially expensive shadow drawing isn't
+// This source takes two images and draws one above the other.
+class StackedImagesImageSource : public gfx::CanvasImageSource {
+ public:
+ StackedImagesImageSource(const gfx::ImageSkia& top,
+ const gfx::ImageSkia& bottom)
+ : CanvasImageSource(
+ gfx::Size(top.width(), top.height() + bottom.height()),
+ false),
+ top_(top),
+ bottom_(bottom) {
+ DCHECK_EQ(top.width(), bottom.width());
+ }
+ ~StackedImagesImageSource() override {}
+
+ // CanvasImageSource overrides:
+ void Draw(gfx::Canvas* canvas) override {
+ canvas->DrawImageInt(top_, 0, 0);
+ canvas->DrawImageInt(bottom_, 0, top_.height());
+ }
+
+ private:
+ const gfx::ImageSkia top_;
+ const gfx::ImageSkia bottom_;
+
+ DISALLOW_COPY_AND_ASSIGN(StackedImagesImageSource);
+};
+
+// Cache the shadow image so that potentially expensive shadow drawing isn't
// repeated.
-base::LazyInstance<gfx::ImageSkia> g_top_shadow = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<gfx::ImageSkia> g_bottom_shadow = LAZY_INSTANCE_INITIALIZER;
+static int g_top_shadow_height = 0;
+static int g_bottom_shadow_height = 0;
+base::LazyInstance<gfx::ImageSkia> g_shadow_ninebox = LAZY_INSTANCE_INITIALIZER;
} // namespace
@@ -83,30 +112,42 @@ OmniboxPopupContentsView::OmniboxPopupContentsView(
// The contents is owned by the LocationBarView.
set_owned_by_client();
- if (g_top_shadow.Get().isNull()) {
- std::vector<gfx::ShadowValue> shadows;
+ if (g_shadow_ninebox.Get().isNull()) {
+ std::vector<gfx::ShadowValue> top_shadows;
// Blur by 1dp. See comment below about blur accounting.
- shadows.emplace_back(gfx::Vector2d(), 2, SK_ColorBLACK);
- g_top_shadow.Get() =
- gfx::ImageSkiaOperations::CreateHorizontalShadow(shadows, false);
- }
- if (g_bottom_shadow.Get().isNull()) {
+ top_shadows.emplace_back(gfx::Vector2d(), 2, SK_ColorBLACK);
+ gfx::ImageSkia top_shadow_image =
+ gfx::ImageSkiaOperations::CreateHorizontalShadow(top_shadows, false);
+ g_top_shadow_height = top_shadow_image.height();
+
+ // Values for the bottom shadow.
const int kSmallShadowBlur = 3;
const int kLargeShadowBlur = 8;
const int kLargeShadowYOffset = 3;
- std::vector<gfx::ShadowValue> shadows;
+ std::vector<gfx::ShadowValue> bottom_shadows;
// gfx::ShadowValue counts blur pixels both inside and outside the shape,
// whereas these blur values only describe the outside portion, hence they
// must be doubled.
- shadows.emplace_back(gfx::Vector2d(), 2 * kSmallShadowBlur,
- SK_ColorBLACK);
- shadows.emplace_back(gfx::Vector2d(0, kLargeShadowYOffset),
- 2 * kLargeShadowBlur, SK_ColorBLACK);
-
- g_bottom_shadow.Get() =
- gfx::ImageSkiaOperations::CreateHorizontalShadow(shadows, true);
+ bottom_shadows.emplace_back(gfx::Vector2d(), 2 * kSmallShadowBlur,
+ SK_ColorBLACK);
+ bottom_shadows.emplace_back(gfx::Vector2d(0, kLargeShadowYOffset),
+ 2 * kLargeShadowBlur, SK_ColorBLACK);
+
+ gfx::ImageSkia bottom_shadow_image =
+ gfx::ImageSkiaOperations::CreateHorizontalShadow(bottom_shadows, true);
+ g_bottom_shadow_height = bottom_shadow_image.height();
+ auto source =
+ new StackedImagesImageSource(top_shadow_image, bottom_shadow_image);
+ g_shadow_ninebox.Get() = gfx::ImageSkia(source, source->size());
}
+ shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH));
+ shadow_layer_->SetFillsBoundsOpaquely(false);
+ shadow_layer_->UpdateNinePatchLayerImage(g_shadow_ninebox.Get());
+ shadow_layer_->UpdateNinePatchLayerAperture(
+ gfx::Rect(0, g_top_shadow_height, 1, 0));
+ shadow_layer_->UpdateNinePatchLayerBorder(gfx::Rect(
+ 0, g_top_shadow_height, 0, g_top_shadow_height + g_bottom_shadow_height));
SetEventTargeter(
std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
@@ -148,8 +189,7 @@ gfx::Rect OmniboxPopupContentsView::GetPopupBounds() const {
void OmniboxPopupContentsView::LayoutChildren() {
gfx::Rect contents_rect = GetContentsBounds();
contents_rect.Inset(GetLayoutInsets(OMNIBOX_DROPDOWN));
- contents_rect.Inset(start_margin_, g_top_shadow.Get().height(), end_margin_,
- 0);
+ contents_rect.Inset(start_margin_, g_top_shadow_height, end_margin_, 0);
int top = contents_rect.y();
for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) {
@@ -226,8 +266,8 @@ void OmniboxPopupContentsView::UpdatePopupAppearance() {
// We want the popup to appear to overlay the bottom of the toolbar. So we
// shift the popup to completely cover the client edge, and then draw an
// additional semitransparent shadow above that.
- int top_edge_overlap = views::NonClientFrameView::kClientEdgeThickness +
- g_top_shadow.Get().height();
+ int top_edge_overlap =
+ views::NonClientFrameView::kClientEdgeThickness + g_top_shadow_height;
gfx::Point top_left_screen_coord;
int width;
@@ -246,6 +286,13 @@ void OmniboxPopupContentsView::UpdatePopupAppearance() {
target_bounds_ = new_target_bounds;
if (!popup_) {
+ // Create a new layer even if one already exists to make sure it's correctly
+ // parented.
Evan Stade 2016/12/01 02:39:02 I'm not entirely sure why this is necessary --- it
sadrul 2016/12/06 20:05:22 Yeah ... this seems weird.
+ SetPaintToLayer(false);
+ SetPaintToLayer(true);
+ layer()->SetFillsBoundsOpaquely(false);
+ layer()->Add(shadow_layer_.get());
+
views::Widget* popup_parent = location_bar_view_->GetWidget();
// If the popup is currently closed, we need to create it.
@@ -357,6 +404,15 @@ views::View* OmniboxPopupContentsView::GetTooltipHandlerForPoint(
return nullptr;
}
+void OmniboxPopupContentsView::OnBoundsChanged(
+ const gfx::Rect& previous_bounds) {
+ gfx::Rect shadow_bounds = GetLocalBounds();
+ shadow_layer_->SetBounds(shadow_bounds);
+ shadow_bounds.Inset(
+ gfx::Insets(g_top_shadow_height, 0, g_bottom_shadow_height, 0));
+ shadow_layer_->UpdateNinePatchOcclusion(shadow_bounds);
sadrul 2016/12/06 20:05:22 ui::Shadow seems to update layer-border/aperture a
+}
+
bool OmniboxPopupContentsView::OnMousePressed(
const ui::MouseEvent& event) {
ignore_mouse_drag_ = false; // See comment on |ignore_mouse_drag_| in header.
@@ -435,7 +491,7 @@ int OmniboxPopupContentsView::CalculatePopupHeight() {
// amount of space between the text and the popup border as there is in the
// interior between each row of text.
return popup_height + GetLayoutInsets(OMNIBOX_DROPDOWN).height() +
- g_top_shadow.Get().height() + g_bottom_shadow.Get().height();
+ g_top_shadow_height + g_bottom_shadow_height;
}
OmniboxResultView* OmniboxPopupContentsView::CreateResultView(
@@ -451,18 +507,10 @@ const char* OmniboxPopupContentsView::GetClassName() const {
return "OmniboxPopupContentsView";
}
-void OmniboxPopupContentsView::OnPaint(gfx::Canvas* canvas) {
- canvas->TileImageInt(g_top_shadow.Get(), 0, 0, width(),
- g_top_shadow.Get().height());
- canvas->TileImageInt(g_bottom_shadow.Get(), 0,
- height() - g_bottom_shadow.Get().height(), width(),
- g_bottom_shadow.Get().height());
-}
-
void OmniboxPopupContentsView::PaintChildren(const ui::PaintContext& context) {
gfx::Rect contents_bounds = GetContentsBounds();
- contents_bounds.Inset(0, g_top_shadow.Get().height(), 0,
- g_bottom_shadow.Get().height());
+ contents_bounds.Inset(
+ gfx::Insets(g_top_shadow_height, 0, g_bottom_shadow_height, 0));
ui::ClipRecorder clip_recorder(context);
clip_recorder.ClipRect(contents_bounds);
« cc/layers/nine_patch_layer.h ('K') | « chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698