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

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

Issue 2364163002: Views - draw omnibox popup shadows (Closed)
Patch Set: shorten comment Created 4 years, 3 months 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
« no previous file with comments | « chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4081c797931e5b7cd46e6de01e46e00e3d736746..26297c76167f4abe6b5dd32450ed7cc4fe1a21c2 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/lazy_instance.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "chrome/browser/search/search.h"
@@ -14,22 +15,66 @@
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/omnibox/omnibox_result_view.h"
#include "chrome/browser/ui/views/theme_copying_widget.h"
-#include "chrome/grit/theme_resources.h"
#include "components/omnibox/browser/omnibox_view.h"
-#include "ui/base/material_design/material_design_controller.h"
-#include "ui/base/resource/resource_bundle.h"
+#include "third_party/skia/include/core/SkDrawLooper.h"
#include "ui/base/theme_provider.h"
#include "ui/compositor/clip_recorder.h"
#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/path.h"
+#include "ui/gfx/shadow_value.h"
+#include "ui/gfx/skia_util.h"
#include "ui/views/controls/image_view.h"
-#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/view_targeter.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/non_client_view.h"
+namespace {
+
+// This creates a shadow image that is 1dp wide, suitable for tiling along the
+// top or bottom edge of the omnibox popup.
+class ShadowImageSource : public gfx::CanvasImageSource {
+ public:
+ ShadowImageSource(const std::vector<gfx::ShadowValue>& shadows, bool bottom)
+ : gfx::CanvasImageSource(gfx::Size(1, GetHeightForShadows(shadows)),
+ false),
+ shadows_(shadows),
+ bottom_(bottom) {}
+ ~ShadowImageSource() override {}
+
+ void Draw(gfx::Canvas* canvas) override {
+ SkPaint paint;
+ paint.setLooper(gfx::CreateShadowDrawLooperCorrectBlur(shadows_));
+ canvas->DrawRect(gfx::RectF(0, bottom_ ? -1 : size().height(), 1, 1),
+ paint);
+ }
+
+ private:
+ static int GetHeightForShadows(const std::vector<gfx::ShadowValue>& shadows) {
+ int height = 0;
+ for (const auto& shadow : shadows) {
+ height =
+ std::max(height, shadow.y() + gfx::ToCeiledInt(shadow.blur() / 2));
+ }
+ return height;
+ }
+
+ const std::vector<gfx::ShadowValue> shadows_;
+ bool bottom_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShadowImageSource);
+};
+
+// Cache the shadow images 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;
+
+} // namespace
+
class OmniboxPopupContentsView::AutocompletePopupWidget
: public ThemeCopyingWidget,
public base::SupportsWeakPtr<AutocompletePopupWidget> {
@@ -73,12 +118,30 @@ OmniboxPopupContentsView::OmniboxPopupContentsView(
// The contents is owned by the LocationBarView.
set_owned_by_client();
- ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
- if (ui::MaterialDesignController::IsModeMaterial()) {
- top_shadow_ = rb->GetImageSkiaNamed(IDR_OMNIBOX_DROPDOWN_SHADOW_TOP);
- bottom_shadow_ = rb->GetImageSkiaNamed(IDR_OMNIBOX_DROPDOWN_SHADOW_BOTTOM);
- } else {
- bottom_shadow_ = rb->GetImageSkiaNamed(IDR_BUBBLE_B);
+ if (g_top_shadow.Get().isNull()) {
+ std::vector<gfx::ShadowValue> shadows;
+ // Blur by 1dp. See comment below about blur accounting.
+ shadows.emplace_back(gfx::Vector2d(), 2, SK_ColorBLACK);
+
+ auto source = new ShadowImageSource(shadows, false);
+ g_top_shadow.Get() = gfx::ImageSkia(source, source->size());
+ }
+ if (g_bottom_shadow.Get().isNull()) {
+ const int kSmallShadowBlur = 3;
+ const int kLargeShadowBlur = 8;
+ const int kLargeShadowYOffset = 3;
+
+ std::vector<gfx::ShadowValue> 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);
+
+ auto source = new ShadowImageSource(shadows, true);
+ g_bottom_shadow.Get() = gfx::ImageSkia(source, source->size());
}
SetEventTargeter(
@@ -121,9 +184,8 @@ gfx::Rect OmniboxPopupContentsView::GetPopupBounds() const {
void OmniboxPopupContentsView::LayoutChildren() {
gfx::Rect contents_rect = GetContentsBounds();
contents_rect.Inset(GetLayoutInsets(OMNIBOX_DROPDOWN));
- contents_rect.Inset(start_margin_,
- views::NonClientFrameView::kClientEdgeThickness,
- end_margin_, 0);
+ contents_rect.Inset(start_margin_, g_top_shadow.Get().height(), end_margin_,
+ 0);
int top = contents_rect.y();
for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) {
@@ -197,24 +259,11 @@ void OmniboxPopupContentsView::UpdatePopupAppearance() {
for (size_t i = result_size; i < AutocompleteResult::kMaxMatches; ++i)
child_at(i)->SetVisible(false);
- // In non-material mode, we want the popup to appear as if it's overlaying
- // the top of the page content, i.e., is flush against the client edge at the
- // bottom of the toolbar. However, if the bookmarks bar is attached, we want
- // to draw over it (so as not to push the results below it), but that means
- // the toolbar won't be drawing a client edge separating itself from the
- // popup. So we unconditionally overlap the toolbar by the thickness of the
- // client edge and draw our own edge (see OnPaint()), which fixes the
- // attached bookmark bar case without breaking the other case.
- int top_edge_overlap = views::NonClientFrameView::kClientEdgeThickness;
- if (ui::MaterialDesignController::IsModeMaterial()) {
- // In material mode, we cover the bookmark bar similarly, but instead of
- // appearing below the client edge, we want the popup to appear to overlay
- // the bottom of the toolbar. So instead of drawing a client edge atop the
- // popup, we shift the popup to completely cover the client edge, and then
- // draw an additional semitransparent shadow above that. So the total
- // overlap necessary is the client edge thickness plus the shadow height.
- top_edge_overlap += top_shadow_->height();
- }
+ // 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();
gfx::Point top_left_screen_coord;
int width;
@@ -421,10 +470,8 @@ int OmniboxPopupContentsView::CalculatePopupHeight() {
// Add enough space on the top and bottom so it looks like there is the same
// amount of space between the text and the popup border as there is in the
// interior between each row of text.
- return popup_height + views::NonClientFrameView::kClientEdgeThickness +
- GetLayoutInsets(OMNIBOX_DROPDOWN).height() +
- bottom_shadow_->height() -
- GetLayoutConstant(OMNIBOX_DROPDOWN_BORDER_INTERIOR);
+ return popup_height + GetLayoutInsets(OMNIBOX_DROPDOWN).height() +
+ g_top_shadow.Get().height() + g_bottom_shadow.Get().height();
}
OmniboxResultView* OmniboxPopupContentsView::CreateResultView(
@@ -442,26 +489,17 @@ const char* OmniboxPopupContentsView::GetClassName() const {
}
void OmniboxPopupContentsView::OnPaint(gfx::Canvas* canvas) {
- // Top border.
- if (ui::MaterialDesignController::IsModeMaterial()) {
- canvas->TileImageInt(*top_shadow_, 0, 0, width(), top_shadow_->height());
- } else {
- canvas->FillRect(gfx::Rect(0, 0, width(),
- views::NonClientFrameView::kClientEdgeThickness),
- location_bar_view_->GetThemeProvider()->GetColor(
- ThemeProperties::COLOR_TOOLBAR_BOTTOM_SEPARATOR));
- }
-
- // Bottom border.
- canvas->TileImageInt(*bottom_shadow_, 0, height() - bottom_shadow_->height(),
- width(), bottom_shadow_->height());
+ 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();
- const int interior = GetLayoutConstant(OMNIBOX_DROPDOWN_BORDER_INTERIOR);
- contents_bounds.Inset(0, views::NonClientFrameView::kClientEdgeThickness, 0,
- bottom_shadow_->height() - interior);
+ contents_bounds.Inset(0, g_top_shadow.Get().height(), 0,
+ g_bottom_shadow.Get().height());
ui::ClipRecorder clip_recorder(context);
clip_recorder.ClipRect(contents_bounds);
« no previous file with comments | « 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