| Index: ui/views/view_unittest.cc
|
| diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
|
| index b1bcb6ac817d358e23d22348a9b91bb7d7d65fcf..3685673ecc9834ee048f2dd431856c0b06de79e7 100644
|
| --- a/ui/views/view_unittest.cc
|
| +++ b/ui/views/view_unittest.cc
|
| @@ -240,7 +240,7 @@ class TestView : public View {
|
| // Ignores GestureEvent by default.
|
| virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
|
|
|
| - virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
|
| + virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set) OVERRIDE;
|
| virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE;
|
| virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
|
|
|
| @@ -670,7 +670,7 @@ TEST_F(ViewTest, ScrollGestureEvent) {
|
| // Painting
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| -void TestView::Paint(gfx::Canvas* canvas) {
|
| +void TestView::Paint(gfx::Canvas* canvas, const CullSet& cull_set) {
|
| canvas->sk_canvas()->getClipBounds(&last_clip_);
|
| }
|
|
|
| @@ -3463,6 +3463,246 @@ TEST_F(ViewLayerTest, RecreateLayerMovesNonViewChildren) {
|
| EXPECT_EQ(v.layer()->children()[1], child.layer());
|
| }
|
|
|
| +class BoundsTreeTestView : public View {
|
| + public:
|
| + BoundsTreeTestView() {}
|
| +
|
| + virtual void PaintChildren(gfx::Canvas* canvas,
|
| + const CullSet& cull_set) OVERRIDE {
|
| + // Save out a copy of the cull_set before calling the base implementation.
|
| + last_cull_set_.clear();
|
| + if (cull_set.cull_set_) {
|
| + for (base::hash_set<intptr_t>::iterator it = cull_set.cull_set_->begin();
|
| + it != cull_set.cull_set_->end();
|
| + ++it) {
|
| + last_cull_set_.insert(reinterpret_cast<View*>(*it));
|
| + }
|
| + }
|
| + View::PaintChildren(canvas, cull_set);
|
| + }
|
| +
|
| + std::set<View*> last_cull_set_;
|
| +};
|
| +
|
| +TEST_F(ViewLayerTest, BoundsTreePaintUpdatesCullSet) {
|
| + BoundsTreeTestView* test_view = new BoundsTreeTestView;
|
| + widget()->SetContentsView(test_view);
|
| +
|
| + View* v1 = new View();
|
| + v1->SetBoundsRect(gfx::Rect(10, 15, 150, 151));
|
| + test_view->AddChildView(v1);
|
| +
|
| + View* v2 = new View();
|
| + v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
|
| + v1->AddChildView(v2);
|
| +
|
| + // Schedule a full-view paint to get everyone's rectangles updated.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| +
|
| + // Now we have test_view - v1 - v2. Damage to only test_view should only
|
| + // return root_view and test_view.
|
| + test_view->SchedulePaintInRect(gfx::Rect(0, 0, 1, 1));
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| + EXPECT_EQ(2U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
|
| +
|
| + // Damage to v1 only should only return root_view, test_view, and v1.
|
| + test_view->SchedulePaintInRect(gfx::Rect(11, 16, 1, 1));
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| + EXPECT_EQ(3U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
|
| +
|
| + // A Damage rect inside v2 should get all 3 views back in the |last_cull_set_|
|
| + // on call to TestView::Paint(), along with the widget root view.
|
| + test_view->SchedulePaintInRect(gfx::Rect(31, 49, 1, 1));
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| + EXPECT_EQ(4U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
|
| +}
|
| +
|
| +TEST_F(ViewLayerTest, BoundsTreeSetBoundsChangesCullSet) {
|
| + BoundsTreeTestView* test_view = new BoundsTreeTestView;
|
| + widget()->SetContentsView(test_view);
|
| +
|
| + View* v1 = new View;
|
| + v1->SetBoundsRect(gfx::Rect(5, 6, 100, 101));
|
| + test_view->AddChildView(v1);
|
| +
|
| + View* v2 = new View;
|
| + v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
|
| + v1->AddChildView(v2);
|
| +
|
| + // Schedule a full-view paint to get everyone's rectangles updated.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| +
|
| + // Move v1 to a new origin out of the way of our next query.
|
| + v1->SetBoundsRect(gfx::Rect(50, 60, 100, 101));
|
| + // The move will force a repaint.
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| +
|
| + // Schedule a paint with damage rect where v1 used to be.
|
| + test_view->SchedulePaintInRect(gfx::Rect(5, 6, 10, 11));
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| +
|
| + // Should only have picked up root_view and test_view.
|
| + EXPECT_EQ(2U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
|
| +}
|
| +
|
| +TEST_F(ViewLayerTest, BoundsTreeLayerChangeMakesNewTree) {
|
| + BoundsTreeTestView* test_view = new BoundsTreeTestView;
|
| + widget()->SetContentsView(test_view);
|
| +
|
| + View* v1 = new View;
|
| + v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
|
| + test_view->AddChildView(v1);
|
| +
|
| + View* v2 = new View;
|
| + v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
|
| + v1->AddChildView(v2);
|
| +
|
| + // Schedule a full-view paint to get everyone's rectangles updated.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| +
|
| + // Set v1 to paint to its own layer, it should remove itself from the
|
| + // test_view heiarchy and no longer intersect with damage rects in that cull
|
| + // set.
|
| + v1->SetPaintToLayer(true);
|
| +
|
| + // Schedule another full-view paint.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| + // v1 and v2 should no longer be present in the test_view cull_set.
|
| + EXPECT_EQ(2U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
|
| + EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
|
| +
|
| + // Now set v1 back to not painting to a layer.
|
| + v1->SetPaintToLayer(false);
|
| + // Schedule another full-view paint.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| + // We should be back to the full cull set including v1 and v2.
|
| + EXPECT_EQ(4U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
|
| +}
|
| +
|
| +TEST_F(ViewLayerTest, BoundsTreeRemoveChildRemovesBounds) {
|
| + BoundsTreeTestView* test_view = new BoundsTreeTestView;
|
| + widget()->SetContentsView(test_view);
|
| +
|
| + View* v1 = new View;
|
| + v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
|
| + test_view->AddChildView(v1);
|
| +
|
| + View* v2 = new View;
|
| + v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
|
| + v1->AddChildView(v2);
|
| +
|
| + // Schedule a full-view paint to get everyone's rectangles updated.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| +
|
| + // Now remove v1 from the root view.
|
| + test_view->RemoveChildView(v1);
|
| +
|
| + // Schedule another full-view paint.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| + // v1 and v2 should no longer be present in the test_view cull_set.
|
| + EXPECT_EQ(2U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
|
| + EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
|
| +
|
| + // View v1 and v2 are no longer part of view hierarchy and therefore won't be
|
| + // deleted with that hierarchy.
|
| + delete v1;
|
| +}
|
| +
|
| +TEST_F(ViewLayerTest, BoundsTreeMoveViewMovesBounds) {
|
| + BoundsTreeTestView* test_view = new BoundsTreeTestView;
|
| + widget()->SetContentsView(test_view);
|
| +
|
| + // Build hierarchy v1 - v2 - v3.
|
| + View* v1 = new View;
|
| + v1->SetBoundsRect(gfx::Rect(20, 30, 150, 160));
|
| + test_view->AddChildView(v1);
|
| +
|
| + View* v2 = new View;
|
| + v2->SetBoundsRect(gfx::Rect(5, 10, 40, 50));
|
| + v1->AddChildView(v2);
|
| +
|
| + View* v3 = new View;
|
| + v3->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
|
| + v2->AddChildView(v3);
|
| +
|
| + // Schedule a full-view paint and ensure all views are present in the cull.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| + EXPECT_EQ(5U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v3));
|
| +
|
| + // Build an unrelated view hierarchy and move v2 in to it.
|
| + scoped_ptr<Widget> test_widget(new Widget);
|
| + Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
|
| + params.bounds = gfx::Rect(10, 10, 500, 500);
|
| + params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
| + test_widget->Init(params);
|
| + test_widget->Show();
|
| + BoundsTreeTestView* widget_view = new BoundsTreeTestView;
|
| + test_widget->SetContentsView(widget_view);
|
| + widget_view->AddChildView(v2);
|
| +
|
| + // Now schedule full-view paints in both widgets.
|
| + test_view->SchedulePaintInRect(test_view->bounds());
|
| + widget_view->SchedulePaintInRect(widget_view->bounds());
|
| + GetRootLayer()->GetCompositor()->ScheduleDraw();
|
| + ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
|
| +
|
| + // Only v1 should be present in the first cull set.
|
| + EXPECT_EQ(3U, test_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
|
| + EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
|
| +
|
| + // We should find v2 and v3 in the widget_view cull_set.
|
| + EXPECT_EQ(4U, widget_view->last_cull_set_.size());
|
| + EXPECT_EQ(1U, widget_view->last_cull_set_.count(test_widget->GetRootView()));
|
| + EXPECT_EQ(1U, widget_view->last_cull_set_.count(widget_view));
|
| + EXPECT_EQ(1U, widget_view->last_cull_set_.count(v2));
|
| + EXPECT_EQ(1U, widget_view->last_cull_set_.count(v3));
|
| +}
|
| +
|
| TEST_F(ViewTest, FocusableAssertions) {
|
| // View subclasses may change insets based on whether they are focusable,
|
| // which effects the preferred size. To avoid preferred size changing around
|
|
|