| 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);
|
|
|