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

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

Issue 2543473005: Draw omnibox shadow with a ninebox layer.
Patch Set: (not for commit --- added benchmarking code) 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
« no previous file with comments | « chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h ('k') | ui/compositor/compositor.h » ('j') | 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 d6d30558582fb3810627bc3970545193c5bbc057..c393ecf107489bcc0d0ae17a9c64d640f7a165cf 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"
@@ -31,12 +32,137 @@
#include "ui/views/widget/widget.h"
#include "ui/views/window/non_client_view.h"
+#include "base/json/json_string_value_serializer.h"
+#include "cc/debug/micro_benchmark_controller.h"
+#include "cc/raster/one_copy_raster_buffer_provider.h"
+#include "cc/trees/layer_tree_host.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/events/base_event_utils.h"
+
namespace {
-// Cache the shadow images so that potentially expensive shadow drawing isn't
+namespace test {
+
+class Experiment : public ui::CompositorAnimationObserver {
+ public:
+ explicit Experiment(views::View* tabstrip) : tabstrip_(tabstrip) {
+ CHECK(tabstrip_->GetWidget());
+ compositor_ = tabstrip_->GetWidget()->GetCompositor();
+ compositor_->AddAnimationObserver(this);
+ // views::View::ConvertPointToWidget(tabstrip_, &start_);
+ // start_.set_y(start_.y() + tabstrip_->height() / 2);
+
+ CHECK_GT(compositor_->layer_tree_host()->ScheduleMicroBenchmark(
+ "rasterize_and_record_benchmark",
+ base::MakeUnique<base::DictionaryValue>(),
+ base::Bind(&Experiment::BenchmarkDone, base::Unretained(this))), 0);
+ // cc::RasterStats::SetInstance(&stats_);
+ }
+
+ private:
+ ~Experiment() override {
+ if (compositor_)
+ compositor_->RemoveAnimationObserver(this);
+ }
+
+ void BenchmarkDone(std::unique_ptr<base::Value> value) {
+ std::string str;
+ JSONStringValueSerializer ser(&str);
+ ser.Serialize(*value);
+ LOG(ERROR) << str;
+ }
+
+ // ui::CompositorAnimationObserver:
+ void OnAnimationStep(base::TimeTicks timestamp) override {
+#if 0
+ gfx::Point location = start_;
+ location.set_x(location.x() + x_);
+
+ if (inc_) {
+ ++x_;
+ if (x_ >= tabstrip_->max_x()) {
+ --x_;
+ inc_ = false;
+ ++round_trips_;
+ }
+ } else {
+ --x_;
+ if (x_ < 0) {
+ ++x_;
+ inc_ = true;
+ ++round_trips_;
+ }
+ }
+
+ CHECK_GT(compositor_->layer_tree_host()->ScheduleMicroBenchmark(
+ "rasterize_and_record_benchmark",
+ base::MakeUnique<base::DictionaryValue>(),
+ base::Bind(&Experiment::BenchmarkDone, base::Unretained(this))), 0);
+ ui::MouseEvent move(ui::ET_MOUSE_MOVED, location, location,
+ ui::EventTimeForNow(),
+ ui::EF_NONE, ui::EF_NONE);
+ tabstrip_->GetWidget()->GetNativeWindow()->delegate()->OnMouseEvent(&move);
+ if (round_trips_ >= 2) {
+ LOG(ERROR) << "DONE ====================================================";
+ LOG(ERROR) << "Total: " << stats_.bytes();
+ compositor_->RemoveAnimationObserver(this);
+ compositor_ = nullptr;
+ cc::RasterStats::SetInstance(nullptr);
+ }
+#endif
+ }
+
+ void OnCompositingShuttingDown(ui::Compositor* compositor) override {
+ CHECK_EQ(compositor_, compositor);
+ compositor_ = nullptr;
+ }
+
+ views::View* tabstrip_;
+ ui::Compositor* compositor_ = nullptr;
+ // gfx::Point start_;
+ // int x_ = 0;
+ // bool inc_ = true;
+ // int round_trips_ = 0;
+ // cc::RasterStats stats_;
+
+ DISALLOW_COPY_AND_ASSIGN(Experiment);
+};
+
+} // test
+
+// 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;
const int kPopupVerticalPadding = 4;
@@ -85,35 +211,57 @@ 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)));
}
+void OmniboxPopupContentsView::ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) {
+ if (experiment_started_)
+ return;
+ if (!GetWidget())
+ return;
+ new test::Experiment(this);
+ experiment_started_ = true;
+}
+
void OmniboxPopupContentsView::Init() {
// This can't be done in the constructor as at that point we aren't
// necessarily our final class yet, and we may have subclasses
@@ -150,7 +298,7 @@ gfx::Rect OmniboxPopupContentsView::GetPopupBounds() const {
void OmniboxPopupContentsView::LayoutChildren() {
gfx::Rect contents_rect = GetContentsBounds();
contents_rect.Inset(gfx::Insets(kPopupVerticalPadding, 0));
- contents_rect.Inset(start_margin_, g_top_shadow.Get().height(), end_margin_,
+ contents_rect.Inset(start_margin_, 0, end_margin_,
0);
int top = contents_rect.y();
@@ -228,8 +376,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;
@@ -248,6 +396,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.
+ 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.
@@ -359,6 +514,15 @@ views::View* OmniboxPopupContentsView::GetTooltipHandlerForPoint(
return nullptr;
}
+void OmniboxPopupContentsView::OnBoundsChanged(
+ const gfx::Rect& previous_bounds) {
+ gfx::Rect shadow_bounds = GetLocalBounds();
+ shadow_layer_->UpdateNinePatchOcclusion(shadow_bounds);
+ shadow_bounds.Inset(
+ gfx::Insets(-g_top_shadow_height, 0, -g_bottom_shadow_height, 0));
+ shadow_layer_->SetBounds(shadow_bounds);
+}
+
bool OmniboxPopupContentsView::OnMousePressed(
const ui::MouseEvent& event) {
ignore_mouse_drag_ = false; // See comment on |ignore_mouse_drag_| in header.
@@ -436,8 +600,7 @@ 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 + kPopupVerticalPadding * 2 +
- g_top_shadow.Get().height() + g_bottom_shadow.Get().height();
+ return popup_height + kPopupVerticalPadding * 2;
}
OmniboxResultView* OmniboxPopupContentsView::CreateResultView(
@@ -453,18 +616,8 @@ 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());
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') | ui/compositor/compositor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698