1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/views/view.h"
6 
7 #include <stddef.h>
8 
9 #include <map>
10 #include <memory>
11 
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/i18n/rtl.h"
15 
16 #include "base/macros.h"
17 #include "base/rand_util.h"
18 #include "base/run_loop.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/test/icu_test_util.h"
24 #include "base/test/scoped_feature_list.h"
25 #include "base/time/time.h"
26 #include "build/build_config.h"
27 #include "cc/paint/display_item_list.h"
28 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
29 #include "ui/accessibility/ax_enums.mojom.h"
30 #include "ui/base/accelerators/accelerator.h"
31 #include "ui/base/clipboard/clipboard.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/compositor/compositor.h"
34 #include "ui/compositor/compositor_switches.h"
35 #include "ui/compositor/layer.h"
36 #include "ui/compositor/layer_animator.h"
37 #include "ui/compositor/paint_context.h"
38 #include "ui/compositor/test/draw_waiter_for_test.h"
39 #include "ui/compositor/test/test_layers.h"
40 #include "ui/events/event.h"
41 #include "ui/events/event_utils.h"
42 #include "ui/events/keycodes/keyboard_codes.h"
43 #include "ui/events/scoped_target_handler.h"
44 #include "ui/events/test/event_generator.h"
45 #include "ui/gfx/canvas.h"
46 #include "ui/gfx/transform.h"
47 #include "ui/native_theme/native_theme.h"
48 #include "ui/native_theme/test_native_theme.h"
49 #include "ui/strings/grit/ui_strings.h"
50 #include "ui/views/background.h"
51 #include "ui/views/controls/native/native_view_host.h"
52 #include "ui/views/controls/scroll_view.h"
53 #include "ui/views/controls/textfield/textfield.h"
54 #include "ui/views/metadata/metadata_types.h"
55 #include "ui/views/paint_info.h"
56 #include "ui/views/test/views_test_base.h"
57 #include "ui/views/view_observer.h"
58 #include "ui/views/views_features.h"
59 #include "ui/views/widget/native_widget.h"
60 #include "ui/views/widget/root_view.h"
61 #include "ui/views/window/dialog_delegate.h"
62 
63 using base::ASCIIToUTF16;
64 
65 namespace {
66 
67 // Returns true if |ancestor| is an ancestor of |layer|.
LayerIsAncestor(const ui::Layer * ancestor,const ui::Layer * layer)68 bool LayerIsAncestor(const ui::Layer* ancestor, const ui::Layer* layer) {
69   while (layer && layer != ancestor)
70     layer = layer->parent();
71   return layer == ancestor;
72 }
73 
74 // Convenience functions for walking a View tree.
FirstView(const views::View * view)75 const views::View* FirstView(const views::View* view) {
76   const views::View* v = view;
77   while (!v->children().empty())
78     v = v->children().front();
79   return v;
80 }
81 
NextView(const views::View * view)82 const views::View* NextView(const views::View* view) {
83   const views::View* v = view;
84   const views::View* parent = v->parent();
85   if (!parent)
86     return nullptr;
87   const auto next = std::next(parent->FindChild(v));
88   return (next == parent->children().cend()) ? parent : FirstView(*next);
89 }
90 
91 // Convenience functions for walking a Layer tree.
FirstLayer(const ui::Layer * layer)92 const ui::Layer* FirstLayer(const ui::Layer* layer) {
93   const ui::Layer* l = layer;
94   while (!l->children().empty())
95     l = l->children().front();
96   return l;
97 }
98 
NextLayer(const ui::Layer * layer)99 const ui::Layer* NextLayer(const ui::Layer* layer) {
100   const ui::Layer* parent = layer->parent();
101   if (!parent)
102     return nullptr;
103   const std::vector<ui::Layer*> children = parent->children();
104   const auto i = std::find(children.cbegin(), children.cend(), layer) + 1;
105   return (i == children.cend()) ? parent : FirstLayer(*i);
106 }
107 
108 // Given the root nodes of a View tree and a Layer tree, makes sure the two
109 // trees are in sync.
ViewAndLayerTreeAreConsistent(const views::View * view,const ui::Layer * layer)110 bool ViewAndLayerTreeAreConsistent(const views::View* view,
111                                    const ui::Layer* layer) {
112   const views::View* v = FirstView(view);
113   const ui::Layer* l = FirstLayer(layer);
114   while (v && l) {
115     // Find the view with a layer.
116     while (v && !v->layer())
117       v = NextView(v);
118     EXPECT_TRUE(v);
119     if (!v)
120       return false;
121 
122     // Check if the View tree and the Layer tree are in sync.
123     EXPECT_EQ(l, v->layer());
124     if (v->layer() != l)
125       return false;
126 
127     // Check if the visibility states of the View and the Layer are in sync.
128     EXPECT_EQ(l->IsDrawn(), v->IsDrawn());
129     if (v->IsDrawn() != l->IsDrawn()) {
130       for (const views::View* vv = v; vv; vv = vv->parent())
131         LOG(ERROR) << "V: " << vv << " " << vv->GetVisible() << " "
132                    << vv->IsDrawn() << " " << vv->layer();
133       for (const ui::Layer* ll = l; ll; ll = ll->parent())
134         LOG(ERROR) << "L: " << ll << " " << ll->IsDrawn();
135       return false;
136     }
137 
138     // Check if the size of the View and the Layer are in sync.
139     EXPECT_EQ(l->bounds(), v->bounds());
140     if (v->bounds() != l->bounds())
141       return false;
142 
143     if (v == view || l == layer)
144       return v == view && l == layer;
145 
146     v = NextView(v);
147     l = NextLayer(l);
148   }
149 
150   return false;
151 }
152 
153 // Constructs a View tree with the specified depth.
ConstructTree(views::View * view,int depth)154 void ConstructTree(views::View* view, int depth) {
155   if (depth == 0)
156     return;
157   int count = base::RandInt(1, 5);
158   for (int i = 0; i < count; i++) {
159     views::View* v = new views::View;
160     view->AddChildView(v);
161     if (base::RandDouble() > 0.5)
162       v->SetPaintToLayer();
163     if (base::RandDouble() < 0.2)
164       v->SetVisible(false);
165 
166     ConstructTree(v, depth - 1);
167   }
168 }
169 
ScrambleTree(views::View * view)170 void ScrambleTree(views::View* view) {
171   if (view->children().empty())
172     return;
173 
174   for (views::View* child : view->children())
175     ScrambleTree(child);
176 
177   size_t count = view->children().size();
178   if (count > 1) {
179     const uint64_t max = count - 1;
180     size_t a = size_t{base::RandGenerator(max)};
181     size_t b = size_t{base::RandGenerator(max)};
182 
183     if (a != b) {
184       views::View* view_a = view->children()[a];
185       views::View* view_b = view->children()[b];
186       view->ReorderChildView(view_a, b);
187       view->ReorderChildView(view_b, a);
188     }
189   }
190 
191   if (!view->layer() && base::RandDouble() < 0.1)
192     view->SetPaintToLayer();
193 
194   if (base::RandDouble() < 0.1)
195     view->SetVisible(!view->GetVisible());
196 }
197 
198 }  // namespace
199 
200 namespace views {
201 
202 using ViewTest = ViewsTestBase;
203 
204 // A derived class for testing purpose.
205 class TestView : public View {
206  public:
207   TestView() = default;
208   ~TestView() override = default;
209 
210   // Reset all test state
Reset()211   void Reset() {
212     did_change_bounds_ = false;
213     did_layout_ = false;
214     last_mouse_event_type_ = 0;
215     location_.SetPoint(0, 0);
216     received_mouse_enter_ = false;
217     received_mouse_exit_ = false;
218     did_paint_ = false;
219     accelerator_count_map_.clear();
220     can_process_events_within_subtree_ = true;
221   }
222 
223   // Exposed as public for testing.
DoFocus()224   void DoFocus() { views::View::Focus(); }
225 
DoBlur()226   void DoBlur() { views::View::Blur(); }
227 
set_can_process_events_within_subtree(bool can_process)228   void set_can_process_events_within_subtree(bool can_process) {
229     can_process_events_within_subtree_ = can_process;
230   }
231 
CanProcessEventsWithinSubtree() const232   bool CanProcessEventsWithinSubtree() const override {
233     return can_process_events_within_subtree_;
234   }
235 
Layout()236   void Layout() override {
237     did_layout_ = true;
238     View::Layout();
239   }
240 
241   void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
242   bool OnMousePressed(const ui::MouseEvent& event) override;
243   bool OnMouseDragged(const ui::MouseEvent& event) override;
244   void OnMouseReleased(const ui::MouseEvent& event) override;
245   void OnMouseEntered(const ui::MouseEvent& event) override;
246   void OnMouseExited(const ui::MouseEvent& event) override;
247 
248   void OnPaint(gfx::Canvas* canvas) override;
249   void OnDidSchedulePaint(const gfx::Rect& rect) override;
250   bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
251 
252   void OnThemeChanged() override;
253 
254   void OnAccessibilityEvent(ax::mojom::Event event_type) override;
255 
256   // OnBoundsChanged.
257   bool did_change_bounds_;
258   gfx::Rect new_bounds_;
259 
260   // Layout.
261   bool did_layout_ = false;
262 
263   // MouseEvent.
264   int last_mouse_event_type_;
265   gfx::Point location_;
266   bool received_mouse_enter_;
267   bool received_mouse_exit_;
268   bool delete_on_pressed_ = false;
269 
270   // Painting.
271   std::vector<gfx::Rect> scheduled_paint_rects_;
272   bool did_paint_ = false;
273 
274   // Accelerators.
275   std::map<ui::Accelerator, int> accelerator_count_map_;
276 
277   // Native theme.
278   const ui::NativeTheme* native_theme_ = nullptr;
279 
280   // Value to return from CanProcessEventsWithinSubtree().
281   bool can_process_events_within_subtree_ = true;
282 
283   // Accessibility events
284   ax::mojom::Event last_a11y_event_;
285 };
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 // Layout
289 ////////////////////////////////////////////////////////////////////////////////
290 
TEST_F(ViewTest,LayoutCalledInvalidateAndOriginChanges)291 TEST_F(ViewTest, LayoutCalledInvalidateAndOriginChanges) {
292   TestView parent;
293   TestView* child = new TestView;
294   gfx::Rect parent_rect(0, 0, 100, 100);
295   parent.SetBoundsRect(parent_rect);
296 
297   parent.Reset();
298   // |AddChildView| invalidates parent's layout.
299   parent.AddChildView(child);
300   // Change rect so that only rect's origin is affected.
301   parent.SetBoundsRect(parent_rect + gfx::Vector2d(10, 0));
302 
303   EXPECT_TRUE(parent.did_layout_);
304 
305   // After child layout is invalidated, parent and child must be laid out
306   // during parent->BoundsChanged(...) call.
307   parent.Reset();
308   child->Reset();
309 
310   child->InvalidateLayout();
311   parent.SetBoundsRect(parent_rect + gfx::Vector2d(20, 0));
312   EXPECT_TRUE(parent.did_layout_);
313   EXPECT_TRUE(child->did_layout_);
314 }
315 
316 // Tests that SizeToPreferredSize will trigger a Layout if the size has changed
317 // or if layout is marked invalid.
TEST_F(ViewTest,SizeToPreferredSizeInducesLayout)318 TEST_F(ViewTest, SizeToPreferredSizeInducesLayout) {
319   TestView example_view;
320   example_view.SetPreferredSize(gfx::Size(101, 102));
321   example_view.SizeToPreferredSize();
322   EXPECT_TRUE(example_view.did_layout_);
323 
324   example_view.Reset();
325   example_view.SizeToPreferredSize();
326   EXPECT_FALSE(example_view.did_layout_);
327 
328   example_view.InvalidateLayout();
329   example_view.SizeToPreferredSize();
330   EXPECT_TRUE(example_view.did_layout_);
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////////
334 // OnBoundsChanged
335 ////////////////////////////////////////////////////////////////////////////////
336 
OnAccessibilityEvent(ax::mojom::Event event_type)337 void TestView::OnAccessibilityEvent(ax::mojom::Event event_type) {
338   last_a11y_event_ = event_type;
339 }
340 
TEST_F(ViewTest,OnBoundsChangedFiresA11yEvent)341 TEST_F(ViewTest, OnBoundsChangedFiresA11yEvent) {
342   TestView v;
343 
344   // Should change when scaled or moved.
345   gfx::Rect initial(0, 0, 200, 200);
346   gfx::Rect scaled(0, 0, 250, 250);
347   gfx::Rect moved(100, 100, 250, 250);
348 
349   v.last_a11y_event_ = ax::mojom::Event::kNone;
350   v.SetBoundsRect(initial);
351   EXPECT_EQ(v.last_a11y_event_, ax::mojom::Event::kLocationChanged);
352 
353   v.last_a11y_event_ = ax::mojom::Event::kNone;
354   v.SetBoundsRect(scaled);
355   EXPECT_EQ(v.last_a11y_event_, ax::mojom::Event::kLocationChanged);
356 
357   v.last_a11y_event_ = ax::mojom::Event::kNone;
358   v.SetBoundsRect(moved);
359   EXPECT_EQ(v.last_a11y_event_, ax::mojom::Event::kLocationChanged);
360 }
361 
OnBoundsChanged(const gfx::Rect & previous_bounds)362 void TestView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
363   did_change_bounds_ = true;
364   new_bounds_ = bounds();
365 }
366 
TEST_F(ViewTest,OnBoundsChanged)367 TEST_F(ViewTest, OnBoundsChanged) {
368   TestView v;
369 
370   gfx::Rect prev_rect(0, 0, 200, 200);
371   gfx::Rect new_rect(100, 100, 250, 250);
372 
373   v.SetBoundsRect(prev_rect);
374   v.Reset();
375   v.SetBoundsRect(new_rect);
376 
377   EXPECT_TRUE(v.did_change_bounds_);
378   EXPECT_EQ(v.new_bounds_, new_rect);
379   EXPECT_EQ(v.bounds(), new_rect);
380 }
381 
382 ////////////////////////////////////////////////////////////////////////////////
383 // OnStateChanged
384 ////////////////////////////////////////////////////////////////////////////////
385 
TEST_F(ViewTest,OnStateChangedFiresA11yEvent)386 TEST_F(ViewTest, OnStateChangedFiresA11yEvent) {
387   TestView v;
388 
389   v.last_a11y_event_ = ax::mojom::Event::kNone;
390   v.SetEnabled(false);
391   EXPECT_EQ(v.last_a11y_event_, ax::mojom::Event::kStateChanged);
392 
393   v.last_a11y_event_ = ax::mojom::Event::kNone;
394   v.SetEnabled(true);
395   EXPECT_EQ(v.last_a11y_event_, ax::mojom::Event::kStateChanged);
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 // MouseEvent
400 ////////////////////////////////////////////////////////////////////////////////
401 
OnMousePressed(const ui::MouseEvent & event)402 bool TestView::OnMousePressed(const ui::MouseEvent& event) {
403   last_mouse_event_type_ = event.type();
404   location_.SetPoint(event.x(), event.y());
405   if (delete_on_pressed_)
406     delete this;
407   return true;
408 }
409 
OnMouseDragged(const ui::MouseEvent & event)410 bool TestView::OnMouseDragged(const ui::MouseEvent& event) {
411   last_mouse_event_type_ = event.type();
412   location_.SetPoint(event.x(), event.y());
413   return true;
414 }
415 
OnMouseReleased(const ui::MouseEvent & event)416 void TestView::OnMouseReleased(const ui::MouseEvent& event) {
417   last_mouse_event_type_ = event.type();
418   location_.SetPoint(event.x(), event.y());
419 }
420 
OnMouseEntered(const ui::MouseEvent & event)421 void TestView::OnMouseEntered(const ui::MouseEvent& event) {
422   received_mouse_enter_ = true;
423 }
424 
OnMouseExited(const ui::MouseEvent & event)425 void TestView::OnMouseExited(const ui::MouseEvent& event) {
426   received_mouse_exit_ = true;
427 }
428 
TEST_F(ViewTest,MouseEvent)429 TEST_F(ViewTest, MouseEvent) {
430   TestView* v1 = new TestView();
431   v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
432 
433   TestView* v2 = new TestView();
434   v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
435 
436   std::unique_ptr<Widget> widget(new Widget);
437   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
438   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
439   params.bounds = gfx::Rect(50, 50, 650, 650);
440   widget->Init(std::move(params));
441   internal::RootView* root =
442       static_cast<internal::RootView*>(widget->GetRootView());
443 
444   root->AddChildView(v1);
445   v1->AddChildView(v2);
446 
447   v1->Reset();
448   v2->Reset();
449 
450   gfx::Point p1(110, 120);
451   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, ui::EventTimeForNow(),
452                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
453   root->OnMousePressed(pressed);
454   EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_PRESSED);
455   EXPECT_EQ(v2->location_.x(), 10);
456   EXPECT_EQ(v2->location_.y(), 20);
457   // Make sure v1 did not receive the event
458   EXPECT_EQ(v1->last_mouse_event_type_, 0);
459 
460   // Drag event out of bounds. Should still go to v2
461   v1->Reset();
462   v2->Reset();
463   gfx::Point p2(50, 40);
464   ui::MouseEvent dragged(ui::ET_MOUSE_DRAGGED, p2, p2, ui::EventTimeForNow(),
465                          ui::EF_LEFT_MOUSE_BUTTON, 0);
466   root->OnMouseDragged(dragged);
467   EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_DRAGGED);
468   EXPECT_EQ(v2->location_.x(), -50);
469   EXPECT_EQ(v2->location_.y(), -60);
470   // Make sure v1 did not receive the event
471   EXPECT_EQ(v1->last_mouse_event_type_, 0);
472 
473   // Releasted event out of bounds. Should still go to v2
474   v1->Reset();
475   v2->Reset();
476   ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
477                           ui::EventTimeForNow(), 0, 0);
478   root->OnMouseDragged(released);
479   EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_RELEASED);
480   EXPECT_EQ(v2->location_.x(), -100);
481   EXPECT_EQ(v2->location_.y(), -100);
482   // Make sure v1 did not receive the event
483   EXPECT_EQ(v1->last_mouse_event_type_, 0);
484 
485   widget->CloseNow();
486 }
487 
488 // Confirm that a view can be deleted as part of processing a mouse press.
TEST_F(ViewTest,DeleteOnPressed)489 TEST_F(ViewTest, DeleteOnPressed) {
490   TestView* v1 = new TestView();
491   v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
492 
493   TestView* v2 = new TestView();
494   v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
495 
496   v1->Reset();
497   v2->Reset();
498 
499   std::unique_ptr<Widget> widget(new Widget);
500   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
501   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
502   params.bounds = gfx::Rect(50, 50, 650, 650);
503   widget->Init(std::move(params));
504   View* root = widget->GetRootView();
505 
506   root->AddChildView(v1);
507   v1->AddChildView(v2);
508 
509   v2->delete_on_pressed_ = true;
510   gfx::Point point(110, 120);
511   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, point, point,
512                          ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
513                          ui::EF_LEFT_MOUSE_BUTTON);
514   root->OnMousePressed(pressed);
515   EXPECT_TRUE(v1->children().empty());
516 
517   widget->CloseNow();
518 }
519 
520 ////////////////////////////////////////////////////////////////////////////////
521 // Painting
522 ////////////////////////////////////////////////////////////////////////////////
523 
OnPaint(gfx::Canvas * canvas)524 void TestView::OnPaint(gfx::Canvas* canvas) {
525   did_paint_ = true;
526 }
527 
528 namespace {
529 
530 // Helper class to create a Widget with standard parameters that is closed when
531 // the helper class goes out of scope.
532 class ScopedTestPaintWidget {
533  public:
ScopedTestPaintWidget(Widget::InitParams params)534   explicit ScopedTestPaintWidget(Widget::InitParams params)
535       : widget_(new Widget) {
536     widget_->Init(std::move(params));
537     widget_->GetRootView()->SetBounds(0, 0, 25, 26);
538   }
539 
~ScopedTestPaintWidget()540   ~ScopedTestPaintWidget() { widget_->CloseNow(); }
541 
operator ->()542   Widget* operator->() { return widget_; }
543 
544  private:
545   Widget* widget_;
546 
547   DISALLOW_COPY_AND_ASSIGN(ScopedTestPaintWidget);
548 };
549 
550 }  // namespace
551 
TEST_F(ViewTest,PaintEmptyView)552 TEST_F(ViewTest, PaintEmptyView) {
553   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
554   View* root_view = widget->GetRootView();
555 
556   // |v1| is empty.
557   TestView* v1 = new TestView;
558   v1->SetBounds(10, 11, 0, 1);
559   root_view->AddChildView(v1);
560 
561   // |v11| is a child of an empty |v1|.
562   TestView* v11 = new TestView;
563   v11->SetBounds(3, 4, 6, 5);
564   v1->AddChildView(v11);
565 
566   // |v2| is not.
567   TestView* v2 = new TestView;
568   v2->SetBounds(3, 4, 6, 5);
569   root_view->AddChildView(v2);
570 
571   // Paint "everything".
572   gfx::Rect first_paint(1, 1);
573   auto list = base::MakeRefCounted<cc::DisplayItemList>();
574   root_view->Paint(PaintInfo::CreateRootPaintInfo(
575       ui::PaintContext(list.get(), 1.f, first_paint, false),
576       first_paint.size()));
577 
578   // The empty view has nothing to paint so it doesn't try build a cache, nor do
579   // its children which would be clipped by its (empty) self.
580   EXPECT_FALSE(v1->did_paint_);
581   EXPECT_FALSE(v11->did_paint_);
582   EXPECT_TRUE(v2->did_paint_);
583 }
584 
TEST_F(ViewTest,PaintWithMovedViewUsesCache)585 TEST_F(ViewTest, PaintWithMovedViewUsesCache) {
586   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
587   View* root_view = widget->GetRootView();
588   TestView* v1 = new TestView;
589   v1->SetBounds(10, 11, 12, 13);
590   root_view->AddChildView(v1);
591 
592   // Paint everything once, since it has to build its cache. Then we can test
593   // invalidation.
594   gfx::Rect pixel_rect = gfx::Rect(1, 1);
595   float device_scale_factor = 1.f;
596   auto list = base::MakeRefCounted<cc::DisplayItemList>();
597   root_view->PaintFromPaintRoot(
598       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
599   EXPECT_TRUE(v1->did_paint_);
600   v1->Reset();
601   // The visual rects for (clip, drawing, transform) should be in layer space.
602   gfx::Rect expected_visual_rect_in_layer_space(10, 11, 12, 13);
603   int item_index = 3;
604   EXPECT_EQ(expected_visual_rect_in_layer_space,
605             list->VisualRectForTesting(item_index++));
606   EXPECT_EQ(expected_visual_rect_in_layer_space,
607             list->VisualRectForTesting(item_index++));
608   EXPECT_EQ(expected_visual_rect_in_layer_space,
609             list->VisualRectForTesting(item_index));
610 
611   // If invalidation doesn't intersect v1, we paint with the cache.
612   list = base::MakeRefCounted<cc::DisplayItemList>();
613   root_view->PaintFromPaintRoot(
614       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
615   EXPECT_FALSE(v1->did_paint_);
616   v1->Reset();
617 
618   // If invalidation does intersect v1, we don't paint with the cache.
619   list = base::MakeRefCounted<cc::DisplayItemList>();
620   root_view->PaintFromPaintRoot(
621       ui::PaintContext(list.get(), device_scale_factor, v1->bounds(), false));
622   EXPECT_TRUE(v1->did_paint_);
623   v1->Reset();
624 
625   // Moving the view should still use the cache when the invalidation doesn't
626   // intersect v1.
627   list = base::MakeRefCounted<cc::DisplayItemList>();
628   v1->SetX(9);
629   root_view->PaintFromPaintRoot(
630       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
631   EXPECT_FALSE(v1->did_paint_);
632   v1->Reset();
633   item_index = 3;
634   expected_visual_rect_in_layer_space.SetRect(9, 11, 12, 13);
635   EXPECT_EQ(expected_visual_rect_in_layer_space,
636             list->VisualRectForTesting(item_index++));
637   EXPECT_EQ(expected_visual_rect_in_layer_space,
638             list->VisualRectForTesting(item_index++));
639   EXPECT_EQ(expected_visual_rect_in_layer_space,
640             list->VisualRectForTesting(item_index));
641 
642   // Moving the view should not use the cache when painting without
643   // invalidation.
644   list = base::MakeRefCounted<cc::DisplayItemList>();
645   v1->SetX(8);
646   root_view->PaintFromPaintRoot(ui::PaintContext(
647       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false),
648       ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
649   EXPECT_TRUE(v1->did_paint_);
650   v1->Reset();
651   item_index = 3;
652   expected_visual_rect_in_layer_space.SetRect(8, 11, 12, 13);
653   EXPECT_EQ(expected_visual_rect_in_layer_space,
654             list->VisualRectForTesting(item_index++));
655   EXPECT_EQ(expected_visual_rect_in_layer_space,
656             list->VisualRectForTesting(item_index++));
657   EXPECT_EQ(expected_visual_rect_in_layer_space,
658             list->VisualRectForTesting(item_index));
659 }
660 
TEST_F(ViewTest,PaintWithMovedViewUsesCacheInRTL)661 TEST_F(ViewTest, PaintWithMovedViewUsesCacheInRTL) {
662   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
663   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
664   View* root_view = widget->GetRootView();
665   TestView* v1 = new TestView;
666   v1->SetBounds(10, 11, 12, 13);
667   root_view->AddChildView(v1);
668 
669   // Paint everything once, since it has to build its cache. Then we can test
670   // invalidation.
671   gfx::Rect pixel_rect = gfx::Rect(1, 1);
672   float device_scale_factor = 1.f;
673   auto list = base::MakeRefCounted<cc::DisplayItemList>();
674   root_view->PaintFromPaintRoot(
675       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
676   EXPECT_TRUE(v1->did_paint_);
677   v1->Reset();
678   // The visual rects for (clip, drawing, transform) should be in layer space.
679   // x: 25 - 10(x) - 12(width) = 3
680   gfx::Rect expected_visual_rect_in_layer_space(3, 11, 12, 13);
681   int item_index = 3;
682   EXPECT_EQ(expected_visual_rect_in_layer_space,
683             list->VisualRectForTesting(item_index++));
684   EXPECT_EQ(expected_visual_rect_in_layer_space,
685             list->VisualRectForTesting(item_index++));
686   EXPECT_EQ(expected_visual_rect_in_layer_space,
687             list->VisualRectForTesting(item_index));
688 
689   // If invalidation doesn't intersect v1, we paint with the cache.
690   list = base::MakeRefCounted<cc::DisplayItemList>();
691   root_view->PaintFromPaintRoot(
692       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
693   EXPECT_FALSE(v1->did_paint_);
694   v1->Reset();
695 
696   // If invalidation does intersect v1, we don't paint with the cache.
697   list = base::MakeRefCounted<cc::DisplayItemList>();
698   root_view->PaintFromPaintRoot(
699       ui::PaintContext(list.get(), device_scale_factor, v1->bounds(), false));
700   EXPECT_TRUE(v1->did_paint_);
701   v1->Reset();
702 
703   // Moving the view should still use the cache when the invalidation doesn't
704   // intersect v1.
705   list = base::MakeRefCounted<cc::DisplayItemList>();
706   v1->SetX(9);
707   root_view->PaintFromPaintRoot(
708       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
709   EXPECT_FALSE(v1->did_paint_);
710   v1->Reset();
711   item_index = 3;
712   // x: 25 - 9(x) - 12(width) = 4
713   expected_visual_rect_in_layer_space.SetRect(4, 11, 12, 13);
714   EXPECT_EQ(expected_visual_rect_in_layer_space,
715             list->VisualRectForTesting(item_index++));
716   EXPECT_EQ(expected_visual_rect_in_layer_space,
717             list->VisualRectForTesting(item_index++));
718   EXPECT_EQ(expected_visual_rect_in_layer_space,
719             list->VisualRectForTesting(item_index));
720 
721   // Moving the view should not use the cache when painting without
722   // invalidation.
723   list = base::MakeRefCounted<cc::DisplayItemList>();
724   v1->SetX(8);
725   root_view->PaintFromPaintRoot(ui::PaintContext(
726       ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false),
727       ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
728   EXPECT_TRUE(v1->did_paint_);
729   v1->Reset();
730   item_index = 3;
731   // x: 25 - 8(x) - 12(width) = 5
732   expected_visual_rect_in_layer_space.SetRect(5, 11, 12, 13);
733   EXPECT_EQ(expected_visual_rect_in_layer_space,
734             list->VisualRectForTesting(item_index++));
735   EXPECT_EQ(expected_visual_rect_in_layer_space,
736             list->VisualRectForTesting(item_index++));
737   EXPECT_EQ(expected_visual_rect_in_layer_space,
738             list->VisualRectForTesting(item_index));
739 }
740 
TEST_F(ViewTest,PaintWithUnknownInvalidation)741 TEST_F(ViewTest, PaintWithUnknownInvalidation) {
742   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
743   View* root_view = widget->GetRootView();
744 
745   TestView* v1 = new TestView;
746   v1->SetBounds(10, 11, 12, 13);
747   root_view->AddChildView(v1);
748 
749   TestView* v2 = new TestView;
750   v2->SetBounds(3, 4, 6, 5);
751   v1->AddChildView(v2);
752 
753   // Paint everything once, since it has to build its cache. Then we can test
754   // invalidation.
755   gfx::Rect first_paint(1, 1);
756   auto list = base::MakeRefCounted<cc::DisplayItemList>();
757   root_view->PaintFromPaintRoot(
758       ui::PaintContext(list.get(), 1.f, first_paint, false));
759   v1->Reset();
760   v2->Reset();
761 
762   gfx::Rect paint_area(1, 1);
763   gfx::Rect root_area(root_view->size());
764   list = base::MakeRefCounted<cc::DisplayItemList>();
765 
766   // With a known invalidation, v1 and v2 are not painted.
767   EXPECT_FALSE(v1->did_paint_);
768   EXPECT_FALSE(v2->did_paint_);
769   root_view->PaintFromPaintRoot(
770       ui::PaintContext(list.get(), 1.f, paint_area, false));
771   EXPECT_FALSE(v1->did_paint_);
772   EXPECT_FALSE(v2->did_paint_);
773 
774   // With unknown invalidation, v1 and v2 are painted.
775   root_view->PaintFromPaintRoot(
776       ui::PaintContext(ui::PaintContext(list.get(), 1.f, paint_area, false),
777                        ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
778   EXPECT_TRUE(v1->did_paint_);
779   EXPECT_TRUE(v2->did_paint_);
780 }
781 
TEST_F(ViewTest,PaintContainsChildren)782 TEST_F(ViewTest, PaintContainsChildren) {
783   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
784   View* root_view = widget->GetRootView();
785 
786   TestView* v1 = new TestView;
787   v1->SetBounds(10, 11, 12, 13);
788   root_view->AddChildView(v1);
789 
790   TestView* v2 = new TestView;
791   v2->SetBounds(3, 4, 6, 5);
792   v1->AddChildView(v2);
793 
794   // Paint everything once, since it has to build its cache. Then we can test
795   // invalidation.
796   gfx::Rect first_paint(1, 1);
797   auto list = base::MakeRefCounted<cc::DisplayItemList>();
798   root_view->Paint(PaintInfo::CreateRootPaintInfo(
799       ui::PaintContext(list.get(), 1.f, first_paint, false),
800       root_view->size()));
801   v1->Reset();
802   v2->Reset();
803 
804   gfx::Rect paint_area(25, 26);
805   gfx::Rect root_area(root_view->size());
806   list = base::MakeRefCounted<cc::DisplayItemList>();
807 
808   EXPECT_FALSE(v1->did_paint_);
809   EXPECT_FALSE(v2->did_paint_);
810   root_view->Paint(PaintInfo::CreateRootPaintInfo(
811       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
812   EXPECT_TRUE(v1->did_paint_);
813   EXPECT_TRUE(v2->did_paint_);
814 }
815 
TEST_F(ViewTest,PaintContainsChildrenInRTL)816 TEST_F(ViewTest, PaintContainsChildrenInRTL) {
817   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
818   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
819   View* root_view = widget->GetRootView();
820 
821   TestView* v1 = new TestView;
822   v1->SetBounds(10, 11, 12, 13);
823   root_view->AddChildView(v1);
824 
825   TestView* v2 = new TestView;
826   v2->SetBounds(3, 4, 6, 5);
827   v1->AddChildView(v2);
828 
829   // Verify where the layers actually appear.
830   v1->SetPaintToLayer();
831   // x: 25 - 10(x) - 12(width) = 3
832   EXPECT_EQ(gfx::Rect(3, 11, 12, 13), v1->layer()->bounds());
833   v1->DestroyLayer();
834 
835   v2->SetPaintToLayer();
836   // x: 25 - 10(parent x) - 3(x) - 6(width) = 6
837   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
838   v2->DestroyLayer();
839 
840   // Paint everything once, since it has to build its cache. Then we can test
841   // invalidation.
842   gfx::Rect first_paint(1, 1);
843   auto list = base::MakeRefCounted<cc::DisplayItemList>();
844   root_view->Paint(PaintInfo::CreateRootPaintInfo(
845       ui::PaintContext(list.get(), 1.f, first_paint, false),
846       root_view->size()));
847   v1->Reset();
848   v2->Reset();
849 
850   gfx::Rect paint_area(25, 26);
851   gfx::Rect root_area(root_view->size());
852   list = base::MakeRefCounted<cc::DisplayItemList>();
853 
854   EXPECT_FALSE(v1->did_paint_);
855   EXPECT_FALSE(v2->did_paint_);
856   root_view->Paint(PaintInfo::CreateRootPaintInfo(
857       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
858   EXPECT_TRUE(v1->did_paint_);
859   EXPECT_TRUE(v2->did_paint_);
860 }
861 
TEST_F(ViewTest,PaintIntersectsChildren)862 TEST_F(ViewTest, PaintIntersectsChildren) {
863   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
864   View* root_view = widget->GetRootView();
865 
866   TestView* v1 = new TestView;
867   v1->SetBounds(10, 11, 12, 13);
868   root_view->AddChildView(v1);
869 
870   TestView* v2 = new TestView;
871   v2->SetBounds(3, 4, 6, 5);
872   v1->AddChildView(v2);
873 
874   // Paint everything once, since it has to build its cache. Then we can test
875   // invalidation.
876   gfx::Rect first_paint(1, 1);
877   auto list = base::MakeRefCounted<cc::DisplayItemList>();
878   root_view->Paint(PaintInfo::CreateRootPaintInfo(
879       ui::PaintContext(list.get(), 1.f, first_paint, false),
880       root_view->size()));
881   v1->Reset();
882   v2->Reset();
883 
884   gfx::Rect paint_area(9, 10, 5, 6);
885   gfx::Rect root_area(root_view->size());
886   list = base::MakeRefCounted<cc::DisplayItemList>();
887 
888   EXPECT_FALSE(v1->did_paint_);
889   EXPECT_FALSE(v2->did_paint_);
890   root_view->Paint(PaintInfo::CreateRootPaintInfo(
891       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
892   EXPECT_TRUE(v1->did_paint_);
893   EXPECT_TRUE(v2->did_paint_);
894 }
895 
TEST_F(ViewTest,PaintIntersectsChildrenInRTL)896 TEST_F(ViewTest, PaintIntersectsChildrenInRTL) {
897   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
898   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
899   View* root_view = widget->GetRootView();
900 
901   TestView* v1 = new TestView;
902   v1->SetBounds(10, 11, 12, 13);
903   root_view->AddChildView(v1);
904 
905   TestView* v2 = new TestView;
906   v2->SetBounds(3, 4, 6, 5);
907   v1->AddChildView(v2);
908 
909   // Verify where the layers actually appear.
910   v1->SetPaintToLayer();
911   // x: 25 - 10(x) - 12(width) = 3
912   EXPECT_EQ(gfx::Rect(3, 11, 12, 13), v1->layer()->bounds());
913   v1->DestroyLayer();
914 
915   v2->SetPaintToLayer();
916   // x: 25 - 10(parent x) - 3(x) - 6(width) = 6
917   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
918   v2->DestroyLayer();
919 
920   // Paint everything once, since it has to build its cache. Then we can test
921   // invalidation.
922   gfx::Rect first_paint(1, 1);
923   auto list = base::MakeRefCounted<cc::DisplayItemList>();
924   root_view->Paint(PaintInfo::CreateRootPaintInfo(
925       ui::PaintContext(list.get(), 1.f, first_paint, false),
926       root_view->size()));
927   v1->Reset();
928   v2->Reset();
929 
930   gfx::Rect paint_area(2, 10, 5, 6);
931   gfx::Rect root_area(root_view->size());
932   list = base::MakeRefCounted<cc::DisplayItemList>();
933 
934   EXPECT_FALSE(v1->did_paint_);
935   EXPECT_FALSE(v2->did_paint_);
936   root_view->Paint(PaintInfo::CreateRootPaintInfo(
937       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
938   EXPECT_TRUE(v1->did_paint_);
939   EXPECT_TRUE(v2->did_paint_);
940 }
941 
TEST_F(ViewTest,PaintIntersectsChildButNotGrandChild)942 TEST_F(ViewTest, PaintIntersectsChildButNotGrandChild) {
943   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
944   View* root_view = widget->GetRootView();
945 
946   TestView* v1 = new TestView;
947   v1->SetBounds(10, 11, 12, 13);
948   root_view->AddChildView(v1);
949 
950   TestView* v2 = new TestView;
951   v2->SetBounds(3, 4, 6, 5);
952   v1->AddChildView(v2);
953 
954   // Paint everything once, since it has to build its cache. Then we can test
955   // invalidation.
956   gfx::Rect first_paint(1, 1);
957   auto list = base::MakeRefCounted<cc::DisplayItemList>();
958   root_view->Paint(PaintInfo::CreateRootPaintInfo(
959       ui::PaintContext(list.get(), 1.f, first_paint, false),
960       root_view->size()));
961   v1->Reset();
962   v2->Reset();
963 
964   gfx::Rect paint_area(9, 10, 2, 3);
965   gfx::Rect root_area(root_view->size());
966   list = base::MakeRefCounted<cc::DisplayItemList>();
967 
968   EXPECT_FALSE(v1->did_paint_);
969   EXPECT_FALSE(v2->did_paint_);
970   root_view->Paint(PaintInfo::CreateRootPaintInfo(
971       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
972   EXPECT_TRUE(v1->did_paint_);
973   EXPECT_FALSE(v2->did_paint_);
974 }
975 
TEST_F(ViewTest,PaintIntersectsChildButNotGrandChildInRTL)976 TEST_F(ViewTest, PaintIntersectsChildButNotGrandChildInRTL) {
977   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
978   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
979   View* root_view = widget->GetRootView();
980 
981   TestView* v1 = new TestView;
982   v1->SetBounds(10, 11, 12, 13);
983   root_view->AddChildView(v1);
984 
985   TestView* v2 = new TestView;
986   v2->SetBounds(3, 4, 6, 5);
987   v1->AddChildView(v2);
988 
989   // Verify where the layers actually appear.
990   v1->SetPaintToLayer();
991   // x: 25 - 10(x) - 12(width) = 3
992   EXPECT_EQ(gfx::Rect(3, 11, 12, 13), v1->layer()->bounds());
993   v1->DestroyLayer();
994 
995   v2->SetPaintToLayer();
996   // x: 25 - 10(parent x) - 3(x) - 6(width) = 6
997   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
998   v2->DestroyLayer();
999 
1000   // Paint everything once, since it has to build its cache. Then we can test
1001   // invalidation.
1002   gfx::Rect first_paint(1, 1);
1003   auto list = base::MakeRefCounted<cc::DisplayItemList>();
1004   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1005       ui::PaintContext(list.get(), 1.f, first_paint, false),
1006       root_view->size()));
1007   v1->Reset();
1008   v2->Reset();
1009 
1010   gfx::Rect paint_area(2, 10, 2, 3);
1011   gfx::Rect root_area(root_view->size());
1012   list = base::MakeRefCounted<cc::DisplayItemList>();
1013 
1014   EXPECT_FALSE(v1->did_paint_);
1015   EXPECT_FALSE(v2->did_paint_);
1016   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1017       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
1018   EXPECT_TRUE(v1->did_paint_);
1019   EXPECT_FALSE(v2->did_paint_);
1020 }
1021 
TEST_F(ViewTest,PaintIntersectsNoChildren)1022 TEST_F(ViewTest, PaintIntersectsNoChildren) {
1023   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
1024   View* root_view = widget->GetRootView();
1025 
1026   TestView* v1 = new TestView;
1027   v1->SetBounds(10, 11, 12, 13);
1028   root_view->AddChildView(v1);
1029 
1030   TestView* v2 = new TestView;
1031   v2->SetBounds(3, 4, 6, 5);
1032   v1->AddChildView(v2);
1033 
1034   // Paint everything once, since it has to build its cache. Then we can test
1035   // invalidation.
1036   gfx::Rect first_paint(1, 1);
1037   auto list = base::MakeRefCounted<cc::DisplayItemList>();
1038   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1039       ui::PaintContext(list.get(), 1.f, first_paint, false),
1040       root_view->size()));
1041   v1->Reset();
1042   v2->Reset();
1043 
1044   gfx::Rect paint_area(9, 10, 2, 1);
1045   gfx::Rect root_area(root_view->size());
1046   list = base::MakeRefCounted<cc::DisplayItemList>();
1047 
1048   EXPECT_FALSE(v1->did_paint_);
1049   EXPECT_FALSE(v2->did_paint_);
1050   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1051       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
1052   EXPECT_FALSE(v1->did_paint_);
1053   EXPECT_FALSE(v2->did_paint_);
1054 }
1055 
TEST_F(ViewTest,PaintIntersectsNoChildrenInRTL)1056 TEST_F(ViewTest, PaintIntersectsNoChildrenInRTL) {
1057   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
1058   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
1059   View* root_view = widget->GetRootView();
1060 
1061   TestView* v1 = new TestView;
1062   v1->SetBounds(10, 11, 12, 13);
1063   root_view->AddChildView(v1);
1064 
1065   TestView* v2 = new TestView;
1066   v2->SetBounds(3, 4, 6, 5);
1067   v1->AddChildView(v2);
1068 
1069   // Verify where the layers actually appear.
1070   v1->SetPaintToLayer();
1071   // x: 25 - 10(x) - 12(width) = 3
1072   EXPECT_EQ(gfx::Rect(3, 11, 12, 13), v1->layer()->bounds());
1073   v1->DestroyLayer();
1074 
1075   v2->SetPaintToLayer();
1076   // x: 25 - 10(parent x) - 3(x) - 6(width) = 6
1077   EXPECT_EQ(gfx::Rect(6, 15, 6, 5), v2->layer()->bounds());
1078   v2->DestroyLayer();
1079 
1080   // Paint everything once, since it has to build its cache. Then we can test
1081   // invalidation.
1082   gfx::Rect first_paint(1, 1);
1083   auto list = base::MakeRefCounted<cc::DisplayItemList>();
1084   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1085       ui::PaintContext(list.get(), 1.f, first_paint, false),
1086       root_view->size()));
1087   v1->Reset();
1088   v2->Reset();
1089 
1090   gfx::Rect paint_area(2, 10, 2, 1);
1091   gfx::Rect root_area(root_view->size());
1092   list = base::MakeRefCounted<cc::DisplayItemList>();
1093 
1094   EXPECT_FALSE(v1->did_paint_);
1095   EXPECT_FALSE(v2->did_paint_);
1096   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1097       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
1098   EXPECT_FALSE(v1->did_paint_);
1099   EXPECT_FALSE(v2->did_paint_);
1100 }
1101 
TEST_F(ViewTest,PaintIntersectsOneChild)1102 TEST_F(ViewTest, PaintIntersectsOneChild) {
1103   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
1104   View* root_view = widget->GetRootView();
1105 
1106   TestView* v1 = new TestView;
1107   v1->SetBounds(10, 11, 12, 13);
1108   root_view->AddChildView(v1);
1109 
1110   TestView* v2 = new TestView;
1111   v2->SetBounds(3, 4, 6, 5);
1112   root_view->AddChildView(v2);
1113 
1114   // Paint everything once, since it has to build its cache. Then we can test
1115   // invalidation.
1116   gfx::Rect first_paint(1, 1);
1117   auto list = base::MakeRefCounted<cc::DisplayItemList>();
1118   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1119       ui::PaintContext(list.get(), 1.f, first_paint, false),
1120       root_view->size()));
1121   v1->Reset();
1122   v2->Reset();
1123 
1124   // Intersects with the second child only.
1125   gfx::Rect paint_area(3, 3, 1, 2);
1126   gfx::Rect root_area(root_view->size());
1127   list = base::MakeRefCounted<cc::DisplayItemList>();
1128 
1129   EXPECT_FALSE(v1->did_paint_);
1130   EXPECT_FALSE(v2->did_paint_);
1131   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1132       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
1133   EXPECT_FALSE(v1->did_paint_);
1134   EXPECT_TRUE(v2->did_paint_);
1135 
1136   // Intersects with the first child only.
1137   paint_area = gfx::Rect(20, 10, 1, 2);
1138 
1139   v1->Reset();
1140   v2->Reset();
1141   EXPECT_FALSE(v1->did_paint_);
1142   EXPECT_FALSE(v2->did_paint_);
1143   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1144       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
1145   EXPECT_TRUE(v1->did_paint_);
1146   EXPECT_FALSE(v2->did_paint_);
1147 }
1148 
TEST_F(ViewTest,PaintIntersectsOneChildInRTL)1149 TEST_F(ViewTest, PaintIntersectsOneChildInRTL) {
1150   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
1151   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
1152   View* root_view = widget->GetRootView();
1153 
1154   TestView* v1 = new TestView;
1155   v1->SetBounds(10, 11, 12, 13);
1156   root_view->AddChildView(v1);
1157 
1158   TestView* v2 = new TestView;
1159   v2->SetBounds(3, 4, 6, 5);
1160   root_view->AddChildView(v2);
1161 
1162   // Verify where the layers actually appear.
1163   v1->SetPaintToLayer();
1164   // x: 25 - 10(x) - 12(width) = 3
1165   EXPECT_EQ(gfx::Rect(3, 11, 12, 13), v1->layer()->bounds());
1166   v1->DestroyLayer();
1167 
1168   v2->SetPaintToLayer();
1169   // x: 25 - 3(x) - 6(width) = 16
1170   EXPECT_EQ(gfx::Rect(16, 4, 6, 5), v2->layer()->bounds());
1171   v2->DestroyLayer();
1172 
1173   // Paint everything once, since it has to build its cache. Then we can test
1174   // invalidation.
1175   gfx::Rect first_paint(1, 1);
1176   auto list = base::MakeRefCounted<cc::DisplayItemList>();
1177   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1178       ui::PaintContext(list.get(), 1.f, first_paint, false),
1179       root_view->size()));
1180   v1->Reset();
1181   v2->Reset();
1182 
1183   // Intersects with the first child only.
1184   gfx::Rect paint_area(3, 10, 1, 2);
1185   gfx::Rect root_area(root_view->size());
1186   list = base::MakeRefCounted<cc::DisplayItemList>();
1187 
1188   EXPECT_FALSE(v1->did_paint_);
1189   EXPECT_FALSE(v2->did_paint_);
1190   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1191       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
1192   EXPECT_TRUE(v1->did_paint_);
1193   EXPECT_FALSE(v2->did_paint_);
1194 
1195   // Intersects with the second child only.
1196   paint_area = gfx::Rect(21, 3, 1, 2);
1197 
1198   v1->Reset();
1199   v2->Reset();
1200   EXPECT_FALSE(v1->did_paint_);
1201   EXPECT_FALSE(v2->did_paint_);
1202   root_view->Paint(PaintInfo::CreateRootPaintInfo(
1203       ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
1204   EXPECT_FALSE(v1->did_paint_);
1205   EXPECT_TRUE(v2->did_paint_);
1206 }
1207 
TEST_F(ViewTest,PaintInPromotedToLayer)1208 TEST_F(ViewTest, PaintInPromotedToLayer) {
1209   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
1210   View* root_view = widget->GetRootView();
1211 
1212   TestView* v1 = new TestView;
1213   v1->SetPaintToLayer();
1214   v1->SetBounds(10, 11, 12, 13);
1215   root_view->AddChildView(v1);
1216 
1217   TestView* v2 = new TestView;
1218   v2->SetBounds(3, 4, 6, 5);
1219   v1->AddChildView(v2);
1220 
1221   // Paint everything once, since it has to build its cache. Then we can test
1222   // invalidation.
1223   gfx::Rect first_paint(1, 1);
1224   auto list = base::MakeRefCounted<cc::DisplayItemList>();
1225   v1->Paint(PaintInfo::CreateRootPaintInfo(
1226       ui::PaintContext(list.get(), 1.f, first_paint, false), v1->size()));
1227   v1->Reset();
1228   v2->Reset();
1229 
1230   {
1231     gfx::Rect paint_area(25, 26);
1232     gfx::Rect view_area(root_view->size());
1233     auto list = base::MakeRefCounted<cc::DisplayItemList>();
1234 
1235     // The promoted views are not painted as they are separate paint roots.
1236     root_view->Paint(PaintInfo::CreateRootPaintInfo(
1237         ui::PaintContext(list.get(), 1.f, paint_area, false),
1238         root_view->size()));
1239     EXPECT_FALSE(v1->did_paint_);
1240     EXPECT_FALSE(v2->did_paint_);
1241   }
1242 
1243   {
1244     gfx::Rect paint_area(1, 1);
1245     gfx::Rect view_area(v1->size());
1246     auto list = base::MakeRefCounted<cc::DisplayItemList>();
1247 
1248     // The |v1| view is painted. If it used its offset incorrect, it would think
1249     // its at (10,11) instead of at (0,0) since it is the paint root.
1250     v1->Paint(PaintInfo::CreateRootPaintInfo(
1251         ui::PaintContext(list.get(), 1.f, paint_area, false), v1->size()));
1252     EXPECT_TRUE(v1->did_paint_);
1253     EXPECT_FALSE(v2->did_paint_);
1254   }
1255 
1256   v1->Reset();
1257 
1258   {
1259     gfx::Rect paint_area(3, 3, 1, 2);
1260     gfx::Rect view_area(v1->size());
1261     auto list = base::MakeRefCounted<cc::DisplayItemList>();
1262 
1263     // The |v2| view is painted also. If it used its offset incorrect, it would
1264     // think its at (13,15) instead of at (3,4) since |v1| is the paint root.
1265     v1->Paint(PaintInfo::CreateRootPaintInfo(
1266         ui::PaintContext(list.get(), 1.f, paint_area, false), v1->size()));
1267     EXPECT_TRUE(v1->did_paint_);
1268     EXPECT_TRUE(v2->did_paint_);
1269   }
1270 }
1271 
1272 // A derived class for testing paint.
1273 class TestPaintView : public TestView {
1274  public:
TestPaintView()1275   TestPaintView() : canvas_bounds_(gfx::Rect()) {}
1276   ~TestPaintView() override = default;
1277 
OnPaint(gfx::Canvas * canvas)1278   void OnPaint(gfx::Canvas* canvas) override {
1279     did_paint_ = true;
1280     // Get the bounds from the canvas this view paints to.
1281     EXPECT_TRUE(canvas->GetClipBounds(&canvas_bounds_));
1282   }
1283 
canvas_bounds() const1284   gfx::Rect canvas_bounds() const { return canvas_bounds_; }
1285 
1286  private:
1287   gfx::Rect canvas_bounds_;
1288 };
1289 
TEST_F(ViewTest,PaintLocalBounds)1290 TEST_F(ViewTest, PaintLocalBounds) {
1291   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
1292   View* root_view = widget->GetRootView();
1293   // Make |root_view|'s bounds larger so |v1|'s visible bounds is not clipped by
1294   // |root_view|.
1295   root_view->SetBounds(0, 0, 200, 200);
1296 
1297   TestPaintView* v1 = new TestPaintView;
1298   v1->SetPaintToLayer();
1299 
1300   // Set bounds for |v1| such that it has an offset to its parent and only part
1301   // of it is visible. The visible bounds does not intersect with |root_view|'s
1302   // bounds.
1303   v1->SetBounds(0, -1000, 100, 1100);
1304   root_view->AddChildView(v1);
1305   EXPECT_EQ(gfx::Rect(0, 0, 100, 1100), v1->GetLocalBounds());
1306   EXPECT_EQ(gfx::Rect(0, 1000, 100, 100), v1->GetVisibleBounds());
1307 
1308   auto list = base::MakeRefCounted<cc::DisplayItemList>();
1309   ui::PaintContext context(list.get(), 1.f, gfx::Rect(), false);
1310 
1311   v1->Paint(PaintInfo::CreateRootPaintInfo(context, gfx::Size()));
1312   EXPECT_TRUE(v1->did_paint_);
1313 
1314   // Check that the canvas produced by |v1| for paint contains all of |v1|'s
1315   // visible bounds.
1316   EXPECT_TRUE(v1->canvas_bounds().Contains(v1->GetVisibleBounds()));
1317 }
1318 
OnDidSchedulePaint(const gfx::Rect & rect)1319 void TestView::OnDidSchedulePaint(const gfx::Rect& rect) {
1320   scheduled_paint_rects_.push_back(rect);
1321   View::OnDidSchedulePaint(rect);
1322 }
1323 
1324 namespace {
1325 
RotateCounterclockwise(gfx::Transform * transform)1326 void RotateCounterclockwise(gfx::Transform* transform) {
1327   // clang-format off
1328   transform->matrix().set3x3(0, -1, 0,
1329                              1,  0, 0,
1330                              0,  0, 1);
1331   // clang-format on
1332 }
1333 
RotateClockwise(gfx::Transform * transform)1334 void RotateClockwise(gfx::Transform* transform) {
1335   // clang-format off
1336   transform->matrix().set3x3( 0, 1, 0,  // NOLINT
1337                              -1, 0, 0,
1338                               0, 0, 1);
1339   // clang-format on
1340 }
1341 
1342 }  // namespace
1343 
1344 // Tests the correctness of the rect-based targeting algorithm implemented in
1345 // View::GetEventHandlerForRect(). See http://goo.gl/3Jp2BD for a description
1346 // of rect-based targeting.
TEST_F(ViewTest,GetEventHandlerForRect)1347 TEST_F(ViewTest, GetEventHandlerForRect) {
1348   Widget* widget = new Widget;
1349   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1350   widget->Init(std::move(params));
1351   View* root_view = widget->GetRootView();
1352   root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
1353 
1354   // Have this hierarchy of views (the coordinates here are all in
1355   // the root view's coordinate space):
1356   // v1 (0, 0, 100, 100)
1357   // v2 (150, 0, 250, 100)
1358   // v3 (0, 200, 150, 100)
1359   //     v31 (10, 210, 80, 80)
1360   //     v32 (110, 210, 30, 80)
1361   // v4 (300, 200, 100, 100)
1362   //     v41 (310, 210, 80, 80)
1363   //         v411 (370, 275, 10, 5)
1364   // v5 (450, 197, 30, 36)
1365   //     v51 (450, 200, 30, 30)
1366 
1367   // The coordinates used for SetBounds are in parent coordinates.
1368 
1369   TestView* v1 = new TestView;
1370   v1->SetBounds(0, 0, 100, 100);
1371   root_view->AddChildView(v1);
1372 
1373   TestView* v2 = new TestView;
1374   v2->SetBounds(150, 0, 250, 100);
1375   root_view->AddChildView(v2);
1376 
1377   TestView* v3 = new TestView;
1378   v3->SetBounds(0, 200, 150, 100);
1379   root_view->AddChildView(v3);
1380 
1381   TestView* v4 = new TestView;
1382   v4->SetBounds(300, 200, 100, 100);
1383   root_view->AddChildView(v4);
1384 
1385   TestView* v31 = new TestView;
1386   v31->SetBounds(10, 10, 80, 80);
1387   v3->AddChildView(v31);
1388 
1389   TestView* v32 = new TestView;
1390   v32->SetBounds(110, 10, 30, 80);
1391   v3->AddChildView(v32);
1392 
1393   TestView* v41 = new TestView;
1394   v41->SetBounds(10, 10, 80, 80);
1395   v4->AddChildView(v41);
1396 
1397   TestView* v411 = new TestView;
1398   v411->SetBounds(60, 65, 10, 5);
1399   v41->AddChildView(v411);
1400 
1401   TestView* v5 = new TestView;
1402   v5->SetBounds(450, 197, 30, 36);
1403   root_view->AddChildView(v5);
1404 
1405   TestView* v51 = new TestView;
1406   v51->SetBounds(0, 3, 30, 30);
1407   v5->AddChildView(v51);
1408 
1409   // |touch_rect| does not intersect any descendant view of |root_view|.
1410   gfx::Rect touch_rect(105, 105, 30, 45);
1411   View* result_view = root_view->GetEventHandlerForRect(touch_rect);
1412   EXPECT_EQ(root_view, result_view);
1413   result_view = nullptr;
1414 
1415   // Covers |v1| by at least 60%.
1416   touch_rect.SetRect(15, 15, 100, 100);
1417   result_view = root_view->GetEventHandlerForRect(touch_rect);
1418   EXPECT_EQ(v1, result_view);
1419   result_view = nullptr;
1420 
1421   // Intersects |v1| but does not cover it by at least 60%. The center
1422   // of |touch_rect| is within |v1|.
1423   touch_rect.SetRect(50, 50, 5, 10);
1424   result_view = root_view->GetEventHandlerForRect(touch_rect);
1425   EXPECT_EQ(v1, result_view);
1426   result_view = nullptr;
1427 
1428   // Intersects |v1| but does not cover it by at least 60%. The center
1429   // of |touch_rect| is not within |v1|.
1430   touch_rect.SetRect(95, 96, 21, 22);
1431   result_view = root_view->GetEventHandlerForRect(touch_rect);
1432   EXPECT_EQ(root_view, result_view);
1433   result_view = nullptr;
1434 
1435   // Intersects |v1| and |v2|, but only covers |v2| by at least 60%.
1436   touch_rect.SetRect(95, 10, 300, 120);
1437   result_view = root_view->GetEventHandlerForRect(touch_rect);
1438   EXPECT_EQ(v2, result_view);
1439   result_view = nullptr;
1440 
1441   // Covers both |v1| and |v2| by at least 60%, but the center point
1442   // of |touch_rect| is closer to the center point of |v2|.
1443   touch_rect.SetRect(20, 20, 400, 100);
1444   result_view = root_view->GetEventHandlerForRect(touch_rect);
1445   EXPECT_EQ(v2, result_view);
1446   result_view = nullptr;
1447 
1448   // Covers both |v1| and |v2| by at least 60%, but the center point
1449   // of |touch_rect| is closer to the center point of |v1|.
1450   touch_rect.SetRect(-700, -15, 1050, 110);
1451   result_view = root_view->GetEventHandlerForRect(touch_rect);
1452   EXPECT_EQ(v1, result_view);
1453   result_view = nullptr;
1454 
1455   // A mouse click within |v1| will target |v1|.
1456   touch_rect.SetRect(15, 15, 1, 1);
1457   result_view = root_view->GetEventHandlerForRect(touch_rect);
1458   EXPECT_EQ(v1, result_view);
1459   result_view = nullptr;
1460 
1461   // Intersects |v3| and |v31| by at least 60% and the center point
1462   // of |touch_rect| is closer to the center point of |v31|.
1463   touch_rect.SetRect(0, 200, 110, 100);
1464   result_view = root_view->GetEventHandlerForRect(touch_rect);
1465   EXPECT_EQ(v31, result_view);
1466   result_view = nullptr;
1467 
1468   // Intersects |v3| and |v31|, but neither by at least 60%. The
1469   // center point of |touch_rect| lies within |v31|.
1470   touch_rect.SetRect(80, 280, 15, 15);
1471   result_view = root_view->GetEventHandlerForRect(touch_rect);
1472   EXPECT_EQ(v31, result_view);
1473   result_view = nullptr;
1474 
1475   // Covers |v3|, |v31|, and |v32| all by at least 60%, and the
1476   // center point of |touch_rect| is closest to the center point
1477   // of |v32|.
1478   touch_rect.SetRect(0, 200, 200, 100);
1479   result_view = root_view->GetEventHandlerForRect(touch_rect);
1480   EXPECT_EQ(v32, result_view);
1481   result_view = nullptr;
1482 
1483   // Intersects all of |v3|, |v31|, and |v32|, but only covers
1484   // |v31| and |v32| by at least 60%. The center point of
1485   // |touch_rect| is closest to the center point of |v32|.
1486   touch_rect.SetRect(30, 225, 180, 115);
1487   result_view = root_view->GetEventHandlerForRect(touch_rect);
1488   EXPECT_EQ(v32, result_view);
1489   result_view = nullptr;
1490 
1491   // A mouse click at the corner of |v3| will target |v3|.
1492   touch_rect.SetRect(0, 200, 1, 1);
1493   result_view = root_view->GetEventHandlerForRect(touch_rect);
1494   EXPECT_EQ(v3, result_view);
1495   result_view = nullptr;
1496 
1497   // A mouse click within |v32| will target |v32|.
1498   touch_rect.SetRect(112, 211, 1, 1);
1499   result_view = root_view->GetEventHandlerForRect(touch_rect);
1500   EXPECT_EQ(v32, result_view);
1501   result_view = nullptr;
1502 
1503   // Covers all of |v4|, |v41|, and |v411| by at least 60%.
1504   // The center point of |touch_rect| is equally close to
1505   // the center points of |v4| and |v41|.
1506   touch_rect.SetRect(310, 210, 80, 80);
1507   result_view = root_view->GetEventHandlerForRect(touch_rect);
1508   EXPECT_EQ(v41, result_view);
1509   result_view = nullptr;
1510 
1511   // Intersects all of |v4|, |v41|, and |v411| but only covers
1512   // |v411| by at least 60%.
1513   touch_rect.SetRect(370, 275, 7, 5);
1514   result_view = root_view->GetEventHandlerForRect(touch_rect);
1515   EXPECT_EQ(v411, result_view);
1516   result_view = nullptr;
1517 
1518   // Intersects |v4| and |v41| but covers neither by at least 60%.
1519   // The center point of |touch_rect| is equally close to the center
1520   // points of |v4| and |v41|.
1521   touch_rect.SetRect(345, 245, 7, 7);
1522   result_view = root_view->GetEventHandlerForRect(touch_rect);
1523   EXPECT_EQ(v41, result_view);
1524   result_view = nullptr;
1525 
1526   // Intersects all of |v4|, |v41|, and |v411| and covers none of
1527   // them by at least 60%. The center point of |touch_rect| lies
1528   // within |v411|.
1529   touch_rect.SetRect(368, 272, 4, 6);
1530   result_view = root_view->GetEventHandlerForRect(touch_rect);
1531   EXPECT_EQ(v411, result_view);
1532   result_view = nullptr;
1533 
1534   // Intersects all of |v4|, |v41|, and |v411| and covers none of
1535   // them by at least 60%. The center point of |touch_rect| lies
1536   // within |v41|.
1537   touch_rect.SetRect(365, 270, 7, 7);
1538   result_view = root_view->GetEventHandlerForRect(touch_rect);
1539   EXPECT_EQ(v41, result_view);
1540   result_view = nullptr;
1541 
1542   // Intersects all of |v4|, |v41|, and |v411| and covers none of
1543   // them by at least 60%. The center point of |touch_rect| lies
1544   // within |v4|.
1545   touch_rect.SetRect(205, 275, 200, 2);
1546   result_view = root_view->GetEventHandlerForRect(touch_rect);
1547   EXPECT_EQ(v4, result_view);
1548   result_view = nullptr;
1549 
1550   // Intersects all of |v4|, |v41|, and |v411| but only covers
1551   // |v41| by at least 60%.
1552   touch_rect.SetRect(310, 210, 61, 66);
1553   result_view = root_view->GetEventHandlerForRect(touch_rect);
1554   EXPECT_EQ(v41, result_view);
1555   result_view = nullptr;
1556 
1557   // A mouse click within |v411| will target |v411|.
1558   touch_rect.SetRect(372, 275, 1, 1);
1559   result_view = root_view->GetEventHandlerForRect(touch_rect);
1560   EXPECT_EQ(v411, result_view);
1561   result_view = nullptr;
1562 
1563   // A mouse click within |v41| will target |v41|.
1564   touch_rect.SetRect(350, 215, 1, 1);
1565   result_view = root_view->GetEventHandlerForRect(touch_rect);
1566   EXPECT_EQ(v41, result_view);
1567   result_view = nullptr;
1568 
1569   // Covers |v3|, |v4|, and all of their descendants by at
1570   // least 60%. The center point of |touch_rect| is closest
1571   // to the center point of |v32|.
1572   touch_rect.SetRect(0, 200, 400, 100);
1573   result_view = root_view->GetEventHandlerForRect(touch_rect);
1574   EXPECT_EQ(v32, result_view);
1575   result_view = nullptr;
1576 
1577   // Intersects all of |v2|, |v3|, |v32|, |v4|, |v41|, and |v411|.
1578   // Covers |v2|, |v32|, |v4|, |v41|, and |v411| by at least 60%.
1579   // The center point of |touch_rect| is closest to the center
1580   // point of |root_view|.
1581   touch_rect.SetRect(110, 15, 375, 450);
1582   result_view = root_view->GetEventHandlerForRect(touch_rect);
1583   EXPECT_EQ(root_view, result_view);
1584   result_view = nullptr;
1585 
1586   // Covers all views (except |v5| and |v51|) by at least 60%. The
1587   // center point of |touch_rect| is equally close to the center
1588   // points of |v2| and |v32|. One is not a descendant of the other,
1589   // so in this case the view selected is arbitrary (i.e.,
1590   // it depends only on the ordering of nodes in the views
1591   // hierarchy).
1592   touch_rect.SetRect(0, 0, 400, 300);
1593   result_view = root_view->GetEventHandlerForRect(touch_rect);
1594   EXPECT_EQ(v32, result_view);
1595   result_view = nullptr;
1596 
1597   // Covers |v5| and |v51| by at least 60%, and the center point of
1598   // the touch is located within both views. Since both views share
1599   // the same center point, the child view should be selected.
1600   touch_rect.SetRect(440, 190, 40, 40);
1601   result_view = root_view->GetEventHandlerForRect(touch_rect);
1602   EXPECT_EQ(v51, result_view);
1603   result_view = nullptr;
1604 
1605   // Covers |v5| and |v51| by at least 60%, but the center point of
1606   // the touch is not located within either view. Since both views
1607   // share the same center point, the child view should be selected.
1608   touch_rect.SetRect(455, 187, 60, 60);
1609   result_view = root_view->GetEventHandlerForRect(touch_rect);
1610   EXPECT_EQ(v51, result_view);
1611   result_view = nullptr;
1612 
1613   // Covers neither |v5| nor |v51| by at least 60%, but the center
1614   // of the touch is located within |v51|.
1615   touch_rect.SetRect(450, 197, 10, 10);
1616   result_view = root_view->GetEventHandlerForRect(touch_rect);
1617   EXPECT_EQ(v51, result_view);
1618   result_view = nullptr;
1619 
1620   // Covers neither |v5| nor |v51| by at least 60% but intersects both.
1621   // The center point is located outside of both views.
1622   touch_rect.SetRect(433, 180, 24, 24);
1623   result_view = root_view->GetEventHandlerForRect(touch_rect);
1624   EXPECT_EQ(root_view, result_view);
1625   result_view = nullptr;
1626 
1627   // Only intersects |v5| but does not cover it by at least 60%. The
1628   // center point of the touch region is located within |v5|.
1629   touch_rect.SetRect(449, 196, 3, 3);
1630   result_view = root_view->GetEventHandlerForRect(touch_rect);
1631   EXPECT_EQ(v5, result_view);
1632   result_view = nullptr;
1633 
1634   // A mouse click within |v5| (but not |v51|) should target |v5|.
1635   touch_rect.SetRect(462, 199, 1, 1);
1636   result_view = root_view->GetEventHandlerForRect(touch_rect);
1637   EXPECT_EQ(v5, result_view);
1638   result_view = nullptr;
1639 
1640   // A mouse click |v5| and |v51| should target the child view.
1641   touch_rect.SetRect(452, 226, 1, 1);
1642   result_view = root_view->GetEventHandlerForRect(touch_rect);
1643   EXPECT_EQ(v51, result_view);
1644   result_view = nullptr;
1645 
1646   // A mouse click on the center of |v5| and |v51| should target
1647   // the child view.
1648   touch_rect.SetRect(465, 215, 1, 1);
1649   result_view = root_view->GetEventHandlerForRect(touch_rect);
1650   EXPECT_EQ(v51, result_view);
1651   result_view = nullptr;
1652 
1653   widget->CloseNow();
1654 }
1655 
1656 // Tests that GetEventHandlerForRect() and GetTooltipHandlerForPoint() behave
1657 // as expected when different views in the view hierarchy return false
1658 // when CanProcessEventsWithinSubtree() is called.
TEST_F(ViewTest,CanProcessEventsWithinSubtree)1659 TEST_F(ViewTest, CanProcessEventsWithinSubtree) {
1660   Widget* widget = new Widget;
1661   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1662   widget->Init(std::move(params));
1663   View* root_view = widget->GetRootView();
1664   root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
1665 
1666   // Have this hierarchy of views (the coords here are in the coordinate
1667   // space of the root view):
1668   // v (0, 0, 100, 100)
1669   //  - v_child (0, 0, 20, 30)
1670   //    - v_grandchild (5, 5, 5, 15)
1671 
1672   TestView* v = new TestView;
1673   v->SetBounds(0, 0, 100, 100);
1674   root_view->AddChildView(v);
1675   v->set_notify_enter_exit_on_child(true);
1676 
1677   TestView* v_child = new TestView;
1678   v_child->SetBounds(0, 0, 20, 30);
1679   v->AddChildView(v_child);
1680 
1681   TestView* v_grandchild = new TestView;
1682   v_grandchild->SetBounds(5, 5, 5, 15);
1683   v_child->AddChildView(v_grandchild);
1684 
1685   v->Reset();
1686   v_child->Reset();
1687   v_grandchild->Reset();
1688 
1689   // Define rects and points within the views in the hierarchy.
1690   gfx::Rect rect_in_v_grandchild(7, 7, 3, 3);
1691   gfx::Point point_in_v_grandchild(rect_in_v_grandchild.origin());
1692   gfx::Rect rect_in_v_child(12, 3, 5, 5);
1693   gfx::Point point_in_v_child(rect_in_v_child.origin());
1694   gfx::Rect rect_in_v(50, 50, 25, 30);
1695   gfx::Point point_in_v(rect_in_v.origin());
1696 
1697   // When all three views return true when CanProcessEventsWithinSubtree()
1698   // is called, targeting should behave as expected.
1699 
1700   View* result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1701   EXPECT_EQ(v_grandchild, result_view);
1702   result_view = nullptr;
1703   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1704   EXPECT_EQ(v_grandchild, result_view);
1705   result_view = nullptr;
1706 
1707   result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1708   EXPECT_EQ(v_child, result_view);
1709   result_view = nullptr;
1710   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1711   EXPECT_EQ(v_child, result_view);
1712   result_view = nullptr;
1713 
1714   result_view = root_view->GetEventHandlerForRect(rect_in_v);
1715   EXPECT_EQ(v, result_view);
1716   result_view = nullptr;
1717   result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1718   EXPECT_EQ(v, result_view);
1719   result_view = nullptr;
1720 
1721   // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
1722   // is called, then |v_grandchild| cannot be returned as a target.
1723 
1724   v_grandchild->set_can_process_events_within_subtree(false);
1725 
1726   result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1727   EXPECT_EQ(v_child, result_view);
1728   result_view = nullptr;
1729   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1730   EXPECT_EQ(v_child, result_view);
1731   result_view = nullptr;
1732 
1733   result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1734   EXPECT_EQ(v_child, result_view);
1735   result_view = nullptr;
1736   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1737   EXPECT_EQ(v_child, result_view);
1738   result_view = nullptr;
1739 
1740   result_view = root_view->GetEventHandlerForRect(rect_in_v);
1741   EXPECT_EQ(v, result_view);
1742   result_view = nullptr;
1743   result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1744   EXPECT_EQ(v, result_view);
1745 
1746   // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
1747   // is called, then NULL should be returned as a target if we call
1748   // GetTooltipHandlerForPoint() with |v_grandchild| as the root of the
1749   // views tree. Note that the location must be in the coordinate space
1750   // of the root view (|v_grandchild| in this case), so use (1, 1).
1751 
1752   result_view = v_grandchild;
1753   result_view = v_grandchild->GetTooltipHandlerForPoint(gfx::Point(1, 1));
1754   EXPECT_EQ(nullptr, result_view);
1755   result_view = nullptr;
1756 
1757   // When |v_child| returns false when CanProcessEventsWithinSubtree()
1758   // is called, then neither |v_child| nor |v_grandchild| can be returned
1759   // as a target (|v| should be returned as the target for each case).
1760 
1761   v_grandchild->Reset();
1762   v_child->set_can_process_events_within_subtree(false);
1763 
1764   result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1765   EXPECT_EQ(v, result_view);
1766   result_view = nullptr;
1767   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1768   EXPECT_EQ(v, result_view);
1769   result_view = nullptr;
1770 
1771   result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1772   EXPECT_EQ(v, result_view);
1773   result_view = nullptr;
1774   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1775   EXPECT_EQ(v, result_view);
1776   result_view = nullptr;
1777 
1778   result_view = root_view->GetEventHandlerForRect(rect_in_v);
1779   EXPECT_EQ(v, result_view);
1780   result_view = nullptr;
1781   result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1782   EXPECT_EQ(v, result_view);
1783   result_view = nullptr;
1784 
1785   // When |v| returns false when CanProcessEventsWithinSubtree()
1786   // is called, then none of |v|, |v_child|, and |v_grandchild| can be returned
1787   // as a target (|root_view| should be returned as the target for each case).
1788 
1789   v_child->Reset();
1790   v->set_can_process_events_within_subtree(false);
1791 
1792   result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1793   EXPECT_EQ(root_view, result_view);
1794   result_view = nullptr;
1795   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1796   EXPECT_EQ(root_view, result_view);
1797   result_view = nullptr;
1798 
1799   result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1800   EXPECT_EQ(root_view, result_view);
1801   result_view = nullptr;
1802   result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1803   EXPECT_EQ(root_view, result_view);
1804   result_view = nullptr;
1805 
1806   result_view = root_view->GetEventHandlerForRect(rect_in_v);
1807   EXPECT_EQ(root_view, result_view);
1808   result_view = nullptr;
1809   result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1810   EXPECT_EQ(root_view, result_view);
1811 
1812   widget->CloseNow();
1813 }
1814 
TEST_F(ViewTest,NotifyEnterExitOnChild)1815 TEST_F(ViewTest, NotifyEnterExitOnChild) {
1816   Widget* widget = new Widget;
1817   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1818   widget->Init(std::move(params));
1819   View* root_view = widget->GetRootView();
1820   root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
1821 
1822   // Have this hierarchy of views (the coords here are in root coord):
1823   // v1 (0, 0, 100, 100)
1824   //  - v11 (0, 0, 20, 30)
1825   //    - v111 (5, 5, 5, 15)
1826   //  - v12 (50, 10, 30, 90)
1827   //    - v121 (60, 20, 10, 10)
1828   // v2 (105, 0, 100, 100)
1829   //  - v21 (120, 10, 50, 20)
1830 
1831   TestView* v1 = new TestView;
1832   v1->SetBounds(0, 0, 100, 100);
1833   root_view->AddChildView(v1);
1834   v1->set_notify_enter_exit_on_child(true);
1835 
1836   TestView* v11 = new TestView;
1837   v11->SetBounds(0, 0, 20, 30);
1838   v1->AddChildView(v11);
1839 
1840   TestView* v111 = new TestView;
1841   v111->SetBounds(5, 5, 5, 15);
1842   v11->AddChildView(v111);
1843 
1844   TestView* v12 = new TestView;
1845   v12->SetBounds(50, 10, 30, 90);
1846   v1->AddChildView(v12);
1847 
1848   TestView* v121 = new TestView;
1849   v121->SetBounds(10, 10, 10, 10);
1850   v12->AddChildView(v121);
1851 
1852   TestView* v2 = new TestView;
1853   v2->SetBounds(105, 0, 100, 100);
1854   root_view->AddChildView(v2);
1855 
1856   TestView* v21 = new TestView;
1857   v21->SetBounds(15, 10, 50, 20);
1858   v2->AddChildView(v21);
1859 
1860   v1->Reset();
1861   v11->Reset();
1862   v111->Reset();
1863   v12->Reset();
1864   v121->Reset();
1865   v2->Reset();
1866   v21->Reset();
1867 
1868   // Move the mouse in v111.
1869   gfx::Point p1(6, 6);
1870   ui::MouseEvent move1(ui::ET_MOUSE_MOVED, p1, p1, ui::EventTimeForNow(), 0, 0);
1871   root_view->OnMouseMoved(move1);
1872   EXPECT_TRUE(v111->received_mouse_enter_);
1873   EXPECT_FALSE(v11->last_mouse_event_type_);
1874   EXPECT_TRUE(v1->received_mouse_enter_);
1875 
1876   v111->Reset();
1877   v1->Reset();
1878 
1879   // Now, move into v121.
1880   gfx::Point p2(65, 21);
1881   ui::MouseEvent move2(ui::ET_MOUSE_MOVED, p2, p2, ui::EventTimeForNow(), 0, 0);
1882   root_view->OnMouseMoved(move2);
1883   EXPECT_TRUE(v111->received_mouse_exit_);
1884   EXPECT_TRUE(v121->received_mouse_enter_);
1885   EXPECT_FALSE(v1->last_mouse_event_type_);
1886 
1887   v111->Reset();
1888   v121->Reset();
1889 
1890   // Now, move into v11.
1891   gfx::Point p3(1, 1);
1892   ui::MouseEvent move3(ui::ET_MOUSE_MOVED, p3, p3, ui::EventTimeForNow(), 0, 0);
1893   root_view->OnMouseMoved(move3);
1894   EXPECT_TRUE(v121->received_mouse_exit_);
1895   EXPECT_TRUE(v11->received_mouse_enter_);
1896   EXPECT_FALSE(v1->last_mouse_event_type_);
1897 
1898   v121->Reset();
1899   v11->Reset();
1900 
1901   // Move to v21.
1902   gfx::Point p4(121, 15);
1903   ui::MouseEvent move4(ui::ET_MOUSE_MOVED, p4, p4, ui::EventTimeForNow(), 0, 0);
1904   root_view->OnMouseMoved(move4);
1905   EXPECT_TRUE(v21->received_mouse_enter_);
1906   EXPECT_FALSE(v2->last_mouse_event_type_);
1907   EXPECT_TRUE(v11->received_mouse_exit_);
1908   EXPECT_TRUE(v1->received_mouse_exit_);
1909 
1910   v21->Reset();
1911   v11->Reset();
1912   v1->Reset();
1913 
1914   // Move to v1.
1915   gfx::Point p5(21, 0);
1916   ui::MouseEvent move5(ui::ET_MOUSE_MOVED, p5, p5, ui::EventTimeForNow(), 0, 0);
1917   root_view->OnMouseMoved(move5);
1918   EXPECT_TRUE(v21->received_mouse_exit_);
1919   EXPECT_TRUE(v1->received_mouse_enter_);
1920 
1921   v21->Reset();
1922   v1->Reset();
1923 
1924   // Now, move into v11.
1925   gfx::Point p6(15, 15);
1926   ui::MouseEvent mouse6(ui::ET_MOUSE_MOVED, p6, p6, ui::EventTimeForNow(), 0,
1927                         0);
1928   root_view->OnMouseMoved(mouse6);
1929   EXPECT_TRUE(v11->received_mouse_enter_);
1930   EXPECT_FALSE(v1->last_mouse_event_type_);
1931 
1932   v11->Reset();
1933   v1->Reset();
1934 
1935   // Move back into v1. Although |v1| had already received an ENTER for mouse6,
1936   // and the mouse remains inside |v1| the whole time, it receives another ENTER
1937   // when the mouse leaves v11.
1938   gfx::Point p7(21, 0);
1939   ui::MouseEvent mouse7(ui::ET_MOUSE_MOVED, p7, p7, ui::EventTimeForNow(), 0,
1940                         0);
1941   root_view->OnMouseMoved(mouse7);
1942   EXPECT_TRUE(v11->received_mouse_exit_);
1943   EXPECT_FALSE(v1->received_mouse_enter_);
1944 
1945   widget->CloseNow();
1946 }
1947 
TEST_F(ViewTest,Textfield)1948 TEST_F(ViewTest, Textfield) {
1949   const base::string16 kText = ASCIIToUTF16(
1950       "Reality is that which, when you stop believing it, doesn't go away.");
1951   const base::string16 kExtraText = ASCIIToUTF16("Pretty deep, Philip!");
1952 
1953   Widget* widget = new Widget;
1954   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1955   params.bounds = gfx::Rect(0, 0, 100, 100);
1956   widget->Init(std::move(params));
1957   View* root_view = widget->GetRootView();
1958 
1959   Textfield* textfield = new Textfield();
1960   root_view->AddChildView(textfield);
1961 
1962   // Test setting, appending text.
1963   textfield->SetText(kText);
1964   EXPECT_EQ(kText, textfield->GetText());
1965   textfield->AppendText(kExtraText);
1966   EXPECT_EQ(kText + kExtraText, textfield->GetText());
1967   textfield->SetText(base::string16());
1968   EXPECT_TRUE(textfield->GetText().empty());
1969 
1970   // Test selection related methods.
1971   textfield->SetText(kText);
1972   EXPECT_TRUE(textfield->GetSelectedText().empty());
1973   textfield->SelectAll(false);
1974   EXPECT_EQ(kText, textfield->GetText());
1975   textfield->ClearSelection();
1976   EXPECT_TRUE(textfield->GetSelectedText().empty());
1977 
1978   widget->CloseNow();
1979 }
1980 
1981 // Tests that the Textfield view respond appropiately to cut/copy/paste.
TEST_F(ViewTest,TextfieldCutCopyPaste)1982 TEST_F(ViewTest, TextfieldCutCopyPaste) {
1983   const base::string16 kNormalText = ASCIIToUTF16("Normal");
1984   const base::string16 kReadOnlyText = ASCIIToUTF16("Read only");
1985   const base::string16 kPasswordText =
1986       ASCIIToUTF16("Password! ** Secret stuff **");
1987 
1988   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1989 
1990   Widget* widget = new Widget;
1991   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1992   params.bounds = gfx::Rect(0, 0, 100, 100);
1993   widget->Init(std::move(params));
1994   View* root_view = widget->GetRootView();
1995 
1996   Textfield* normal = new Textfield();
1997   Textfield* read_only = new Textfield();
1998   read_only->SetReadOnly(true);
1999   Textfield* password = new Textfield();
2000   password->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
2001 
2002   root_view->AddChildView(normal);
2003   root_view->AddChildView(read_only);
2004   root_view->AddChildView(password);
2005 
2006   normal->SetText(kNormalText);
2007   read_only->SetText(kReadOnlyText);
2008   password->SetText(kPasswordText);
2009 
2010   //
2011   // Test cut.
2012   //
2013 
2014   normal->SelectAll(false);
2015   normal->ExecuteCommand(IDS_APP_CUT, 0);
2016   base::string16 result;
2017   clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
2018   EXPECT_EQ(kNormalText, result);
2019   normal->SetText(kNormalText);  // Let's revert to the original content.
2020 
2021   read_only->SelectAll(false);
2022   read_only->ExecuteCommand(IDS_APP_CUT, 0);
2023   result.clear();
2024   clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
2025   // Cut should have failed, so the clipboard content should not have changed.
2026   EXPECT_EQ(kNormalText, result);
2027 
2028   password->SelectAll(false);
2029   password->ExecuteCommand(IDS_APP_CUT, 0);
2030   result.clear();
2031   clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
2032   // Cut should have failed, so the clipboard content should not have changed.
2033   EXPECT_EQ(kNormalText, result);
2034 
2035   //
2036   // Test copy.
2037   //
2038 
2039   // Start with |read_only| to observe a change in clipboard text.
2040   read_only->SelectAll(false);
2041   read_only->ExecuteCommand(IDS_APP_COPY, 0);
2042   result.clear();
2043   clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
2044   EXPECT_EQ(kReadOnlyText, result);
2045 
2046   normal->SelectAll(false);
2047   normal->ExecuteCommand(IDS_APP_COPY, 0);
2048   result.clear();
2049   clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
2050   EXPECT_EQ(kNormalText, result);
2051 
2052   password->SelectAll(false);
2053   password->ExecuteCommand(IDS_APP_COPY, 0);
2054   result.clear();
2055   clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
2056   // Text cannot be copied from an obscured field; the clipboard won't change.
2057   EXPECT_EQ(kNormalText, result);
2058 
2059   //
2060   // Test paste.
2061   //
2062 
2063   // Attempting to paste kNormalText in a read-only text-field should fail.
2064   read_only->SelectAll(false);
2065   read_only->ExecuteCommand(IDS_APP_PASTE, 0);
2066   EXPECT_EQ(kReadOnlyText, read_only->GetText());
2067 
2068   password->SelectAll(false);
2069   password->ExecuteCommand(IDS_APP_PASTE, 0);
2070   EXPECT_EQ(kNormalText, password->GetText());
2071 
2072   // Copy from |read_only| to observe a change in the normal textfield text.
2073   read_only->SelectAll(false);
2074   read_only->ExecuteCommand(IDS_APP_COPY, 0);
2075   normal->SelectAll(false);
2076   normal->ExecuteCommand(IDS_APP_PASTE, 0);
2077   EXPECT_EQ(kReadOnlyText, normal->GetText());
2078   widget->CloseNow();
2079 }
2080 
2081 class ViewPaintOptimizationTest : public ViewsTestBase {
2082  public:
2083   ViewPaintOptimizationTest() = default;
2084 
2085   ~ViewPaintOptimizationTest() override = default;
2086 
SetUp()2087   void SetUp() override {
2088     scoped_feature_list_.InitAndEnableFeature(
2089         views::features::kEnableViewPaintOptimization);
2090     ViewTest::SetUp();
2091   }
2092 
2093  private:
2094   base::test::ScopedFeatureList scoped_feature_list_;
2095 
2096   DISALLOW_COPY_AND_ASSIGN(ViewPaintOptimizationTest);
2097 };
2098 
2099 // Tests that only Views where SchedulePaint was invoked get repainted.
TEST_F(ViewPaintOptimizationTest,PaintDirtyViewsOnly)2100 TEST_F(ViewPaintOptimizationTest, PaintDirtyViewsOnly) {
2101   ScopedTestPaintWidget widget(CreateParams(Widget::InitParams::TYPE_POPUP));
2102   View* root_view = widget->GetRootView();
2103 
2104   TestView* v1 = root_view->AddChildView(std::make_unique<TestView>());
2105   v1->SetBounds(10, 11, 12, 13);
2106 
2107   TestView* v2 = root_view->AddChildView(std::make_unique<TestView>());
2108   v2->SetBounds(3, 4, 6, 5);
2109 
2110   TestView* v21 = v2->AddChildView(std::make_unique<TestView>());
2111   v21->SetBounds(2, 3, 4, 5);
2112 
2113   // Paint everything once, since it has to build its cache. Then we can test
2114   // invalidation.
2115   gfx::Rect first_paint(1, 1);
2116   auto list = base::MakeRefCounted<cc::DisplayItemList>();
2117   root_view->Paint(PaintInfo::CreateRootPaintInfo(
2118       ui::PaintContext(list.get(), 1.f, first_paint, false),
2119       root_view->size()));
2120   v1->Reset();
2121   v2->Reset();
2122   v21->Reset();
2123 
2124   gfx::Rect paint_area(10, 11, 12, 13);
2125   list = base::MakeRefCounted<cc::DisplayItemList>();
2126 
2127   // Schedule a paint on v2 which marks it invalidated.
2128   v2->SchedulePaint();
2129   EXPECT_FALSE(v1->did_paint_);
2130   EXPECT_FALSE(v2->did_paint_);
2131   EXPECT_FALSE(v21->did_paint_);
2132 
2133   // Paint with an unknown invalidation. The invalidation is irrelevant since
2134   // repainting a view only depends on whether the view had a scheduled paint.
2135   gfx::Rect empty_rect;
2136   EXPECT_TRUE(empty_rect.IsEmpty());
2137 
2138   root_view->Paint(PaintInfo::CreateRootPaintInfo(
2139       ui::PaintContext(list.get(), 1.f, paint_area, false), empty_rect.size()));
2140 
2141   // Only v2 should be repainted.
2142   EXPECT_FALSE(v1->did_paint_);
2143   EXPECT_TRUE(v2->did_paint_);
2144   EXPECT_FALSE(v21->did_paint_);
2145 }
2146 
2147 ////////////////////////////////////////////////////////////////////////////////
2148 // Accelerators
2149 ////////////////////////////////////////////////////////////////////////////////
AcceleratorPressed(const ui::Accelerator & accelerator)2150 bool TestView::AcceleratorPressed(const ui::Accelerator& accelerator) {
2151   accelerator_count_map_[accelerator]++;
2152   return true;
2153 }
2154 
2155 namespace {
2156 
2157 // A Widget with a TestView in the view hierarchy. Used for accelerator tests.
2158 class TestViewWidget {
2159  public:
TestViewWidget(Widget::InitParams create_params,ui::Accelerator * initial_accelerator,bool show_after_init=true)2160   TestViewWidget(Widget::InitParams create_params,
2161                  ui::Accelerator* initial_accelerator,
2162                  bool show_after_init = true)
2163       : view_(new TestView) {
2164     view_->Reset();
2165 
2166     // Register a keyboard accelerator before the view is added to a window.
2167     if (initial_accelerator) {
2168       view_->AddAccelerator(*initial_accelerator);
2169       EXPECT_EQ(view_->accelerator_count_map_[*initial_accelerator], 0);
2170     }
2171 
2172     // Create a window and add the view as its child.
2173     Widget::InitParams params = std::move(create_params);
2174     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2175     params.bounds = gfx::Rect(0, 0, 100, 100);
2176     widget_.Init(std::move(params));
2177     View* root = widget_.GetRootView();
2178     root->AddChildView(view_);
2179     if (show_after_init)
2180       widget_.Show();
2181 
2182     EXPECT_TRUE(widget_.GetFocusManager());
2183   }
2184 
view()2185   TestView* view() { return view_; }
widget()2186   Widget* widget() { return &widget_; }
2187 
2188  private:
2189   TestView* view_;
2190   Widget widget_;
2191 
2192   DISALLOW_COPY_AND_ASSIGN(TestViewWidget);
2193 };
2194 
2195 }  // namespace
2196 
2197 // On non-ChromeOS aura there is extra logic to determine whether a view should
2198 // handle accelerators or not (see View::CanHandleAccelerators for details).
2199 // This test targets that extra logic, but should also work on other platforms.
TEST_F(ViewTest,HandleAccelerator)2200 TEST_F(ViewTest, HandleAccelerator) {
2201   ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
2202   TestViewWidget test_widget(CreateParams(Widget::InitParams::TYPE_POPUP),
2203                              &return_accelerator);
2204   TestView* view = test_widget.view();
2205   Widget* widget = test_widget.widget();
2206   FocusManager* focus_manager = widget->GetFocusManager();
2207 
2208 #if BUILDFLAG(ENABLE_DESKTOP_AURA)
2209   // When a non-child view is not active, it shouldn't handle accelerators.
2210   EXPECT_FALSE(widget->IsActive());
2211   EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
2212   EXPECT_EQ(0, view->accelerator_count_map_[return_accelerator]);
2213 #endif
2214 
2215   // TYPE_POPUP widgets default to non-activatable, so the Show() above wouldn't
2216   // have activated the Widget. First, allow activation.
2217   widget->widget_delegate()->SetCanActivate(true);
2218 
2219   // When a non-child view is active, it should handle accelerators.
2220   view->accelerator_count_map_[return_accelerator] = 0;
2221   widget->Activate();
2222   EXPECT_TRUE(widget->IsActive());
2223   EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
2224   EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]);
2225 
2226   // Add a child view associated with a child widget.
2227   TestView* child_view = new TestView();
2228   child_view->Reset();
2229   child_view->AddAccelerator(return_accelerator);
2230   EXPECT_EQ(child_view->accelerator_count_map_[return_accelerator], 0);
2231   Widget* child_widget = new Widget;
2232   Widget::InitParams child_params =
2233       CreateParams(Widget::InitParams::TYPE_CONTROL);
2234   child_params.parent = widget->GetNativeView();
2235   child_widget->Init(std::move(child_params));
2236   child_widget->SetContentsView(child_view);
2237 
2238   FocusManager* child_focus_manager = child_widget->GetFocusManager();
2239   ASSERT_TRUE(child_focus_manager);
2240 
2241   // When a child view is in focus, it should handle accelerators.
2242   child_view->accelerator_count_map_[return_accelerator] = 0;
2243   view->accelerator_count_map_[return_accelerator] = 0;
2244   child_focus_manager->SetFocusedView(child_view);
2245   EXPECT_FALSE(child_view->GetWidget()->IsActive());
2246   EXPECT_TRUE(child_focus_manager->ProcessAccelerator(return_accelerator));
2247   EXPECT_EQ(1, child_view->accelerator_count_map_[return_accelerator]);
2248   EXPECT_EQ(0, view->accelerator_count_map_[return_accelerator]);
2249 
2250 #if BUILDFLAG(ENABLE_DESKTOP_AURA)
2251   // When a child view is not in focus, its parent should handle accelerators.
2252   child_view->accelerator_count_map_[return_accelerator] = 0;
2253   view->accelerator_count_map_[return_accelerator] = 0;
2254   child_focus_manager->ClearFocus();
2255   EXPECT_FALSE(child_view->GetWidget()->IsActive());
2256   EXPECT_TRUE(child_focus_manager->ProcessAccelerator(return_accelerator));
2257   EXPECT_EQ(0, child_view->accelerator_count_map_[return_accelerator]);
2258   EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]);
2259 #endif
2260 }
2261 
2262 // TODO(themblsha): Bring this up on non-Mac platforms. It currently fails
2263 // because TestView::AcceleratorPressed() is not called. See
2264 // http://crbug.com/667757.
2265 #if defined(OS_MACOSX)
2266 // Test that BridgedContentView correctly handles Accelerator key events when
2267 // subject to OS event dispatch.
TEST_F(ViewTest,ActivateAcceleratorOnMac)2268 TEST_F(ViewTest, ActivateAcceleratorOnMac) {
2269   // Cmd+1 translates to "noop:" command by interpretKeyEvents.
2270   ui::Accelerator command_accelerator(ui::VKEY_1, ui::EF_COMMAND_DOWN);
2271   TestViewWidget test_widget(CreateParams(Widget::InitParams::TYPE_POPUP),
2272                              &command_accelerator);
2273   TestView* view = test_widget.view();
2274 
2275   ui::test::EventGenerator event_generator(
2276       test_widget.widget()->GetNativeWindow());
2277   // Emulate normal event dispatch through -[NSWindow sendEvent:].
2278   event_generator.set_target(ui::test::EventGenerator::Target::WINDOW);
2279 
2280   event_generator.PressKey(command_accelerator.key_code(),
2281                            command_accelerator.modifiers());
2282   event_generator.ReleaseKey(command_accelerator.key_code(),
2283                              command_accelerator.modifiers());
2284   EXPECT_EQ(view->accelerator_count_map_[command_accelerator], 1);
2285 
2286   // Without an _wantsKeyDownForEvent: override we'll only get a keyUp: event
2287   // for this accelerator.
2288   ui::Accelerator key_up_accelerator(ui::VKEY_TAB,
2289                                      ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
2290   view->AddAccelerator(key_up_accelerator);
2291   event_generator.PressKey(key_up_accelerator.key_code(),
2292                            key_up_accelerator.modifiers());
2293   event_generator.ReleaseKey(key_up_accelerator.key_code(),
2294                              key_up_accelerator.modifiers());
2295   EXPECT_EQ(view->accelerator_count_map_[key_up_accelerator], 1);
2296 
2297   // We should handle this accelerator inside keyDown: as it doesn't translate
2298   // to any command by default.
2299   ui::Accelerator key_down_accelerator(
2300       ui::VKEY_L, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN | ui::EF_SHIFT_DOWN);
2301   view->AddAccelerator(key_down_accelerator);
2302   event_generator.PressKey(key_down_accelerator.key_code(),
2303                            key_down_accelerator.modifiers());
2304   event_generator.ReleaseKey(key_down_accelerator.key_code(),
2305                              key_down_accelerator.modifiers());
2306   EXPECT_EQ(view->accelerator_count_map_[key_down_accelerator], 1);
2307 }
2308 #endif  // OS_MACOSX
2309 
2310 // TODO(crbug.com/667757): these tests were initially commented out when getting
2311 // aura to run. Figure out if still valuable and either nuke or fix.
2312 #if defined(OS_MACOSX)
TEST_F(ViewTest,ActivateAccelerator)2313 TEST_F(ViewTest, ActivateAccelerator) {
2314   ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
2315   TestViewWidget test_widget(CreateParams(Widget::InitParams::TYPE_POPUP),
2316                              &return_accelerator);
2317   TestView* view = test_widget.view();
2318   FocusManager* focus_manager = test_widget.widget()->GetFocusManager();
2319 
2320   // Hit the return key and see if it takes effect.
2321   EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
2322   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
2323 
2324   // Hit the escape key. Nothing should happen.
2325   ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, ui::EF_NONE);
2326   EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator));
2327   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
2328   EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 0);
2329 
2330   // Now register the escape key and hit it again.
2331   view->AddAccelerator(escape_accelerator);
2332   EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
2333   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
2334   EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1);
2335 
2336   // Remove the return key accelerator.
2337   view->RemoveAccelerator(return_accelerator);
2338   EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
2339   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
2340   EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1);
2341 
2342   // Add it again. Hit the return key and the escape key.
2343   view->AddAccelerator(return_accelerator);
2344   EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
2345   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
2346   EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1);
2347   EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
2348   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
2349   EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2);
2350 
2351   // Remove all the accelerators.
2352   view->ResetAccelerators();
2353   EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
2354   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
2355   EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2);
2356   EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator));
2357   EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
2358   EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2);
2359 }
2360 
TEST_F(ViewTest,HiddenViewWithAccelerator)2361 TEST_F(ViewTest, HiddenViewWithAccelerator) {
2362   ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
2363   TestViewWidget test_widget(CreateParams(Widget::InitParams::TYPE_POPUP),
2364                              &return_accelerator);
2365   TestView* view = test_widget.view();
2366   FocusManager* focus_manager = test_widget.widget()->GetFocusManager();
2367 
2368   view->SetVisible(false);
2369   EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
2370 
2371   view->SetVisible(true);
2372   EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
2373 }
2374 
TEST_F(ViewTest,ViewInHiddenWidgetWithAccelerator)2375 TEST_F(ViewTest, ViewInHiddenWidgetWithAccelerator) {
2376   ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
2377   TestViewWidget test_widget(CreateParams(Widget::InitParams::TYPE_POPUP),
2378                              &return_accelerator, false);
2379   TestView* view = test_widget.view();
2380   Widget* widget = test_widget.widget();
2381   FocusManager* focus_manager = test_widget.widget()->GetFocusManager();
2382 
2383   EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
2384   EXPECT_EQ(0, view->accelerator_count_map_[return_accelerator]);
2385 
2386   widget->Show();
2387   EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
2388   EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]);
2389 
2390   widget->Hide();
2391   EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
2392   EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]);
2393 }
2394 #endif  // OS_MACOSX
2395 
2396 // TODO(crbug.com/667757): these tests were initially commented out when getting
2397 // aura to run. Figure out if still valuable and either nuke or fix.
2398 #if 0
2399 ////////////////////////////////////////////////////////////////////////////////
2400 // Mouse-wheel message rerouting
2401 ////////////////////////////////////////////////////////////////////////////////
2402 class ScrollableTestView : public View {
2403  public:
2404   ScrollableTestView() { }
2405 
2406   virtual gfx::Size GetPreferredSize() {
2407     return gfx::Size(100, 10000);
2408   }
2409 
2410   virtual void Layout() {
2411     SizeToPreferredSize();
2412   }
2413 };
2414 
2415 class TestViewWithControls : public View {
2416  public:
2417   TestViewWithControls() {
2418     text_field_ = new Textfield();
2419     AddChildView(text_field_);
2420   }
2421 
2422   Textfield* text_field_;
2423 };
2424 
2425 class SimpleWidgetDelegate : public WidgetDelegate {
2426  public:
2427   explicit SimpleWidgetDelegate(View* contents) : contents_(contents) {  }
2428 
2429   virtual void DeleteDelegate() { delete this; }
2430 
2431   virtual View* GetContentsView() { return contents_; }
2432 
2433   virtual Widget* GetWidget() { return contents_->GetWidget(); }
2434   virtual const Widget* GetWidget() const { return contents_->GetWidget(); }
2435 
2436  private:
2437   View* contents_;
2438 };
2439 
2440 // Tests that the mouse-wheel messages are correctly rerouted to the window
2441 // under the mouse.
2442 // TODO(jcampan): http://crbug.com/10572 Disabled as it fails on the Vista build
2443 //                bot.
2444 // Note that this fails for a variety of reasons:
2445 // - focused view is apparently reset across window activations and never
2446 //   properly restored
2447 // - this test depends on you not having any other window visible open under the
2448 //   area that it opens the test windows. --beng
2449 TEST_F(ViewTest, DISABLED_RerouteMouseWheelTest) {
2450   TestViewWithControls* view_with_controls = new TestViewWithControls();
2451   Widget* window1 = Widget::CreateWindowWithBounds(
2452       new SimpleWidgetDelegate(view_with_controls),
2453       gfx::Rect(0, 0, 100, 100));
2454   window1->Show();
2455   ScrollView* scroll_view = new ScrollView();
2456   scroll_view->SetContents(new ScrollableTestView());
2457   Widget* window2 = Widget::CreateWindowWithBounds(
2458       new SimpleWidgetDelegate(scroll_view),
2459       gfx::Rect(200, 200, 100, 100));
2460   window2->Show();
2461   EXPECT_EQ(0, scroll_view->GetVisibleRect().y());
2462 
2463   // Make the window1 active, as this is what it would be in real-world.
2464   window1->Activate();
2465 
2466   // Let's send a mouse-wheel message to the different controls and check that
2467   // it is rerouted to the window under the mouse (effectively scrolling the
2468   // scroll-view).
2469 
2470   // First to the Window's HWND.
2471   ::SendMessage(view_with_controls->GetWidget()->GetNativeView(),
2472                 WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250));
2473   EXPECT_EQ(20, scroll_view->GetVisibleRect().y());
2474 
2475   window1->CloseNow();
2476   window2->CloseNow();
2477 }
2478 #endif  // 0
2479 
2480 ////////////////////////////////////////////////////////////////////////////////
2481 // Native view hierachy
2482 ////////////////////////////////////////////////////////////////////////////////
2483 class ToplevelWidgetObserverView : public View {
2484  public:
2485   ToplevelWidgetObserverView() = default;
2486   ~ToplevelWidgetObserverView() override = default;
2487 
2488   // View overrides:
ViewHierarchyChanged(const ViewHierarchyChangedDetails & details)2489   void ViewHierarchyChanged(
2490       const ViewHierarchyChangedDetails& details) override {
2491     if (details.is_add) {
2492       toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : nullptr;
2493     } else {
2494       toplevel_ = nullptr;
2495     }
2496   }
NativeViewHierarchyChanged()2497   void NativeViewHierarchyChanged() override {
2498     toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : nullptr;
2499   }
2500 
toplevel()2501   Widget* toplevel() { return toplevel_; }
2502 
2503  private:
2504   Widget* toplevel_ = nullptr;
2505 
2506   DISALLOW_COPY_AND_ASSIGN(ToplevelWidgetObserverView);
2507 };
2508 
2509 // Test that a view can track the current top level widget by overriding
2510 // View::ViewHierarchyChanged() and View::NativeViewHierarchyChanged().
TEST_F(ViewTest,NativeViewHierarchyChanged)2511 TEST_F(ViewTest, NativeViewHierarchyChanged) {
2512   std::unique_ptr<Widget> toplevel1(new Widget);
2513   Widget::InitParams toplevel1_params =
2514       CreateParams(Widget::InitParams::TYPE_POPUP);
2515   toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2516   toplevel1->Init(std::move(toplevel1_params));
2517 
2518   std::unique_ptr<Widget> toplevel2(new Widget);
2519   Widget::InitParams toplevel2_params =
2520       CreateParams(Widget::InitParams::TYPE_POPUP);
2521   toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2522   toplevel2->Init(std::move(toplevel2_params));
2523 
2524   Widget* child = new Widget;
2525   Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL);
2526   child_params.parent = toplevel1->GetNativeView();
2527   child->Init(std::move(child_params));
2528 
2529   ToplevelWidgetObserverView* observer_view = new ToplevelWidgetObserverView();
2530   EXPECT_EQ(nullptr, observer_view->toplevel());
2531 
2532   child->SetContentsView(observer_view);
2533   EXPECT_EQ(toplevel1.get(), observer_view->toplevel());
2534 
2535   Widget::ReparentNativeView(child->GetNativeView(),
2536                              toplevel2->GetNativeView());
2537   EXPECT_EQ(toplevel2.get(), observer_view->toplevel());
2538 
2539   observer_view->parent()->RemoveChildView(observer_view);
2540   EXPECT_EQ(nullptr, observer_view->toplevel());
2541 
2542   // Make |observer_view| |child|'s contents view again so that it gets deleted
2543   // with the widget.
2544   child->SetContentsView(observer_view);
2545 }
2546 
2547 ////////////////////////////////////////////////////////////////////////////////
2548 // Transformations
2549 ////////////////////////////////////////////////////////////////////////////////
2550 
2551 class TransformPaintView : public TestView {
2552  public:
2553   TransformPaintView() = default;
2554   ~TransformPaintView() override = default;
2555 
ClearScheduledPaintRect()2556   void ClearScheduledPaintRect() { scheduled_paint_rect_ = gfx::Rect(); }
2557 
scheduled_paint_rect() const2558   gfx::Rect scheduled_paint_rect() const { return scheduled_paint_rect_; }
2559 
2560   // Overridden from View:
OnDidSchedulePaint(const gfx::Rect & rect)2561   void OnDidSchedulePaint(const gfx::Rect& rect) override {
2562     gfx::Rect xrect = ConvertRectToParent(rect);
2563     scheduled_paint_rect_.Union(xrect);
2564   }
2565 
2566  private:
2567   gfx::Rect scheduled_paint_rect_;
2568 
2569   DISALLOW_COPY_AND_ASSIGN(TransformPaintView);
2570 };
2571 
TEST_F(ViewTest,TransformPaint)2572 TEST_F(ViewTest, TransformPaint) {
2573   TransformPaintView* v1 = new TransformPaintView();
2574   v1->SetBoundsRect(gfx::Rect(0, 0, 500, 300));
2575 
2576   TestView* v2 = new TestView();
2577   v2->SetBoundsRect(gfx::Rect(100, 100, 200, 100));
2578 
2579   Widget* widget = new Widget;
2580   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2581   params.bounds = gfx::Rect(50, 50, 650, 650);
2582   widget->Init(std::move(params));
2583   widget->Show();
2584   View* root = widget->GetRootView();
2585 
2586   root->AddChildView(v1);
2587   v1->AddChildView(v2);
2588 
2589   // At this moment, |v2| occupies (100, 100) to (300, 200) in |root|.
2590   v1->ClearScheduledPaintRect();
2591   v2->SchedulePaint();
2592 
2593   EXPECT_EQ(gfx::Rect(100, 100, 200, 100), v1->scheduled_paint_rect());
2594 
2595   // Rotate |v1| counter-clockwise.
2596   gfx::Transform transform;
2597   RotateCounterclockwise(&transform);
2598   transform.matrix().set(1, 3, 500.0);
2599   v1->SetTransform(transform);
2600 
2601   // |v2| now occupies (100, 200) to (200, 400) in |root|.
2602 
2603   v1->ClearScheduledPaintRect();
2604   v2->SchedulePaint();
2605 
2606   EXPECT_EQ(gfx::Rect(100, 200, 100, 200), v1->scheduled_paint_rect());
2607 
2608   widget->CloseNow();
2609 }
2610 
TEST_F(ViewTest,TransformEvent)2611 TEST_F(ViewTest, TransformEvent) {
2612   TestView* v1 = new TestView();
2613   v1->SetBoundsRect(gfx::Rect(0, 0, 500, 300));
2614 
2615   TestView* v2 = new TestView();
2616   v2->SetBoundsRect(gfx::Rect(100, 100, 200, 100));
2617 
2618   Widget* widget = new Widget;
2619   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2620   params.bounds = gfx::Rect(50, 50, 650, 650);
2621   widget->Init(std::move(params));
2622   View* root = widget->GetRootView();
2623 
2624   root->AddChildView(v1);
2625   v1->AddChildView(v2);
2626 
2627   // At this moment, |v2| occupies (100, 100) to (300, 200) in |root|.
2628 
2629   // Rotate |v1| counter-clockwise.
2630   gfx::Transform transform(v1->GetTransform());
2631   RotateCounterclockwise(&transform);
2632   transform.matrix().set(1, 3, 500.0);
2633   v1->SetTransform(transform);
2634 
2635   // |v2| now occupies (100, 200) to (200, 400) in |root|.
2636   v1->Reset();
2637   v2->Reset();
2638 
2639   gfx::Point p1(110, 210);
2640   ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, ui::EventTimeForNow(),
2641                          ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2642   root->OnMousePressed(pressed);
2643   EXPECT_EQ(0, v1->last_mouse_event_type_);
2644   EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
2645   EXPECT_EQ(190, v2->location_.x());
2646   EXPECT_EQ(10, v2->location_.y());
2647 
2648   ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
2649                           ui::EventTimeForNow(), 0, 0);
2650   root->OnMouseReleased(released);
2651 
2652   // Now rotate |v2| inside |v1| clockwise.
2653   transform = v2->GetTransform();
2654   RotateClockwise(&transform);
2655   transform.matrix().set(0, 3, 100.f);
2656   v2->SetTransform(transform);
2657 
2658   // Now, |v2| occupies (100, 100) to (200, 300) in |v1|, and (100, 300) to
2659   // (300, 400) in |root|.
2660 
2661   v1->Reset();
2662   v2->Reset();
2663 
2664   gfx::Point point2(110, 320);
2665   ui::MouseEvent p2(ui::ET_MOUSE_PRESSED, point2, point2, ui::EventTimeForNow(),
2666                     ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2667   root->OnMousePressed(p2);
2668   EXPECT_EQ(0, v1->last_mouse_event_type_);
2669   EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
2670   EXPECT_EQ(10, v2->location_.x());
2671   EXPECT_EQ(20, v2->location_.y());
2672 
2673   root->OnMouseReleased(released);
2674 
2675   v1->SetTransform(gfx::Transform());
2676   v2->SetTransform(gfx::Transform());
2677 
2678   TestView* v3 = new TestView();
2679   v3->SetBoundsRect(gfx::Rect(10, 10, 20, 30));
2680   v2->AddChildView(v3);
2681 
2682   // Rotate |v3| clockwise with respect to |v2|.
2683   transform = v1->GetTransform();
2684   RotateClockwise(&transform);
2685   transform.matrix().set(0, 3, 30.f);
2686   v3->SetTransform(transform);
2687 
2688   // Scale |v2| with respect to |v1| along both axis.
2689   transform = v2->GetTransform();
2690   transform.matrix().set(0, 0, 0.8f);
2691   transform.matrix().set(1, 1, 0.5f);
2692   v2->SetTransform(transform);
2693 
2694   // |v3| occupies (108, 105) to (132, 115) in |root|.
2695 
2696   v1->Reset();
2697   v2->Reset();
2698   v3->Reset();
2699 
2700   gfx::Point point(112, 110);
2701   ui::MouseEvent p3(ui::ET_MOUSE_PRESSED, point, point, ui::EventTimeForNow(),
2702                     ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2703   root->OnMousePressed(p3);
2704 
2705   EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
2706   EXPECT_EQ(10, v3->location_.x());
2707   EXPECT_EQ(25, v3->location_.y());
2708 
2709   root->OnMouseReleased(released);
2710 
2711   v1->SetTransform(gfx::Transform());
2712   v2->SetTransform(gfx::Transform());
2713   v3->SetTransform(gfx::Transform());
2714 
2715   v1->Reset();
2716   v2->Reset();
2717   v3->Reset();
2718 
2719   // Rotate |v3| clockwise with respect to |v2|, and scale it along both axis.
2720   transform = v3->GetTransform();
2721   RotateClockwise(&transform);
2722   transform.matrix().set(0, 3, 30.f);
2723   // Rotation sets some scaling transformation. Using SetScale would overwrite
2724   // that and pollute the rotation. So combine the scaling with the existing
2725   // transforamtion.
2726   gfx::Transform scale;
2727   scale.Scale(0.8f, 0.5f);
2728   transform.ConcatTransform(scale);
2729   v3->SetTransform(transform);
2730 
2731   // Translate |v2| with respect to |v1|.
2732   transform = v2->GetTransform();
2733   transform.matrix().set(0, 3, 10.f);
2734   transform.matrix().set(1, 3, 10.f);
2735   v2->SetTransform(transform);
2736 
2737   // |v3| now occupies (120, 120) to (144, 130) in |root|.
2738 
2739   gfx::Point point3(124, 125);
2740   ui::MouseEvent p4(ui::ET_MOUSE_PRESSED, point3, point3, ui::EventTimeForNow(),
2741                     ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2742   root->OnMousePressed(p4);
2743 
2744   EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
2745   EXPECT_EQ(10, v3->location_.x());
2746   EXPECT_EQ(25, v3->location_.y());
2747 
2748   root->OnMouseReleased(released);
2749 
2750   widget->CloseNow();
2751 }
2752 
TEST_F(ViewTest,TransformVisibleBound)2753 TEST_F(ViewTest, TransformVisibleBound) {
2754   gfx::Rect viewport_bounds(0, 0, 100, 100);
2755 
2756   std::unique_ptr<Widget> widget(new Widget);
2757   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2758   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2759   params.bounds = viewport_bounds;
2760   widget->Init(std::move(params));
2761   widget->GetRootView()->SetBoundsRect(viewport_bounds);
2762 
2763   View* viewport = new View;
2764   widget->SetContentsView(viewport);
2765   View* contents = new View;
2766   viewport->AddChildView(contents);
2767   viewport->SetBoundsRect(viewport_bounds);
2768   contents->SetBoundsRect(gfx::Rect(0, 0, 100, 200));
2769 
2770   View* child = new View;
2771   contents->AddChildView(child);
2772   child->SetBoundsRect(gfx::Rect(10, 90, 50, 50));
2773   EXPECT_EQ(gfx::Rect(0, 0, 50, 10), child->GetVisibleBounds());
2774 
2775   // Rotate |child| counter-clockwise
2776   gfx::Transform transform;
2777   RotateCounterclockwise(&transform);
2778   transform.matrix().set(1, 3, 50.f);
2779   child->SetTransform(transform);
2780   EXPECT_EQ(gfx::Rect(40, 0, 10, 50), child->GetVisibleBounds());
2781 
2782   widget->CloseNow();
2783 }
2784 
2785 ////////////////////////////////////////////////////////////////////////////////
2786 // OnVisibleBoundsChanged()
2787 
2788 class VisibleBoundsView : public View {
2789  public:
2790   VisibleBoundsView() = default;
2791   ~VisibleBoundsView() override = default;
2792 
received_notification() const2793   bool received_notification() const { return received_notification_; }
set_received_notification(bool received)2794   void set_received_notification(bool received) {
2795     received_notification_ = received;
2796   }
2797 
2798  private:
2799   // Overridden from View:
GetNeedsNotificationWhenVisibleBoundsChange() const2800   bool GetNeedsNotificationWhenVisibleBoundsChange() const override {
2801     return true;
2802   }
OnVisibleBoundsChanged()2803   void OnVisibleBoundsChanged() override { received_notification_ = true; }
2804 
2805   bool received_notification_ = false;
2806 
2807   DISALLOW_COPY_AND_ASSIGN(VisibleBoundsView);
2808 };
2809 
TEST_F(ViewTest,OnVisibleBoundsChanged)2810 TEST_F(ViewTest, OnVisibleBoundsChanged) {
2811   gfx::Rect viewport_bounds(0, 0, 100, 100);
2812 
2813   std::unique_ptr<Widget> widget(new Widget);
2814   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2815   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2816   params.bounds = viewport_bounds;
2817   widget->Init(std::move(params));
2818   widget->GetRootView()->SetBoundsRect(viewport_bounds);
2819 
2820   View* viewport = new View;
2821   widget->SetContentsView(viewport);
2822   View* contents = new View;
2823   viewport->AddChildView(contents);
2824   viewport->SetBoundsRect(viewport_bounds);
2825   contents->SetBoundsRect(gfx::Rect(0, 0, 100, 200));
2826 
2827   // Create a view that cares about visible bounds notifications, and position
2828   // it just outside the visible bounds of the viewport.
2829   VisibleBoundsView* child = new VisibleBoundsView;
2830   contents->AddChildView(child);
2831   child->SetBoundsRect(gfx::Rect(10, 110, 50, 50));
2832 
2833   // The child bound should be fully clipped.
2834   EXPECT_TRUE(child->GetVisibleBounds().IsEmpty());
2835 
2836   // Now scroll the contents, but not enough to make the child visible.
2837   contents->SetY(contents->y() - 1);
2838 
2839   // We should have received the notification since the visible bounds may have
2840   // changed (even though they didn't).
2841   EXPECT_TRUE(child->received_notification());
2842   EXPECT_TRUE(child->GetVisibleBounds().IsEmpty());
2843   child->set_received_notification(false);
2844 
2845   // Now scroll the contents, this time by enough to make the child visible by
2846   // one pixel.
2847   contents->SetY(contents->y() - 10);
2848   EXPECT_TRUE(child->received_notification());
2849   EXPECT_EQ(1, child->GetVisibleBounds().height());
2850   child->set_received_notification(false);
2851 
2852   widget->CloseNow();
2853 }
2854 
TEST_F(ViewTest,SetBoundsPaint)2855 TEST_F(ViewTest, SetBoundsPaint) {
2856   TestView top_view;
2857   TestView* child_view = new TestView;
2858 
2859   top_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2860   top_view.scheduled_paint_rects_.clear();
2861   child_view->SetBoundsRect(gfx::Rect(10, 10, 20, 20));
2862   top_view.AddChildView(child_view);
2863 
2864   top_view.scheduled_paint_rects_.clear();
2865   child_view->SetBoundsRect(gfx::Rect(30, 30, 20, 20));
2866   EXPECT_EQ(2U, top_view.scheduled_paint_rects_.size());
2867 
2868   // There should be 2 rects, spanning from (10, 10) to (50, 50).
2869   gfx::Rect paint_rect = top_view.scheduled_paint_rects_[0];
2870   paint_rect.Union(top_view.scheduled_paint_rects_[1]);
2871   EXPECT_EQ(gfx::Rect(10, 10, 40, 40), paint_rect);
2872 }
2873 
2874 // Assertions around painting and focus gain/lost.
TEST_F(ViewTest,FocusBlurPaints)2875 TEST_F(ViewTest, FocusBlurPaints) {
2876   TestView parent_view;
2877   TestView* child_view1 = new TestView;  // Owned by |parent_view|.
2878 
2879   parent_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2880 
2881   child_view1->SetBoundsRect(gfx::Rect(0, 0, 20, 20));
2882   parent_view.AddChildView(child_view1);
2883 
2884   parent_view.scheduled_paint_rects_.clear();
2885   child_view1->scheduled_paint_rects_.clear();
2886 
2887   // Focus change shouldn't trigger paints.
2888   child_view1->DoFocus();
2889 
2890   EXPECT_TRUE(parent_view.scheduled_paint_rects_.empty());
2891   EXPECT_TRUE(child_view1->scheduled_paint_rects_.empty());
2892 
2893   child_view1->DoBlur();
2894   EXPECT_TRUE(parent_view.scheduled_paint_rects_.empty());
2895   EXPECT_TRUE(child_view1->scheduled_paint_rects_.empty());
2896 }
2897 
2898 // Verifies SetBounds(same bounds) doesn't trigger a SchedulePaint().
TEST_F(ViewTest,SetBoundsSameBoundsDoesntSchedulePaint)2899 TEST_F(ViewTest, SetBoundsSameBoundsDoesntSchedulePaint) {
2900   TestView view;
2901 
2902   view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2903   view.InvalidateLayout();
2904   view.scheduled_paint_rects_.clear();
2905   view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2906   EXPECT_TRUE(view.scheduled_paint_rects_.empty());
2907 }
2908 
2909 // Verifies AddChildView() and RemoveChildView() schedule appropriate paints.
TEST_F(ViewTest,AddAndRemoveSchedulePaints)2910 TEST_F(ViewTest, AddAndRemoveSchedulePaints) {
2911   gfx::Rect viewport_bounds(0, 0, 100, 100);
2912 
2913   // We have to put the View hierarchy into a Widget or no paints will be
2914   // scheduled.
2915   std::unique_ptr<Widget> widget(new Widget);
2916   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2917   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2918   params.bounds = viewport_bounds;
2919   widget->Init(std::move(params));
2920   widget->GetRootView()->SetBoundsRect(viewport_bounds);
2921 
2922   TestView* parent_view = new TestView;
2923   widget->SetContentsView(parent_view);
2924   parent_view->SetBoundsRect(viewport_bounds);
2925   parent_view->scheduled_paint_rects_.clear();
2926 
2927   View* child_view = new View;
2928   child_view->SetBoundsRect(gfx::Rect(0, 0, 20, 20));
2929   parent_view->AddChildView(child_view);
2930   ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size());
2931   EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front());
2932 
2933   parent_view->scheduled_paint_rects_.clear();
2934   parent_view->RemoveChildView(child_view);
2935   std::unique_ptr<View> child_deleter(child_view);
2936   ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size());
2937   EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front());
2938 
2939   widget->CloseNow();
2940 }
2941 
2942 // Tests conversion methods with a transform.
TEST_F(ViewTest,ConversionsWithTransform)2943 TEST_F(ViewTest, ConversionsWithTransform) {
2944   TestView top_view;
2945 
2946   // View hierarchy used to test scale transforms.
2947   TestView* child = new TestView;
2948   TestView* child_child = new TestView;
2949 
2950   // View used to test a rotation transform.
2951   TestView* child_2 = new TestView;
2952 
2953   top_view.AddChildView(child);
2954   child->AddChildView(child_child);
2955 
2956   top_view.SetBoundsRect(gfx::Rect(0, 0, 1000, 1000));
2957 
2958   child->SetBoundsRect(gfx::Rect(7, 19, 500, 500));
2959   gfx::Transform transform;
2960   transform.Scale(3.0, 4.0);
2961   child->SetTransform(transform);
2962 
2963   child_child->SetBoundsRect(gfx::Rect(17, 13, 100, 100));
2964   transform.MakeIdentity();
2965   transform.Scale(5.0, 7.0);
2966   child_child->SetTransform(transform);
2967 
2968   top_view.AddChildView(child_2);
2969   child_2->SetBoundsRect(gfx::Rect(700, 725, 100, 100));
2970   transform.MakeIdentity();
2971   RotateClockwise(&transform);
2972   child_2->SetTransform(transform);
2973 
2974   // Sanity check to make sure basic transforms act as expected.
2975   {
2976     gfx::Transform transform;
2977     transform.Translate(110.0, -110.0);
2978     transform.Scale(100.0, 55.0);
2979     transform.Translate(1.0, 1.0);
2980 
2981     // convert to a 3x3 matrix.
2982     const SkMatrix& matrix = SkMatrix(transform.matrix());
2983 
2984     EXPECT_EQ(210, matrix.getTranslateX());
2985     EXPECT_EQ(-55, matrix.getTranslateY());
2986     EXPECT_EQ(100, matrix.getScaleX());
2987     EXPECT_EQ(55, matrix.getScaleY());
2988     EXPECT_EQ(0, matrix.getSkewX());
2989     EXPECT_EQ(0, matrix.getSkewY());
2990   }
2991 
2992   {
2993     gfx::Transform transform;
2994     transform.Translate(1.0, 1.0);
2995     gfx::Transform t2;
2996     t2.Scale(100.0, 55.0);
2997     gfx::Transform t3;
2998     t3.Translate(110.0, -110.0);
2999     transform.ConcatTransform(t2);
3000     transform.ConcatTransform(t3);
3001 
3002     // convert to a 3x3 matrix
3003     const SkMatrix& matrix = SkMatrix(transform.matrix());
3004 
3005     EXPECT_EQ(210, matrix.getTranslateX());
3006     EXPECT_EQ(-55, matrix.getTranslateY());
3007     EXPECT_EQ(100, matrix.getScaleX());
3008     EXPECT_EQ(55, matrix.getScaleY());
3009     EXPECT_EQ(0, matrix.getSkewX());
3010     EXPECT_EQ(0, matrix.getSkewY());
3011   }
3012 
3013   // Conversions from child->top and top->child.
3014   {
3015     gfx::Point point(5, 5);
3016     View::ConvertPointToTarget(child, &top_view, &point);
3017     EXPECT_EQ(22, point.x());
3018     EXPECT_EQ(39, point.y());
3019 
3020     gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f);
3021     View::ConvertRectToTarget(child, &top_view, &rect);
3022     EXPECT_FLOAT_EQ(22.0f, rect.x());
3023     EXPECT_FLOAT_EQ(39.0f, rect.y());
3024     EXPECT_FLOAT_EQ(30.0f, rect.width());
3025     EXPECT_FLOAT_EQ(80.0f, rect.height());
3026 
3027     point.SetPoint(22, 39);
3028     View::ConvertPointToTarget(&top_view, child, &point);
3029     EXPECT_EQ(5, point.x());
3030     EXPECT_EQ(5, point.y());
3031 
3032     rect.SetRect(22.0f, 39.0f, 30.0f, 80.0f);
3033     View::ConvertRectToTarget(&top_view, child, &rect);
3034     EXPECT_FLOAT_EQ(5.0f, rect.x());
3035     EXPECT_FLOAT_EQ(5.0f, rect.y());
3036     EXPECT_FLOAT_EQ(10.0f, rect.width());
3037     EXPECT_FLOAT_EQ(20.0f, rect.height());
3038   }
3039 
3040   // Conversions from child_child->top and top->child_child.
3041   {
3042     gfx::Point point(5, 5);
3043     View::ConvertPointToTarget(child_child, &top_view, &point);
3044     EXPECT_EQ(133, point.x());
3045     EXPECT_EQ(211, point.y());
3046 
3047     gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f);
3048     View::ConvertRectToTarget(child_child, &top_view, &rect);
3049     EXPECT_FLOAT_EQ(133.0f, rect.x());
3050     EXPECT_FLOAT_EQ(211.0f, rect.y());
3051     EXPECT_FLOAT_EQ(150.0f, rect.width());
3052     EXPECT_FLOAT_EQ(560.0f, rect.height());
3053 
3054     point.SetPoint(133, 211);
3055     View::ConvertPointToTarget(&top_view, child_child, &point);
3056     EXPECT_EQ(5, point.x());
3057     EXPECT_EQ(5, point.y());
3058 
3059     rect.SetRect(133.0f, 211.0f, 150.0f, 560.0f);
3060     View::ConvertRectToTarget(&top_view, child_child, &rect);
3061     EXPECT_FLOAT_EQ(5.0f, rect.x());
3062     EXPECT_FLOAT_EQ(5.0f, rect.y());
3063     EXPECT_FLOAT_EQ(10.0f, rect.width());
3064     EXPECT_FLOAT_EQ(20.0f, rect.height());
3065   }
3066 
3067   // Conversions from child_child->child and child->child_child
3068   {
3069     gfx::Point point(5, 5);
3070     View::ConvertPointToTarget(child_child, child, &point);
3071     EXPECT_EQ(42, point.x());
3072     EXPECT_EQ(48, point.y());
3073 
3074     gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f);
3075     View::ConvertRectToTarget(child_child, child, &rect);
3076     EXPECT_FLOAT_EQ(42.0f, rect.x());
3077     EXPECT_FLOAT_EQ(48.0f, rect.y());
3078     EXPECT_FLOAT_EQ(50.0f, rect.width());
3079     EXPECT_FLOAT_EQ(140.0f, rect.height());
3080 
3081     point.SetPoint(42, 48);
3082     View::ConvertPointToTarget(child, child_child, &point);
3083     EXPECT_EQ(5, point.x());
3084     EXPECT_EQ(5, point.y());
3085 
3086     rect.SetRect(42.0f, 48.0f, 50.0f, 140.0f);
3087     View::ConvertRectToTarget(child, child_child, &rect);
3088     EXPECT_FLOAT_EQ(5.0f, rect.x());
3089     EXPECT_FLOAT_EQ(5.0f, rect.y());
3090     EXPECT_FLOAT_EQ(10.0f, rect.width());
3091     EXPECT_FLOAT_EQ(20.0f, rect.height());
3092   }
3093 
3094   // Conversions from top_view to child with a value that should be negative.
3095   // This ensures we don't round up with negative numbers.
3096   {
3097     gfx::Point point(6, 18);
3098     View::ConvertPointToTarget(&top_view, child, &point);
3099     EXPECT_EQ(-1, point.x());
3100     EXPECT_EQ(-1, point.y());
3101 
3102     float error = 0.01f;
3103     gfx::RectF rect(6.0f, 18.0f, 10.0f, 39.0f);
3104     View::ConvertRectToTarget(&top_view, child, &rect);
3105     EXPECT_NEAR(-0.33f, rect.x(), error);
3106     EXPECT_NEAR(-0.25f, rect.y(), error);
3107     EXPECT_NEAR(3.33f, rect.width(), error);
3108     EXPECT_NEAR(9.75f, rect.height(), error);
3109   }
3110 
3111   // Rect conversions from top_view->child_2 and child_2->top_view.
3112   {
3113     gfx::RectF rect(50.0f, 55.0f, 20.0f, 30.0f);
3114     View::ConvertRectToTarget(child_2, &top_view, &rect);
3115     EXPECT_FLOAT_EQ(615.0f, rect.x());
3116     EXPECT_FLOAT_EQ(775.0f, rect.y());
3117     EXPECT_FLOAT_EQ(30.0f, rect.width());
3118     EXPECT_FLOAT_EQ(20.0f, rect.height());
3119 
3120     rect.SetRect(615.0f, 775.0f, 30.0f, 20.0f);
3121     View::ConvertRectToTarget(&top_view, child_2, &rect);
3122     EXPECT_FLOAT_EQ(50.0f, rect.x());
3123     EXPECT_FLOAT_EQ(55.0f, rect.y());
3124     EXPECT_FLOAT_EQ(20.0f, rect.width());
3125     EXPECT_FLOAT_EQ(30.0f, rect.height());
3126   }
3127 }
3128 
3129 // Tests conversion methods to and from screen coordinates.
TEST_F(ViewTest,ConversionsToFromScreen)3130 TEST_F(ViewTest, ConversionsToFromScreen) {
3131   std::unique_ptr<Widget> widget(new Widget);
3132   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3133   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3134   params.bounds = gfx::Rect(50, 50, 650, 650);
3135   widget->Init(std::move(params));
3136 
3137   View* child = new View;
3138   widget->GetRootView()->AddChildView(child);
3139   child->SetBounds(10, 10, 100, 200);
3140   gfx::Transform t;
3141   t.Scale(0.5, 0.5);
3142   child->SetTransform(t);
3143 
3144   gfx::Size size(10, 10);
3145   gfx::Point point_in_screen(100, 90);
3146   gfx::Point point_in_child(80, 60);
3147   gfx::Rect rect_in_screen(point_in_screen, size);
3148   gfx::Rect rect_in_child(point_in_child, size);
3149 
3150   gfx::Point point = point_in_screen;
3151   View::ConvertPointFromScreen(child, &point);
3152   EXPECT_EQ(point_in_child.ToString(), point.ToString());
3153 
3154   View::ConvertPointToScreen(child, &point);
3155   EXPECT_EQ(point_in_screen.ToString(), point.ToString());
3156 
3157   View::ConvertRectToScreen(child, &rect_in_child);
3158   EXPECT_EQ(rect_in_screen.ToString(), rect_in_child.ToString());
3159 }
3160 
3161 // Tests conversion methods for rectangles.
TEST_F(ViewTest,ConvertRectWithTransform)3162 TEST_F(ViewTest, ConvertRectWithTransform) {
3163   std::unique_ptr<Widget> widget(new Widget);
3164   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3165   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3166   params.bounds = gfx::Rect(50, 50, 650, 650);
3167   widget->Init(std::move(params));
3168   View* root = widget->GetRootView();
3169 
3170   TestView* v1 = new TestView;
3171   TestView* v2 = new TestView;
3172   root->AddChildView(v1);
3173   v1->AddChildView(v2);
3174 
3175   v1->SetBoundsRect(gfx::Rect(10, 10, 500, 500));
3176   v2->SetBoundsRect(gfx::Rect(20, 20, 100, 200));
3177 
3178   // |v2| now occupies (30, 30) to (130, 230) in |widget|
3179   gfx::Rect rect(5, 5, 15, 40);
3180   EXPECT_EQ(gfx::Rect(25, 25, 15, 40), v2->ConvertRectToParent(rect));
3181   EXPECT_EQ(gfx::Rect(35, 35, 15, 40), v2->ConvertRectToWidget(rect));
3182 
3183   // Rotate |v2|
3184   gfx::Transform t2;
3185   RotateCounterclockwise(&t2);
3186   t2.matrix().set(1, 3, 100.f);
3187   v2->SetTransform(t2);
3188 
3189   // |v2| now occupies (30, 30) to (230, 130) in |widget|
3190   EXPECT_EQ(gfx::Rect(25, 100, 40, 15), v2->ConvertRectToParent(rect));
3191   EXPECT_EQ(gfx::Rect(35, 110, 40, 15), v2->ConvertRectToWidget(rect));
3192 
3193   // Scale down |v1|
3194   gfx::Transform t1;
3195   t1.Scale(0.5, 0.5);
3196   v1->SetTransform(t1);
3197 
3198   // The rectangle should remain the same for |v1|.
3199   EXPECT_EQ(gfx::Rect(25, 100, 40, 15), v2->ConvertRectToParent(rect));
3200 
3201   // |v2| now occupies (20, 20) to (120, 70) in |widget|
3202   EXPECT_EQ(gfx::Rect(22, 60, 21, 8).ToString(),
3203             v2->ConvertRectToWidget(rect).ToString());
3204 
3205   widget->CloseNow();
3206 }
3207 
3208 class ObserverView : public View {
3209  public:
3210   ObserverView();
3211   ~ObserverView() override;
3212 
3213   void ResetTestState();
3214 
has_add_details() const3215   bool has_add_details() const { return has_add_details_; }
has_remove_details() const3216   bool has_remove_details() const { return has_remove_details_; }
3217 
add_details() const3218   const ViewHierarchyChangedDetails& add_details() const {
3219     return add_details_;
3220   }
3221 
remove_details() const3222   const ViewHierarchyChangedDetails& remove_details() const {
3223     return remove_details_;
3224   }
3225 
3226  private:
3227   // View:
3228   void ViewHierarchyChanged(
3229       const ViewHierarchyChangedDetails& details) override;
3230 
3231   bool has_add_details_ = false;
3232   bool has_remove_details_ = false;
3233   ViewHierarchyChangedDetails add_details_;
3234   ViewHierarchyChangedDetails remove_details_;
3235 
3236   DISALLOW_COPY_AND_ASSIGN(ObserverView);
3237 };
3238 
3239 ObserverView::ObserverView() = default;
3240 
3241 ObserverView::~ObserverView() = default;
3242 
ResetTestState()3243 void ObserverView::ResetTestState() {
3244   has_add_details_ = false;
3245   has_remove_details_ = false;
3246   add_details_ = ViewHierarchyChangedDetails();
3247   remove_details_ = ViewHierarchyChangedDetails();
3248 }
3249 
ViewHierarchyChanged(const ViewHierarchyChangedDetails & details)3250 void ObserverView::ViewHierarchyChanged(
3251     const ViewHierarchyChangedDetails& details) {
3252   if (details.is_add) {
3253     has_add_details_ = true;
3254     add_details_ = details;
3255   } else {
3256     has_remove_details_ = true;
3257     remove_details_ = details;
3258   }
3259 }
3260 
3261 // Verifies that the ViewHierarchyChanged() notification is sent correctly when
3262 // a child view is added or removed to all the views in the hierarchy (up and
3263 // down).
3264 // The tree looks like this:
3265 // v1
3266 // +-- v2
3267 //     +-- v3
3268 //     +-- v4 (starts here, then get reparented to v1)
TEST_F(ViewTest,ViewHierarchyChanged)3269 TEST_F(ViewTest, ViewHierarchyChanged) {
3270   ObserverView v1;
3271 
3272   ObserverView* v3 = new ObserverView();
3273 
3274   // Add |v3| to |v2|.
3275   std::unique_ptr<ObserverView> v2(new ObserverView());
3276   v2->AddChildView(v3);
3277 
3278   // Make sure both |v2| and |v3| receive the ViewHierarchyChanged()
3279   // notification.
3280   EXPECT_TRUE(v2->has_add_details());
3281   EXPECT_FALSE(v2->has_remove_details());
3282   EXPECT_EQ(v2.get(), v2->add_details().parent);
3283   EXPECT_EQ(v3, v2->add_details().child);
3284   EXPECT_EQ(nullptr, v2->add_details().move_view);
3285 
3286   EXPECT_TRUE(v3->has_add_details());
3287   EXPECT_FALSE(v3->has_remove_details());
3288   EXPECT_EQ(v2.get(), v3->add_details().parent);
3289   EXPECT_EQ(v3, v3->add_details().child);
3290   EXPECT_EQ(nullptr, v3->add_details().move_view);
3291 
3292   // Reset everything to the initial state.
3293   v2->ResetTestState();
3294   v3->ResetTestState();
3295 
3296   // Add |v2| to v1.
3297   v1.AddChildView(v2.get());
3298 
3299   // Verifies that |v2| is the child view *added* and the parent view is |v1|.
3300   // Make sure all the views (v1, v2, v3) received _that_ information.
3301   EXPECT_TRUE(v1.has_add_details());
3302   EXPECT_FALSE(v1.has_remove_details());
3303   EXPECT_EQ(&v1, v1.add_details().parent);
3304   EXPECT_EQ(v2.get(), v1.add_details().child);
3305   EXPECT_EQ(nullptr, v1.add_details().move_view);
3306 
3307   EXPECT_TRUE(v2->has_add_details());
3308   EXPECT_FALSE(v2->has_remove_details());
3309   EXPECT_EQ(&v1, v2->add_details().parent);
3310   EXPECT_EQ(v2.get(), v2->add_details().child);
3311   EXPECT_EQ(nullptr, v2->add_details().move_view);
3312 
3313   EXPECT_TRUE(v3->has_add_details());
3314   EXPECT_FALSE(v3->has_remove_details());
3315   EXPECT_EQ(&v1, v3->add_details().parent);
3316   EXPECT_EQ(v2.get(), v3->add_details().child);
3317   EXPECT_EQ(nullptr, v3->add_details().move_view);
3318 
3319   // Reset everything to the initial state.
3320   v1.ResetTestState();
3321   v2->ResetTestState();
3322   v3->ResetTestState();
3323 
3324   // Remove |v2| from |v1|.
3325   v1.RemoveChildView(v2.get());
3326 
3327   // Verifies that |v2| is the child view *removed* and the parent view is |v1|.
3328   // Make sure all the views (v1, v2, v3) received _that_ information.
3329   EXPECT_FALSE(v1.has_add_details());
3330   EXPECT_TRUE(v1.has_remove_details());
3331   EXPECT_EQ(&v1, v1.remove_details().parent);
3332   EXPECT_EQ(v2.get(), v1.remove_details().child);
3333   EXPECT_EQ(nullptr, v1.remove_details().move_view);
3334 
3335   EXPECT_FALSE(v2->has_add_details());
3336   EXPECT_TRUE(v2->has_remove_details());
3337   EXPECT_EQ(&v1, v2->remove_details().parent);
3338   EXPECT_EQ(v2.get(), v2->remove_details().child);
3339   EXPECT_EQ(nullptr, v2->remove_details().move_view);
3340 
3341   EXPECT_FALSE(v3->has_add_details());
3342   EXPECT_TRUE(v3->has_remove_details());
3343   EXPECT_EQ(&v1, v3->remove_details().parent);
3344   EXPECT_EQ(v3, v3->remove_details().child);
3345   EXPECT_EQ(nullptr, v3->remove_details().move_view);
3346 
3347   // Verifies notifications when reparenting a view.
3348   ObserverView* v4 = new ObserverView();
3349   // Add |v4| to |v2|.
3350   v2->AddChildView(v4);
3351 
3352   // Reset everything to the initial state.
3353   v1.ResetTestState();
3354   v2->ResetTestState();
3355   v3->ResetTestState();
3356   v4->ResetTestState();
3357 
3358   // Reparent |v4| to |v1|.
3359   v1.AddChildView(v4);
3360 
3361   // Verifies that all views receive the correct information for all the child,
3362   // parent and move views.
3363 
3364   // |v1| is the new parent, |v4| is the child for add, |v2| is the old parent.
3365   EXPECT_TRUE(v1.has_add_details());
3366   EXPECT_FALSE(v1.has_remove_details());
3367   EXPECT_EQ(&v1, v1.add_details().parent);
3368   EXPECT_EQ(v4, v1.add_details().child);
3369   EXPECT_EQ(v2.get(), v1.add_details().move_view);
3370 
3371   // |v2| is the old parent, |v4| is the child for remove, |v1| is the new
3372   // parent.
3373   EXPECT_FALSE(v2->has_add_details());
3374   EXPECT_TRUE(v2->has_remove_details());
3375   EXPECT_EQ(v2.get(), v2->remove_details().parent);
3376   EXPECT_EQ(v4, v2->remove_details().child);
3377   EXPECT_EQ(&v1, v2->remove_details().move_view);
3378 
3379   // |v3| is not impacted by this operation, and hence receives no notification.
3380   EXPECT_FALSE(v3->has_add_details());
3381   EXPECT_FALSE(v3->has_remove_details());
3382 
3383   // |v4| is the reparented child, so it receives notifications for the remove
3384   // and then the add.  |v2| is its old parent, |v1| is its new parent.
3385   EXPECT_TRUE(v4->has_remove_details());
3386   EXPECT_TRUE(v4->has_add_details());
3387   EXPECT_EQ(v2.get(), v4->remove_details().parent);
3388   EXPECT_EQ(&v1, v4->add_details().parent);
3389   EXPECT_EQ(v4, v4->add_details().child);
3390   EXPECT_EQ(v4, v4->remove_details().child);
3391   EXPECT_EQ(&v1, v4->remove_details().move_view);
3392   EXPECT_EQ(v2.get(), v4->add_details().move_view);
3393 }
3394 
3395 class WidgetObserverView : public View {
3396  public:
3397   WidgetObserverView();
3398   ~WidgetObserverView() override;
3399 
3400   void ResetTestState();
3401 
added_to_widget_count()3402   int added_to_widget_count() { return added_to_widget_count_; }
removed_from_widget_count()3403   int removed_from_widget_count() { return removed_from_widget_count_; }
3404 
3405  private:
3406   void AddedToWidget() override;
3407   void RemovedFromWidget() override;
3408 
3409   int added_to_widget_count_ = 0;
3410   int removed_from_widget_count_ = 0;
3411 
3412   DISALLOW_COPY_AND_ASSIGN(WidgetObserverView);
3413 };
3414 
WidgetObserverView()3415 WidgetObserverView::WidgetObserverView() {
3416   ResetTestState();
3417 }
3418 
3419 WidgetObserverView::~WidgetObserverView() = default;
3420 
ResetTestState()3421 void WidgetObserverView::ResetTestState() {
3422   added_to_widget_count_ = 0;
3423   removed_from_widget_count_ = 0;
3424 }
3425 
AddedToWidget()3426 void WidgetObserverView::AddedToWidget() {
3427   ++added_to_widget_count_;
3428 }
3429 
RemovedFromWidget()3430 void WidgetObserverView::RemovedFromWidget() {
3431   ++removed_from_widget_count_;
3432 }
3433 
3434 // Verifies that AddedToWidget and RemovedFromWidget are called for a view when
3435 // it is added to hierarchy.
3436 // The tree looks like this:
3437 // widget
3438 // +-- root
3439 //
3440 // then v1 is added to root:
3441 //
3442 //     v1
3443 //     +-- v2
3444 //
3445 // finally v1 is removed from root.
TEST_F(ViewTest,AddedToRemovedFromWidget)3446 TEST_F(ViewTest, AddedToRemovedFromWidget) {
3447   Widget widget;
3448   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3449   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3450   params.bounds = gfx::Rect(50, 50, 650, 650);
3451   widget.Init(std::move(params));
3452 
3453   View* root = widget.GetRootView();
3454 
3455   auto v1 = std::make_unique<WidgetObserverView>();
3456   auto v2 = std::make_unique<WidgetObserverView>();
3457   auto v3 = std::make_unique<WidgetObserverView>();
3458 
3459   auto* v2_ptr = v1->AddChildView(std::move(v2));
3460   EXPECT_EQ(0, v2_ptr->added_to_widget_count());
3461   EXPECT_EQ(0, v2_ptr->removed_from_widget_count());
3462 
3463   auto* v1_ptr = root->AddChildView(std::move(v1));
3464   EXPECT_EQ(1, v1_ptr->added_to_widget_count());
3465   EXPECT_EQ(0, v1_ptr->removed_from_widget_count());
3466   EXPECT_EQ(1, v2_ptr->added_to_widget_count());
3467   EXPECT_EQ(0, v2_ptr->removed_from_widget_count());
3468 
3469   v1_ptr->ResetTestState();
3470   v2_ptr->ResetTestState();
3471 
3472   auto* v3_ptr = v2_ptr->AddChildView(std::move(v3));
3473   EXPECT_EQ(0, v1_ptr->added_to_widget_count());
3474   EXPECT_EQ(0, v1_ptr->removed_from_widget_count());
3475   EXPECT_EQ(0, v2_ptr->added_to_widget_count());
3476   EXPECT_EQ(0, v2_ptr->removed_from_widget_count());
3477 
3478   v1_ptr->ResetTestState();
3479   v2_ptr->ResetTestState();
3480 
3481   v1 = root->RemoveChildViewT(v1_ptr);
3482   EXPECT_EQ(0, v1->added_to_widget_count());
3483   EXPECT_EQ(1, v1->removed_from_widget_count());
3484   EXPECT_EQ(0, v2_ptr->added_to_widget_count());
3485   EXPECT_EQ(1, v2_ptr->removed_from_widget_count());
3486 
3487   v2_ptr->ResetTestState();
3488   v2 = v1->RemoveChildViewT(v2_ptr);
3489   EXPECT_EQ(0, v2->removed_from_widget_count());
3490 
3491   // Test move between parents in a single Widget.
3492   v3 = v2->RemoveChildViewT(v3_ptr);
3493   v1->ResetTestState();
3494   v2->ResetTestState();
3495   v3->ResetTestState();
3496 
3497   v2_ptr = v1->AddChildView(std::move(v2));
3498   v1_ptr = root->AddChildView(std::move(v1));
3499   v3_ptr = root->AddChildView(std::move(v3));
3500   EXPECT_EQ(1, v1_ptr->added_to_widget_count());
3501   EXPECT_EQ(1, v2_ptr->added_to_widget_count());
3502   EXPECT_EQ(1, v3_ptr->added_to_widget_count());
3503 
3504   // This should not invoke added or removed to/from the widget.
3505   v1_ptr = v3_ptr->AddChildView(v1_ptr);
3506   EXPECT_EQ(1, v1_ptr->added_to_widget_count());
3507   EXPECT_EQ(0, v1_ptr->removed_from_widget_count());
3508   EXPECT_EQ(1, v2_ptr->added_to_widget_count());
3509   EXPECT_EQ(0, v2_ptr->removed_from_widget_count());
3510   EXPECT_EQ(1, v3_ptr->added_to_widget_count());
3511   EXPECT_EQ(0, v3_ptr->removed_from_widget_count());
3512 
3513   // Test move between widgets.
3514   Widget second_widget;
3515   params.bounds = gfx::Rect(150, 150, 650, 650);
3516   second_widget.Init(std::move(params));
3517 
3518   View* second_root = second_widget.GetRootView();
3519 
3520   v1_ptr->ResetTestState();
3521   v2_ptr->ResetTestState();
3522   v3_ptr->ResetTestState();
3523 
3524   v1_ptr =
3525       second_root->AddChildView(v1_ptr->parent()->RemoveChildViewT(v1_ptr));
3526   EXPECT_EQ(1, v1_ptr->removed_from_widget_count());
3527   EXPECT_EQ(1, v1_ptr->added_to_widget_count());
3528   EXPECT_EQ(1, v2_ptr->added_to_widget_count());
3529   EXPECT_EQ(1, v2_ptr->removed_from_widget_count());
3530   EXPECT_EQ(0, v3_ptr->added_to_widget_count());
3531   EXPECT_EQ(0, v3_ptr->removed_from_widget_count());
3532 }
3533 
3534 // Verifies if the child views added under the root are all deleted when calling
3535 // RemoveAllChildViews.
3536 // The tree looks like this:
3537 // root
3538 // +-- child1
3539 //     +-- foo
3540 //         +-- bar0
3541 //         +-- bar1
3542 //         +-- bar2
3543 // +-- child2
3544 // +-- child3
TEST_F(ViewTest,RemoveAllChildViews)3545 TEST_F(ViewTest, RemoveAllChildViews) {
3546   View root;
3547 
3548   View* child1 = root.AddChildView(std::make_unique<View>());
3549 
3550   for (size_t i = 0; i < 2; ++i)
3551     root.AddChildView(std::make_unique<View>());
3552 
3553   View* foo = child1->AddChildView(std::make_unique<View>());
3554 
3555   // Add some nodes to |foo|.
3556   for (size_t i = 0; i < 3; ++i)
3557     foo->AddChildView(std::make_unique<View>());
3558 
3559   EXPECT_EQ(3u, root.children().size());
3560   EXPECT_EQ(1u, child1->children().size());
3561   EXPECT_EQ(3u, foo->children().size());
3562 
3563   // Now remove all child views from root.
3564   root.RemoveAllChildViews(true);
3565 
3566   EXPECT_TRUE(root.children().empty());
3567 }
3568 
TEST_F(ViewTest,Contains)3569 TEST_F(ViewTest, Contains) {
3570   auto v1 = std::make_unique<View>();
3571 
3572   auto* v2 = v1->AddChildView(std::make_unique<View>());
3573   auto* v3 = v2->AddChildView(std::make_unique<View>());
3574 
3575   EXPECT_FALSE(v1->Contains(nullptr));
3576   EXPECT_TRUE(v1->Contains(v1.get()));
3577   EXPECT_TRUE(v1->Contains(v2));
3578   EXPECT_TRUE(v1->Contains(v3));
3579 
3580   EXPECT_FALSE(v2->Contains(nullptr));
3581   EXPECT_TRUE(v2->Contains(v2));
3582   EXPECT_FALSE(v2->Contains(v1.get()));
3583   EXPECT_TRUE(v2->Contains(v3));
3584 
3585   EXPECT_FALSE(v3->Contains(nullptr));
3586   EXPECT_TRUE(v3->Contains(v3));
3587   EXPECT_FALSE(v3->Contains(v1.get()));
3588   EXPECT_FALSE(v3->Contains(v2));
3589 }
3590 
3591 // Verifies if GetIndexOf() returns the correct index for the specified child
3592 // view.
3593 // The tree looks like this:
3594 // root
3595 // +-- child1
3596 //     +-- foo1
3597 // +-- child2
TEST_F(ViewTest,GetIndexOf)3598 TEST_F(ViewTest, GetIndexOf) {
3599   auto root = std::make_unique<View>();
3600 
3601   auto* child1 = root->AddChildView(std::make_unique<View>());
3602 
3603   auto* child2 = root->AddChildView(std::make_unique<View>());
3604 
3605   auto* foo1 = child1->AddChildView(std::make_unique<View>());
3606 
3607   EXPECT_EQ(-1, root->GetIndexOf(nullptr));
3608   EXPECT_EQ(-1, root->GetIndexOf(root.get()));
3609   EXPECT_EQ(0, root->GetIndexOf(child1));
3610   EXPECT_EQ(1, root->GetIndexOf(child2));
3611   EXPECT_EQ(-1, root->GetIndexOf(foo1));
3612 
3613   EXPECT_EQ(-1, child1->GetIndexOf(nullptr));
3614   EXPECT_EQ(-1, child1->GetIndexOf(root.get()));
3615   EXPECT_EQ(-1, child1->GetIndexOf(child1));
3616   EXPECT_EQ(-1, child1->GetIndexOf(child2));
3617   EXPECT_EQ(0, child1->GetIndexOf(foo1));
3618 
3619   EXPECT_EQ(-1, child2->GetIndexOf(nullptr));
3620   EXPECT_EQ(-1, child2->GetIndexOf(root.get()));
3621   EXPECT_EQ(-1, child2->GetIndexOf(child2));
3622   EXPECT_EQ(-1, child2->GetIndexOf(child1));
3623   EXPECT_EQ(-1, child2->GetIndexOf(foo1));
3624 }
3625 
3626 // Verifies that the child views can be reordered correctly.
TEST_F(ViewTest,ReorderChildren)3627 TEST_F(ViewTest, ReorderChildren) {
3628   auto root = std::make_unique<View>();
3629 
3630   auto* child = root->AddChildView(std::make_unique<View>());
3631 
3632   auto* foo1 = child->AddChildView(std::make_unique<View>());
3633   View* foo2 = child->AddChildView(std::make_unique<View>());
3634   View* foo3 = child->AddChildView(std::make_unique<View>());
3635   foo1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
3636   foo2->SetFocusBehavior(View::FocusBehavior::ALWAYS);
3637   foo3->SetFocusBehavior(View::FocusBehavior::ALWAYS);
3638 
3639   ASSERT_EQ(0, child->GetIndexOf(foo1));
3640   ASSERT_EQ(1, child->GetIndexOf(foo2));
3641   ASSERT_EQ(2, child->GetIndexOf(foo3));
3642   ASSERT_EQ(foo2, foo1->GetNextFocusableView());
3643   ASSERT_EQ(foo3, foo2->GetNextFocusableView());
3644   ASSERT_EQ(nullptr, foo3->GetNextFocusableView());
3645 
3646   // Move |foo2| at the end.
3647   child->ReorderChildView(foo2, -1);
3648   ASSERT_EQ(0, child->GetIndexOf(foo1));
3649   ASSERT_EQ(1, child->GetIndexOf(foo3));
3650   ASSERT_EQ(2, child->GetIndexOf(foo2));
3651   ASSERT_EQ(foo3, foo1->GetNextFocusableView());
3652   ASSERT_EQ(foo2, foo3->GetNextFocusableView());
3653   ASSERT_EQ(nullptr, foo2->GetNextFocusableView());
3654 
3655   // Move |foo1| at the end.
3656   child->ReorderChildView(foo1, -1);
3657   ASSERT_EQ(0, child->GetIndexOf(foo3));
3658   ASSERT_EQ(1, child->GetIndexOf(foo2));
3659   ASSERT_EQ(2, child->GetIndexOf(foo1));
3660   ASSERT_EQ(nullptr, foo1->GetNextFocusableView());
3661   ASSERT_EQ(foo2, foo1->GetPreviousFocusableView());
3662   ASSERT_EQ(foo2, foo3->GetNextFocusableView());
3663   ASSERT_EQ(foo1, foo2->GetNextFocusableView());
3664 
3665   // Move |foo2| to the front.
3666   child->ReorderChildView(foo2, 0);
3667   ASSERT_EQ(0, child->GetIndexOf(foo2));
3668   ASSERT_EQ(1, child->GetIndexOf(foo3));
3669   ASSERT_EQ(2, child->GetIndexOf(foo1));
3670   ASSERT_EQ(nullptr, foo1->GetNextFocusableView());
3671   ASSERT_EQ(foo3, foo1->GetPreviousFocusableView());
3672   ASSERT_EQ(foo3, foo2->GetNextFocusableView());
3673   ASSERT_EQ(foo1, foo3->GetNextFocusableView());
3674 }
3675 
3676 // Verifies that GetViewByID returns the correctly child view from the specified
3677 // ID.
3678 // The tree looks like this:
3679 // v1
3680 // +-- v2
3681 //     +-- v3
3682 //     +-- v4
TEST_F(ViewTest,GetViewByID)3683 TEST_F(ViewTest, GetViewByID) {
3684   View v1;
3685   const int kV1ID = 1;
3686   v1.SetID(kV1ID);
3687 
3688   View v2;
3689   const int kV2ID = 2;
3690   v2.SetID(kV2ID);
3691 
3692   View v3;
3693   const int kV3ID = 3;
3694   v3.SetID(kV3ID);
3695 
3696   View v4;
3697   const int kV4ID = 4;
3698   v4.SetID(kV4ID);
3699 
3700   const int kV5ID = 5;
3701 
3702   v1.AddChildView(&v2);
3703   v2.AddChildView(&v3);
3704   v2.AddChildView(&v4);
3705 
3706   EXPECT_EQ(&v1, v1.GetViewByID(kV1ID));
3707   EXPECT_EQ(&v2, v1.GetViewByID(kV2ID));
3708   EXPECT_EQ(&v4, v1.GetViewByID(kV4ID));
3709 
3710   EXPECT_EQ(nullptr, v1.GetViewByID(kV5ID));  // No V5 exists.
3711   EXPECT_EQ(nullptr,
3712             v2.GetViewByID(kV1ID));  // It can get only from child views.
3713 
3714   const int kGroup = 1;
3715   v3.SetGroup(kGroup);
3716   v4.SetGroup(kGroup);
3717 
3718   View::Views views;
3719   v1.GetViewsInGroup(kGroup, &views);
3720   EXPECT_EQ(2U, views.size());
3721   EXPECT_TRUE(base::Contains(views, &v3));
3722   EXPECT_TRUE(base::Contains(views, &v4));
3723 }
3724 
TEST_F(ViewTest,AddExistingChild)3725 TEST_F(ViewTest, AddExistingChild) {
3726   View v1, v2, v3;
3727 
3728   v1.AddChildView(&v2);
3729   v1.AddChildView(&v3);
3730   EXPECT_EQ(0, v1.GetIndexOf(&v2));
3731   EXPECT_EQ(1, v1.GetIndexOf(&v3));
3732 
3733   // Check that there's no change in order when adding at same index.
3734   v1.AddChildViewAt(&v2, 0);
3735   EXPECT_EQ(0, v1.GetIndexOf(&v2));
3736   EXPECT_EQ(1, v1.GetIndexOf(&v3));
3737   v1.AddChildViewAt(&v3, 1);
3738   EXPECT_EQ(0, v1.GetIndexOf(&v2));
3739   EXPECT_EQ(1, v1.GetIndexOf(&v3));
3740 
3741   // Add it at a different index and check for change in order.
3742   v1.AddChildViewAt(&v2, 1);
3743   EXPECT_EQ(1, v1.GetIndexOf(&v2));
3744   EXPECT_EQ(0, v1.GetIndexOf(&v3));
3745   v1.AddChildViewAt(&v2, 0);
3746   EXPECT_EQ(0, v1.GetIndexOf(&v2));
3747   EXPECT_EQ(1, v1.GetIndexOf(&v3));
3748 
3749   // Check that calling AddChildView() moves to the end.
3750   v1.AddChildView(&v2);
3751   EXPECT_EQ(1, v1.GetIndexOf(&v2));
3752   EXPECT_EQ(0, v1.GetIndexOf(&v3));
3753   v1.AddChildView(&v3);
3754   EXPECT_EQ(0, v1.GetIndexOf(&v2));
3755   EXPECT_EQ(1, v1.GetIndexOf(&v3));
3756 }
3757 
3758 ////////////////////////////////////////////////////////////////////////////////
3759 // FocusManager
3760 ////////////////////////////////////////////////////////////////////////////////
3761 
3762 // A widget that always claims to be active, regardless of its real activation
3763 // status.
3764 class ActiveWidget : public Widget {
3765  public:
3766   ActiveWidget() = default;
3767   ~ActiveWidget() override = default;
3768 
IsActive() const3769   bool IsActive() const override { return true; }
3770 
3771  private:
3772   DISALLOW_COPY_AND_ASSIGN(ActiveWidget);
3773 };
3774 
TEST_F(ViewTest,AdvanceFocusIfNecessaryForUnfocusableView)3775 TEST_F(ViewTest, AdvanceFocusIfNecessaryForUnfocusableView) {
3776   // Create a widget with two views and give the first one focus.
3777   ActiveWidget widget;
3778   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3779   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3780   widget.Init(std::move(params));
3781 
3782   View* view1 = widget.GetRootView()->AddChildView(std::make_unique<View>());
3783   view1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
3784 
3785   View* view2 = widget.GetRootView()->AddChildView(std::make_unique<View>());
3786   view2->SetFocusBehavior(View::FocusBehavior::ALWAYS);
3787 
3788   FocusManager* focus_manager = widget.GetFocusManager();
3789   ASSERT_TRUE(focus_manager);
3790 
3791   focus_manager->SetFocusedView(view1);
3792   EXPECT_EQ(view1, focus_manager->GetFocusedView());
3793 
3794   // Disable the focused view and check if the next view gets focused.
3795   view1->SetEnabled(false);
3796   EXPECT_EQ(view2, focus_manager->GetFocusedView());
3797 
3798   // Re-enable and re-focus.
3799   view1->SetEnabled(true);
3800   focus_manager->SetFocusedView(view1);
3801   EXPECT_EQ(view1, focus_manager->GetFocusedView());
3802 
3803   // Hide the focused view and check it the next view gets focused.
3804   view1->SetVisible(false);
3805   EXPECT_EQ(view2, focus_manager->GetFocusedView());
3806 
3807   // Re-show and re-focus.
3808   view1->SetVisible(true);
3809   focus_manager->SetFocusedView(view1);
3810   EXPECT_EQ(view1, focus_manager->GetFocusedView());
3811 
3812   // Set the focused view as not focusable and check if the next view gets
3813   // focused.
3814   view1->SetFocusBehavior(View::FocusBehavior::NEVER);
3815   EXPECT_EQ(view2, focus_manager->GetFocusedView());
3816 }
3817 
3818 ////////////////////////////////////////////////////////////////////////////////
3819 // Layers
3820 ////////////////////////////////////////////////////////////////////////////////
3821 
3822 namespace {
3823 
3824 // Test implementation of LayerAnimator.
3825 class TestLayerAnimator : public ui::LayerAnimator {
3826  public:
3827   TestLayerAnimator();
3828 
last_bounds() const3829   const gfx::Rect& last_bounds() const { return last_bounds_; }
3830 
3831   // LayerAnimator.
3832   void SetBounds(const gfx::Rect& bounds) override;
3833 
3834  protected:
3835   ~TestLayerAnimator() override = default;
3836 
3837  private:
3838   gfx::Rect last_bounds_;
3839 
3840   DISALLOW_COPY_AND_ASSIGN(TestLayerAnimator);
3841 };
3842 
TestLayerAnimator()3843 TestLayerAnimator::TestLayerAnimator()
3844     : ui::LayerAnimator(base::TimeDelta::FromMilliseconds(0)) {}
3845 
SetBounds(const gfx::Rect & bounds)3846 void TestLayerAnimator::SetBounds(const gfx::Rect& bounds) {
3847   last_bounds_ = bounds;
3848 }
3849 
3850 class TestingLayerViewObserver : public ViewObserver {
3851  public:
TestingLayerViewObserver(View * view)3852   explicit TestingLayerViewObserver(View* view) : view_(view) {
3853     view_->AddObserver(this);
3854   }
~TestingLayerViewObserver()3855   ~TestingLayerViewObserver() override { view_->RemoveObserver(this); }
3856 
GetLastLayerBoundsAndReset()3857   gfx::Rect GetLastLayerBoundsAndReset() {
3858     gfx::Rect value = last_layer_bounds_;
3859     last_layer_bounds_ = gfx::Rect();
3860     return value;
3861   }
3862 
3863  private:
3864   // ViewObserver:
OnLayerTargetBoundsChanged(View * view)3865   void OnLayerTargetBoundsChanged(View* view) override {
3866     last_layer_bounds_ = view->layer()->bounds();
3867   }
3868 
3869   gfx::Rect last_layer_bounds_;
3870   View* view_;
3871 
3872   DISALLOW_COPY_AND_ASSIGN(TestingLayerViewObserver);
3873 };
3874 
3875 }  // namespace
3876 
3877 class ViewLayerTest : public ViewsTestBase {
3878  public:
3879   ViewLayerTest() = default;
3880 
3881   ~ViewLayerTest() override = default;
3882 
3883   // Returns the Layer used by the RootView.
GetRootLayer()3884   ui::Layer* GetRootLayer() { return widget()->GetLayer(); }
3885 
SetUp()3886   void SetUp() override {
3887     SetUpPixelCanvas();
3888     ViewTest::SetUp();
3889     widget_ = new Widget;
3890     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3891     params.bounds = gfx::Rect(50, 50, 200, 200);
3892     widget_->Init(std::move(params));
3893     widget_->Show();
3894     widget_->GetRootView()->SetBounds(0, 0, 200, 200);
3895   }
3896 
TearDown()3897   void TearDown() override {
3898     widget_->CloseNow();
3899     ViewsTestBase::TearDown();
3900   }
3901 
widget()3902   Widget* widget() { return widget_; }
3903 
SetUpPixelCanvas()3904   virtual void SetUpPixelCanvas() {
3905     scoped_feature_list_.InitAndDisableFeature(
3906         ::features::kEnablePixelCanvasRecording);
3907   }
3908 
3909  protected:
3910   // Accessors to View internals.
SchedulePaintOnParent(View * view)3911   void SchedulePaintOnParent(View* view) { view->SchedulePaintOnParent(); }
3912 
3913  private:
3914   Widget* widget_ = nullptr;
3915   base::test::ScopedFeatureList scoped_feature_list_;
3916 };
3917 
TEST_F(ViewLayerTest,LayerCreationAndDestruction)3918 TEST_F(ViewLayerTest, LayerCreationAndDestruction) {
3919   View view;
3920   EXPECT_EQ(nullptr, view.layer());
3921 
3922   view.SetPaintToLayer();
3923   EXPECT_NE(nullptr, view.layer());
3924 
3925   view.DestroyLayer();
3926   EXPECT_EQ(nullptr, view.layer());
3927 }
3928 
TEST_F(ViewLayerTest,SetTransformCreatesAndDestroysLayer)3929 TEST_F(ViewLayerTest, SetTransformCreatesAndDestroysLayer) {
3930   View view;
3931   EXPECT_EQ(nullptr, view.layer());
3932 
3933   // Set an arbitrary non-identity transform, which should cause a layer to be
3934   // created.
3935   gfx::Transform transform;
3936   transform.Translate(1.0, 1.0);
3937   view.SetTransform(transform);
3938   EXPECT_NE(nullptr, view.layer());
3939 
3940   // Set the identity transform, which should destroy the layer.
3941   view.SetTransform(gfx::Transform());
3942   EXPECT_EQ(nullptr, view.layer());
3943 }
3944 
3945 // Verify that setting an identity transform after SetPaintToLayer() has been
3946 // called doesn't destroy the layer.
TEST_F(ViewLayerTest,IdentityTransformDoesntOverrideSetPaintToLayer)3947 TEST_F(ViewLayerTest, IdentityTransformDoesntOverrideSetPaintToLayer) {
3948   View view;
3949   EXPECT_EQ(nullptr, view.layer());
3950 
3951   view.SetPaintToLayer();
3952   EXPECT_NE(nullptr, view.layer());
3953 
3954   gfx::Transform transform;
3955   transform.Translate(1.0, 1.0);
3956   view.SetTransform(transform);
3957   EXPECT_NE(nullptr, view.layer());
3958 
3959   view.SetTransform(transform);
3960   EXPECT_NE(nullptr, view.layer());
3961 }
3962 
3963 // Verify that calling DestroyLayer() while a non-identity transform is present
3964 // doesn't destroy the layer.
TEST_F(ViewLayerTest,DestroyLayerDoesntOverrideTransform)3965 TEST_F(ViewLayerTest, DestroyLayerDoesntOverrideTransform) {
3966   View view;
3967   EXPECT_EQ(nullptr, view.layer());
3968 
3969   view.SetPaintToLayer();
3970   EXPECT_NE(nullptr, view.layer());
3971 
3972   gfx::Transform transform;
3973   transform.Translate(1.0, 1.0);
3974   view.SetTransform(transform);
3975   EXPECT_NE(nullptr, view.layer());
3976 
3977   view.DestroyLayer();
3978   EXPECT_NE(nullptr, view.layer());
3979 }
3980 
TEST_F(ViewLayerTest,LayerToggling)3981 TEST_F(ViewLayerTest, LayerToggling) {
3982   // Because we lazily create textures the calls to DrawTree are necessary to
3983   // ensure we trigger creation of textures.
3984   ui::Layer* root_layer = widget()->GetLayer();
3985   View* content_view = new View;
3986   widget()->SetContentsView(content_view);
3987 
3988   // Create v1, give it a bounds and verify everything is set up correctly.
3989   View* v1 = new View;
3990   v1->SetPaintToLayer();
3991   EXPECT_TRUE(v1->layer() != nullptr);
3992   v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
3993   content_view->AddChildView(v1);
3994   ASSERT_TRUE(v1->layer() != nullptr);
3995   EXPECT_EQ(root_layer, v1->layer()->parent());
3996   EXPECT_EQ(gfx::Rect(20, 30, 140, 150), v1->layer()->bounds());
3997 
3998   // Create v2 as a child of v1 and do basic assertion testing.
3999   View* v2 = new View;
4000   TestingLayerViewObserver v2_observer(v2);
4001   v1->AddChildView(v2);
4002   EXPECT_TRUE(v2->layer() == nullptr);
4003   v2->SetBoundsRect(gfx::Rect(10, 20, 30, 40));
4004   v2->SetPaintToLayer();
4005   ASSERT_TRUE(v2->layer() != nullptr);
4006   EXPECT_EQ(v1->layer(), v2->layer()->parent());
4007   EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds());
4008   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4009 
4010   // Turn off v1s layer. v2 should still have a layer but its parent should have
4011   // changed.
4012   v1->DestroyLayer();
4013   EXPECT_TRUE(v1->layer() == nullptr);
4014   EXPECT_TRUE(v2->layer() != nullptr);
4015   EXPECT_EQ(root_layer, v2->layer()->parent());
4016   ASSERT_EQ(1u, root_layer->children().size());
4017   EXPECT_EQ(root_layer->children()[0], v2->layer());
4018   // The bounds of the layer should have changed to be relative to the root view
4019   // now.
4020   EXPECT_EQ(gfx::Rect(30, 50, 30, 40), v2->layer()->bounds());
4021   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4022 
4023   // Make v1 have a layer again and verify v2s layer is wired up correctly.
4024   gfx::Transform transform;
4025   transform.Scale(2.0, 2.0);
4026   v1->SetTransform(transform);
4027   EXPECT_TRUE(v1->layer() != nullptr);
4028   EXPECT_TRUE(v2->layer() != nullptr);
4029   EXPECT_EQ(root_layer, v1->layer()->parent());
4030   EXPECT_EQ(v1->layer(), v2->layer()->parent());
4031   ASSERT_EQ(1u, root_layer->children().size());
4032   EXPECT_EQ(root_layer->children()[0], v1->layer());
4033   ASSERT_EQ(1u, v1->layer()->children().size());
4034   EXPECT_EQ(v1->layer()->children()[0], v2->layer());
4035   EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds());
4036   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4037 }
4038 
4039 // Verifies turning on a layer wires up children correctly.
TEST_F(ViewLayerTest,NestedLayerToggling)4040 TEST_F(ViewLayerTest, NestedLayerToggling) {
4041   View* content_view = new View;
4042   widget()->SetContentsView(content_view);
4043 
4044   // Create v1, give it a bounds and verify everything is set up correctly.
4045   View* v1 = content_view->AddChildView(std::make_unique<View>());
4046   v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
4047 
4048   View* v2 = v1->AddChildView(std::make_unique<View>());
4049   v2->SetBoundsRect(gfx::Rect(10, 10, 100, 100));
4050 
4051   View* v3 = v2->AddChildView(std::make_unique<View>());
4052   TestingLayerViewObserver v3_observer(v3);
4053   v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
4054   v3->SetPaintToLayer();
4055   ASSERT_TRUE(v3->layer() != nullptr);
4056   EXPECT_EQ(v3->layer()->bounds(), v3_observer.GetLastLayerBoundsAndReset());
4057 
4058   // At this point we have v1-v2-v3. v3 has a layer, v1 and v2 don't.
4059 
4060   v1->SetPaintToLayer();
4061   EXPECT_EQ(v1->layer(), v3->layer()->parent());
4062   EXPECT_EQ(v3->layer()->bounds(), v3_observer.GetLastLayerBoundsAndReset());
4063 }
4064 
TEST_F(ViewLayerTest,LayerAnimator)4065 TEST_F(ViewLayerTest, LayerAnimator) {
4066   View* content_view = new View;
4067   widget()->SetContentsView(content_view);
4068 
4069   View* v1 = content_view->AddChildView(std::make_unique<View>());
4070   v1->SetPaintToLayer();
4071   EXPECT_TRUE(v1->layer() != nullptr);
4072 
4073   TestLayerAnimator* animator = new TestLayerAnimator();
4074   v1->layer()->SetAnimator(animator);
4075 
4076   gfx::Rect bounds(1, 2, 3, 4);
4077   v1->SetBoundsRect(bounds);
4078   EXPECT_EQ(bounds, animator->last_bounds());
4079   // TestLayerAnimator doesn't update the layer.
4080   EXPECT_NE(bounds, v1->layer()->bounds());
4081 }
4082 
4083 // Verifies the bounds of a layer are updated if the bounds of ancestor that
4084 // doesn't have a layer change.
TEST_F(ViewLayerTest,BoundsChangeWithLayer)4085 TEST_F(ViewLayerTest, BoundsChangeWithLayer) {
4086   View* content_view = new View;
4087   widget()->SetContentsView(content_view);
4088 
4089   View* v1 = content_view->AddChildView(std::make_unique<View>());
4090   v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
4091 
4092   View* v2 = v1->AddChildView(std::make_unique<View>());
4093   TestingLayerViewObserver v2_observer(v2);
4094   v2->SetBoundsRect(gfx::Rect(10, 11, 40, 50));
4095   v2->SetPaintToLayer();
4096   ASSERT_TRUE(v2->layer() != nullptr);
4097   EXPECT_EQ(gfx::Rect(30, 41, 40, 50), v2->layer()->bounds());
4098   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4099 
4100   v1->SetPosition(gfx::Point(25, 36));
4101   EXPECT_EQ(gfx::Rect(35, 47, 40, 50), v2->layer()->bounds());
4102   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4103 
4104   v2->SetPosition(gfx::Point(11, 12));
4105   EXPECT_EQ(gfx::Rect(36, 48, 40, 50), v2->layer()->bounds());
4106   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4107 
4108   // Bounds of the layer should change even if the view is not invisible.
4109   v1->SetVisible(false);
4110   v1->SetPosition(gfx::Point(20, 30));
4111   EXPECT_EQ(gfx::Rect(31, 42, 40, 50), v2->layer()->bounds());
4112   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4113 
4114   v2->SetVisible(false);
4115   v2->SetBoundsRect(gfx::Rect(10, 11, 20, 30));
4116   EXPECT_EQ(gfx::Rect(30, 41, 20, 30), v2->layer()->bounds());
4117   EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
4118 }
4119 
4120 // Make sure layers are positioned correctly in RTL.
TEST_F(ViewLayerTest,BoundInRTL)4121 TEST_F(ViewLayerTest, BoundInRTL) {
4122   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
4123   View* view = new View;
4124   widget()->SetContentsView(view);
4125 
4126   int content_width = view->width();
4127 
4128   // |v1| is initially not attached to anything. So its layer will have the same
4129   // bounds as the view.
4130   View* v1 = new View;
4131   v1->SetPaintToLayer();
4132   v1->SetBounds(10, 10, 20, 10);
4133   EXPECT_EQ(gfx::Rect(10, 10, 20, 10), v1->layer()->bounds());
4134 
4135   // Once |v1| is attached to the widget, its layer will get RTL-appropriate
4136   // bounds.
4137   view->AddChildView(v1);
4138   EXPECT_EQ(gfx::Rect(content_width - 30, 10, 20, 10), v1->layer()->bounds());
4139   gfx::Rect l1bounds = v1->layer()->bounds();
4140 
4141   // Now attach a View to the widget first, then create a layer for it. Make
4142   // sure the bounds are correct.
4143   View* v2 = new View;
4144   v2->SetBounds(50, 10, 30, 10);
4145   EXPECT_FALSE(v2->layer());
4146   view->AddChildView(v2);
4147   v2->SetPaintToLayer();
4148   EXPECT_EQ(gfx::Rect(content_width - 80, 10, 30, 10), v2->layer()->bounds());
4149   gfx::Rect l2bounds = v2->layer()->bounds();
4150 
4151   view->SetPaintToLayer();
4152   EXPECT_EQ(l1bounds, v1->layer()->bounds());
4153   EXPECT_EQ(l2bounds, v2->layer()->bounds());
4154 
4155   // Move one of the views. Make sure the layer is positioned correctly
4156   // afterwards.
4157   v1->SetBounds(v1->x() - 5, v1->y(), v1->width(), v1->height());
4158   l1bounds.set_x(l1bounds.x() + 5);
4159   EXPECT_EQ(l1bounds, v1->layer()->bounds());
4160 
4161   view->DestroyLayer();
4162   EXPECT_EQ(l1bounds, v1->layer()->bounds());
4163   EXPECT_EQ(l2bounds, v2->layer()->bounds());
4164 
4165   // Move a view again.
4166   v2->SetBounds(v2->x() + 5, v2->y(), v2->width(), v2->height());
4167   l2bounds.set_x(l2bounds.x() - 5);
4168   EXPECT_EQ(l2bounds, v2->layer()->bounds());
4169 }
4170 
4171 // Make sure that resizing a parent in RTL correctly repositions its children.
TEST_F(ViewLayerTest,ResizeParentInRTL)4172 TEST_F(ViewLayerTest, ResizeParentInRTL) {
4173   base::test::ScopedRestoreICUDefaultLocale scoped_locale_("he");
4174   View* view = new View;
4175   widget()->SetContentsView(view);
4176 
4177   int content_width = view->width();
4178 
4179   // Create a paints-to-layer view |v1|.
4180   View* v1 = view->AddChildView(std::make_unique<View>());
4181   v1->SetPaintToLayer();
4182   v1->SetBounds(10, 10, 20, 10);
4183   EXPECT_EQ(gfx::Rect(content_width - 30, 10, 20, 10), v1->layer()->bounds());
4184 
4185   // Attach a paints-to-layer child view to |v1|.
4186   View* v2 = new View;
4187   v2->SetPaintToLayer();
4188   v2->SetBounds(3, 5, 6, 4);
4189   EXPECT_EQ(gfx::Rect(3, 5, 6, 4), v2->layer()->bounds());
4190   v1->AddChildView(v2);
4191   // Check that |v2| now has RTL-appropriate bounds.
4192   EXPECT_EQ(gfx::Rect(11, 5, 6, 4), v2->layer()->bounds());
4193 
4194   // Attach a non-layer child view to |v1|, and give it a paints-to-layer child.
4195   View* v3 = new View;
4196   v3->SetBounds(1, 1, 18, 8);
4197   View* v4 = new View;
4198   v4->SetPaintToLayer();
4199   v4->SetBounds(2, 4, 6, 4);
4200   EXPECT_EQ(gfx::Rect(2, 4, 6, 4), v4->layer()->bounds());
4201   v3->AddChildView(v4);
4202   EXPECT_EQ(gfx::Rect(10, 4, 6, 4), v4->layer()->bounds());
4203   v1->AddChildView(v3);
4204   // Check that |v4| now has RTL-appropriate bounds.
4205   EXPECT_EQ(gfx::Rect(11, 5, 6, 4), v4->layer()->bounds());
4206 
4207   // Resize |v1|. Make sure that |v2| and |v4|'s layers have been moved
4208   // correctly to RTL-appropriate bounds.
4209   v1->SetSize(gfx::Size(30, 10));
4210   EXPECT_EQ(gfx::Rect(21, 5, 6, 4), v2->layer()->bounds());
4211   EXPECT_EQ(gfx::Rect(21, 5, 6, 4), v4->layer()->bounds());
4212 
4213   // Move and resize |v3|. Make sure that |v4|'s layer has been moved correctly
4214   // to RTL-appropriate bounds.
4215   v3->SetBounds(2, 1, 12, 8);
4216   EXPECT_EQ(gfx::Rect(20, 5, 6, 4), v4->layer()->bounds());
4217 }
4218 
4219 // Makes sure a transform persists after toggling the visibility.
TEST_F(ViewLayerTest,ToggleVisibilityWithTransform)4220 TEST_F(ViewLayerTest, ToggleVisibilityWithTransform) {
4221   View* view = new View;
4222   gfx::Transform transform;
4223   transform.Scale(2.0, 2.0);
4224   view->SetTransform(transform);
4225   widget()->SetContentsView(view);
4226   EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
4227 
4228   view->SetVisible(false);
4229   EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
4230 
4231   view->SetVisible(true);
4232   EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
4233 }
4234 
4235 // Verifies a transform persists after removing/adding a view with a transform.
TEST_F(ViewLayerTest,ResetTransformOnLayerAfterAdd)4236 TEST_F(ViewLayerTest, ResetTransformOnLayerAfterAdd) {
4237   View* view = new View;
4238   gfx::Transform transform;
4239   transform.Scale(2.0, 2.0);
4240   view->SetTransform(transform);
4241   widget()->SetContentsView(view);
4242   EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
4243   ASSERT_TRUE(view->layer() != nullptr);
4244   EXPECT_EQ(2.0f, view->layer()->transform().matrix().get(0, 0));
4245 
4246   View* parent = view->parent();
4247   parent->RemoveChildView(view);
4248   parent->AddChildView(view);
4249 
4250   EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
4251   ASSERT_TRUE(view->layer() != nullptr);
4252   EXPECT_EQ(2.0f, view->layer()->transform().matrix().get(0, 0));
4253 }
4254 
4255 // Makes sure that layer visibility is correct after toggling View visibility.
TEST_F(ViewLayerTest,ToggleVisibilityWithLayer)4256 TEST_F(ViewLayerTest, ToggleVisibilityWithLayer) {
4257   View* content_view = new View;
4258   widget()->SetContentsView(content_view);
4259 
4260   // The view isn't attached to a widget or a parent view yet. But it should
4261   // still have a layer, but the layer should not be attached to the root
4262   // layer.
4263   View* v1 = new View;
4264   v1->SetPaintToLayer();
4265   EXPECT_TRUE(v1->layer());
4266   EXPECT_FALSE(
4267       LayerIsAncestor(widget()->GetCompositor()->root_layer(), v1->layer()));
4268 
4269   // Once the view is attached to a widget, its layer should be attached to the
4270   // root layer and visible.
4271   content_view->AddChildView(v1);
4272   EXPECT_TRUE(
4273       LayerIsAncestor(widget()->GetCompositor()->root_layer(), v1->layer()));
4274   EXPECT_TRUE(v1->layer()->IsDrawn());
4275 
4276   v1->SetVisible(false);
4277   EXPECT_FALSE(v1->layer()->IsDrawn());
4278 
4279   v1->SetVisible(true);
4280   EXPECT_TRUE(v1->layer()->IsDrawn());
4281 
4282   widget()->Hide();
4283   EXPECT_FALSE(v1->layer()->IsDrawn());
4284 
4285   widget()->Show();
4286   EXPECT_TRUE(v1->layer()->IsDrawn());
4287 }
4288 
4289 // Tests that the layers in the subtree are orphaned after a View is removed
4290 // from the parent.
TEST_F(ViewLayerTest,OrphanLayerAfterViewRemove)4291 TEST_F(ViewLayerTest, OrphanLayerAfterViewRemove) {
4292   View* content_view = new View;
4293   widget()->SetContentsView(content_view);
4294 
4295   View* v1 = new View;
4296   content_view->AddChildView(v1);
4297 
4298   View* v2 = new View;
4299   v1->AddChildView(v2);
4300   v2->SetPaintToLayer();
4301   EXPECT_TRUE(
4302       LayerIsAncestor(widget()->GetCompositor()->root_layer(), v2->layer()));
4303   EXPECT_TRUE(v2->layer()->IsDrawn());
4304 
4305   content_view->RemoveChildView(v1);
4306 
4307   EXPECT_FALSE(
4308       LayerIsAncestor(widget()->GetCompositor()->root_layer(), v2->layer()));
4309 
4310   // Reparent |v2|.
4311   v1->RemoveChildView(v2);
4312   content_view->AddChildView(v2);
4313   delete v1;
4314   v1 = nullptr;
4315   EXPECT_TRUE(
4316       LayerIsAncestor(widget()->GetCompositor()->root_layer(), v2->layer()));
4317   EXPECT_TRUE(v2->layer()->IsDrawn());
4318 }
4319 
4320 class PaintTrackingView : public View {
4321  public:
4322   PaintTrackingView() = default;
4323 
painted() const4324   bool painted() const { return painted_; }
set_painted(bool value)4325   void set_painted(bool value) { painted_ = value; }
4326 
OnPaint(gfx::Canvas * canvas)4327   void OnPaint(gfx::Canvas* canvas) override { painted_ = true; }
4328 
4329  private:
4330   bool painted_ = false;
4331 
4332   DISALLOW_COPY_AND_ASSIGN(PaintTrackingView);
4333 };
4334 
4335 // Makes sure child views with layers aren't painted when paint starts at an
4336 // ancestor.
TEST_F(ViewLayerTest,DontPaintChildrenWithLayers)4337 TEST_F(ViewLayerTest, DontPaintChildrenWithLayers) {
4338   PaintTrackingView* content_view = new PaintTrackingView;
4339   widget()->SetContentsView(content_view);
4340   content_view->SetPaintToLayer();
4341   GetRootLayer()->GetCompositor()->ScheduleDraw();
4342   ui::DrawWaiterForTest::WaitForCompositingEnded(
4343       GetRootLayer()->GetCompositor());
4344   GetRootLayer()->SchedulePaint(gfx::Rect(0, 0, 10, 10));
4345   content_view->set_painted(false);
4346   // content_view no longer has a dirty rect. Paint from the root and make sure
4347   // PaintTrackingView isn't painted.
4348   GetRootLayer()->GetCompositor()->ScheduleDraw();
4349   ui::DrawWaiterForTest::WaitForCompositingEnded(
4350       GetRootLayer()->GetCompositor());
4351   EXPECT_FALSE(content_view->painted());
4352 
4353   // Make content_view have a dirty rect, paint the layers and make sure
4354   // PaintTrackingView is painted.
4355   content_view->layer()->SchedulePaint(gfx::Rect(0, 0, 10, 10));
4356   GetRootLayer()->GetCompositor()->ScheduleDraw();
4357   ui::DrawWaiterForTest::WaitForCompositingEnded(
4358       GetRootLayer()->GetCompositor());
4359   EXPECT_TRUE(content_view->painted());
4360 }
4361 
TEST_F(ViewLayerTest,NoCrashWhenParentlessViewSchedulesPaintOnParent)4362 TEST_F(ViewLayerTest, NoCrashWhenParentlessViewSchedulesPaintOnParent) {
4363   TestView v;
4364   SchedulePaintOnParent(&v);
4365 }
4366 
TEST_F(ViewLayerTest,ScheduledRectsInParentAfterSchedulingPaint)4367 TEST_F(ViewLayerTest, ScheduledRectsInParentAfterSchedulingPaint) {
4368   TestView parent_view;
4369   parent_view.SetBounds(10, 10, 100, 100);
4370 
4371   TestView* child_view = parent_view.AddChildView(std::make_unique<TestView>());
4372   child_view->SetBounds(5, 6, 10, 20);
4373 
4374   parent_view.scheduled_paint_rects_.clear();
4375   SchedulePaintOnParent(child_view);
4376   ASSERT_EQ(1U, parent_view.scheduled_paint_rects_.size());
4377   EXPECT_EQ(gfx::Rect(5, 6, 10, 20),
4378             parent_view.scheduled_paint_rects_.front());
4379 }
4380 
TEST_F(ViewLayerTest,ParentPaintWhenSwitchingPaintToLayerFromFalseToTrue)4381 TEST_F(ViewLayerTest, ParentPaintWhenSwitchingPaintToLayerFromFalseToTrue) {
4382   TestView parent_view;
4383   parent_view.SetBounds(10, 11, 12, 13);
4384 
4385   TestView* child_view = parent_view.AddChildView(std::make_unique<TestView>());
4386 
4387   parent_view.scheduled_paint_rects_.clear();
4388   child_view->SetPaintToLayer();
4389   EXPECT_EQ(1U, parent_view.scheduled_paint_rects_.size());
4390 }
4391 
TEST_F(ViewLayerTest,NoParentPaintWhenSwitchingPaintToLayerFromTrueToTrue)4392 TEST_F(ViewLayerTest, NoParentPaintWhenSwitchingPaintToLayerFromTrueToTrue) {
4393   TestView parent_view;
4394   parent_view.SetBounds(10, 11, 12, 13);
4395 
4396   TestView* child_view = parent_view.AddChildView(std::make_unique<TestView>());
4397   child_view->SetPaintToLayer();
4398 
4399   parent_view.scheduled_paint_rects_.clear();
4400   EXPECT_EQ(0U, parent_view.scheduled_paint_rects_.size());
4401 }
4402 
4403 // Tests that the visibility of child layers are updated correctly when a View's
4404 // visibility changes.
TEST_F(ViewLayerTest,VisibilityChildLayers)4405 TEST_F(ViewLayerTest, VisibilityChildLayers) {
4406   View* v1 = new View;
4407   v1->SetPaintToLayer();
4408   widget()->SetContentsView(v1);
4409 
4410   View* v2 = v1->AddChildView(std::make_unique<View>());
4411 
4412   View* v3 = v2->AddChildView(std::make_unique<View>());
4413   v3->SetVisible(false);
4414 
4415   View* v4 = v3->AddChildView(std::make_unique<View>());
4416   v4->SetPaintToLayer();
4417 
4418   EXPECT_TRUE(v1->layer()->IsDrawn());
4419   EXPECT_FALSE(v4->layer()->IsDrawn());
4420 
4421   v2->SetVisible(false);
4422   EXPECT_TRUE(v1->layer()->IsDrawn());
4423   EXPECT_FALSE(v4->layer()->IsDrawn());
4424 
4425   v2->SetVisible(true);
4426   EXPECT_TRUE(v1->layer()->IsDrawn());
4427   EXPECT_FALSE(v4->layer()->IsDrawn());
4428 
4429   v2->SetVisible(false);
4430   EXPECT_TRUE(v1->layer()->IsDrawn());
4431   EXPECT_FALSE(v4->layer()->IsDrawn());
4432   EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer()));
4433 
4434   v3->SetVisible(true);
4435   EXPECT_TRUE(v1->layer()->IsDrawn());
4436   EXPECT_FALSE(v4->layer()->IsDrawn());
4437   EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer()));
4438 
4439   // Reparent |v3| to |v1|.
4440   v2->RemoveChildView(v3);
4441   v1->AddChildView(v3);
4442   EXPECT_TRUE(v1->layer()->IsDrawn());
4443   EXPECT_TRUE(v4->layer()->IsDrawn());
4444   EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer()));
4445 }
4446 
4447 // This test creates a random View tree, and then randomly reorders child views,
4448 // reparents views etc. Unrelated changes can appear to break this test. So
4449 // marking this as FLAKY.
TEST_F(ViewLayerTest,DISABLED_ViewLayerTreesInSync)4450 TEST_F(ViewLayerTest, DISABLED_ViewLayerTreesInSync) {
4451   View* content = new View;
4452   content->SetPaintToLayer();
4453   widget()->SetContentsView(content);
4454   widget()->Show();
4455 
4456   ConstructTree(content, 5);
4457   EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
4458 
4459   ScrambleTree(content);
4460   EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
4461 
4462   ScrambleTree(content);
4463   EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
4464 
4465   ScrambleTree(content);
4466   EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
4467 }
4468 
4469 // Verifies when views are reordered the layer is also reordered. The widget is
4470 // providing the parent layer.
TEST_F(ViewLayerTest,ReorderUnderWidget)4471 TEST_F(ViewLayerTest, ReorderUnderWidget) {
4472   View* content = new View;
4473   widget()->SetContentsView(content);
4474   View* c1 = content->AddChildView(std::make_unique<View>());
4475   c1->SetPaintToLayer();
4476   View* c2 = content->AddChildView(std::make_unique<View>());
4477   c2->SetPaintToLayer();
4478 
4479   ui::Layer* parent_layer = c1->layer()->parent();
4480   ASSERT_TRUE(parent_layer);
4481   ASSERT_EQ(2u, parent_layer->children().size());
4482   EXPECT_EQ(c1->layer(), parent_layer->children()[0]);
4483   EXPECT_EQ(c2->layer(), parent_layer->children()[1]);
4484 
4485   // Move c1 to the front. The layers should have moved too.
4486   content->ReorderChildView(c1, -1);
4487   EXPECT_EQ(c1->layer(), parent_layer->children()[1]);
4488   EXPECT_EQ(c2->layer(), parent_layer->children()[0]);
4489 }
4490 
4491 // Verifies that the layer of a view can be acquired properly.
TEST_F(ViewLayerTest,AcquireLayer)4492 TEST_F(ViewLayerTest, AcquireLayer) {
4493   View* content = new View;
4494   widget()->SetContentsView(content);
4495   std::unique_ptr<View> c1(new View);
4496   c1->SetPaintToLayer();
4497   EXPECT_TRUE(c1->layer());
4498   content->AddChildView(c1.get());
4499 
4500   std::unique_ptr<ui::Layer> layer(c1->AcquireLayer());
4501   EXPECT_EQ(layer.get(), c1->layer());
4502 
4503   std::unique_ptr<ui::Layer> layer2(c1->RecreateLayer());
4504   EXPECT_NE(c1->layer(), layer2.get());
4505 
4506   // Destroy view before destroying layer.
4507   c1.reset();
4508 }
4509 
4510 // Verify the z-order of the layers as a result of calling RecreateLayer().
TEST_F(ViewLayerTest,RecreateLayerZOrder)4511 TEST_F(ViewLayerTest, RecreateLayerZOrder) {
4512   std::unique_ptr<View> v(new View());
4513   v->SetPaintToLayer();
4514 
4515   View* v1 = v->AddChildView(std::make_unique<View>());
4516   v1->SetPaintToLayer();
4517   View* v2 = v->AddChildView(std::make_unique<View>());
4518   v2->SetPaintToLayer();
4519 
4520   // Test the initial z-order.
4521   const std::vector<ui::Layer*>& child_layers_pre = v->layer()->children();
4522   ASSERT_EQ(2u, child_layers_pre.size());
4523   EXPECT_EQ(v1->layer(), child_layers_pre[0]);
4524   EXPECT_EQ(v2->layer(), child_layers_pre[1]);
4525 
4526   std::unique_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer());
4527 
4528   // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|.
4529   // for |v1| and |v2|.
4530   const std::vector<ui::Layer*>& child_layers_post = v->layer()->children();
4531   ASSERT_EQ(3u, child_layers_post.size());
4532   EXPECT_EQ(v1->layer(), child_layers_post[0]);
4533   EXPECT_EQ(v1_old_layer.get(), child_layers_post[1]);
4534   EXPECT_EQ(v2->layer(), child_layers_post[2]);
4535 }
4536 
4537 // Verify the z-order of the layers as a result of calling RecreateLayer when
4538 // the widget is the parent with the layer.
TEST_F(ViewLayerTest,RecreateLayerZOrderWidgetParent)4539 TEST_F(ViewLayerTest, RecreateLayerZOrderWidgetParent) {
4540   View* v = new View();
4541   widget()->SetContentsView(v);
4542 
4543   View* v1 = v->AddChildView(std::make_unique<View>());
4544   v1->SetPaintToLayer();
4545   View* v2 = v->AddChildView(std::make_unique<View>());
4546   v2->SetPaintToLayer();
4547 
4548   ui::Layer* root_layer = GetRootLayer();
4549 
4550   // Test the initial z-order.
4551   const std::vector<ui::Layer*>& child_layers_pre = root_layer->children();
4552   ASSERT_EQ(2u, child_layers_pre.size());
4553   EXPECT_EQ(v1->layer(), child_layers_pre[0]);
4554   EXPECT_EQ(v2->layer(), child_layers_pre[1]);
4555 
4556   std::unique_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer());
4557 
4558   // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|.
4559   const std::vector<ui::Layer*>& child_layers_post = root_layer->children();
4560   ASSERT_EQ(3u, child_layers_post.size());
4561   EXPECT_EQ(v1->layer(), child_layers_post[0]);
4562   EXPECT_EQ(v1_old_layer.get(), child_layers_post[1]);
4563   EXPECT_EQ(v2->layer(), child_layers_post[2]);
4564 }
4565 
4566 // Verifies RecreateLayer() moves all Layers over, even those that don't have
4567 // a View.
TEST_F(ViewLayerTest,RecreateLayerMovesNonViewChildren)4568 TEST_F(ViewLayerTest, RecreateLayerMovesNonViewChildren) {
4569   View v;
4570   v.SetPaintToLayer();
4571   View child;
4572   child.SetPaintToLayer();
4573   v.AddChildView(&child);
4574   ASSERT_TRUE(v.layer() != nullptr);
4575   ASSERT_EQ(1u, v.layer()->children().size());
4576   EXPECT_EQ(v.layer()->children()[0], child.layer());
4577 
4578   ui::Layer layer(ui::LAYER_NOT_DRAWN);
4579   v.layer()->Add(&layer);
4580   v.layer()->StackAtBottom(&layer);
4581 
4582   std::unique_ptr<ui::Layer> old_layer(v.RecreateLayer());
4583 
4584   // All children should be moved from old layer to new layer.
4585   ASSERT_TRUE(old_layer.get() != nullptr);
4586   EXPECT_TRUE(old_layer->children().empty());
4587 
4588   // And new layer should have the two children.
4589   ASSERT_TRUE(v.layer() != nullptr);
4590   ASSERT_EQ(2u, v.layer()->children().size());
4591   EXPECT_EQ(v.layer()->children()[0], &layer);
4592   EXPECT_EQ(v.layer()->children()[1], child.layer());
4593 }
4594 
4595 namespace {
4596 
ToString(const gfx::Vector2dF & vector)4597 std::string ToString(const gfx::Vector2dF& vector) {
4598   // Explicitly round it because linux uses banker's rounding
4599   // while Windows is using "away-from-zero" in printf.
4600   return base::StringPrintf("%0.2f %0.2f", std::round(vector.x() * 100) / 100.f,
4601                             std::round(vector.y() * 100) / 100.f);
4602 }
4603 
4604 }  // namespace
4605 
TEST_F(ViewLayerTest,SnapLayerToPixel)4606 TEST_F(ViewLayerTest, SnapLayerToPixel) {
4607   viz::ParentLocalSurfaceIdAllocator allocator;
4608   allocator.GenerateId();
4609   View* v1 = new View;
4610 
4611   View* v11 = v1->AddChildView(std::make_unique<View>());
4612 
4613   widget()->SetContentsView(v1);
4614 
4615   const gfx::Size& size = GetRootLayer()->GetCompositor()->size();
4616   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4617       1.25f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4618 
4619   v11->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
4620   v1->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
4621   v11->SetPaintToLayer();
4622 
4623   EXPECT_EQ("0.40 0.40", ToString(v11->layer()->GetSubpixelOffset()));
4624 
4625   // Creating a layer in parent should update the child view's layer offset.
4626   v1->SetPaintToLayer();
4627   EXPECT_EQ("-0.20 -0.20", ToString(v1->layer()->GetSubpixelOffset()));
4628   EXPECT_EQ("-0.20 -0.20", ToString(v11->layer()->GetSubpixelOffset()));
4629 
4630   // DSF change should get propagated and update offsets.
4631   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4632       1.5f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4633   EXPECT_EQ("0.33 0.33", ToString(v1->layer()->GetSubpixelOffset()));
4634   EXPECT_EQ("0.33 0.33", ToString(v11->layer()->GetSubpixelOffset()));
4635 
4636   // Deleting parent's layer should update the child view's layer's offset.
4637   v1->DestroyLayer();
4638   EXPECT_EQ("0.00 0.00", ToString(v11->layer()->GetSubpixelOffset()));
4639 
4640   // Setting parent view should update the child view's layer's offset.
4641   v1->SetBoundsRect(gfx::Rect(2, 2, 10, 10));
4642   EXPECT_EQ("0.33 0.33", ToString(v11->layer()->GetSubpixelOffset()));
4643 
4644   // Setting integral DSF should reset the offset.
4645   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4646       2.0f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4647   EXPECT_EQ("0.00 0.00", ToString(v11->layer()->GetSubpixelOffset()));
4648 
4649   // DSF reset followed by DSF change should update the offset.
4650   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4651       1.0f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4652   EXPECT_EQ("0.00 0.00", ToString(v11->layer()->GetSubpixelOffset()));
4653   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4654       1.5f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4655   EXPECT_EQ("0.33 0.33", ToString(v11->layer()->GetSubpixelOffset()));
4656 }
4657 
TEST_F(ViewLayerTest,LayerBeneathTriggersPaintToLayer)4658 TEST_F(ViewLayerTest, LayerBeneathTriggersPaintToLayer) {
4659   View root;
4660   root.SetPaintToLayer();
4661 
4662   View* view = root.AddChildView(std::make_unique<View>());
4663   EXPECT_EQ(nullptr, view->layer());
4664 
4665   ui::Layer layer1;
4666   ui::Layer layer2;
4667   view->AddLayerBeneathView(&layer1);
4668   EXPECT_NE(nullptr, view->layer());
4669   view->AddLayerBeneathView(&layer2);
4670   EXPECT_NE(nullptr, view->layer());
4671 
4672   view->RemoveLayerBeneathView(&layer1);
4673   EXPECT_NE(nullptr, view->layer());
4674   view->RemoveLayerBeneathView(&layer2);
4675   EXPECT_EQ(nullptr, view->layer());
4676 }
4677 
TEST_F(ViewLayerTest,LayerBeneathAddedToTree)4678 TEST_F(ViewLayerTest, LayerBeneathAddedToTree) {
4679   View root;
4680   root.SetPaintToLayer();
4681 
4682   ui::Layer layer;
4683   View* view = root.AddChildView(std::make_unique<View>());
4684 
4685   view->AddLayerBeneathView(&layer);
4686   ASSERT_NE(nullptr, view->layer());
4687   EXPECT_TRUE(view->layer()->parent()->Contains(&layer));
4688 
4689   view->RemoveLayerBeneathView(&layer);
4690   EXPECT_EQ(nullptr, layer.parent());
4691 }
4692 
TEST_F(ViewLayerTest,LayerBeneathAtFractionalScale)4693 TEST_F(ViewLayerTest, LayerBeneathAtFractionalScale) {
4694   constexpr float device_scale = 1.5f;
4695 
4696   viz::ParentLocalSurfaceIdAllocator allocator;
4697   allocator.GenerateId();
4698   const gfx::Size& size = GetRootLayer()->GetCompositor()->size();
4699   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4700       device_scale, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4701 
4702   View* view = new View;
4703   widget()->SetContentsView(view);
4704 
4705   ui::Layer layer;
4706   view->AddLayerBeneathView(&layer);
4707 
4708   view->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
4709   EXPECT_NE(gfx::Vector2dF(), view->layer()->GetSubpixelOffset());
4710   EXPECT_EQ(view->layer()->GetSubpixelOffset(), layer.GetSubpixelOffset());
4711 
4712   view->RemoveLayerBeneathView(&layer);
4713 }
4714 
TEST_F(ViewLayerTest,LayerBeneathRemovedOnDestruction)4715 TEST_F(ViewLayerTest, LayerBeneathRemovedOnDestruction) {
4716   View root;
4717   root.SetPaintToLayer();
4718 
4719   auto layer = std::make_unique<ui::Layer>();
4720   View* view = root.AddChildView(std::make_unique<View>());
4721 
4722   // No assertions, just get coverage of deleting the layer while it is added.
4723   view->AddLayerBeneathView(layer.get());
4724   layer.reset();
4725   root.RemoveChildView(view);
4726   delete view;
4727 }
4728 
TEST_F(ViewLayerTest,LayerBeneathVisibilityUpdated)4729 TEST_F(ViewLayerTest, LayerBeneathVisibilityUpdated) {
4730   View root;
4731   root.SetPaintToLayer();
4732 
4733   ui::Layer layer;
4734 
4735   // Make a parent view that has no layer, and a child view that has a layer.
4736   View* parent = root.AddChildView(std::make_unique<View>());
4737   View* child = parent->AddChildView(std::make_unique<View>());
4738   child->AddLayerBeneathView(&layer);
4739 
4740   EXPECT_EQ(nullptr, parent->layer());
4741   EXPECT_NE(nullptr, child->layer());
4742 
4743   // Test setting the views' visbilities in various orders.
4744   EXPECT_TRUE(layer.visible());
4745   child->SetVisible(false);
4746   EXPECT_FALSE(layer.visible());
4747   child->SetVisible(true);
4748   EXPECT_TRUE(layer.visible());
4749 
4750   parent->SetVisible(false);
4751   EXPECT_FALSE(layer.visible());
4752   parent->SetVisible(true);
4753   EXPECT_TRUE(layer.visible());
4754 
4755   parent->SetVisible(false);
4756   EXPECT_FALSE(layer.visible());
4757   child->SetVisible(false);
4758   EXPECT_FALSE(layer.visible());
4759   parent->SetVisible(true);
4760   EXPECT_FALSE(layer.visible());
4761   child->SetVisible(true);
4762   EXPECT_TRUE(layer.visible());
4763 
4764   child->RemoveLayerBeneathView(&layer);
4765 
4766   // Now check the visibility upon adding.
4767   child->SetVisible(false);
4768   child->AddLayerBeneathView(&layer);
4769   EXPECT_FALSE(layer.visible());
4770   child->SetVisible(true);
4771   EXPECT_TRUE(layer.visible());
4772 
4773   child->RemoveLayerBeneathView(&layer);
4774 }
4775 
TEST_F(ViewLayerTest,LayerBeneathHasCorrectBounds)4776 TEST_F(ViewLayerTest, LayerBeneathHasCorrectBounds) {
4777   View root;
4778   root.SetBoundsRect(gfx::Rect(100, 100));
4779   root.SetPaintToLayer();
4780 
4781   View* view = root.AddChildView(std::make_unique<View>());
4782   view->SetBoundsRect(gfx::Rect(25, 25, 50, 50));
4783 
4784   // The layer's position will be changed, but its size should be respected.
4785   ui::Layer layer;
4786   layer.SetBounds(gfx::Rect(25, 25));
4787 
4788   // First check when |view| is already painting to a layer.
4789   view->SetPaintToLayer();
4790   view->AddLayerBeneathView(&layer);
4791   EXPECT_NE(nullptr, layer.parent());
4792   EXPECT_EQ(gfx::Rect(25, 25, 25, 25), layer.bounds());
4793 
4794   view->RemoveLayerBeneathView(&layer);
4795   EXPECT_EQ(nullptr, layer.parent());
4796   layer.SetBounds(gfx::Rect(25, 25));
4797 
4798   // Next check when |view| wasn't painting to a layer.
4799   view->DestroyLayer();
4800   EXPECT_EQ(nullptr, view->layer());
4801   view->AddLayerBeneathView(&layer);
4802   EXPECT_NE(nullptr, view->layer());
4803   EXPECT_NE(nullptr, layer.parent());
4804   EXPECT_EQ(gfx::Rect(25, 25, 25, 25), layer.bounds());
4805 
4806   // Finally check that moving |view| also moves the layer.
4807   view->SetBoundsRect(gfx::Rect(50, 50, 50, 50));
4808   EXPECT_EQ(gfx::Rect(50, 50, 25, 25), layer.bounds());
4809 
4810   view->RemoveLayerBeneathView(&layer);
4811 }
4812 
TEST_F(ViewLayerTest,LayerBeneathTransformed)4813 TEST_F(ViewLayerTest, LayerBeneathTransformed) {
4814   View root;
4815   root.SetPaintToLayer();
4816 
4817   ui::Layer layer;
4818   View* view = root.AddChildView(std::make_unique<View>());
4819   view->SetPaintToLayer();
4820   view->AddLayerBeneathView(&layer);
4821   EXPECT_TRUE(layer.transform().IsIdentity());
4822 
4823   gfx::Transform transform;
4824   transform.Rotate(90);
4825   view->SetTransform(transform);
4826   EXPECT_EQ(transform, layer.transform());
4827   view->SetTransform(gfx::Transform());
4828   EXPECT_TRUE(layer.transform().IsIdentity());
4829 }
4830 
TEST_F(ViewLayerTest,LayerBeneathStackedCorrectly)4831 TEST_F(ViewLayerTest, LayerBeneathStackedCorrectly) {
4832   using ui::test::ChildLayerNamesAsString;
4833 
4834   View root;
4835   root.SetPaintToLayer();
4836 
4837   ui::Layer layer;
4838   layer.SetName("layer");
4839 
4840   View* v1 = root.AddChildView(std::make_unique<View>());
4841   View* v2 = root.AddChildView(std::make_unique<View>());
4842   View* v3 = root.AddChildView(std::make_unique<View>());
4843 
4844   // Check that |layer| is stacked correctly as we add more layers to the tree.
4845   v2->AddLayerBeneathView(&layer);
4846   v2->layer()->SetName("v2");
4847   EXPECT_EQ(ChildLayerNamesAsString(*root.layer()), "layer v2");
4848   v3->SetPaintToLayer();
4849   v3->layer()->SetName("v3");
4850   EXPECT_EQ(ChildLayerNamesAsString(*root.layer()), "layer v2 v3");
4851   v1->SetPaintToLayer();
4852   v1->layer()->SetName("v1");
4853   EXPECT_EQ(ChildLayerNamesAsString(*root.layer()), "v1 layer v2 v3");
4854 
4855   v2->RemoveLayerBeneathView(&layer);
4856 }
4857 
TEST_F(ViewLayerTest,LayerBeneathOrphanedOnRemoval)4858 TEST_F(ViewLayerTest, LayerBeneathOrphanedOnRemoval) {
4859   View root;
4860   root.SetPaintToLayer();
4861 
4862   ui::Layer layer;
4863   View* view = root.AddChildView(std::make_unique<View>());
4864   view->AddLayerBeneathView(&layer);
4865   EXPECT_EQ(layer.parent(), root.layer());
4866 
4867   // Ensure that the layer beneath is orphaned and re-parented appropriately.
4868   root.RemoveChildView(view);
4869   EXPECT_EQ(layer.parent(), nullptr);
4870   root.AddChildView(view);
4871   EXPECT_EQ(layer.parent(), root.layer());
4872 
4873   view->RemoveLayerBeneathView(&layer);
4874 }
4875 
TEST_F(ViewLayerTest,LayerBeneathMovedWithView)4876 TEST_F(ViewLayerTest, LayerBeneathMovedWithView) {
4877   using ui::test::ChildLayerNamesAsString;
4878 
4879   View root;
4880   root.SetPaintToLayer();
4881   root.layer()->SetName("root");
4882 
4883   ui::Layer layer;
4884   layer.SetName("layer");
4885 
4886   View* v1 = root.AddChildView(std::make_unique<View>());
4887   View* v2 = root.AddChildView(std::make_unique<View>());
4888   View* v3 = v1->AddChildView(std::make_unique<View>());
4889 
4890   v1->SetPaintToLayer();
4891   v1->layer()->SetName("v1");
4892   v2->SetPaintToLayer();
4893   v2->layer()->SetName("v2");
4894   v3->SetPaintToLayer();
4895   v3->layer()->SetName("v3");
4896 
4897   // Verify that |layer| is stacked correctly.
4898   v3->AddLayerBeneathView(&layer);
4899   EXPECT_EQ(ChildLayerNamesAsString(*v1->layer()), "layer v3");
4900 
4901   // Move |v3| to under |v2| and check |layer|'s stacking.
4902   v1->RemoveChildView(v3);
4903   v2->AddChildView(std::unique_ptr<View>(v3));
4904   EXPECT_EQ(ChildLayerNamesAsString(*v2->layer()), "layer v3");
4905 }
4906 
4907 namespace {
4908 
4909 class PaintLayerView : public View {
4910  public:
4911   PaintLayerView() = default;
4912 
PaintChildren(const PaintInfo & info)4913   void PaintChildren(const PaintInfo& info) override {
4914     last_paint_info_ = std::make_unique<PaintInfo>(info);
4915     View::PaintChildren(info);
4916   }
4917 
GetLastPaintInfo()4918   std::unique_ptr<PaintInfo> GetLastPaintInfo() {
4919     return std::move(last_paint_info_);
4920   }
4921 
4922  private:
4923   std::unique_ptr<PaintInfo> last_paint_info_;
4924 
4925   DISALLOW_COPY_AND_ASSIGN(PaintLayerView);
4926 };
4927 
4928 }  // namespace
4929 
4930 class ViewLayerPixelCanvasTest : public ViewLayerTest {
4931  public:
4932   ViewLayerPixelCanvasTest() = default;
4933 
4934   ~ViewLayerPixelCanvasTest() override = default;
4935 
SetUpPixelCanvas()4936   void SetUpPixelCanvas() override {
4937     scoped_feature_list_.InitAndEnableFeature(
4938         ::features::kEnablePixelCanvasRecording);
4939   }
4940 
4941   // Test if the recording rects are same with and without layer.
PaintRecordingSizeTest(PaintLayerView * v3,const gfx::Size & expected_size)4942   void PaintRecordingSizeTest(PaintLayerView* v3,
4943                               const gfx::Size& expected_size) {
4944     v3->DestroyLayer();
4945     ui::Compositor* compositor = widget()->GetCompositor();
4946     auto list = base::MakeRefCounted<cc::DisplayItemList>();
4947     ui::PaintContext context(list.get(), compositor->device_scale_factor(),
4948                              gfx::Rect(compositor->size()), true);
4949     widget()->GetRootView()->PaintFromPaintRoot(context);
4950     EXPECT_EQ(expected_size, v3->GetLastPaintInfo()->paint_recording_size());
4951     v3->SetPaintToLayer();
4952     v3->OnPaintLayer(context);
4953     EXPECT_EQ(expected_size, v3->GetLastPaintInfo()->paint_recording_size());
4954   }
4955 
4956  private:
4957   base::test::ScopedFeatureList scoped_feature_list_;
4958 
4959   DISALLOW_COPY_AND_ASSIGN(ViewLayerPixelCanvasTest);
4960 };
4961 
TEST_F(ViewLayerPixelCanvasTest,SnapLayerToPixel)4962 TEST_F(ViewLayerPixelCanvasTest, SnapLayerToPixel) {
4963   viz::ParentLocalSurfaceIdAllocator allocator;
4964   allocator.GenerateId();
4965   View* v1 = new View;
4966   View* v2 = v1->AddChildView(std::make_unique<View>());
4967   PaintLayerView* v3 = v2->AddChildView(std::make_unique<PaintLayerView>());
4968 
4969   widget()->SetContentsView(v1);
4970 
4971   const gfx::Size& size = GetRootLayer()->GetCompositor()->size();
4972   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4973       1.6f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4974 
4975   v3->SetBoundsRect(gfx::Rect(14, 13, 13, 5));
4976   v2->SetBoundsRect(gfx::Rect(7, 7, 50, 50));
4977   v1->SetBoundsRect(gfx::Rect(9, 9, 100, 100));
4978 
4979   PaintRecordingSizeTest(v3, gfx::Size(21, 8));  // Enclosing Rect = (21, 8)
4980   EXPECT_EQ("-0.63 -0.25", ToString(v3->layer()->GetSubpixelOffset()));
4981 
4982   // Creating a layer in parent should update the child view's layer offset.
4983   v1->SetPaintToLayer();
4984   EXPECT_EQ("-0.25 -0.25", ToString(v1->layer()->GetSubpixelOffset()));
4985   EXPECT_EQ("-0.37 -0.00", ToString(v3->layer()->GetSubpixelOffset()));
4986 
4987   // DSF change should get propagated and update offsets.
4988   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4989       1.5f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
4990 
4991   EXPECT_EQ("0.33 0.33", ToString(v1->layer()->GetSubpixelOffset()));
4992   EXPECT_EQ("0.33 0.67", ToString(v3->layer()->GetSubpixelOffset()));
4993 
4994   v1->DestroyLayer();
4995   PaintRecordingSizeTest(v3, gfx::Size(20, 7));  // Enclosing Rect = (20, 8)
4996   v1->SetPaintToLayer();
4997 
4998   GetRootLayer()->GetCompositor()->SetScaleAndSize(
4999       1.33f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
5000 
5001   EXPECT_EQ("0.02 0.02", ToString(v1->layer()->GetSubpixelOffset()));
5002   EXPECT_EQ("0.05 -0.45", ToString(v3->layer()->GetSubpixelOffset()));
5003 
5004   v1->DestroyLayer();
5005   PaintRecordingSizeTest(v3, gfx::Size(17, 7));  // Enclosing Rect = (18, 7)
5006 
5007   // Deleting parent's layer should update the child view's layer's offset.
5008   EXPECT_EQ("0.08 -0.43", ToString(v3->layer()->GetSubpixelOffset()));
5009 
5010   // Setting parent view should update the child view's layer's offset.
5011   v1->SetBoundsRect(gfx::Rect(3, 3, 10, 10));
5012   EXPECT_EQ("0.06 -0.44", ToString(v3->layer()->GetSubpixelOffset()));
5013 
5014   // Setting integral DSF should reset the offset.
5015   GetRootLayer()->GetCompositor()->SetScaleAndSize(
5016       2.0f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
5017   EXPECT_EQ("0.00 0.00", ToString(v3->layer()->GetSubpixelOffset()));
5018 
5019   // DSF reset followed by DSF change should update the offset.
5020   GetRootLayer()->GetCompositor()->SetScaleAndSize(
5021       1.0f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
5022   EXPECT_EQ("0.00 0.00", ToString(v3->layer()->GetSubpixelOffset()));
5023   GetRootLayer()->GetCompositor()->SetScaleAndSize(
5024       1.33f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
5025   EXPECT_EQ("0.06 -0.44", ToString(v3->layer()->GetSubpixelOffset()));
5026 }
5027 
TEST_F(ViewLayerPixelCanvasTest,LayerBeneathOnPixelCanvas)5028 TEST_F(ViewLayerPixelCanvasTest, LayerBeneathOnPixelCanvas) {
5029   constexpr float device_scale = 1.5f;
5030 
5031   viz::ParentLocalSurfaceIdAllocator allocator;
5032   allocator.GenerateId();
5033   const gfx::Size& size = GetRootLayer()->GetCompositor()->size();
5034   GetRootLayer()->GetCompositor()->SetScaleAndSize(
5035       device_scale, size, allocator.GetCurrentLocalSurfaceIdAllocation());
5036 
5037   View* view = new View;
5038   widget()->SetContentsView(view);
5039 
5040   ui::Layer layer;
5041   view->AddLayerBeneathView(&layer);
5042 
5043   view->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
5044   EXPECT_NE(gfx::Vector2dF(), view->layer()->GetSubpixelOffset());
5045   EXPECT_EQ(view->layer()->GetSubpixelOffset(), layer.GetSubpixelOffset());
5046 
5047   view->RemoveLayerBeneathView(&layer);
5048 }
5049 
TEST_F(ViewTest,FocusableAssertions)5050 TEST_F(ViewTest, FocusableAssertions) {
5051   // View subclasses may change insets based on whether they are focusable,
5052   // which effects the preferred size. To avoid preferred size changing around
5053   // these Views need to key off the last value set to SetFocusBehavior(), not
5054   // whether the View is focusable right now. For this reason it's important
5055   // that the return value of GetFocusBehavior() depends on the last value
5056   // passed to SetFocusBehavior and not whether the View is focusable right now.
5057   TestView view;
5058   view.SetFocusBehavior(View::FocusBehavior::ALWAYS);
5059   EXPECT_EQ(View::FocusBehavior::ALWAYS, view.GetFocusBehavior());
5060   view.SetEnabled(false);
5061   EXPECT_EQ(View::FocusBehavior::ALWAYS, view.GetFocusBehavior());
5062   view.SetFocusBehavior(View::FocusBehavior::NEVER);
5063   EXPECT_EQ(View::FocusBehavior::NEVER, view.GetFocusBehavior());
5064   view.SetFocusBehavior(View::FocusBehavior::ACCESSIBLE_ONLY);
5065   EXPECT_EQ(View::FocusBehavior::ACCESSIBLE_ONLY, view.GetFocusBehavior());
5066 }
5067 
5068 ////////////////////////////////////////////////////////////////////////////////
5069 // NativeTheme
5070 ////////////////////////////////////////////////////////////////////////////////
5071 
OnThemeChanged()5072 void TestView::OnThemeChanged() {
5073   View::OnThemeChanged();
5074   native_theme_ = GetNativeTheme();
5075 }
5076 
TEST_F(ViewTest,OnThemeChanged)5077 TEST_F(ViewTest, OnThemeChanged) {
5078   TestView* test_view = new TestView();
5079   EXPECT_FALSE(test_view->native_theme_);
5080 
5081   // Child view added before the widget hierarchy exists should get the
5082   // new native theme notification.
5083   TestView* test_view_child =
5084       test_view->AddChildView(std::make_unique<TestView>());
5085   EXPECT_FALSE(test_view_child->native_theme_);
5086 
5087   std::unique_ptr<Widget> widget(new Widget);
5088   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
5089   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
5090   widget->Init(std::move(params));
5091 
5092   widget->GetRootView()->AddChildView(test_view);
5093   EXPECT_TRUE(test_view->native_theme_);
5094   EXPECT_EQ(widget->GetNativeTheme(), test_view->native_theme_);
5095   EXPECT_TRUE(test_view_child->native_theme_);
5096   EXPECT_EQ(widget->GetNativeTheme(), test_view_child->native_theme_);
5097 
5098   // Child view added after the widget hierarchy exists should also get the
5099   // notification.
5100   TestView* test_view_child_2 =
5101       test_view->AddChildView(std::make_unique<TestView>());
5102   EXPECT_TRUE(test_view_child_2->native_theme_);
5103   EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_);
5104 
5105   widget->CloseNow();
5106 }
5107 
5108 class TestEventHandler : public ui::EventHandler {
5109  public:
TestEventHandler(TestView * view)5110   explicit TestEventHandler(TestView* view)
5111       : view_(view), had_mouse_event_(false) {}
5112   ~TestEventHandler() override = default;
5113 
OnMouseEvent(ui::MouseEvent * event)5114   void OnMouseEvent(ui::MouseEvent* event) override {
5115     // The |view_| should have received the event first.
5116     EXPECT_EQ(ui::ET_MOUSE_PRESSED, view_->last_mouse_event_type_);
5117     had_mouse_event_ = true;
5118   }
5119 
5120   TestView* view_;
5121   bool had_mouse_event_;
5122 };
5123 
TEST_F(ViewTest,ScopedTargetHandlerReceivesEvents)5124 TEST_F(ViewTest, ScopedTargetHandlerReceivesEvents) {
5125   std::unique_ptr<Widget> widget(new Widget);
5126   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
5127   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
5128   params.bounds = gfx::Rect(50, 50, 350, 350);
5129   widget->Init(std::move(params));
5130   View* root = widget->GetRootView();
5131   TestView* v = root->AddChildView(std::make_unique<TestView>());
5132   v->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
5133   v->Reset();
5134   {
5135     TestEventHandler handler(v);
5136     ui::ScopedTargetHandler scoped_target_handler(v, &handler);
5137     // View's target EventHandler should be set to the |scoped_target_handler|.
5138     EXPECT_EQ(&scoped_target_handler,
5139               v->SetTargetHandler(&scoped_target_handler));
5140 
5141     EXPECT_EQ(ui::ET_UNKNOWN, v->last_mouse_event_type_);
5142     gfx::Point p(10, 120);
5143     ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p, p, ui::EventTimeForNow(),
5144                            ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
5145     root->OnMousePressed(pressed);
5146 
5147     // Both the View |v| and the |handler| should have received the event.
5148     EXPECT_EQ(ui::ET_MOUSE_PRESSED, v->last_mouse_event_type_);
5149     EXPECT_TRUE(handler.had_mouse_event_);
5150   }
5151 
5152   // The View should continue receiving events after the |handler| is deleted.
5153   v->Reset();
5154   ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
5155                           ui::EventTimeForNow(), 0, 0);
5156   root->OnMouseReleased(released);
5157   EXPECT_EQ(ui::ET_MOUSE_RELEASED, v->last_mouse_event_type_);
5158 }
5159 
5160 // See comment above test for details.
5161 class WidgetWithCustomTheme : public Widget {
5162  public:
WidgetWithCustomTheme(ui::NativeTheme * theme)5163   explicit WidgetWithCustomTheme(ui::NativeTheme* theme) : theme_(theme) {}
5164   ~WidgetWithCustomTheme() override = default;
5165 
5166   // Widget:
GetNativeTheme() const5167   const ui::NativeTheme* GetNativeTheme() const override { return theme_; }
5168 
5169  private:
5170   ui::NativeTheme* theme_;
5171 
5172   DISALLOW_COPY_AND_ASSIGN(WidgetWithCustomTheme);
5173 };
5174 
5175 // See comment above test for details.
5176 class ViewThatAddsViewInOnThemeChanged : public View {
5177  public:
ViewThatAddsViewInOnThemeChanged()5178   ViewThatAddsViewInOnThemeChanged() { SetPaintToLayer(); }
5179   ~ViewThatAddsViewInOnThemeChanged() override = default;
5180 
on_native_theme_changed_called() const5181   bool on_native_theme_changed_called() const {
5182     return on_native_theme_changed_called_;
5183   }
5184 
5185   // View:
OnThemeChanged()5186   void OnThemeChanged() override {
5187     View::OnThemeChanged();
5188     on_native_theme_changed_called_ = true;
5189     GetWidget()->GetRootView()->AddChildView(std::make_unique<View>());
5190   }
5191 
5192  private:
5193   bool on_native_theme_changed_called_ = false;
5194 
5195   DISALLOW_COPY_AND_ASSIGN(ViewThatAddsViewInOnThemeChanged);
5196 };
5197 
5198 // Creates and adds a new child view to |parent| that has a layer.
AddViewWithChildLayer(View * parent)5199 void AddViewWithChildLayer(View* parent) {
5200   View* child = parent->AddChildView(std::make_unique<View>());
5201   child->SetPaintToLayer();
5202 }
5203 
5204 // This test does the following:
5205 // . creates a couple of views with layers added to the root.
5206 // . Add a view that overrides OnThemeChanged(). In OnThemeChanged() another
5207 // view is added. This sequence triggered DCHECKs or crashes previously. This
5208 // tests verifies that doesn't happen. Reason for crash was OnThemeChanged() was
5209 // called before the layer hierarchy was updated. OnThemeChanged() should be
5210 // called after the layer hierarchy matches the view hierarchy.
TEST_F(ViewTest,CrashOnAddFromFromOnThemeChanged)5211 TEST_F(ViewTest, CrashOnAddFromFromOnThemeChanged) {
5212   ui::TestNativeTheme theme;
5213   WidgetWithCustomTheme widget(&theme);
5214   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
5215   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
5216   params.bounds = gfx::Rect(50, 50, 350, 350);
5217   widget.Init(std::move(params));
5218 
5219   AddViewWithChildLayer(widget.GetRootView());
5220   ViewThatAddsViewInOnThemeChanged* v = widget.GetRootView()->AddChildView(
5221       std::make_unique<ViewThatAddsViewInOnThemeChanged>());
5222   EXPECT_TRUE(v->on_native_theme_changed_called());
5223 }
5224 
5225 // A View that removes its Layer when hidden.
5226 class NoLayerWhenHiddenView : public View {
5227  public:
5228   using RemovedFromWidgetCallback = base::OnceCallback<void()>;
NoLayerWhenHiddenView(RemovedFromWidgetCallback removed_from_widget)5229   explicit NoLayerWhenHiddenView(RemovedFromWidgetCallback removed_from_widget)
5230       : removed_from_widget_(std::move(removed_from_widget)) {
5231     SetPaintToLayer();
5232     SetBounds(0, 0, 100, 100);
5233   }
5234 
was_hidden() const5235   bool was_hidden() const { return was_hidden_; }
5236 
5237   // View:
VisibilityChanged(View * starting_from,bool is_visible)5238   void VisibilityChanged(View* starting_from, bool is_visible) override {
5239     if (!is_visible) {
5240       was_hidden_ = true;
5241       DestroyLayer();
5242     }
5243   }
5244 
RemovedFromWidget()5245   void RemovedFromWidget() override {
5246     if (removed_from_widget_)
5247       std::move(removed_from_widget_).Run();
5248   }
5249 
5250  private:
5251   bool was_hidden_ = false;
5252   RemovedFromWidgetCallback removed_from_widget_;
5253 
5254   DISALLOW_COPY_AND_ASSIGN(NoLayerWhenHiddenView);
5255 };
5256 
5257 // Test that Views can safely manipulate Layers during Widget closure.
TEST_F(ViewTest,DestroyLayerInClose)5258 TEST_F(ViewTest, DestroyLayerInClose) {
5259   bool removed_from_widget = false;
5260   auto widget = std::make_unique<Widget>();
5261   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
5262   widget->Init(std::move(params));
5263   widget->SetBounds(gfx::Rect(0, 0, 100, 100));
5264   auto* view = widget->GetContentsView()->AddChildView(
5265       std::make_unique<NoLayerWhenHiddenView>(base::BindOnce(
5266           [](bool* removed_from_widget) { *removed_from_widget = true; },
5267           &removed_from_widget)));
5268   widget->Show();
5269 
5270   EXPECT_TRUE(view->layer());
5271   EXPECT_TRUE(view->GetWidget());
5272   EXPECT_FALSE(view->was_hidden());
5273 
5274   // Release and close the widget. It will be destroyed once it closes.
5275   widget.release()->Close();
5276   EXPECT_FALSE(view->layer());
5277   // Ensure the layer went away via VisibilityChanged().
5278   EXPECT_TRUE(view->was_hidden());
5279 
5280   // Not removed from Widget until Close() completes.
5281   EXPECT_FALSE(removed_from_widget);
5282   base::RunLoop().RunUntilIdle();  // Let the Close() complete.
5283   EXPECT_TRUE(removed_from_widget);
5284 }
5285 
5286 // A View that keeps the children with a special ID above other children.
5287 class OrderableView : public View {
5288  public:
5289   // ID used by the children that are stacked above other children.
5290   static constexpr int VIEW_ID_RAISED = 1000;
5291 
5292   OrderableView() = default;
5293   ~OrderableView() override = default;
5294 
GetChildrenInZOrder()5295   View::Views GetChildrenInZOrder() override {
5296     View::Views children_in_z_order = children();
5297     std::stable_partition(
5298         children_in_z_order.begin(), children_in_z_order.end(),
5299         [](const View* child) { return child->GetID() != VIEW_ID_RAISED; });
5300     return children_in_z_order;
5301   }
5302 
5303  private:
5304   DISALLOW_COPY_AND_ASSIGN(OrderableView);
5305 };
5306 
TEST_F(ViewTest,ChildViewZOrderChanged)5307 TEST_F(ViewTest, ChildViewZOrderChanged) {
5308   const size_t kNumChildren = 4;
5309   auto view = std::make_unique<OrderableView>();
5310   view->SetPaintToLayer();
5311   for (size_t i = 0; i < kNumChildren; ++i)
5312     AddViewWithChildLayer(view.get());
5313   View::Views children = view->GetChildrenInZOrder();
5314   const std::vector<ui::Layer*>& layers = view->layer()->children();
5315   ASSERT_EQ(kNumChildren, children.size());
5316   ASSERT_EQ(kNumChildren, layers.size());
5317   for (size_t i = 0; i < kNumChildren; ++i) {
5318     EXPECT_EQ(view->children()[i], children[i]);
5319     EXPECT_EQ(view->children()[i]->layer(), layers[i]);
5320   }
5321 
5322   // Raise one of the children in z-order and add another child to reorder.
5323   view->children()[2]->SetID(OrderableView::VIEW_ID_RAISED);
5324   AddViewWithChildLayer(view.get());
5325 
5326   // 2nd child should be now on top, i.e. the last element in the array returned
5327   // by GetChildrenInZOrder(). Its layer should also be above the others.
5328   // The rest of the children and layers order should be unchanged.
5329   const size_t expected_order[] = {0, 1, 3, 4, 2};
5330   children = view->GetChildrenInZOrder();
5331   EXPECT_EQ(kNumChildren + 1, children.size());
5332   EXPECT_EQ(kNumChildren + 1, layers.size());
5333   for (size_t i = 0; i < kNumChildren + 1; ++i) {
5334     EXPECT_EQ(view->children()[expected_order[i]], children[i]);
5335     EXPECT_EQ(view->children()[expected_order[i]]->layer(), layers[i]);
5336   }
5337 }
5338 
TEST_F(ViewTest,AttachChildViewWithComplicatedLayers)5339 TEST_F(ViewTest, AttachChildViewWithComplicatedLayers) {
5340   std::unique_ptr<View> grand_parent_view = std::make_unique<View>();
5341   grand_parent_view->SetPaintToLayer();
5342 
5343   auto parent_view = std::make_unique<OrderableView>();
5344   parent_view->SetPaintToLayer();
5345 
5346   // child_view1 has layer and has id OrderableView::VIEW_ID_RAISED.
5347   View* child_view1 = parent_view->AddChildView(std::make_unique<View>());
5348   child_view1->SetPaintToLayer();
5349   child_view1->SetID(OrderableView::VIEW_ID_RAISED);
5350 
5351   // child_view2 has no layer.
5352   View* child_view2 = parent_view->AddChildView(std::make_unique<View>());
5353   // grand_child_view has layer.
5354   View* grand_child_view = child_view2->AddChildView(std::make_unique<View>());
5355   grand_child_view->SetPaintToLayer();
5356   const std::vector<ui::Layer*>& layers = parent_view->layer()->children();
5357   EXPECT_EQ(2u, layers.size());
5358   EXPECT_EQ(layers[0], grand_child_view->layer());
5359   EXPECT_EQ(layers[1], child_view1->layer());
5360 
5361   // Attach parent_view to grand_parent_view. children layers of parent_view
5362   // should not change.
5363   auto* parent_view_ptr =
5364       grand_parent_view->AddChildView(std::move(parent_view));
5365   const std::vector<ui::Layer*>& layers_after_attached =
5366       parent_view_ptr->layer()->children();
5367   EXPECT_EQ(2u, layers_after_attached.size());
5368   EXPECT_EQ(layers_after_attached[0], grand_child_view->layer());
5369   EXPECT_EQ(layers_after_attached[1], child_view1->layer());
5370 }
5371 
TEST_F(ViewTest,TestEnabledPropertyMetadata)5372 TEST_F(ViewTest, TestEnabledPropertyMetadata) {
5373   auto test_view = std::make_unique<View>();
5374   bool enabled_changed = false;
5375   auto subscription = test_view->AddEnabledChangedCallback(base::BindRepeating(
5376       [](bool* enabled_changed) { *enabled_changed = true; },
5377       &enabled_changed));
5378   views::metadata::ClassMetaData* view_metadata = View::MetaData();
5379   ASSERT_TRUE(view_metadata);
5380   views::metadata::MemberMetaDataBase* enabled_property =
5381       view_metadata->FindMemberData("Enabled");
5382   ASSERT_TRUE(enabled_property);
5383   base::string16 false_value = base::ASCIIToUTF16("false");
5384   enabled_property->SetValueAsString(test_view.get(), false_value);
5385   EXPECT_TRUE(enabled_changed);
5386   EXPECT_FALSE(test_view->GetEnabled());
5387   EXPECT_EQ(enabled_property->GetValueAsString(test_view.get()), false_value);
5388 }
5389 
TEST_F(ViewTest,TestEnabledChangedCallback)5390 TEST_F(ViewTest, TestEnabledChangedCallback) {
5391   auto test_view = std::make_unique<View>();
5392   bool enabled_changed = false;
5393   auto subscription = test_view->AddEnabledChangedCallback(base::BindRepeating(
5394       [](bool* enabled_changed) { *enabled_changed = true; },
5395       &enabled_changed));
5396   test_view->SetEnabled(false);
5397   EXPECT_TRUE(enabled_changed);
5398   EXPECT_FALSE(test_view->GetEnabled());
5399 }
5400 
TEST_F(ViewTest,TestVisibleChangedCallback)5401 TEST_F(ViewTest, TestVisibleChangedCallback) {
5402   auto test_view = std::make_unique<View>();
5403   bool visibility_changed = false;
5404   auto subscription = test_view->AddVisibleChangedCallback(base::BindRepeating(
5405       [](bool* visibility_changed) { *visibility_changed = true; },
5406       &visibility_changed));
5407   test_view->SetVisible(false);
5408   EXPECT_TRUE(visibility_changed);
5409   EXPECT_FALSE(test_view->GetVisible());
5410 }
5411 
TEST_F(ViewTest,TooltipShowsForDisabledView)5412 TEST_F(ViewTest, TooltipShowsForDisabledView) {
5413   auto widget = std::make_unique<Widget>();
5414   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
5415   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
5416   widget->Init(std::move(params));
5417   widget->SetBounds(gfx::Rect(0, 0, 100, 100));
5418 
5419   View enabled_parent;
5420   View* const disabled_child =
5421       enabled_parent.AddChildView(std::make_unique<View>());
5422   disabled_child->SetEnabled(false);
5423 
5424   enabled_parent.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
5425   disabled_child->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
5426   widget->GetContentsView()->AddChildView(&enabled_parent);
5427   widget->Show();
5428 
5429   EXPECT_EQ(disabled_child,
5430             enabled_parent.GetTooltipHandlerForPoint(gfx::Point(50, 50)));
5431 }
5432 
5433 ////////////////////////////////////////////////////////////////////////////////
5434 // Observer tests.
5435 ////////////////////////////////////////////////////////////////////////////////
5436 
5437 class ViewObserverTest : public ViewTest, public ViewObserver {
5438  public:
5439   ViewObserverTest() = default;
5440 
5441   ~ViewObserverTest() override = default;
5442 
5443   // ViewObserver:
OnChildViewAdded(View * parent,View * child)5444   void OnChildViewAdded(View* parent, View* child) override {
5445     child_view_added_times_++;
5446     child_view_added_ = child;
5447     child_view_added_parent_ = parent;
5448   }
OnChildViewRemoved(View * parent,View * child)5449   void OnChildViewRemoved(View* parent, View* child) override {
5450     child_view_removed_times_++;
5451     child_view_removed_ = child;
5452     child_view_removed_parent_ = parent;
5453   }
5454 
OnViewVisibilityChanged(View * view,View * starting_view)5455   void OnViewVisibilityChanged(View* view, View* starting_view) override {
5456     view_visibility_changed_ = view;
5457     view_visibility_changed_starting_ = starting_view;
5458   }
5459 
OnViewBoundsChanged(View * view)5460   void OnViewBoundsChanged(View* view) override { view_bounds_changed_ = view; }
5461 
OnChildViewReordered(View * parent,View * view)5462   void OnChildViewReordered(View* parent, View* view) override {
5463     view_reordered_ = view;
5464   }
5465 
reset()5466   void reset() {
5467     child_view_added_times_ = 0;
5468     child_view_removed_times_ = 0;
5469     child_view_added_ = nullptr;
5470     child_view_added_parent_ = nullptr;
5471     child_view_removed_ = nullptr;
5472     child_view_removed_parent_ = nullptr;
5473     view_visibility_changed_ = nullptr;
5474     view_bounds_changed_ = nullptr;
5475     view_reordered_ = nullptr;
5476   }
5477 
NewView()5478   std::unique_ptr<View> NewView() {
5479     auto view = std::make_unique<View>();
5480     view->AddObserver(this);
5481     return view;
5482   }
5483 
child_view_added_times()5484   int child_view_added_times() { return child_view_added_times_; }
child_view_removed_times()5485   int child_view_removed_times() { return child_view_removed_times_; }
child_view_added() const5486   const View* child_view_added() const { return child_view_added_; }
child_view_added_parent() const5487   const View* child_view_added_parent() const {
5488     return child_view_added_parent_;
5489   }
child_view_removed() const5490   const View* child_view_removed() const { return child_view_removed_; }
child_view_removed_parent() const5491   const View* child_view_removed_parent() const {
5492     return child_view_removed_parent_;
5493   }
view_visibility_changed() const5494   const View* view_visibility_changed() const {
5495     return view_visibility_changed_;
5496   }
view_visibility_changed_starting() const5497   const View* view_visibility_changed_starting() const {
5498     return view_visibility_changed_starting_;
5499   }
view_bounds_changed() const5500   const View* view_bounds_changed() const { return view_bounds_changed_; }
view_reordered() const5501   const View* view_reordered() const { return view_reordered_; }
5502 
5503  private:
5504   int child_view_added_times_ = 0;
5505   int child_view_removed_times_ = 0;
5506 
5507   View* child_view_added_parent_ = nullptr;
5508   View* child_view_added_ = nullptr;
5509   View* child_view_removed_ = nullptr;
5510   View* child_view_removed_parent_ = nullptr;
5511   View* view_visibility_changed_ = nullptr;
5512   View* view_visibility_changed_starting_ = nullptr;
5513   View* view_bounds_changed_ = nullptr;
5514   View* view_reordered_ = nullptr;
5515 
5516   DISALLOW_COPY_AND_ASSIGN(ViewObserverTest);
5517 };
5518 
TEST_F(ViewObserverTest,ViewParentChanged)5519 TEST_F(ViewObserverTest, ViewParentChanged) {
5520   std::unique_ptr<View> parent1 = NewView();
5521   std::unique_ptr<View> parent2 = NewView();
5522   std::unique_ptr<View> child_view = NewView();
5523 
5524   parent1->AddChildView(child_view.get());
5525   EXPECT_EQ(0, child_view_removed_times());
5526   EXPECT_EQ(1, child_view_added_times());
5527   EXPECT_EQ(child_view.get(), child_view_added());
5528   EXPECT_EQ(child_view->parent(), child_view_added_parent());
5529   EXPECT_EQ(child_view->parent(), parent1.get());
5530   reset();
5531 
5532   // Removed from parent1, added to parent2
5533   parent1->RemoveChildView(child_view.get());
5534   parent2->AddChildView(child_view.get());
5535   EXPECT_EQ(1, child_view_removed_times());
5536   EXPECT_EQ(1, child_view_added_times());
5537   EXPECT_EQ(child_view.get(), child_view_removed());
5538   EXPECT_EQ(parent1.get(), child_view_removed_parent());
5539   EXPECT_EQ(child_view.get(), child_view_added());
5540   EXPECT_EQ(child_view->parent(), parent2.get());
5541 
5542   reset();
5543 
5544   parent2->RemoveChildView(child_view.get());
5545   EXPECT_EQ(1, child_view_removed_times());
5546   EXPECT_EQ(0, child_view_added_times());
5547   EXPECT_EQ(child_view.get(), child_view_removed());
5548   EXPECT_EQ(parent2.get(), child_view_removed_parent());
5549 }
5550 
TEST_F(ViewObserverTest,ViewVisibilityChanged)5551 TEST_F(ViewObserverTest, ViewVisibilityChanged) {
5552   std::unique_ptr<View> parent(new View);
5553   View* view = parent->AddChildView(NewView());
5554 
5555   // Ensure setting |view| itself not visible calls the observer.
5556   view->SetVisible(false);
5557   EXPECT_EQ(view, view_visibility_changed());
5558   EXPECT_EQ(view, view_visibility_changed_starting());
5559   reset();
5560 
5561   // Ditto for setting it visible.
5562   view->SetVisible(true);
5563   EXPECT_EQ(view, view_visibility_changed());
5564   EXPECT_EQ(view, view_visibility_changed_starting());
5565   reset();
5566 
5567   // Ensure setting |parent| not visible also calls the
5568   // observer. |view->GetVisible()| should still return true however.
5569   parent->SetVisible(false);
5570   EXPECT_EQ(view, view_visibility_changed());
5571   EXPECT_EQ(parent.get(), view_visibility_changed_starting());
5572 }
5573 
TEST_F(ViewObserverTest,ViewBoundsChanged)5574 TEST_F(ViewObserverTest, ViewBoundsChanged) {
5575   std::unique_ptr<View> view = NewView();
5576   gfx::Rect bounds(2, 2, 2, 2);
5577   view->SetBoundsRect(bounds);
5578   EXPECT_EQ(view.get(), view_bounds_changed());
5579   EXPECT_EQ(bounds, view->bounds());
5580 
5581   reset();
5582 
5583   gfx::Rect new_bounds(1, 1, 1, 1);
5584   view->SetBoundsRect(new_bounds);
5585   EXPECT_EQ(view.get(), view_bounds_changed());
5586   EXPECT_EQ(new_bounds, view->bounds());
5587 }
5588 
TEST_F(ViewObserverTest,ChildViewReordered)5589 TEST_F(ViewObserverTest, ChildViewReordered) {
5590   std::unique_ptr<View> view = NewView();
5591   view->AddChildView(NewView());
5592   View* child_view2 = view->AddChildView(NewView());
5593   view->ReorderChildView(child_view2, 0);
5594   EXPECT_EQ(child_view2, view_reordered());
5595 }
5596 
5597 // Provides a simple parent view implementation which tracks layer change
5598 // notifications from child views.
5599 class TestParentView : public View {
5600  public:
5601   TestParentView() = default;
5602 
Reset()5603   void Reset() {
5604     received_layer_change_notification_ = false;
5605     layer_change_count_ = 0;
5606   }
5607 
received_layer_change_notification() const5608   bool received_layer_change_notification() const {
5609     return received_layer_change_notification_;
5610   }
5611 
layer_change_count() const5612   int layer_change_count() const { return layer_change_count_; }
5613 
5614   // View overrides.
OnChildLayerChanged(View * child)5615   void OnChildLayerChanged(View* child) override {
5616     received_layer_change_notification_ = true;
5617     layer_change_count_++;
5618   }
5619 
5620  private:
5621   // Set to true if we receive the OnChildLayerChanged() notification for a
5622   // child.
5623   bool received_layer_change_notification_ = false;
5624 
5625   // Contains the number of OnChildLayerChanged() notifications for a child.
5626   int layer_change_count_ = 0;
5627 
5628   DISALLOW_COPY_AND_ASSIGN(TestParentView);
5629 };
5630 
5631 // Tests the following cases.
5632 // 1. We receive the OnChildLayerChanged() notification when a layer change
5633 //    occurs in a child view.
5634 // 2. We don't receive two layer changes when a child with an existing layer
5635 //    creates a new layer.
TEST_F(ViewObserverTest,ChildViewLayerNotificationTest)5636 TEST_F(ViewObserverTest, ChildViewLayerNotificationTest) {
5637   std::unique_ptr<TestParentView> parent_view(new TestParentView);
5638   std::unique_ptr<View> child_view = NewView();
5639   parent_view->AddChildView(child_view.get());
5640 
5641   EXPECT_FALSE(parent_view->received_layer_change_notification());
5642   EXPECT_EQ(0, parent_view->layer_change_count());
5643 
5644   child_view->SetPaintToLayer(ui::LAYER_TEXTURED);
5645   EXPECT_TRUE(parent_view->received_layer_change_notification());
5646   EXPECT_EQ(1, parent_view->layer_change_count());
5647 
5648   parent_view->Reset();
5649   child_view->SetPaintToLayer(ui::LAYER_SOLID_COLOR);
5650   EXPECT_TRUE(parent_view->received_layer_change_notification());
5651   EXPECT_EQ(1, parent_view->layer_change_count());
5652 }
5653 
5654 }  // namespace views
5655