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 <map>
6
7#include "base/memory/scoped_ptr.h"
8#include "base/rand_util.h"
9#include "base/strings/string_util.h"
10#include "base/strings/utf_string_conversions.h"
11#include "grit/ui_strings.h"
12#include "ui/base/accelerators/accelerator.h"
13#include "ui/base/clipboard/clipboard.h"
14#include "ui/base/l10n/l10n_util.h"
15#include "ui/compositor/compositor.h"
16#include "ui/compositor/layer.h"
17#include "ui/compositor/layer_animator.h"
18#include "ui/compositor/test/draw_waiter_for_test.h"
19#include "ui/events/event.h"
20#include "ui/events/gestures/gesture_recognizer.h"
21#include "ui/events/keycodes/keyboard_codes.h"
22#include "ui/gfx/canvas.h"
23#include "ui/gfx/path.h"
24#include "ui/gfx/transform.h"
25#include "ui/views/background.h"
26#include "ui/views/controls/native/native_view_host.h"
27#include "ui/views/controls/scroll_view.h"
28#include "ui/views/controls/textfield/textfield.h"
29#include "ui/views/focus/view_storage.h"
30#include "ui/views/test/views_test_base.h"
31#include "ui/views/view.h"
32#include "ui/views/views_delegate.h"
33#include "ui/views/widget/native_widget.h"
34#include "ui/views/widget/root_view.h"
35#include "ui/views/window/dialog_client_view.h"
36#include "ui/views/window/dialog_delegate.h"
37
38using base::ASCIIToUTF16;
39
40namespace {
41
42// Returns true if |ancestor| is an ancestor of |layer|.
43bool LayerIsAncestor(const ui::Layer* ancestor, const ui::Layer* layer) {
44  while (layer && layer != ancestor)
45    layer = layer->parent();
46  return layer == ancestor;
47}
48
49// Convenience functions for walking a View tree.
50const views::View* FirstView(const views::View* view) {
51  const views::View* v = view;
52  while (v->has_children())
53    v = v->child_at(0);
54  return v;
55}
56
57const views::View* NextView(const views::View* view) {
58  const views::View* v = view;
59  const views::View* parent = v->parent();
60  if (!parent)
61    return NULL;
62  int next = parent->GetIndexOf(v) + 1;
63  if (next != parent->child_count())
64    return FirstView(parent->child_at(next));
65  return parent;
66}
67
68// Convenience functions for walking a Layer tree.
69const ui::Layer* FirstLayer(const ui::Layer* layer) {
70  const ui::Layer* l = layer;
71  while (l->children().size() > 0)
72    l = l->children()[0];
73  return l;
74}
75
76const ui::Layer* NextLayer(const ui::Layer* layer) {
77  const ui::Layer* parent = layer->parent();
78  if (!parent)
79    return NULL;
80  const std::vector<ui::Layer*> children = parent->children();
81  size_t index;
82  for (index = 0; index < children.size(); index++) {
83    if (children[index] == layer)
84      break;
85  }
86  size_t next = index + 1;
87  if (next < children.size())
88    return FirstLayer(children[next]);
89  return parent;
90}
91
92// Given the root nodes of a View tree and a Layer tree, makes sure the two
93// trees are in sync.
94bool ViewAndLayerTreeAreConsistent(const views::View* view,
95                                   const ui::Layer* layer) {
96  const views::View* v = FirstView(view);
97  const ui::Layer* l = FirstLayer(layer);
98  while (v && l) {
99    // Find the view with a layer.
100    while (v && !v->layer())
101      v = NextView(v);
102    EXPECT_TRUE(v);
103    if (!v)
104      return false;
105
106    // Check if the View tree and the Layer tree are in sync.
107    EXPECT_EQ(l, v->layer());
108    if (v->layer() != l)
109      return false;
110
111    // Check if the visibility states of the View and the Layer are in sync.
112    EXPECT_EQ(l->IsDrawn(), v->IsDrawn());
113    if (v->IsDrawn() != l->IsDrawn()) {
114      for (const views::View* vv = v; vv; vv = vv->parent())
115        LOG(ERROR) << "V: " << vv << " " << vv->visible() << " "
116                   << vv->IsDrawn() << " " << vv->layer();
117      for (const ui::Layer* ll = l; ll; ll = ll->parent())
118        LOG(ERROR) << "L: " << ll << " " << ll->IsDrawn();
119      return false;
120    }
121
122    // Check if the size of the View and the Layer are in sync.
123    EXPECT_EQ(l->bounds(), v->bounds());
124    if (v->bounds() != l->bounds())
125      return false;
126
127    if (v == view || l == layer)
128      return v == view && l == layer;
129
130    v = NextView(v);
131    l = NextLayer(l);
132  }
133
134  return false;
135}
136
137// Constructs a View tree with the specified depth.
138void ConstructTree(views::View* view, int depth) {
139  if (depth == 0)
140    return;
141  int count = base::RandInt(1, 5);
142  for (int i = 0; i < count; i++) {
143    views::View* v = new views::View;
144    view->AddChildView(v);
145    if (base::RandDouble() > 0.5)
146      v->SetPaintToLayer(true);
147    if (base::RandDouble() < 0.2)
148      v->SetVisible(false);
149
150    ConstructTree(v, depth - 1);
151  }
152}
153
154void ScrambleTree(views::View* view) {
155  int count = view->child_count();
156  if (count == 0)
157    return;
158  for (int i = 0; i < count; i++) {
159    ScrambleTree(view->child_at(i));
160  }
161
162  if (count > 1) {
163    int a = base::RandInt(0, count - 1);
164    int b = base::RandInt(0, count - 1);
165
166    views::View* view_a = view->child_at(a);
167    views::View* view_b = view->child_at(b);
168    view->ReorderChildView(view_a, b);
169    view->ReorderChildView(view_b, a);
170  }
171
172  if (!view->layer() && base::RandDouble() < 0.1)
173    view->SetPaintToLayer(true);
174
175  if (base::RandDouble() < 0.1)
176    view->SetVisible(!view->visible());
177}
178
179// Convenience to make constructing a GestureEvent simpler.
180class GestureEventForTest : public ui::GestureEvent {
181 public:
182  GestureEventForTest(ui::EventType type, int x, int y, int flags)
183      : GestureEvent(type, x, y, flags, base::TimeDelta(),
184                     ui::GestureEventDetails(type, 0.0f, 0.0f), 0) {
185  }
186
187 private:
188  DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
189};
190
191}  // namespace
192
193namespace views {
194
195typedef ViewsTestBase ViewTest;
196
197// A derived class for testing purpose.
198class TestView : public View {
199 public:
200  TestView()
201      : View(),
202        delete_on_pressed_(false),
203        native_theme_(NULL),
204        can_process_events_within_subtree_(true) {}
205  virtual ~TestView() {}
206
207  // Reset all test state
208  void Reset() {
209    did_change_bounds_ = false;
210    last_mouse_event_type_ = 0;
211    location_.SetPoint(0, 0);
212    received_mouse_enter_ = false;
213    received_mouse_exit_ = false;
214    last_gesture_event_type_ = 0;
215    last_gesture_event_was_handled_ = false;
216    last_clip_.setEmpty();
217    accelerator_count_map_.clear();
218    can_process_events_within_subtree_ = true;
219  }
220
221  // Exposed as public for testing.
222  void DoFocus() {
223    views::View::Focus();
224  }
225
226  void DoBlur() {
227    views::View::Blur();
228  }
229
230  bool focusable() const { return View::focusable(); }
231
232  void set_can_process_events_within_subtree(bool can_process) {
233    can_process_events_within_subtree_ = can_process;
234  }
235
236  virtual bool CanProcessEventsWithinSubtree() const OVERRIDE {
237    return can_process_events_within_subtree_;
238  }
239
240  virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
241  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
242  virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
243  virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
244  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
245  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
246
247  // Ignores GestureEvent by default.
248  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
249
250  virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set) OVERRIDE;
251  virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE;
252  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
253
254  virtual void OnNativeThemeChanged(const ui::NativeTheme* native_theme)
255      OVERRIDE;
256
257  // OnBoundsChanged.
258  bool did_change_bounds_;
259  gfx::Rect new_bounds_;
260
261  // MouseEvent.
262  int last_mouse_event_type_;
263  gfx::Point location_;
264  bool received_mouse_enter_;
265  bool received_mouse_exit_;
266  bool delete_on_pressed_;
267
268  // Painting.
269  std::vector<gfx::Rect> scheduled_paint_rects_;
270
271  // GestureEvent
272  int last_gesture_event_type_;
273  bool last_gesture_event_was_handled_;
274
275  // Painting.
276  SkRect last_clip_;
277
278  // Accelerators.
279  std::map<ui::Accelerator, int> accelerator_count_map_;
280
281  // Native theme.
282  const ui::NativeTheme* native_theme_;
283
284  // Value to return from CanProcessEventsWithinSubtree().
285  bool can_process_events_within_subtree_;
286};
287
288// A view subclass that consumes all Gesture events for testing purposes.
289class TestViewConsumeGesture : public TestView {
290 public:
291  TestViewConsumeGesture() : TestView() {}
292  virtual ~TestViewConsumeGesture() {}
293
294 protected:
295  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
296    last_gesture_event_type_ = event->type();
297    location_.SetPoint(event->x(), event->y());
298    event->StopPropagation();
299  }
300
301 private:
302  DISALLOW_COPY_AND_ASSIGN(TestViewConsumeGesture);
303};
304
305// A view subclass that ignores all Gesture events.
306class TestViewIgnoreGesture: public TestView {
307 public:
308  TestViewIgnoreGesture() : TestView() {}
309  virtual ~TestViewIgnoreGesture() {}
310
311 private:
312  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
313  }
314
315  DISALLOW_COPY_AND_ASSIGN(TestViewIgnoreGesture);
316};
317
318// A view subclass that ignores all scroll-gesture events, but consume all other
319// gesture events.
320class TestViewIgnoreScrollGestures : public TestViewConsumeGesture {
321 public:
322  TestViewIgnoreScrollGestures() {}
323  virtual ~TestViewIgnoreScrollGestures() {}
324
325 private:
326  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
327    if (event->IsScrollGestureEvent())
328      return;
329    TestViewConsumeGesture::OnGestureEvent(event);
330  }
331
332  DISALLOW_COPY_AND_ASSIGN(TestViewIgnoreScrollGestures);
333};
334
335////////////////////////////////////////////////////////////////////////////////
336// OnBoundsChanged
337////////////////////////////////////////////////////////////////////////////////
338
339void TestView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
340  did_change_bounds_ = true;
341  new_bounds_ = bounds();
342}
343
344TEST_F(ViewTest, OnBoundsChanged) {
345  TestView v;
346
347  gfx::Rect prev_rect(0, 0, 200, 200);
348  gfx::Rect new_rect(100, 100, 250, 250);
349
350  v.SetBoundsRect(prev_rect);
351  v.Reset();
352  v.SetBoundsRect(new_rect);
353
354  EXPECT_TRUE(v.did_change_bounds_);
355  EXPECT_EQ(v.new_bounds_, new_rect);
356  EXPECT_EQ(v.bounds(), new_rect);
357}
358
359////////////////////////////////////////////////////////////////////////////////
360// MouseEvent
361////////////////////////////////////////////////////////////////////////////////
362
363bool TestView::OnMousePressed(const ui::MouseEvent& event) {
364  last_mouse_event_type_ = event.type();
365  location_.SetPoint(event.x(), event.y());
366  if (delete_on_pressed_)
367    delete this;
368  return true;
369}
370
371bool TestView::OnMouseDragged(const ui::MouseEvent& event) {
372  last_mouse_event_type_ = event.type();
373  location_.SetPoint(event.x(), event.y());
374  return true;
375}
376
377void TestView::OnMouseReleased(const ui::MouseEvent& event) {
378  last_mouse_event_type_ = event.type();
379  location_.SetPoint(event.x(), event.y());
380}
381
382void TestView::OnMouseEntered(const ui::MouseEvent& event) {
383  received_mouse_enter_ = true;
384}
385
386void TestView::OnMouseExited(const ui::MouseEvent& event) {
387  received_mouse_exit_ = true;
388}
389
390TEST_F(ViewTest, MouseEvent) {
391  TestView* v1 = new TestView();
392  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
393
394  TestView* v2 = new TestView();
395  v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
396
397  scoped_ptr<Widget> widget(new Widget);
398  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
399  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
400  params.bounds = gfx::Rect(50, 50, 650, 650);
401  widget->Init(params);
402  internal::RootView* root =
403      static_cast<internal::RootView*>(widget->GetRootView());
404
405  root->AddChildView(v1);
406  v1->AddChildView(v2);
407
408  v1->Reset();
409  v2->Reset();
410
411  gfx::Point p1(110, 120);
412  ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1,
413                         ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
414  root->OnMousePressed(pressed);
415  EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_PRESSED);
416  EXPECT_EQ(v2->location_.x(), 10);
417  EXPECT_EQ(v2->location_.y(), 20);
418  // Make sure v1 did not receive the event
419  EXPECT_EQ(v1->last_mouse_event_type_, 0);
420
421  // Drag event out of bounds. Should still go to v2
422  v1->Reset();
423  v2->Reset();
424  gfx::Point p2(50, 40);
425  ui::MouseEvent dragged(ui::ET_MOUSE_DRAGGED, p2, p2,
426                         ui::EF_LEFT_MOUSE_BUTTON, 0);
427  root->OnMouseDragged(dragged);
428  EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_DRAGGED);
429  EXPECT_EQ(v2->location_.x(), -50);
430  EXPECT_EQ(v2->location_.y(), -60);
431  // Make sure v1 did not receive the event
432  EXPECT_EQ(v1->last_mouse_event_type_, 0);
433
434  // Releasted event out of bounds. Should still go to v2
435  v1->Reset();
436  v2->Reset();
437  ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0,
438                          0);
439  root->OnMouseDragged(released);
440  EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_RELEASED);
441  EXPECT_EQ(v2->location_.x(), -100);
442  EXPECT_EQ(v2->location_.y(), -100);
443  // Make sure v1 did not receive the event
444  EXPECT_EQ(v1->last_mouse_event_type_, 0);
445
446  widget->CloseNow();
447}
448
449// Confirm that a view can be deleted as part of processing a mouse press.
450TEST_F(ViewTest, DeleteOnPressed) {
451  TestView* v1 = new TestView();
452  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
453
454  TestView* v2 = new TestView();
455  v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
456
457  v1->Reset();
458  v2->Reset();
459
460  scoped_ptr<Widget> widget(new Widget);
461  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
462  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
463  params.bounds = gfx::Rect(50, 50, 650, 650);
464  widget->Init(params);
465  View* root = widget->GetRootView();
466
467  root->AddChildView(v1);
468  v1->AddChildView(v2);
469
470  v2->delete_on_pressed_ = true;
471  gfx::Point point(110, 120);
472  ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, point, point,
473                         ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
474  root->OnMousePressed(pressed);
475  EXPECT_EQ(0, v1->child_count());
476
477  widget->CloseNow();
478}
479
480////////////////////////////////////////////////////////////////////////////////
481// GestureEvent
482////////////////////////////////////////////////////////////////////////////////
483
484void TestView::OnGestureEvent(ui::GestureEvent* event) {
485}
486
487TEST_F(ViewTest, GestureEvent) {
488  // Views hierarchy for non delivery of GestureEvent.
489  TestView* v1 = new TestViewConsumeGesture();
490  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
491
492  TestView* v2 = new TestViewConsumeGesture();
493  v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
494
495  TestView* v3 = new TestViewIgnoreGesture();
496  v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
497
498  scoped_ptr<Widget> widget(new Widget());
499  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
500  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
501  params.bounds = gfx::Rect(50, 50, 650, 650);
502  widget->Init(params);
503  internal::RootView* root =
504      static_cast<internal::RootView*>(widget->GetRootView());
505  ui::EventDispatchDetails details;
506
507  root->AddChildView(v1);
508  v1->AddChildView(v2);
509  v2->AddChildView(v3);
510
511  // |v3| completely obscures |v2|, but all the gesture events on |v3| should
512  // reach |v2| because |v3| doesn't process any gesture events. However, since
513  // |v2| does process gesture events, gesture events on |v3| or |v2| should not
514  // reach |v1|.
515
516  v1->Reset();
517  v2->Reset();
518  v3->Reset();
519
520  // Gesture on |v3|
521  GestureEventForTest g1(ui::ET_GESTURE_TAP, 110, 110, 0);
522  details = root->OnEventFromSource(&g1);
523  EXPECT_FALSE(details.dispatcher_destroyed);
524  EXPECT_FALSE(details.target_destroyed);
525
526  EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
527  EXPECT_EQ(gfx::Point(10, 10), v2->location_);
528  EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
529
530  // Simulate an up so that RootView is no longer targetting |v3|.
531  GestureEventForTest g1_up(ui::ET_GESTURE_END, 110, 110, 0);
532  details = root->OnEventFromSource(&g1_up);
533  EXPECT_FALSE(details.dispatcher_destroyed);
534  EXPECT_FALSE(details.target_destroyed);
535
536  v1->Reset();
537  v2->Reset();
538  v3->Reset();
539
540  // Gesture on |v1|
541  GestureEventForTest g2(ui::ET_GESTURE_TAP, 80, 80, 0);
542  details = root->OnEventFromSource(&g2);
543  EXPECT_FALSE(details.dispatcher_destroyed);
544  EXPECT_FALSE(details.target_destroyed);
545
546  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
547  EXPECT_EQ(gfx::Point(80, 80), v1->location_);
548  EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
549
550  // Send event |g1| again. Even though the coordinates target |v3| it should go
551  // to |v1| as that is the view the touch was initially down on.
552  v1->last_gesture_event_type_ = ui::ET_UNKNOWN;
553  v3->last_gesture_event_type_ = ui::ET_UNKNOWN;
554  details = root->OnEventFromSource(&g1);
555  EXPECT_FALSE(details.dispatcher_destroyed);
556  EXPECT_FALSE(details.target_destroyed);
557
558  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
559  EXPECT_EQ(ui::ET_UNKNOWN, v3->last_gesture_event_type_);
560  EXPECT_EQ("110,110", v1->location_.ToString());
561
562  widget->CloseNow();
563}
564
565TEST_F(ViewTest, ScrollGestureEvent) {
566  // Views hierarchy for non delivery of GestureEvent.
567  TestView* v1 = new TestViewConsumeGesture();
568  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
569
570  TestView* v2 = new TestViewIgnoreScrollGestures();
571  v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
572
573  TestView* v3 = new TestViewIgnoreGesture();
574  v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
575
576  scoped_ptr<Widget> widget(new Widget());
577  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
578  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
579  params.bounds = gfx::Rect(50, 50, 650, 650);
580  widget->Init(params);
581  internal::RootView* root =
582      static_cast<internal::RootView*>(widget->GetRootView());
583  ui::EventDispatchDetails details;
584
585  root->AddChildView(v1);
586  v1->AddChildView(v2);
587  v2->AddChildView(v3);
588
589  // |v3| completely obscures |v2|, but all the gesture events on |v3| should
590  // reach |v2| because |v3| doesn't process any gesture events. However, since
591  // |v2| does process gesture events, gesture events on |v3| or |v2| should not
592  // reach |v1|.
593
594  v1->Reset();
595  v2->Reset();
596  v3->Reset();
597
598  // Gesture on |v3|
599  GestureEventForTest g1(ui::ET_GESTURE_TAP, 110, 110, 0);
600  details = root->OnEventFromSource(&g1);
601  EXPECT_FALSE(details.dispatcher_destroyed);
602  EXPECT_FALSE(details.target_destroyed);
603
604  EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
605  EXPECT_EQ(gfx::Point(10, 10), v2->location_);
606  EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
607
608  v2->Reset();
609
610  // Send scroll gestures on |v3|. The gesture should reach |v2|, however,
611  // since it does not process scroll-gesture events, these events should reach
612  // |v1|.
613  GestureEventForTest gscroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, 115, 115, 0);
614  details = root->OnEventFromSource(&gscroll_begin);
615  EXPECT_FALSE(details.dispatcher_destroyed);
616  EXPECT_FALSE(details.target_destroyed);
617
618  EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
619  EXPECT_EQ(ui::ET_GESTURE_SCROLL_BEGIN, v1->last_gesture_event_type_);
620  v1->Reset();
621
622  // Send a second tap on |v1|. The event should reach |v2| since it is the
623  // default gesture handler, and not |v1| (even though it is the view under the
624  // point, and is the scroll event handler).
625  GestureEventForTest second_tap(ui::ET_GESTURE_TAP, 70, 70, 0);
626  details = root->OnEventFromSource(&second_tap);
627  EXPECT_FALSE(details.dispatcher_destroyed);
628  EXPECT_FALSE(details.target_destroyed);
629
630  EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
631  EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
632  v2->Reset();
633
634  GestureEventForTest gscroll_end(ui::ET_GESTURE_SCROLL_END, 50, 50, 0);
635  details = root->OnEventFromSource(&gscroll_end);
636  EXPECT_FALSE(details.dispatcher_destroyed);
637  EXPECT_FALSE(details.target_destroyed);
638
639  EXPECT_EQ(ui::ET_GESTURE_SCROLL_END, v1->last_gesture_event_type_);
640  v1->Reset();
641
642  // Simulate an up so that RootView is no longer targetting |v3|.
643  GestureEventForTest g1_up(ui::ET_GESTURE_END, 110, 110, 0);
644  details = root->OnEventFromSource(&g1_up);
645  EXPECT_FALSE(details.dispatcher_destroyed);
646  EXPECT_FALSE(details.target_destroyed);
647
648  EXPECT_EQ(ui::ET_GESTURE_END, v2->last_gesture_event_type_);
649
650  v1->Reset();
651  v2->Reset();
652  v3->Reset();
653
654  // Gesture on |v1|
655  GestureEventForTest g2(ui::ET_GESTURE_TAP, 80, 80, 0);
656  details = root->OnEventFromSource(&g2);
657  EXPECT_FALSE(details.dispatcher_destroyed);
658  EXPECT_FALSE(details.target_destroyed);
659
660  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
661  EXPECT_EQ(gfx::Point(80, 80), v1->location_);
662  EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
663
664  // Send event |g1| again. Even though the coordinates target |v3| it should go
665  // to |v1| as that is the view the touch was initially down on.
666  v1->last_gesture_event_type_ = ui::ET_UNKNOWN;
667  v3->last_gesture_event_type_ = ui::ET_UNKNOWN;
668  details = root->OnEventFromSource(&g1);
669  EXPECT_FALSE(details.dispatcher_destroyed);
670  EXPECT_FALSE(details.target_destroyed);
671
672  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
673  EXPECT_EQ(ui::ET_UNKNOWN, v3->last_gesture_event_type_);
674  EXPECT_EQ("110,110", v1->location_.ToString());
675
676  widget->CloseNow();
677}
678
679////////////////////////////////////////////////////////////////////////////////
680// Painting
681////////////////////////////////////////////////////////////////////////////////
682
683void TestView::Paint(gfx::Canvas* canvas, const CullSet& cull_set) {
684  canvas->sk_canvas()->getClipBounds(&last_clip_);
685}
686
687void TestView::SchedulePaintInRect(const gfx::Rect& rect) {
688  scheduled_paint_rects_.push_back(rect);
689  View::SchedulePaintInRect(rect);
690}
691
692void CheckRect(const SkRect& check_rect, const SkRect& target_rect) {
693  EXPECT_EQ(target_rect.fLeft, check_rect.fLeft);
694  EXPECT_EQ(target_rect.fRight, check_rect.fRight);
695  EXPECT_EQ(target_rect.fTop, check_rect.fTop);
696  EXPECT_EQ(target_rect.fBottom, check_rect.fBottom);
697}
698
699TEST_F(ViewTest, RemoveNotification) {
700  ViewStorage* vs = ViewStorage::GetInstance();
701  Widget* widget = new Widget;
702  widget->Init(CreateParams(Widget::InitParams::TYPE_POPUP));
703  View* root_view = widget->GetRootView();
704
705  View* v1 = new View;
706  int s1 = vs->CreateStorageID();
707  vs->StoreView(s1, v1);
708  root_view->AddChildView(v1);
709  View* v11 = new View;
710  int s11 = vs->CreateStorageID();
711  vs->StoreView(s11, v11);
712  v1->AddChildView(v11);
713  View* v111 = new View;
714  int s111 = vs->CreateStorageID();
715  vs->StoreView(s111, v111);
716  v11->AddChildView(v111);
717  View* v112 = new View;
718  int s112 = vs->CreateStorageID();
719  vs->StoreView(s112, v112);
720  v11->AddChildView(v112);
721  View* v113 = new View;
722  int s113 = vs->CreateStorageID();
723  vs->StoreView(s113, v113);
724  v11->AddChildView(v113);
725  View* v1131 = new View;
726  int s1131 = vs->CreateStorageID();
727  vs->StoreView(s1131, v1131);
728  v113->AddChildView(v1131);
729  View* v12 = new View;
730  int s12 = vs->CreateStorageID();
731  vs->StoreView(s12, v12);
732  v1->AddChildView(v12);
733
734  View* v2 = new View;
735  int s2 = vs->CreateStorageID();
736  vs->StoreView(s2, v2);
737  root_view->AddChildView(v2);
738  View* v21 = new View;
739  int s21 = vs->CreateStorageID();
740  vs->StoreView(s21, v21);
741  v2->AddChildView(v21);
742  View* v211 = new View;
743  int s211 = vs->CreateStorageID();
744  vs->StoreView(s211, v211);
745  v21->AddChildView(v211);
746
747  size_t stored_views = vs->view_count();
748
749  // Try removing a leaf view.
750  v21->RemoveChildView(v211);
751  EXPECT_EQ(stored_views - 1, vs->view_count());
752  EXPECT_EQ(NULL, vs->RetrieveView(s211));
753  delete v211;  // We won't use this one anymore.
754
755  // Now try removing a view with a hierarchy of depth 1.
756  v11->RemoveChildView(v113);
757  EXPECT_EQ(stored_views - 3, vs->view_count());
758  EXPECT_EQ(NULL, vs->RetrieveView(s113));
759  EXPECT_EQ(NULL, vs->RetrieveView(s1131));
760  delete v113;  // We won't use this one anymore.
761
762  // Now remove even more.
763  root_view->RemoveChildView(v1);
764  EXPECT_EQ(NULL, vs->RetrieveView(s1));
765  EXPECT_EQ(NULL, vs->RetrieveView(s11));
766  EXPECT_EQ(NULL, vs->RetrieveView(s12));
767  EXPECT_EQ(NULL, vs->RetrieveView(s111));
768  EXPECT_EQ(NULL, vs->RetrieveView(s112));
769
770  // Put v1 back for more tests.
771  root_view->AddChildView(v1);
772  vs->StoreView(s1, v1);
773
774  // Synchronously closing the window deletes the view hierarchy, which should
775  // remove all its views from ViewStorage.
776  widget->CloseNow();
777  EXPECT_EQ(stored_views - 10, vs->view_count());
778  EXPECT_EQ(NULL, vs->RetrieveView(s1));
779  EXPECT_EQ(NULL, vs->RetrieveView(s12));
780  EXPECT_EQ(NULL, vs->RetrieveView(s11));
781  EXPECT_EQ(NULL, vs->RetrieveView(s12));
782  EXPECT_EQ(NULL, vs->RetrieveView(s21));
783  EXPECT_EQ(NULL, vs->RetrieveView(s111));
784  EXPECT_EQ(NULL, vs->RetrieveView(s112));
785}
786
787namespace {
788class HitTestView : public View {
789 public:
790  explicit HitTestView(bool has_hittest_mask)
791      : has_hittest_mask_(has_hittest_mask) {
792  }
793  virtual ~HitTestView() {}
794
795 protected:
796  // Overridden from View:
797  virtual bool HasHitTestMask() const OVERRIDE {
798    return has_hittest_mask_;
799  }
800  virtual void GetHitTestMask(HitTestSource source,
801                              gfx::Path* mask) const OVERRIDE {
802    DCHECK(has_hittest_mask_);
803    DCHECK(mask);
804
805    SkScalar w = SkIntToScalar(width());
806    SkScalar h = SkIntToScalar(height());
807
808    // Create a triangular mask within the bounds of this View.
809    mask->moveTo(w / 2, 0);
810    mask->lineTo(w, h);
811    mask->lineTo(0, h);
812    mask->close();
813  }
814
815 private:
816  bool has_hittest_mask_;
817
818  DISALLOW_COPY_AND_ASSIGN(HitTestView);
819};
820
821gfx::Point ConvertPointToView(View* view, const gfx::Point& p) {
822  gfx::Point tmp(p);
823  View::ConvertPointToTarget(view->GetWidget()->GetRootView(), view, &tmp);
824  return tmp;
825}
826
827gfx::Rect ConvertRectToView(View* view, const gfx::Rect& r) {
828  gfx::Rect tmp(r);
829  tmp.set_origin(ConvertPointToView(view, r.origin()));
830  return tmp;
831}
832
833void RotateCounterclockwise(gfx::Transform* transform) {
834  transform->matrix().set3x3(0, -1, 0,
835                             1,  0, 0,
836                             0,  0, 1);
837}
838
839void RotateClockwise(gfx::Transform* transform) {
840  transform->matrix().set3x3( 0, 1, 0,
841                             -1, 0, 0,
842                              0, 0, 1);
843}
844
845}  // namespace
846
847TEST_F(ViewTest, HitTestMasks) {
848  Widget* widget = new Widget;
849  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
850  widget->Init(params);
851  View* root_view = widget->GetRootView();
852  root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
853
854  gfx::Rect v1_bounds = gfx::Rect(0, 0, 100, 100);
855  HitTestView* v1 = new HitTestView(false);
856  v1->SetBoundsRect(v1_bounds);
857  root_view->AddChildView(v1);
858
859  gfx::Rect v2_bounds = gfx::Rect(105, 0, 100, 100);
860  HitTestView* v2 = new HitTestView(true);
861  v2->SetBoundsRect(v2_bounds);
862  root_view->AddChildView(v2);
863
864  gfx::Point v1_centerpoint = v1_bounds.CenterPoint();
865  gfx::Point v2_centerpoint = v2_bounds.CenterPoint();
866  gfx::Point v1_origin = v1_bounds.origin();
867  gfx::Point v2_origin = v2_bounds.origin();
868
869  gfx::Rect r1(10, 10, 110, 15);
870  gfx::Rect r2(106, 1, 98, 98);
871  gfx::Rect r3(0, 0, 300, 300);
872  gfx::Rect r4(115, 342, 200, 10);
873
874  // Test HitTestPoint
875  EXPECT_TRUE(v1->HitTestPoint(ConvertPointToView(v1, v1_centerpoint)));
876  EXPECT_TRUE(v2->HitTestPoint(ConvertPointToView(v2, v2_centerpoint)));
877
878  EXPECT_TRUE(v1->HitTestPoint(ConvertPointToView(v1, v1_origin)));
879  EXPECT_FALSE(v2->HitTestPoint(ConvertPointToView(v2, v2_origin)));
880
881  // Test HitTestRect
882  EXPECT_TRUE(v1->HitTestRect(ConvertRectToView(v1, r1)));
883  EXPECT_FALSE(v2->HitTestRect(ConvertRectToView(v2, r1)));
884
885  EXPECT_FALSE(v1->HitTestRect(ConvertRectToView(v1, r2)));
886  EXPECT_TRUE(v2->HitTestRect(ConvertRectToView(v2, r2)));
887
888  EXPECT_TRUE(v1->HitTestRect(ConvertRectToView(v1, r3)));
889  EXPECT_TRUE(v2->HitTestRect(ConvertRectToView(v2, r3)));
890
891  EXPECT_FALSE(v1->HitTestRect(ConvertRectToView(v1, r4)));
892  EXPECT_FALSE(v2->HitTestRect(ConvertRectToView(v2, r4)));
893
894  // Test GetEventHandlerForPoint
895  EXPECT_EQ(v1, root_view->GetEventHandlerForPoint(v1_centerpoint));
896  EXPECT_EQ(v2, root_view->GetEventHandlerForPoint(v2_centerpoint));
897
898  EXPECT_EQ(v1, root_view->GetEventHandlerForPoint(v1_origin));
899  EXPECT_EQ(root_view, root_view->GetEventHandlerForPoint(v2_origin));
900
901  // Test GetTooltipHandlerForPoint
902  EXPECT_EQ(v1, root_view->GetTooltipHandlerForPoint(v1_centerpoint));
903  EXPECT_EQ(v2, root_view->GetTooltipHandlerForPoint(v2_centerpoint));
904
905  EXPECT_EQ(v1, root_view->GetTooltipHandlerForPoint(v1_origin));
906  EXPECT_EQ(root_view, root_view->GetTooltipHandlerForPoint(v2_origin));
907
908  EXPECT_FALSE(v1->GetTooltipHandlerForPoint(v2_origin));
909
910  widget->CloseNow();
911}
912
913// Tests the correctness of the rect-based targeting algorithm implemented in
914// View::GetEventHandlerForRect(). See http://goo.gl/3Jp2BD for a description
915// of rect-based targeting.
916TEST_F(ViewTest, GetEventHandlerForRect) {
917  Widget* widget = new Widget;
918  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
919  widget->Init(params);
920  View* root_view = widget->GetRootView();
921  root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
922
923  // Have this hierarchy of views (the coordinates here are all in
924  // the root view's coordinate space):
925  // v1 (0, 0, 100, 100)
926  // v2 (150, 0, 250, 100)
927  // v3 (0, 200, 150, 100)
928  //     v31 (10, 210, 80, 80)
929  //     v32 (110, 210, 30, 80)
930  // v4 (300, 200, 100, 100)
931  //     v41 (310, 210, 80, 80)
932  //         v411 (370, 275, 10, 5)
933  // v5 (450, 197, 30, 36)
934  //     v51 (450, 200, 30, 30)
935
936  // The coordinates used for SetBounds are in parent coordinates.
937
938  TestView* v1 = new TestView;
939  v1->SetBounds(0, 0, 100, 100);
940  root_view->AddChildView(v1);
941
942  TestView* v2 = new TestView;
943  v2->SetBounds(150, 0, 250, 100);
944  root_view->AddChildView(v2);
945
946  TestView* v3 = new TestView;
947  v3->SetBounds(0, 200, 150, 100);
948  root_view->AddChildView(v3);
949
950  TestView* v4 = new TestView;
951  v4->SetBounds(300, 200, 100, 100);
952  root_view->AddChildView(v4);
953
954  TestView* v31 = new TestView;
955  v31->SetBounds(10, 10, 80, 80);
956  v3->AddChildView(v31);
957
958  TestView* v32 = new TestView;
959  v32->SetBounds(110, 10, 30, 80);
960  v3->AddChildView(v32);
961
962  TestView* v41 = new TestView;
963  v41->SetBounds(10, 10, 80, 80);
964  v4->AddChildView(v41);
965
966  TestView* v411 = new TestView;
967  v411->SetBounds(60, 65, 10, 5);
968  v41->AddChildView(v411);
969
970  TestView* v5 = new TestView;
971  v5->SetBounds(450, 197, 30, 36);
972  root_view->AddChildView(v5);
973
974  TestView* v51 = new TestView;
975  v51->SetBounds(0, 3, 30, 30);
976  v5->AddChildView(v51);
977
978  // |touch_rect| does not intersect any descendant view of |root_view|.
979  gfx::Rect touch_rect(105, 105, 30, 45);
980  View* result_view = root_view->GetEventHandlerForRect(touch_rect);
981  EXPECT_EQ(root_view, result_view);
982  result_view = NULL;
983
984  // Covers |v1| by at least 60%.
985  touch_rect.SetRect(15, 15, 100, 100);
986  result_view = root_view->GetEventHandlerForRect(touch_rect);
987  EXPECT_EQ(v1, result_view);
988  result_view = NULL;
989
990  // Intersects |v1| but does not cover it by at least 60%. The center
991  // of |touch_rect| is within |v1|.
992  touch_rect.SetRect(50, 50, 5, 10);
993  result_view = root_view->GetEventHandlerForRect(touch_rect);
994  EXPECT_EQ(v1, result_view);
995  result_view = NULL;
996
997  // Intersects |v1| but does not cover it by at least 60%. The center
998  // of |touch_rect| is not within |v1|.
999  touch_rect.SetRect(95, 96, 21, 22);
1000  result_view = root_view->GetEventHandlerForRect(touch_rect);
1001  EXPECT_EQ(root_view, result_view);
1002  result_view = NULL;
1003
1004  // Intersects |v1| and |v2|, but only covers |v2| by at least 60%.
1005  touch_rect.SetRect(95, 10, 300, 120);
1006  result_view = root_view->GetEventHandlerForRect(touch_rect);
1007  EXPECT_EQ(v2, result_view);
1008  result_view = NULL;
1009
1010  // Covers both |v1| and |v2| by at least 60%, but the center point
1011  // of |touch_rect| is closer to the center point of |v2|.
1012  touch_rect.SetRect(20, 20, 400, 100);
1013  result_view = root_view->GetEventHandlerForRect(touch_rect);
1014  EXPECT_EQ(v2, result_view);
1015  result_view = NULL;
1016
1017  // Covers both |v1| and |v2| by at least 60%, but the center point
1018  // of |touch_rect| is closer to the center point of |v1|.
1019  touch_rect.SetRect(-700, -15, 1050, 110);
1020  result_view = root_view->GetEventHandlerForRect(touch_rect);
1021  EXPECT_EQ(v1, result_view);
1022  result_view = NULL;
1023
1024  // A mouse click within |v1| will target |v1|.
1025  touch_rect.SetRect(15, 15, 1, 1);
1026  result_view = root_view->GetEventHandlerForRect(touch_rect);
1027  EXPECT_EQ(v1, result_view);
1028  result_view = NULL;
1029
1030  // Intersects |v3| and |v31| by at least 60% and the center point
1031  // of |touch_rect| is closer to the center point of |v31|.
1032  touch_rect.SetRect(0, 200, 110, 100);
1033  result_view = root_view->GetEventHandlerForRect(touch_rect);
1034  EXPECT_EQ(v31, result_view);
1035  result_view = NULL;
1036
1037  // Intersects |v3| and |v31|, but neither by at least 60%. The
1038  // center point of |touch_rect| lies within |v31|.
1039  touch_rect.SetRect(80, 280, 15, 15);
1040  result_view = root_view->GetEventHandlerForRect(touch_rect);
1041  EXPECT_EQ(v31, result_view);
1042  result_view = NULL;
1043
1044  // Covers |v3|, |v31|, and |v32| all by at least 60%, and the
1045  // center point of |touch_rect| is closest to the center point
1046  // of |v32|.
1047  touch_rect.SetRect(0, 200, 200, 100);
1048  result_view = root_view->GetEventHandlerForRect(touch_rect);
1049  EXPECT_EQ(v32, result_view);
1050  result_view = NULL;
1051
1052  // Intersects all of |v3|, |v31|, and |v32|, but only covers
1053  // |v31| and |v32| by at least 60%. The center point of
1054  // |touch_rect| is closest to the center point of |v32|.
1055  touch_rect.SetRect(30, 225, 180, 115);
1056  result_view = root_view->GetEventHandlerForRect(touch_rect);
1057  EXPECT_EQ(v32, result_view);
1058  result_view = NULL;
1059
1060  // A mouse click at the corner of |v3| will target |v3|.
1061  touch_rect.SetRect(0, 200, 1, 1);
1062  result_view = root_view->GetEventHandlerForRect(touch_rect);
1063  EXPECT_EQ(v3, result_view);
1064  result_view = NULL;
1065
1066  // A mouse click within |v32| will target |v32|.
1067  touch_rect.SetRect(112, 211, 1, 1);
1068  result_view = root_view->GetEventHandlerForRect(touch_rect);
1069  EXPECT_EQ(v32, result_view);
1070  result_view = NULL;
1071
1072  // Covers all of |v4|, |v41|, and |v411| by at least 60%.
1073  // The center point of |touch_rect| is equally close to
1074  // the center points of |v4| and |v41|.
1075  touch_rect.SetRect(310, 210, 80, 80);
1076  result_view = root_view->GetEventHandlerForRect(touch_rect);
1077  EXPECT_EQ(v41, result_view);
1078  result_view = NULL;
1079
1080  // Intersects all of |v4|, |v41|, and |v411| but only covers
1081  // |v411| by at least 60%.
1082  touch_rect.SetRect(370, 275, 7, 5);
1083  result_view = root_view->GetEventHandlerForRect(touch_rect);
1084  EXPECT_EQ(v411, result_view);
1085  result_view = NULL;
1086
1087  // Intersects |v4| and |v41| but covers neither by at least 60%.
1088  // The center point of |touch_rect| is equally close to the center
1089  // points of |v4| and |v41|.
1090  touch_rect.SetRect(345, 245, 7, 7);
1091  result_view = root_view->GetEventHandlerForRect(touch_rect);
1092  EXPECT_EQ(v41, result_view);
1093  result_view = NULL;
1094
1095  // Intersects all of |v4|, |v41|, and |v411| and covers none of
1096  // them by at least 60%. The center point of |touch_rect| lies
1097  // within |v411|.
1098  touch_rect.SetRect(368, 272, 4, 6);
1099  result_view = root_view->GetEventHandlerForRect(touch_rect);
1100  EXPECT_EQ(v411, result_view);
1101  result_view = NULL;
1102
1103  // Intersects all of |v4|, |v41|, and |v411| and covers none of
1104  // them by at least 60%. The center point of |touch_rect| lies
1105  // within |v41|.
1106  touch_rect.SetRect(365, 270, 7, 7);
1107  result_view = root_view->GetEventHandlerForRect(touch_rect);
1108  EXPECT_EQ(v41, result_view);
1109  result_view = NULL;
1110
1111  // Intersects all of |v4|, |v41|, and |v411| and covers none of
1112  // them by at least 60%. The center point of |touch_rect| lies
1113  // within |v4|.
1114  touch_rect.SetRect(205, 275, 200, 2);
1115  result_view = root_view->GetEventHandlerForRect(touch_rect);
1116  EXPECT_EQ(v4, result_view);
1117  result_view = NULL;
1118
1119  // Intersects all of |v4|, |v41|, and |v411| but only covers
1120  // |v41| by at least 60%.
1121  touch_rect.SetRect(310, 210, 61, 66);
1122  result_view = root_view->GetEventHandlerForRect(touch_rect);
1123  EXPECT_EQ(v41, result_view);
1124  result_view = NULL;
1125
1126  // A mouse click within |v411| will target |v411|.
1127  touch_rect.SetRect(372, 275, 1, 1);
1128  result_view = root_view->GetEventHandlerForRect(touch_rect);
1129  EXPECT_EQ(v411, result_view);
1130  result_view = NULL;
1131
1132  // A mouse click within |v41| will target |v41|.
1133  touch_rect.SetRect(350, 215, 1, 1);
1134  result_view = root_view->GetEventHandlerForRect(touch_rect);
1135  EXPECT_EQ(v41, result_view);
1136  result_view = NULL;
1137
1138  // Covers |v3|, |v4|, and all of their descendants by at
1139  // least 60%. The center point of |touch_rect| is closest
1140  // to the center point of |v32|.
1141  touch_rect.SetRect(0, 200, 400, 100);
1142  result_view = root_view->GetEventHandlerForRect(touch_rect);
1143  EXPECT_EQ(v32, result_view);
1144  result_view = NULL;
1145
1146  // Intersects all of |v2|, |v3|, |v32|, |v4|, |v41|, and |v411|.
1147  // Covers |v2|, |v32|, |v4|, |v41|, and |v411| by at least 60%.
1148  // The center point of |touch_rect| is closest to the center
1149  // point of |root_view|.
1150  touch_rect.SetRect(110, 15, 375, 450);
1151  result_view = root_view->GetEventHandlerForRect(touch_rect);
1152  EXPECT_EQ(root_view, result_view);
1153  result_view = NULL;
1154
1155  // Covers all views (except |v5| and |v51|) by at least 60%. The
1156  // center point of |touch_rect| is equally close to the center
1157  // points of |v2| and |v32|. One is not a descendant of the other,
1158  // so in this case the view selected is arbitrary (i.e.,
1159  // it depends only on the ordering of nodes in the views
1160  // hierarchy).
1161  touch_rect.SetRect(0, 0, 400, 300);
1162  result_view = root_view->GetEventHandlerForRect(touch_rect);
1163  EXPECT_EQ(v32, result_view);
1164  result_view = NULL;
1165
1166  // Covers |v5| and |v51| by at least 60%, and the center point of
1167  // the touch is located within both views. Since both views share
1168  // the same center point, the child view should be selected.
1169  touch_rect.SetRect(440, 190, 40, 40);
1170  result_view = root_view->GetEventHandlerForRect(touch_rect);
1171  EXPECT_EQ(v51, result_view);
1172  result_view = NULL;
1173
1174  // Covers |v5| and |v51| by at least 60%, but the center point of
1175  // the touch is not located within either view. Since both views
1176  // share the same center point, the child view should be selected.
1177  touch_rect.SetRect(455, 187, 60, 60);
1178  result_view = root_view->GetEventHandlerForRect(touch_rect);
1179  EXPECT_EQ(v51, result_view);
1180  result_view = NULL;
1181
1182  // Covers neither |v5| nor |v51| by at least 60%, but the center
1183  // of the touch is located within |v51|.
1184  touch_rect.SetRect(450, 197, 10, 10);
1185  result_view = root_view->GetEventHandlerForRect(touch_rect);
1186  EXPECT_EQ(v51, result_view);
1187  result_view = NULL;
1188
1189  // Covers neither |v5| nor |v51| by at least 60% but intersects both.
1190  // The center point is located outside of both views.
1191  touch_rect.SetRect(433, 180, 24, 24);
1192  result_view = root_view->GetEventHandlerForRect(touch_rect);
1193  EXPECT_EQ(root_view, result_view);
1194  result_view = NULL;
1195
1196  // Only intersects |v5| but does not cover it by at least 60%. The
1197  // center point of the touch region is located within |v5|.
1198  touch_rect.SetRect(449, 196, 3, 3);
1199  result_view = root_view->GetEventHandlerForRect(touch_rect);
1200  EXPECT_EQ(v5, result_view);
1201  result_view = NULL;
1202
1203  // A mouse click within |v5| (but not |v51|) should target |v5|.
1204  touch_rect.SetRect(462, 199, 1, 1);
1205  result_view = root_view->GetEventHandlerForRect(touch_rect);
1206  EXPECT_EQ(v5, result_view);
1207  result_view = NULL;
1208
1209  // A mouse click |v5| and |v51| should target the child view.
1210  touch_rect.SetRect(452, 226, 1, 1);
1211  result_view = root_view->GetEventHandlerForRect(touch_rect);
1212  EXPECT_EQ(v51, result_view);
1213  result_view = NULL;
1214
1215  // A mouse click on the center of |v5| and |v51| should target
1216  // the child view.
1217  touch_rect.SetRect(465, 215, 1, 1);
1218  result_view = root_view->GetEventHandlerForRect(touch_rect);
1219  EXPECT_EQ(v51, result_view);
1220  result_view = NULL;
1221
1222  widget->CloseNow();
1223}
1224
1225// Tests that GetEventHandlerForRect() and GetTooltipHandlerForPoint() behave
1226// as expected when different views in the view hierarchy return false
1227// when CanProcessEventsWithinSubtree() is called.
1228TEST_F(ViewTest, CanProcessEventsWithinSubtree) {
1229  Widget* widget = new Widget;
1230  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1231  widget->Init(params);
1232  View* root_view = widget->GetRootView();
1233  root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
1234
1235  // Have this hierarchy of views (the coords here are in the coordinate
1236  // space of the root view):
1237  // v (0, 0, 100, 100)
1238  //  - v_child (0, 0, 20, 30)
1239  //    - v_grandchild (5, 5, 5, 15)
1240
1241  TestView* v = new TestView;
1242  v->SetBounds(0, 0, 100, 100);
1243  root_view->AddChildView(v);
1244  v->set_notify_enter_exit_on_child(true);
1245
1246  TestView* v_child = new TestView;
1247  v_child->SetBounds(0, 0, 20, 30);
1248  v->AddChildView(v_child);
1249
1250  TestView* v_grandchild = new TestView;
1251  v_grandchild->SetBounds(5, 5, 5, 15);
1252  v_child->AddChildView(v_grandchild);
1253
1254  v->Reset();
1255  v_child->Reset();
1256  v_grandchild->Reset();
1257
1258  // Define rects and points within the views in the hierarchy.
1259  gfx::Rect rect_in_v_grandchild(7, 7, 3, 3);
1260  gfx::Point point_in_v_grandchild(rect_in_v_grandchild.origin());
1261  gfx::Rect rect_in_v_child(12, 3, 5, 5);
1262  gfx::Point point_in_v_child(rect_in_v_child.origin());
1263  gfx::Rect rect_in_v(50, 50, 25, 30);
1264  gfx::Point point_in_v(rect_in_v.origin());
1265
1266  // When all three views return true when CanProcessEventsWithinSubtree()
1267  // is called, targeting should behave as expected.
1268
1269  View* result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1270  EXPECT_EQ(v_grandchild, result_view);
1271  result_view = NULL;
1272  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1273  EXPECT_EQ(v_grandchild, result_view);
1274  result_view = NULL;
1275
1276  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1277  EXPECT_EQ(v_child, result_view);
1278  result_view = NULL;
1279  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1280  EXPECT_EQ(v_child, result_view);
1281  result_view = NULL;
1282
1283  result_view = root_view->GetEventHandlerForRect(rect_in_v);
1284  EXPECT_EQ(v, result_view);
1285  result_view = NULL;
1286  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1287  EXPECT_EQ(v, result_view);
1288  result_view = NULL;
1289
1290  // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
1291  // is called, then |v_grandchild| cannot be returned as a target.
1292
1293  v_grandchild->set_can_process_events_within_subtree(false);
1294
1295  result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1296  EXPECT_EQ(v_child, result_view);
1297  result_view = NULL;
1298  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1299  EXPECT_EQ(v_child, result_view);
1300  result_view = NULL;
1301
1302  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1303  EXPECT_EQ(v_child, result_view);
1304  result_view = NULL;
1305  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1306  EXPECT_EQ(v_child, result_view);
1307  result_view = NULL;
1308
1309  result_view = root_view->GetEventHandlerForRect(rect_in_v);
1310  EXPECT_EQ(v, result_view);
1311  result_view = NULL;
1312  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1313  EXPECT_EQ(v, result_view);
1314
1315  // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
1316  // is called, then NULL should be returned as a target if we call
1317  // GetTooltipHandlerForPoint() with |v_grandchild| as the root of the
1318  // views tree. Note that the location must be in the coordinate space
1319  // of the root view (|v_grandchild| in this case), so use (1, 1).
1320
1321  result_view = v_grandchild;
1322  result_view = v_grandchild->GetTooltipHandlerForPoint(gfx::Point(1, 1));
1323  EXPECT_EQ(NULL, result_view);
1324  result_view = NULL;
1325
1326  // When |v_child| returns false when CanProcessEventsWithinSubtree()
1327  // is called, then neither |v_child| nor |v_grandchild| can be returned
1328  // as a target (|v| should be returned as the target for each case).
1329
1330  v_grandchild->Reset();
1331  v_child->set_can_process_events_within_subtree(false);
1332
1333  result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1334  EXPECT_EQ(v, result_view);
1335  result_view = NULL;
1336  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1337  EXPECT_EQ(v, result_view);
1338  result_view = NULL;
1339
1340  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1341  EXPECT_EQ(v, result_view);
1342  result_view = NULL;
1343  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1344  EXPECT_EQ(v, result_view);
1345  result_view = NULL;
1346
1347  result_view = root_view->GetEventHandlerForRect(rect_in_v);
1348  EXPECT_EQ(v, result_view);
1349  result_view = NULL;
1350  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1351  EXPECT_EQ(v, result_view);
1352  result_view = NULL;
1353
1354  // When |v| returns false when CanProcessEventsWithinSubtree()
1355  // is called, then none of |v|, |v_child|, and |v_grandchild| can be returned
1356  // as a target (|root_view| should be returned as the target for each case).
1357
1358  v_child->Reset();
1359  v->set_can_process_events_within_subtree(false);
1360
1361  result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
1362  EXPECT_EQ(root_view, result_view);
1363  result_view = NULL;
1364  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
1365  EXPECT_EQ(root_view, result_view);
1366  result_view = NULL;
1367
1368  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
1369  EXPECT_EQ(root_view, result_view);
1370  result_view = NULL;
1371  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
1372  EXPECT_EQ(root_view, result_view);
1373  result_view = NULL;
1374
1375  result_view = root_view->GetEventHandlerForRect(rect_in_v);
1376  EXPECT_EQ(root_view, result_view);
1377  result_view = NULL;
1378  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
1379  EXPECT_EQ(root_view, result_view);
1380}
1381
1382TEST_F(ViewTest, NotifyEnterExitOnChild) {
1383  Widget* widget = new Widget;
1384  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1385  widget->Init(params);
1386  View* root_view = widget->GetRootView();
1387  root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
1388
1389  // Have this hierarchy of views (the coords here are in root coord):
1390  // v1 (0, 0, 100, 100)
1391  //  - v11 (0, 0, 20, 30)
1392  //    - v111 (5, 5, 5, 15)
1393  //  - v12 (50, 10, 30, 90)
1394  //    - v121 (60, 20, 10, 10)
1395  // v2 (105, 0, 100, 100)
1396  //  - v21 (120, 10, 50, 20)
1397
1398  TestView* v1 = new TestView;
1399  v1->SetBounds(0, 0, 100, 100);
1400  root_view->AddChildView(v1);
1401  v1->set_notify_enter_exit_on_child(true);
1402
1403  TestView* v11 = new TestView;
1404  v11->SetBounds(0, 0, 20, 30);
1405  v1->AddChildView(v11);
1406
1407  TestView* v111 = new TestView;
1408  v111->SetBounds(5, 5, 5, 15);
1409  v11->AddChildView(v111);
1410
1411  TestView* v12 = new TestView;
1412  v12->SetBounds(50, 10, 30, 90);
1413  v1->AddChildView(v12);
1414
1415  TestView* v121 = new TestView;
1416  v121->SetBounds(10, 10, 10, 10);
1417  v12->AddChildView(v121);
1418
1419  TestView* v2 = new TestView;
1420  v2->SetBounds(105, 0, 100, 100);
1421  root_view->AddChildView(v2);
1422
1423  TestView* v21 = new TestView;
1424  v21->SetBounds(15, 10, 50, 20);
1425  v2->AddChildView(v21);
1426
1427  v1->Reset();
1428  v11->Reset();
1429  v111->Reset();
1430  v12->Reset();
1431  v121->Reset();
1432  v2->Reset();
1433  v21->Reset();
1434
1435  // Move the mouse in v111.
1436  gfx::Point p1(6, 6);
1437  ui::MouseEvent move1(ui::ET_MOUSE_MOVED, p1, p1, 0, 0);
1438  root_view->OnMouseMoved(move1);
1439  EXPECT_TRUE(v111->received_mouse_enter_);
1440  EXPECT_FALSE(v11->last_mouse_event_type_);
1441  EXPECT_TRUE(v1->received_mouse_enter_);
1442
1443  v111->Reset();
1444  v1->Reset();
1445
1446  // Now, move into v121.
1447  gfx::Point p2(65, 21);
1448  ui::MouseEvent move2(ui::ET_MOUSE_MOVED, p2, p2, 0, 0);
1449  root_view->OnMouseMoved(move2);
1450  EXPECT_TRUE(v111->received_mouse_exit_);
1451  EXPECT_TRUE(v121->received_mouse_enter_);
1452  EXPECT_FALSE(v1->last_mouse_event_type_);
1453
1454  v111->Reset();
1455  v121->Reset();
1456
1457  // Now, move into v11.
1458  gfx::Point p3(1, 1);
1459  ui::MouseEvent move3(ui::ET_MOUSE_MOVED, p3, p3, 0, 0);
1460  root_view->OnMouseMoved(move3);
1461  EXPECT_TRUE(v121->received_mouse_exit_);
1462  EXPECT_TRUE(v11->received_mouse_enter_);
1463  EXPECT_FALSE(v1->last_mouse_event_type_);
1464
1465  v121->Reset();
1466  v11->Reset();
1467
1468  // Move to v21.
1469  gfx::Point p4(121, 15);
1470  ui::MouseEvent move4(ui::ET_MOUSE_MOVED, p4, p4, 0, 0);
1471  root_view->OnMouseMoved(move4);
1472  EXPECT_TRUE(v21->received_mouse_enter_);
1473  EXPECT_FALSE(v2->last_mouse_event_type_);
1474  EXPECT_TRUE(v11->received_mouse_exit_);
1475  EXPECT_TRUE(v1->received_mouse_exit_);
1476
1477  v21->Reset();
1478  v11->Reset();
1479  v1->Reset();
1480
1481  // Move to v1.
1482  gfx::Point p5(21, 0);
1483  ui::MouseEvent move5(ui::ET_MOUSE_MOVED, p5, p5, 0, 0);
1484  root_view->OnMouseMoved(move5);
1485  EXPECT_TRUE(v21->received_mouse_exit_);
1486  EXPECT_TRUE(v1->received_mouse_enter_);
1487
1488  v21->Reset();
1489  v1->Reset();
1490
1491  // Now, move into v11.
1492  gfx::Point p6(15, 15);
1493  ui::MouseEvent mouse6(ui::ET_MOUSE_MOVED, p6, p6, 0, 0);
1494  root_view->OnMouseMoved(mouse6);
1495  EXPECT_TRUE(v11->received_mouse_enter_);
1496  EXPECT_FALSE(v1->last_mouse_event_type_);
1497
1498  v11->Reset();
1499  v1->Reset();
1500
1501  // Move back into v1. Although |v1| had already received an ENTER for mouse6,
1502  // and the mouse remains inside |v1| the whole time, it receives another ENTER
1503  // when the mouse leaves v11.
1504  gfx::Point p7(21, 0);
1505  ui::MouseEvent mouse7(ui::ET_MOUSE_MOVED, p7, p7, 0, 0);
1506  root_view->OnMouseMoved(mouse7);
1507  EXPECT_TRUE(v11->received_mouse_exit_);
1508  EXPECT_FALSE(v1->received_mouse_enter_);
1509
1510  widget->CloseNow();
1511}
1512
1513TEST_F(ViewTest, Textfield) {
1514  const base::string16 kText = ASCIIToUTF16(
1515      "Reality is that which, when you stop believing it, doesn't go away.");
1516  const base::string16 kExtraText = ASCIIToUTF16("Pretty deep, Philip!");
1517  const base::string16 kEmptyString;
1518
1519  Widget* widget = new Widget;
1520  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1521  params.bounds = gfx::Rect(0, 0, 100, 100);
1522  widget->Init(params);
1523  View* root_view = widget->GetRootView();
1524
1525  Textfield* textfield = new Textfield();
1526  root_view->AddChildView(textfield);
1527
1528  // Test setting, appending text.
1529  textfield->SetText(kText);
1530  EXPECT_EQ(kText, textfield->text());
1531  textfield->AppendText(kExtraText);
1532  EXPECT_EQ(kText + kExtraText, textfield->text());
1533  textfield->SetText(base::string16());
1534  EXPECT_EQ(kEmptyString, textfield->text());
1535
1536  // Test selection related methods.
1537  textfield->SetText(kText);
1538  EXPECT_EQ(kEmptyString, textfield->GetSelectedText());
1539  textfield->SelectAll(false);
1540  EXPECT_EQ(kText, textfield->text());
1541  textfield->ClearSelection();
1542  EXPECT_EQ(kEmptyString, textfield->GetSelectedText());
1543
1544  widget->CloseNow();
1545}
1546
1547// Tests that the Textfield view respond appropiately to cut/copy/paste.
1548TEST_F(ViewTest, TextfieldCutCopyPaste) {
1549  const base::string16 kNormalText = ASCIIToUTF16("Normal");
1550  const base::string16 kReadOnlyText = ASCIIToUTF16("Read only");
1551  const base::string16 kPasswordText =
1552      ASCIIToUTF16("Password! ** Secret stuff **");
1553
1554  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1555
1556  Widget* widget = new Widget;
1557  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1558  params.bounds = gfx::Rect(0, 0, 100, 100);
1559  widget->Init(params);
1560  View* root_view = widget->GetRootView();
1561
1562  Textfield* normal = new Textfield();
1563  Textfield* read_only = new Textfield();
1564  read_only->SetReadOnly(true);
1565  Textfield* password = new Textfield();
1566  password->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
1567
1568  root_view->AddChildView(normal);
1569  root_view->AddChildView(read_only);
1570  root_view->AddChildView(password);
1571
1572  normal->SetText(kNormalText);
1573  read_only->SetText(kReadOnlyText);
1574  password->SetText(kPasswordText);
1575
1576  //
1577  // Test cut.
1578  //
1579
1580  normal->SelectAll(false);
1581  normal->ExecuteCommand(IDS_APP_CUT);
1582  base::string16 result;
1583  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1584  EXPECT_EQ(kNormalText, result);
1585  normal->SetText(kNormalText);  // Let's revert to the original content.
1586
1587  read_only->SelectAll(false);
1588  read_only->ExecuteCommand(IDS_APP_CUT);
1589  result.clear();
1590  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1591  // Cut should have failed, so the clipboard content should not have changed.
1592  EXPECT_EQ(kNormalText, result);
1593
1594  password->SelectAll(false);
1595  password->ExecuteCommand(IDS_APP_CUT);
1596  result.clear();
1597  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1598  // Cut should have failed, so the clipboard content should not have changed.
1599  EXPECT_EQ(kNormalText, result);
1600
1601  //
1602  // Test copy.
1603  //
1604
1605  // Start with |read_only| to observe a change in clipboard text.
1606  read_only->SelectAll(false);
1607  read_only->ExecuteCommand(IDS_APP_COPY);
1608  result.clear();
1609  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1610  EXPECT_EQ(kReadOnlyText, result);
1611
1612  normal->SelectAll(false);
1613  normal->ExecuteCommand(IDS_APP_COPY);
1614  result.clear();
1615  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1616  EXPECT_EQ(kNormalText, result);
1617
1618  password->SelectAll(false);
1619  password->ExecuteCommand(IDS_APP_COPY);
1620  result.clear();
1621  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1622  // Text cannot be copied from an obscured field; the clipboard won't change.
1623  EXPECT_EQ(kNormalText, result);
1624
1625  //
1626  // Test paste.
1627  //
1628
1629  // Attempting to paste kNormalText in a read-only text-field should fail.
1630  read_only->SelectAll(false);
1631  read_only->ExecuteCommand(IDS_APP_PASTE);
1632  EXPECT_EQ(kReadOnlyText, read_only->text());
1633
1634  password->SelectAll(false);
1635  password->ExecuteCommand(IDS_APP_PASTE);
1636  EXPECT_EQ(kNormalText, password->text());
1637
1638  // Copy from |read_only| to observe a change in the normal textfield text.
1639  read_only->SelectAll(false);
1640  read_only->ExecuteCommand(IDS_APP_COPY);
1641  normal->SelectAll(false);
1642  normal->ExecuteCommand(IDS_APP_PASTE);
1643  EXPECT_EQ(kReadOnlyText, normal->text());
1644  widget->CloseNow();
1645}
1646
1647////////////////////////////////////////////////////////////////////////////////
1648// Accelerators
1649////////////////////////////////////////////////////////////////////////////////
1650bool TestView::AcceleratorPressed(const ui::Accelerator& accelerator) {
1651  accelerator_count_map_[accelerator]++;
1652  return true;
1653}
1654
1655// TODO: these tests were initially commented out when getting aura to
1656// run. Figure out if still valuable and either nuke or fix.
1657#if 0
1658TEST_F(ViewTest, ActivateAccelerator) {
1659  // Register a keyboard accelerator before the view is added to a window.
1660  ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
1661  TestView* view = new TestView();
1662  view->Reset();
1663  view->AddAccelerator(return_accelerator);
1664  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 0);
1665
1666  // Create a window and add the view as its child.
1667  scoped_ptr<Widget> widget(new Widget);
1668  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1669  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1670  params.bounds = gfx::Rect(0, 0, 100, 100);
1671  widget->Init(params);
1672  View* root = widget->GetRootView();
1673  root->AddChildView(view);
1674  widget->Show();
1675
1676  // Get the focus manager.
1677  FocusManager* focus_manager = widget->GetFocusManager();
1678  ASSERT_TRUE(focus_manager);
1679
1680  // Hit the return key and see if it takes effect.
1681  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
1682  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
1683
1684  // Hit the escape key. Nothing should happen.
1685  ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, ui::EF_NONE);
1686  EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator));
1687  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
1688  EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 0);
1689
1690  // Now register the escape key and hit it again.
1691  view->AddAccelerator(escape_accelerator);
1692  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
1693  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
1694  EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1);
1695
1696  // Remove the return key accelerator.
1697  view->RemoveAccelerator(return_accelerator);
1698  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
1699  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1);
1700  EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1);
1701
1702  // Add it again. Hit the return key and the escape key.
1703  view->AddAccelerator(return_accelerator);
1704  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
1705  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
1706  EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1);
1707  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
1708  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
1709  EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2);
1710
1711  // Remove all the accelerators.
1712  view->ResetAccelerators();
1713  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
1714  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
1715  EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2);
1716  EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator));
1717  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2);
1718  EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2);
1719
1720  widget->CloseNow();
1721}
1722
1723TEST_F(ViewTest, HiddenViewWithAccelerator) {
1724  ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
1725  TestView* view = new TestView();
1726  view->Reset();
1727  view->AddAccelerator(return_accelerator);
1728  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 0);
1729
1730  scoped_ptr<Widget> widget(new Widget);
1731  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1732  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1733  params.bounds = gfx::Rect(0, 0, 100, 100);
1734  widget->Init(params);
1735  View* root = widget->GetRootView();
1736  root->AddChildView(view);
1737  widget->Show();
1738
1739  FocusManager* focus_manager = widget->GetFocusManager();
1740  ASSERT_TRUE(focus_manager);
1741
1742  view->SetVisible(false);
1743  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
1744
1745  view->SetVisible(true);
1746  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
1747
1748  widget->CloseNow();
1749}
1750
1751TEST_F(ViewTest, ViewInHiddenWidgetWithAccelerator) {
1752  ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
1753  TestView* view = new TestView();
1754  view->Reset();
1755  view->AddAccelerator(return_accelerator);
1756  EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 0);
1757
1758  scoped_ptr<Widget> widget(new Widget);
1759  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1760  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1761  params.bounds = gfx::Rect(0, 0, 100, 100);
1762  widget->Init(params);
1763  View* root = widget->GetRootView();
1764  root->AddChildView(view);
1765
1766  FocusManager* focus_manager = widget->GetFocusManager();
1767  ASSERT_TRUE(focus_manager);
1768
1769  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
1770  EXPECT_EQ(0, view->accelerator_count_map_[return_accelerator]);
1771
1772  widget->Show();
1773  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
1774  EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]);
1775
1776  widget->Hide();
1777  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
1778  EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]);
1779
1780  widget->CloseNow();
1781}
1782
1783////////////////////////////////////////////////////////////////////////////////
1784// Mouse-wheel message rerouting
1785////////////////////////////////////////////////////////////////////////////////
1786class ScrollableTestView : public View {
1787 public:
1788  ScrollableTestView() { }
1789
1790  virtual gfx::Size GetPreferredSize() {
1791    return gfx::Size(100, 10000);
1792  }
1793
1794  virtual void Layout() {
1795    SizeToPreferredSize();
1796  }
1797};
1798
1799class TestViewWithControls : public View {
1800 public:
1801  TestViewWithControls() {
1802    text_field_ = new Textfield();
1803    AddChildView(text_field_);
1804  }
1805
1806  Textfield* text_field_;
1807};
1808
1809class SimpleWidgetDelegate : public WidgetDelegate {
1810 public:
1811  explicit SimpleWidgetDelegate(View* contents) : contents_(contents) {  }
1812
1813  virtual void DeleteDelegate() { delete this; }
1814
1815  virtual View* GetContentsView() { return contents_; }
1816
1817  virtual Widget* GetWidget() { return contents_->GetWidget(); }
1818  virtual const Widget* GetWidget() const { return contents_->GetWidget(); }
1819
1820 private:
1821  View* contents_;
1822};
1823
1824// Tests that the mouse-wheel messages are correctly rerouted to the window
1825// under the mouse.
1826// TODO(jcampan): http://crbug.com/10572 Disabled as it fails on the Vista build
1827//                bot.
1828// Note that this fails for a variety of reasons:
1829// - focused view is apparently reset across window activations and never
1830//   properly restored
1831// - this test depends on you not having any other window visible open under the
1832//   area that it opens the test windows. --beng
1833TEST_F(ViewTest, DISABLED_RerouteMouseWheelTest) {
1834  TestViewWithControls* view_with_controls = new TestViewWithControls();
1835  Widget* window1 = Widget::CreateWindowWithBounds(
1836      new SimpleWidgetDelegate(view_with_controls),
1837      gfx::Rect(0, 0, 100, 100));
1838  window1->Show();
1839  ScrollView* scroll_view = new ScrollView();
1840  scroll_view->SetContents(new ScrollableTestView());
1841  Widget* window2 = Widget::CreateWindowWithBounds(
1842      new SimpleWidgetDelegate(scroll_view),
1843      gfx::Rect(200, 200, 100, 100));
1844  window2->Show();
1845  EXPECT_EQ(0, scroll_view->GetVisibleRect().y());
1846
1847  // Make the window1 active, as this is what it would be in real-world.
1848  window1->Activate();
1849
1850  // Let's send a mouse-wheel message to the different controls and check that
1851  // it is rerouted to the window under the mouse (effectively scrolling the
1852  // scroll-view).
1853
1854  // First to the Window's HWND.
1855  ::SendMessage(view_with_controls->GetWidget()->GetNativeView(),
1856                WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250));
1857  EXPECT_EQ(20, scroll_view->GetVisibleRect().y());
1858
1859  window1->CloseNow();
1860  window2->CloseNow();
1861}
1862#endif  // 0
1863
1864////////////////////////////////////////////////////////////////////////////////
1865// Native view hierachy
1866////////////////////////////////////////////////////////////////////////////////
1867class ToplevelWidgetObserverView : public View {
1868 public:
1869  ToplevelWidgetObserverView() : toplevel_(NULL) {
1870  }
1871  virtual ~ToplevelWidgetObserverView() {
1872  }
1873
1874  // View overrides:
1875  virtual void ViewHierarchyChanged(
1876      const ViewHierarchyChangedDetails& details) OVERRIDE {
1877    if (details.is_add) {
1878      toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : NULL;
1879    } else {
1880      toplevel_ = NULL;
1881    }
1882  }
1883  virtual void NativeViewHierarchyChanged() OVERRIDE {
1884    toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : NULL;
1885  }
1886
1887  Widget* toplevel() { return toplevel_; }
1888
1889 private:
1890  Widget* toplevel_;
1891
1892  DISALLOW_COPY_AND_ASSIGN(ToplevelWidgetObserverView);
1893};
1894
1895// Test that a view can track the current top level widget by overriding
1896// View::ViewHierarchyChanged() and View::NativeViewHierarchyChanged().
1897TEST_F(ViewTest, NativeViewHierarchyChanged) {
1898  scoped_ptr<Widget> toplevel1(new Widget);
1899  Widget::InitParams toplevel1_params =
1900      CreateParams(Widget::InitParams::TYPE_POPUP);
1901  toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1902  toplevel1->Init(toplevel1_params);
1903
1904  scoped_ptr<Widget> toplevel2(new Widget);
1905  Widget::InitParams toplevel2_params =
1906      CreateParams(Widget::InitParams::TYPE_POPUP);
1907  toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1908  toplevel2->Init(toplevel2_params);
1909
1910  Widget* child = new Widget;
1911  Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL);
1912  child_params.parent = toplevel1->GetNativeView();
1913  child->Init(child_params);
1914
1915  ToplevelWidgetObserverView* observer_view =
1916      new ToplevelWidgetObserverView();
1917  EXPECT_EQ(NULL, observer_view->toplevel());
1918
1919  child->SetContentsView(observer_view);
1920  EXPECT_EQ(toplevel1, observer_view->toplevel());
1921
1922  Widget::ReparentNativeView(child->GetNativeView(),
1923                             toplevel2->GetNativeView());
1924  EXPECT_EQ(toplevel2, observer_view->toplevel());
1925
1926  observer_view->parent()->RemoveChildView(observer_view);
1927  EXPECT_EQ(NULL, observer_view->toplevel());
1928
1929  // Make |observer_view| |child|'s contents view again so that it gets deleted
1930  // with the widget.
1931  child->SetContentsView(observer_view);
1932}
1933
1934////////////////////////////////////////////////////////////////////////////////
1935// Transformations
1936////////////////////////////////////////////////////////////////////////////////
1937
1938class TransformPaintView : public TestView {
1939 public:
1940  TransformPaintView() {}
1941  virtual ~TransformPaintView() {}
1942
1943  void ClearScheduledPaintRect() {
1944    scheduled_paint_rect_ = gfx::Rect();
1945  }
1946
1947  gfx::Rect scheduled_paint_rect() const { return scheduled_paint_rect_; }
1948
1949  // Overridden from View:
1950  virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE {
1951    gfx::Rect xrect = ConvertRectToParent(rect);
1952    scheduled_paint_rect_.Union(xrect);
1953  }
1954
1955 private:
1956  gfx::Rect scheduled_paint_rect_;
1957
1958  DISALLOW_COPY_AND_ASSIGN(TransformPaintView);
1959};
1960
1961TEST_F(ViewTest, TransformPaint) {
1962  TransformPaintView* v1 = new TransformPaintView();
1963  v1->SetBoundsRect(gfx::Rect(0, 0, 500, 300));
1964
1965  TestView* v2 = new TestView();
1966  v2->SetBoundsRect(gfx::Rect(100, 100, 200, 100));
1967
1968  Widget* widget = new Widget;
1969  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
1970  params.bounds = gfx::Rect(50, 50, 650, 650);
1971  widget->Init(params);
1972  widget->Show();
1973  View* root = widget->GetRootView();
1974
1975  root->AddChildView(v1);
1976  v1->AddChildView(v2);
1977
1978  // At this moment, |v2| occupies (100, 100) to (300, 200) in |root|.
1979  v1->ClearScheduledPaintRect();
1980  v2->SchedulePaint();
1981
1982  EXPECT_EQ(gfx::Rect(100, 100, 200, 100), v1->scheduled_paint_rect());
1983
1984  // Rotate |v1| counter-clockwise.
1985  gfx::Transform transform;
1986  RotateCounterclockwise(&transform);
1987  transform.matrix().set(1, 3, 500.0);
1988  v1->SetTransform(transform);
1989
1990  // |v2| now occupies (100, 200) to (200, 400) in |root|.
1991
1992  v1->ClearScheduledPaintRect();
1993  v2->SchedulePaint();
1994
1995  EXPECT_EQ(gfx::Rect(100, 200, 100, 200), v1->scheduled_paint_rect());
1996
1997  widget->CloseNow();
1998}
1999
2000TEST_F(ViewTest, TransformEvent) {
2001  TestView* v1 = new TestView();
2002  v1->SetBoundsRect(gfx::Rect(0, 0, 500, 300));
2003
2004  TestView* v2 = new TestView();
2005  v2->SetBoundsRect(gfx::Rect(100, 100, 200, 100));
2006
2007  Widget* widget = new Widget;
2008  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2009  params.bounds = gfx::Rect(50, 50, 650, 650);
2010  widget->Init(params);
2011  View* root = widget->GetRootView();
2012
2013  root->AddChildView(v1);
2014  v1->AddChildView(v2);
2015
2016  // At this moment, |v2| occupies (100, 100) to (300, 200) in |root|.
2017
2018  // Rotate |v1| counter-clockwise.
2019  gfx::Transform transform(v1->GetTransform());
2020  RotateCounterclockwise(&transform);
2021  transform.matrix().set(1, 3, 500.0);
2022  v1->SetTransform(transform);
2023
2024  // |v2| now occupies (100, 200) to (200, 400) in |root|.
2025  v1->Reset();
2026  v2->Reset();
2027
2028  gfx::Point p1(110, 210);
2029  ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1,
2030                         ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2031  root->OnMousePressed(pressed);
2032  EXPECT_EQ(0, v1->last_mouse_event_type_);
2033  EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
2034  EXPECT_EQ(190, v2->location_.x());
2035  EXPECT_EQ(10, v2->location_.y());
2036
2037  ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0,
2038                          0);
2039  root->OnMouseReleased(released);
2040
2041  // Now rotate |v2| inside |v1| clockwise.
2042  transform = v2->GetTransform();
2043  RotateClockwise(&transform);
2044  transform.matrix().set(0, 3, 100.f);
2045  v2->SetTransform(transform);
2046
2047  // Now, |v2| occupies (100, 100) to (200, 300) in |v1|, and (100, 300) to
2048  // (300, 400) in |root|.
2049
2050  v1->Reset();
2051  v2->Reset();
2052
2053  gfx::Point point2(110, 320);
2054  ui::MouseEvent p2(ui::ET_MOUSE_PRESSED, point2, point2,
2055                    ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2056  root->OnMousePressed(p2);
2057  EXPECT_EQ(0, v1->last_mouse_event_type_);
2058  EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_);
2059  EXPECT_EQ(10, v2->location_.x());
2060  EXPECT_EQ(20, v2->location_.y());
2061
2062  root->OnMouseReleased(released);
2063
2064  v1->SetTransform(gfx::Transform());
2065  v2->SetTransform(gfx::Transform());
2066
2067  TestView* v3 = new TestView();
2068  v3->SetBoundsRect(gfx::Rect(10, 10, 20, 30));
2069  v2->AddChildView(v3);
2070
2071  // Rotate |v3| clockwise with respect to |v2|.
2072  transform = v1->GetTransform();
2073  RotateClockwise(&transform);
2074  transform.matrix().set(0, 3, 30.f);
2075  v3->SetTransform(transform);
2076
2077  // Scale |v2| with respect to |v1| along both axis.
2078  transform = v2->GetTransform();
2079  transform.matrix().set(0, 0, 0.8f);
2080  transform.matrix().set(1, 1, 0.5f);
2081  v2->SetTransform(transform);
2082
2083  // |v3| occupies (108, 105) to (132, 115) in |root|.
2084
2085  v1->Reset();
2086  v2->Reset();
2087  v3->Reset();
2088
2089  gfx::Point point(112, 110);
2090  ui::MouseEvent p3(ui::ET_MOUSE_PRESSED, point, point,
2091                    ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2092  root->OnMousePressed(p3);
2093
2094  EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
2095  EXPECT_EQ(10, v3->location_.x());
2096  EXPECT_EQ(25, v3->location_.y());
2097
2098  root->OnMouseReleased(released);
2099
2100  v1->SetTransform(gfx::Transform());
2101  v2->SetTransform(gfx::Transform());
2102  v3->SetTransform(gfx::Transform());
2103
2104  v1->Reset();
2105  v2->Reset();
2106  v3->Reset();
2107
2108  // Rotate |v3| clockwise with respect to |v2|, and scale it along both axis.
2109  transform = v3->GetTransform();
2110  RotateClockwise(&transform);
2111  transform.matrix().set(0, 3, 30.f);
2112  // Rotation sets some scaling transformation. Using SetScale would overwrite
2113  // that and pollute the rotation. So combine the scaling with the existing
2114  // transforamtion.
2115  gfx::Transform scale;
2116  scale.Scale(0.8f, 0.5f);
2117  transform.ConcatTransform(scale);
2118  v3->SetTransform(transform);
2119
2120  // Translate |v2| with respect to |v1|.
2121  transform = v2->GetTransform();
2122  transform.matrix().set(0, 3, 10.f);
2123  transform.matrix().set(1, 3, 10.f);
2124  v2->SetTransform(transform);
2125
2126  // |v3| now occupies (120, 120) to (144, 130) in |root|.
2127
2128  gfx::Point point3(124, 125);
2129  ui::MouseEvent p4(ui::ET_MOUSE_PRESSED, point3, point3,
2130                    ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
2131  root->OnMousePressed(p4);
2132
2133  EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_);
2134  EXPECT_EQ(10, v3->location_.x());
2135  EXPECT_EQ(25, v3->location_.y());
2136
2137  root->OnMouseReleased(released);
2138
2139  widget->CloseNow();
2140}
2141
2142TEST_F(ViewTest, TransformVisibleBound) {
2143  gfx::Rect viewport_bounds(0, 0, 100, 100);
2144
2145  scoped_ptr<Widget> widget(new Widget);
2146  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2147  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2148  params.bounds = viewport_bounds;
2149  widget->Init(params);
2150  widget->GetRootView()->SetBoundsRect(viewport_bounds);
2151
2152  View* viewport = new View;
2153  widget->SetContentsView(viewport);
2154  View* contents = new View;
2155  viewport->AddChildView(contents);
2156  viewport->SetBoundsRect(viewport_bounds);
2157  contents->SetBoundsRect(gfx::Rect(0, 0, 100, 200));
2158
2159  View* child = new View;
2160  contents->AddChildView(child);
2161  child->SetBoundsRect(gfx::Rect(10, 90, 50, 50));
2162  EXPECT_EQ(gfx::Rect(0, 0, 50, 10), child->GetVisibleBounds());
2163
2164  // Rotate |child| counter-clockwise
2165  gfx::Transform transform;
2166  RotateCounterclockwise(&transform);
2167  transform.matrix().set(1, 3, 50.f);
2168  child->SetTransform(transform);
2169  EXPECT_EQ(gfx::Rect(40, 0, 10, 50), child->GetVisibleBounds());
2170
2171  widget->CloseNow();
2172}
2173
2174////////////////////////////////////////////////////////////////////////////////
2175// OnVisibleBoundsChanged()
2176
2177class VisibleBoundsView : public View {
2178 public:
2179  VisibleBoundsView() : received_notification_(false) {}
2180  virtual ~VisibleBoundsView() {}
2181
2182  bool received_notification() const { return received_notification_; }
2183  void set_received_notification(bool received) {
2184    received_notification_ = received;
2185  }
2186
2187 private:
2188  // Overridden from View:
2189  virtual bool NeedsNotificationWhenVisibleBoundsChange() const OVERRIDE {
2190     return true;
2191  }
2192  virtual void OnVisibleBoundsChanged() OVERRIDE {
2193    received_notification_ = true;
2194  }
2195
2196  bool received_notification_;
2197
2198  DISALLOW_COPY_AND_ASSIGN(VisibleBoundsView);
2199};
2200
2201TEST_F(ViewTest, OnVisibleBoundsChanged) {
2202  gfx::Rect viewport_bounds(0, 0, 100, 100);
2203
2204  scoped_ptr<Widget> widget(new Widget);
2205  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2206  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2207  params.bounds = viewport_bounds;
2208  widget->Init(params);
2209  widget->GetRootView()->SetBoundsRect(viewport_bounds);
2210
2211  View* viewport = new View;
2212  widget->SetContentsView(viewport);
2213  View* contents = new View;
2214  viewport->AddChildView(contents);
2215  viewport->SetBoundsRect(viewport_bounds);
2216  contents->SetBoundsRect(gfx::Rect(0, 0, 100, 200));
2217
2218  // Create a view that cares about visible bounds notifications, and position
2219  // it just outside the visible bounds of the viewport.
2220  VisibleBoundsView* child = new VisibleBoundsView;
2221  contents->AddChildView(child);
2222  child->SetBoundsRect(gfx::Rect(10, 110, 50, 50));
2223
2224  // The child bound should be fully clipped.
2225  EXPECT_TRUE(child->GetVisibleBounds().IsEmpty());
2226
2227  // Now scroll the contents, but not enough to make the child visible.
2228  contents->SetY(contents->y() - 1);
2229
2230  // We should have received the notification since the visible bounds may have
2231  // changed (even though they didn't).
2232  EXPECT_TRUE(child->received_notification());
2233  EXPECT_TRUE(child->GetVisibleBounds().IsEmpty());
2234  child->set_received_notification(false);
2235
2236  // Now scroll the contents, this time by enough to make the child visible by
2237  // one pixel.
2238  contents->SetY(contents->y() - 10);
2239  EXPECT_TRUE(child->received_notification());
2240  EXPECT_EQ(1, child->GetVisibleBounds().height());
2241  child->set_received_notification(false);
2242
2243  widget->CloseNow();
2244}
2245
2246TEST_F(ViewTest, SetBoundsPaint) {
2247  TestView top_view;
2248  TestView* child_view = new TestView;
2249
2250  top_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2251  top_view.scheduled_paint_rects_.clear();
2252  child_view->SetBoundsRect(gfx::Rect(10, 10, 20, 20));
2253  top_view.AddChildView(child_view);
2254
2255  top_view.scheduled_paint_rects_.clear();
2256  child_view->SetBoundsRect(gfx::Rect(30, 30, 20, 20));
2257  EXPECT_EQ(2U, top_view.scheduled_paint_rects_.size());
2258
2259  // There should be 2 rects, spanning from (10, 10) to (50, 50).
2260  gfx::Rect paint_rect = top_view.scheduled_paint_rects_[0];
2261  paint_rect.Union(top_view.scheduled_paint_rects_[1]);
2262  EXPECT_EQ(gfx::Rect(10, 10, 40, 40), paint_rect);
2263}
2264
2265// Assertions around painting and focus gain/lost.
2266TEST_F(ViewTest, FocusBlurPaints) {
2267  TestView parent_view;
2268  TestView* child_view1 = new TestView;  // Owned by |parent_view|.
2269
2270  parent_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2271
2272  child_view1->SetBoundsRect(gfx::Rect(0, 0, 20, 20));
2273  parent_view.AddChildView(child_view1);
2274
2275  parent_view.scheduled_paint_rects_.clear();
2276  child_view1->scheduled_paint_rects_.clear();
2277
2278  // Focus change shouldn't trigger paints.
2279  child_view1->DoFocus();
2280
2281  EXPECT_TRUE(parent_view.scheduled_paint_rects_.empty());
2282  EXPECT_TRUE(child_view1->scheduled_paint_rects_.empty());
2283
2284  child_view1->DoBlur();
2285  EXPECT_TRUE(parent_view.scheduled_paint_rects_.empty());
2286  EXPECT_TRUE(child_view1->scheduled_paint_rects_.empty());
2287}
2288
2289// Verifies SetBounds(same bounds) doesn't trigger a SchedulePaint().
2290TEST_F(ViewTest, SetBoundsSameBoundsDoesntSchedulePaint) {
2291  TestView view;
2292
2293  view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2294  view.InvalidateLayout();
2295  view.scheduled_paint_rects_.clear();
2296  view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
2297  EXPECT_TRUE(view.scheduled_paint_rects_.empty());
2298}
2299
2300// Verifies AddChildView() and RemoveChildView() schedule appropriate paints.
2301TEST_F(ViewTest, AddAndRemoveSchedulePaints) {
2302  gfx::Rect viewport_bounds(0, 0, 100, 100);
2303
2304  // We have to put the View hierarchy into a Widget or no paints will be
2305  // scheduled.
2306  scoped_ptr<Widget> widget(new Widget);
2307  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2308  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2309  params.bounds = viewport_bounds;
2310  widget->Init(params);
2311  widget->GetRootView()->SetBoundsRect(viewport_bounds);
2312
2313  TestView* parent_view = new TestView;
2314  widget->SetContentsView(parent_view);
2315  parent_view->SetBoundsRect(viewport_bounds);
2316  parent_view->scheduled_paint_rects_.clear();
2317
2318  View* child_view = new View;
2319  child_view->SetBoundsRect(gfx::Rect(0, 0, 20, 20));
2320  parent_view->AddChildView(child_view);
2321  ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size());
2322  EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front());
2323
2324  parent_view->scheduled_paint_rects_.clear();
2325  parent_view->RemoveChildView(child_view);
2326  scoped_ptr<View> child_deleter(child_view);
2327  ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size());
2328  EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front());
2329
2330  widget->CloseNow();
2331}
2332
2333// Tests conversion methods with a transform.
2334TEST_F(ViewTest, ConversionsWithTransform) {
2335  TestView top_view;
2336
2337  // View hierarchy used to test scale transforms.
2338  TestView* child = new TestView;
2339  TestView* child_child = new TestView;
2340
2341  // View used to test a rotation transform.
2342  TestView* child_2 = new TestView;
2343
2344  top_view.AddChildView(child);
2345  child->AddChildView(child_child);
2346
2347  top_view.SetBoundsRect(gfx::Rect(0, 0, 1000, 1000));
2348
2349  child->SetBoundsRect(gfx::Rect(7, 19, 500, 500));
2350  gfx::Transform transform;
2351  transform.Scale(3.0, 4.0);
2352  child->SetTransform(transform);
2353
2354  child_child->SetBoundsRect(gfx::Rect(17, 13, 100, 100));
2355  transform.MakeIdentity();
2356  transform.Scale(5.0, 7.0);
2357  child_child->SetTransform(transform);
2358
2359  top_view.AddChildView(child_2);
2360  child_2->SetBoundsRect(gfx::Rect(700, 725, 100, 100));
2361  transform.MakeIdentity();
2362  RotateClockwise(&transform);
2363  child_2->SetTransform(transform);
2364
2365  // Sanity check to make sure basic transforms act as expected.
2366  {
2367    gfx::Transform transform;
2368    transform.Translate(110.0, -110.0);
2369    transform.Scale(100.0, 55.0);
2370    transform.Translate(1.0, 1.0);
2371
2372    // convert to a 3x3 matrix.
2373    const SkMatrix& matrix = transform.matrix();
2374
2375    EXPECT_EQ(210, matrix.getTranslateX());
2376    EXPECT_EQ(-55, matrix.getTranslateY());
2377    EXPECT_EQ(100, matrix.getScaleX());
2378    EXPECT_EQ(55, matrix.getScaleY());
2379    EXPECT_EQ(0, matrix.getSkewX());
2380    EXPECT_EQ(0, matrix.getSkewY());
2381  }
2382
2383  {
2384    gfx::Transform transform;
2385    transform.Translate(1.0, 1.0);
2386    gfx::Transform t2;
2387    t2.Scale(100.0, 55.0);
2388    gfx::Transform t3;
2389    t3.Translate(110.0, -110.0);
2390    transform.ConcatTransform(t2);
2391    transform.ConcatTransform(t3);
2392
2393    // convert to a 3x3 matrix
2394    const SkMatrix& matrix = transform.matrix();
2395
2396    EXPECT_EQ(210, matrix.getTranslateX());
2397    EXPECT_EQ(-55, matrix.getTranslateY());
2398    EXPECT_EQ(100, matrix.getScaleX());
2399    EXPECT_EQ(55, matrix.getScaleY());
2400    EXPECT_EQ(0, matrix.getSkewX());
2401    EXPECT_EQ(0, matrix.getSkewY());
2402  }
2403
2404  // Conversions from child->top and top->child.
2405  {
2406    gfx::Point point(5, 5);
2407    View::ConvertPointToTarget(child, &top_view, &point);
2408    EXPECT_EQ(22, point.x());
2409    EXPECT_EQ(39, point.y());
2410
2411    gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f);
2412    View::ConvertRectToTarget(child, &top_view, &rect);
2413    EXPECT_FLOAT_EQ(22.0f, rect.x());
2414    EXPECT_FLOAT_EQ(39.0f, rect.y());
2415    EXPECT_FLOAT_EQ(30.0f, rect.width());
2416    EXPECT_FLOAT_EQ(80.0f, rect.height());
2417
2418    point.SetPoint(22, 39);
2419    View::ConvertPointToTarget(&top_view, child, &point);
2420    EXPECT_EQ(5, point.x());
2421    EXPECT_EQ(5, point.y());
2422
2423    rect.SetRect(22.0f, 39.0f, 30.0f, 80.0f);
2424    View::ConvertRectToTarget(&top_view, child, &rect);
2425    EXPECT_FLOAT_EQ(5.0f, rect.x());
2426    EXPECT_FLOAT_EQ(5.0f, rect.y());
2427    EXPECT_FLOAT_EQ(10.0f, rect.width());
2428    EXPECT_FLOAT_EQ(20.0f, rect.height());
2429  }
2430
2431  // Conversions from child_child->top and top->child_child.
2432  {
2433    gfx::Point point(5, 5);
2434    View::ConvertPointToTarget(child_child, &top_view, &point);
2435    EXPECT_EQ(133, point.x());
2436    EXPECT_EQ(211, point.y());
2437
2438    gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f);
2439    View::ConvertRectToTarget(child_child, &top_view, &rect);
2440    EXPECT_FLOAT_EQ(133.0f, rect.x());
2441    EXPECT_FLOAT_EQ(211.0f, rect.y());
2442    EXPECT_FLOAT_EQ(150.0f, rect.width());
2443    EXPECT_FLOAT_EQ(560.0f, rect.height());
2444
2445    point.SetPoint(133, 211);
2446    View::ConvertPointToTarget(&top_view, child_child, &point);
2447    EXPECT_EQ(5, point.x());
2448    EXPECT_EQ(5, point.y());
2449
2450    rect.SetRect(133.0f, 211.0f, 150.0f, 560.0f);
2451    View::ConvertRectToTarget(&top_view, child_child, &rect);
2452    EXPECT_FLOAT_EQ(5.0f, rect.x());
2453    EXPECT_FLOAT_EQ(5.0f, rect.y());
2454    EXPECT_FLOAT_EQ(10.0f, rect.width());
2455    EXPECT_FLOAT_EQ(20.0f, rect.height());
2456  }
2457
2458  // Conversions from child_child->child and child->child_child
2459  {
2460    gfx::Point point(5, 5);
2461    View::ConvertPointToTarget(child_child, child, &point);
2462    EXPECT_EQ(42, point.x());
2463    EXPECT_EQ(48, point.y());
2464
2465    gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f);
2466    View::ConvertRectToTarget(child_child, child, &rect);
2467    EXPECT_FLOAT_EQ(42.0f, rect.x());
2468    EXPECT_FLOAT_EQ(48.0f, rect.y());
2469    EXPECT_FLOAT_EQ(50.0f, rect.width());
2470    EXPECT_FLOAT_EQ(140.0f, rect.height());
2471
2472    point.SetPoint(42, 48);
2473    View::ConvertPointToTarget(child, child_child, &point);
2474    EXPECT_EQ(5, point.x());
2475    EXPECT_EQ(5, point.y());
2476
2477    rect.SetRect(42.0f, 48.0f, 50.0f, 140.0f);
2478    View::ConvertRectToTarget(child, child_child, &rect);
2479    EXPECT_FLOAT_EQ(5.0f, rect.x());
2480    EXPECT_FLOAT_EQ(5.0f, rect.y());
2481    EXPECT_FLOAT_EQ(10.0f, rect.width());
2482    EXPECT_FLOAT_EQ(20.0f, rect.height());
2483  }
2484
2485  // Conversions from top_view to child with a value that should be negative.
2486  // This ensures we don't round up with negative numbers.
2487  {
2488    gfx::Point point(6, 18);
2489    View::ConvertPointToTarget(&top_view, child, &point);
2490    EXPECT_EQ(-1, point.x());
2491    EXPECT_EQ(-1, point.y());
2492
2493    float error = 0.01f;
2494    gfx::RectF rect(6.0f, 18.0f, 10.0f, 39.0f);
2495    View::ConvertRectToTarget(&top_view, child, &rect);
2496    EXPECT_NEAR(-0.33f, rect.x(), error);
2497    EXPECT_NEAR(-0.25f, rect.y(), error);
2498    EXPECT_NEAR(3.33f, rect.width(), error);
2499    EXPECT_NEAR(9.75f, rect.height(), error);
2500  }
2501
2502  // Rect conversions from top_view->child_2 and child_2->top_view.
2503  {
2504    gfx::RectF rect(50.0f, 55.0f, 20.0f, 30.0f);
2505    View::ConvertRectToTarget(child_2, &top_view, &rect);
2506    EXPECT_FLOAT_EQ(615.0f, rect.x());
2507    EXPECT_FLOAT_EQ(775.0f, rect.y());
2508    EXPECT_FLOAT_EQ(30.0f, rect.width());
2509    EXPECT_FLOAT_EQ(20.0f, rect.height());
2510
2511    rect.SetRect(615.0f, 775.0f, 30.0f, 20.0f);
2512    View::ConvertRectToTarget(&top_view, child_2, &rect);
2513    EXPECT_FLOAT_EQ(50.0f, rect.x());
2514    EXPECT_FLOAT_EQ(55.0f, rect.y());
2515    EXPECT_FLOAT_EQ(20.0f, rect.width());
2516    EXPECT_FLOAT_EQ(30.0f, rect.height());
2517  }
2518}
2519
2520// Tests conversion methods to and from screen coordinates.
2521TEST_F(ViewTest, ConversionsToFromScreen) {
2522  scoped_ptr<Widget> widget(new Widget);
2523  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2524  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2525  params.bounds = gfx::Rect(50, 50, 650, 650);
2526  widget->Init(params);
2527
2528  View* child = new View;
2529  widget->GetRootView()->AddChildView(child);
2530  child->SetBounds(10, 10, 100, 200);
2531  gfx::Transform t;
2532  t.Scale(0.5, 0.5);
2533  child->SetTransform(t);
2534
2535  gfx::Point point_in_screen(100, 90);
2536  gfx::Point point_in_child(80,60);
2537
2538  gfx::Point point = point_in_screen;
2539  View::ConvertPointFromScreen(child, &point);
2540  EXPECT_EQ(point_in_child.ToString(), point.ToString());
2541
2542  View::ConvertPointToScreen(child, &point);
2543  EXPECT_EQ(point_in_screen.ToString(), point.ToString());
2544}
2545
2546// Tests conversion methods for rectangles.
2547TEST_F(ViewTest, ConvertRectWithTransform) {
2548  scoped_ptr<Widget> widget(new Widget);
2549  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
2550  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
2551  params.bounds = gfx::Rect(50, 50, 650, 650);
2552  widget->Init(params);
2553  View* root = widget->GetRootView();
2554
2555  TestView* v1 = new TestView;
2556  TestView* v2 = new TestView;
2557  root->AddChildView(v1);
2558  v1->AddChildView(v2);
2559
2560  v1->SetBoundsRect(gfx::Rect(10, 10, 500, 500));
2561  v2->SetBoundsRect(gfx::Rect(20, 20, 100, 200));
2562
2563  // |v2| now occupies (30, 30) to (130, 230) in |widget|
2564  gfx::Rect rect(5, 5, 15, 40);
2565  EXPECT_EQ(gfx::Rect(25, 25, 15, 40), v2->ConvertRectToParent(rect));
2566  EXPECT_EQ(gfx::Rect(35, 35, 15, 40), v2->ConvertRectToWidget(rect));
2567
2568  // Rotate |v2|
2569  gfx::Transform t2;
2570  RotateCounterclockwise(&t2);
2571  t2.matrix().set(1, 3, 100.f);
2572  v2->SetTransform(t2);
2573
2574  // |v2| now occupies (30, 30) to (230, 130) in |widget|
2575  EXPECT_EQ(gfx::Rect(25, 100, 40, 15), v2->ConvertRectToParent(rect));
2576  EXPECT_EQ(gfx::Rect(35, 110, 40, 15), v2->ConvertRectToWidget(rect));
2577
2578  // Scale down |v1|
2579  gfx::Transform t1;
2580  t1.Scale(0.5, 0.5);
2581  v1->SetTransform(t1);
2582
2583  // The rectangle should remain the same for |v1|.
2584  EXPECT_EQ(gfx::Rect(25, 100, 40, 15), v2->ConvertRectToParent(rect));
2585
2586  // |v2| now occupies (20, 20) to (120, 70) in |widget|
2587  EXPECT_EQ(gfx::Rect(22, 60, 21, 8).ToString(),
2588            v2->ConvertRectToWidget(rect).ToString());
2589
2590  widget->CloseNow();
2591}
2592
2593class ObserverView : public View {
2594 public:
2595  ObserverView();
2596  virtual ~ObserverView();
2597
2598  void ResetTestState();
2599
2600  bool has_add_details() const { return has_add_details_; }
2601  bool has_remove_details() const { return has_remove_details_; }
2602
2603  const ViewHierarchyChangedDetails& add_details() const {
2604    return add_details_;
2605  }
2606
2607  const ViewHierarchyChangedDetails& remove_details() const {
2608    return remove_details_;
2609  }
2610
2611 private:
2612  // View:
2613  virtual void ViewHierarchyChanged(
2614      const ViewHierarchyChangedDetails& details) OVERRIDE;
2615
2616  bool has_add_details_;
2617  bool has_remove_details_;
2618  ViewHierarchyChangedDetails add_details_;
2619  ViewHierarchyChangedDetails remove_details_;
2620
2621  DISALLOW_COPY_AND_ASSIGN(ObserverView);
2622};
2623
2624ObserverView::ObserverView()
2625    : has_add_details_(false),
2626      has_remove_details_(false) {
2627}
2628
2629ObserverView::~ObserverView() {}
2630
2631void ObserverView::ResetTestState() {
2632  has_add_details_ = false;
2633  has_remove_details_ = false;
2634  add_details_ = ViewHierarchyChangedDetails();
2635  remove_details_ = ViewHierarchyChangedDetails();
2636}
2637
2638void ObserverView::ViewHierarchyChanged(
2639    const ViewHierarchyChangedDetails& details) {
2640  if (details.is_add) {
2641    has_add_details_ = true;
2642    add_details_ = details;
2643  } else {
2644    has_remove_details_ = true;
2645    remove_details_ = details;
2646  }
2647}
2648
2649// Verifies that the ViewHierarchyChanged() notification is sent correctly when
2650// a child view is added or removed to all the views in the hierarchy (up and
2651// down).
2652// The tree looks like this:
2653// v1
2654// +-- v2
2655//     +-- v3
2656//     +-- v4 (starts here, then get reparented to v1)
2657TEST_F(ViewTest, ViewHierarchyChanged) {
2658  ObserverView v1;
2659
2660  ObserverView* v3 = new ObserverView();
2661
2662  // Add |v3| to |v2|.
2663  scoped_ptr<ObserverView> v2(new ObserverView());
2664  v2->AddChildView(v3);
2665
2666  // Make sure both |v2| and |v3| receive the ViewHierarchyChanged()
2667  // notification.
2668  EXPECT_TRUE(v2->has_add_details());
2669  EXPECT_FALSE(v2->has_remove_details());
2670  EXPECT_EQ(v2.get(), v2->add_details().parent);
2671  EXPECT_EQ(v3, v2->add_details().child);
2672  EXPECT_EQ(NULL, v2->add_details().move_view);
2673
2674  EXPECT_TRUE(v3->has_add_details());
2675  EXPECT_FALSE(v3->has_remove_details());
2676  EXPECT_EQ(v2.get(), v3->add_details().parent);
2677  EXPECT_EQ(v3, v3->add_details().child);
2678  EXPECT_EQ(NULL, v3->add_details().move_view);
2679
2680  // Reset everything to the initial state.
2681  v2->ResetTestState();
2682  v3->ResetTestState();
2683
2684  // Add |v2| to v1.
2685  v1.AddChildView(v2.get());
2686
2687  // Verifies that |v2| is the child view *added* and the parent view is |v1|.
2688  // Make sure all the views (v1, v2, v3) received _that_ information.
2689  EXPECT_TRUE(v1.has_add_details());
2690  EXPECT_FALSE(v1.has_remove_details());
2691  EXPECT_EQ(&v1, v1.add_details().parent);
2692  EXPECT_EQ(v2.get(), v1.add_details().child);
2693  EXPECT_EQ(NULL, v1.add_details().move_view);
2694
2695  EXPECT_TRUE(v2->has_add_details());
2696  EXPECT_FALSE(v2->has_remove_details());
2697  EXPECT_EQ(&v1, v2->add_details().parent);
2698  EXPECT_EQ(v2.get(), v2->add_details().child);
2699  EXPECT_EQ(NULL, v2->add_details().move_view);
2700
2701  EXPECT_TRUE(v3->has_add_details());
2702  EXPECT_FALSE(v3->has_remove_details());
2703  EXPECT_EQ(&v1, v3->add_details().parent);
2704  EXPECT_EQ(v2.get(), v3->add_details().child);
2705  EXPECT_EQ(NULL, v3->add_details().move_view);
2706
2707  // Reset everything to the initial state.
2708  v1.ResetTestState();
2709  v2->ResetTestState();
2710  v3->ResetTestState();
2711
2712  // Remove |v2| from |v1|.
2713  v1.RemoveChildView(v2.get());
2714
2715  // Verifies that |v2| is the child view *removed* and the parent view is |v1|.
2716  // Make sure all the views (v1, v2, v3) received _that_ information.
2717  EXPECT_FALSE(v1.has_add_details());
2718  EXPECT_TRUE(v1.has_remove_details());
2719  EXPECT_EQ(&v1, v1.remove_details().parent);
2720  EXPECT_EQ(v2.get(), v1.remove_details().child);
2721  EXPECT_EQ(NULL, v1.remove_details().move_view);
2722
2723  EXPECT_FALSE(v2->has_add_details());
2724  EXPECT_TRUE(v2->has_remove_details());
2725  EXPECT_EQ(&v1, v2->remove_details().parent);
2726  EXPECT_EQ(v2.get(), v2->remove_details().child);
2727  EXPECT_EQ(NULL, v2->remove_details().move_view);
2728
2729  EXPECT_FALSE(v3->has_add_details());
2730  EXPECT_TRUE(v3->has_remove_details());
2731  EXPECT_EQ(&v1, v3->remove_details().parent);
2732  EXPECT_EQ(v3, v3->remove_details().child);
2733  EXPECT_EQ(NULL, v3->remove_details().move_view);
2734
2735  // Verifies notifications when reparenting a view.
2736  ObserverView* v4 = new ObserverView();
2737  // Add |v4| to |v2|.
2738  v2->AddChildView(v4);
2739
2740  // Reset everything to the initial state.
2741  v1.ResetTestState();
2742  v2->ResetTestState();
2743  v3->ResetTestState();
2744  v4->ResetTestState();
2745
2746  // Reparent |v4| to |v1|.
2747  v1.AddChildView(v4);
2748
2749  // Verifies that all views receive the correct information for all the child,
2750  // parent and move views.
2751
2752  // |v1| is the new parent, |v4| is the child for add, |v2| is the old parent.
2753  EXPECT_TRUE(v1.has_add_details());
2754  EXPECT_FALSE(v1.has_remove_details());
2755  EXPECT_EQ(&v1, v1.add_details().parent);
2756  EXPECT_EQ(v4, v1.add_details().child);
2757  EXPECT_EQ(v2.get(), v1.add_details().move_view);
2758
2759  // |v2| is the old parent, |v4| is the child for remove, |v1| is the new
2760  // parent.
2761  EXPECT_FALSE(v2->has_add_details());
2762  EXPECT_TRUE(v2->has_remove_details());
2763  EXPECT_EQ(v2.get(), v2->remove_details().parent);
2764  EXPECT_EQ(v4, v2->remove_details().child);
2765  EXPECT_EQ(&v1, v2->remove_details().move_view);
2766
2767  // |v3| is not impacted by this operation, and hence receives no notification.
2768  EXPECT_FALSE(v3->has_add_details());
2769  EXPECT_FALSE(v3->has_remove_details());
2770
2771  // |v4| is the reparented child, so it receives notifications for the remove
2772  // and then the add.  |v2| is its old parent, |v1| is its new parent.
2773  EXPECT_TRUE(v4->has_remove_details());
2774  EXPECT_TRUE(v4->has_add_details());
2775  EXPECT_EQ(v2.get(), v4->remove_details().parent);
2776  EXPECT_EQ(&v1, v4->add_details().parent);
2777  EXPECT_EQ(v4, v4->add_details().child);
2778  EXPECT_EQ(v4, v4->remove_details().child);
2779  EXPECT_EQ(&v1, v4->remove_details().move_view);
2780  EXPECT_EQ(v2.get(), v4->add_details().move_view);
2781}
2782
2783// Verifies if the child views added under the root are all deleted when calling
2784// RemoveAllChildViews.
2785// The tree looks like this:
2786// root
2787// +-- child1
2788//     +-- foo
2789//         +-- bar0
2790//         +-- bar1
2791//         +-- bar2
2792// +-- child2
2793// +-- child3
2794TEST_F(ViewTest, RemoveAllChildViews) {
2795  View root;
2796
2797  View* child1 = new View;
2798  root.AddChildView(child1);
2799
2800  for (int i = 0; i < 2; ++i)
2801    root.AddChildView(new View);
2802
2803  View* foo = new View;
2804  child1->AddChildView(foo);
2805
2806  // Add some nodes to |foo|.
2807  for (int i = 0; i < 3; ++i)
2808    foo->AddChildView(new View);
2809
2810  EXPECT_EQ(3, root.child_count());
2811  EXPECT_EQ(1, child1->child_count());
2812  EXPECT_EQ(3, foo->child_count());
2813
2814  // Now remove all child views from root.
2815  root.RemoveAllChildViews(true);
2816
2817  EXPECT_EQ(0, root.child_count());
2818  EXPECT_FALSE(root.has_children());
2819}
2820
2821TEST_F(ViewTest, Contains) {
2822  View v1;
2823  View* v2 = new View;
2824  View* v3 = new View;
2825
2826  v1.AddChildView(v2);
2827  v2->AddChildView(v3);
2828
2829  EXPECT_FALSE(v1.Contains(NULL));
2830  EXPECT_TRUE(v1.Contains(&v1));
2831  EXPECT_TRUE(v1.Contains(v2));
2832  EXPECT_TRUE(v1.Contains(v3));
2833
2834  EXPECT_FALSE(v2->Contains(NULL));
2835  EXPECT_TRUE(v2->Contains(v2));
2836  EXPECT_FALSE(v2->Contains(&v1));
2837  EXPECT_TRUE(v2->Contains(v3));
2838
2839  EXPECT_FALSE(v3->Contains(NULL));
2840  EXPECT_TRUE(v3->Contains(v3));
2841  EXPECT_FALSE(v3->Contains(&v1));
2842  EXPECT_FALSE(v3->Contains(v2));
2843}
2844
2845// Verifies if GetIndexOf() returns the correct index for the specified child
2846// view.
2847// The tree looks like this:
2848// root
2849// +-- child1
2850//     +-- foo1
2851// +-- child2
2852TEST_F(ViewTest, GetIndexOf) {
2853  View root;
2854
2855  View* child1 = new View;
2856  root.AddChildView(child1);
2857
2858  View* child2 = new View;
2859  root.AddChildView(child2);
2860
2861  View* foo1 = new View;
2862  child1->AddChildView(foo1);
2863
2864  EXPECT_EQ(-1, root.GetIndexOf(NULL));
2865  EXPECT_EQ(-1, root.GetIndexOf(&root));
2866  EXPECT_EQ(0, root.GetIndexOf(child1));
2867  EXPECT_EQ(1, root.GetIndexOf(child2));
2868  EXPECT_EQ(-1, root.GetIndexOf(foo1));
2869
2870  EXPECT_EQ(-1, child1->GetIndexOf(NULL));
2871  EXPECT_EQ(-1, child1->GetIndexOf(&root));
2872  EXPECT_EQ(-1, child1->GetIndexOf(child1));
2873  EXPECT_EQ(-1, child1->GetIndexOf(child2));
2874  EXPECT_EQ(0, child1->GetIndexOf(foo1));
2875
2876  EXPECT_EQ(-1, child2->GetIndexOf(NULL));
2877  EXPECT_EQ(-1, child2->GetIndexOf(&root));
2878  EXPECT_EQ(-1, child2->GetIndexOf(child2));
2879  EXPECT_EQ(-1, child2->GetIndexOf(child1));
2880  EXPECT_EQ(-1, child2->GetIndexOf(foo1));
2881}
2882
2883// Verifies that the child views can be reordered correctly.
2884TEST_F(ViewTest, ReorderChildren) {
2885  View root;
2886
2887  View* child = new View();
2888  root.AddChildView(child);
2889
2890  View* foo1 = new View();
2891  child->AddChildView(foo1);
2892  View* foo2 = new View();
2893  child->AddChildView(foo2);
2894  View* foo3 = new View();
2895  child->AddChildView(foo3);
2896  foo1->SetFocusable(true);
2897  foo2->SetFocusable(true);
2898  foo3->SetFocusable(true);
2899
2900  ASSERT_EQ(0, child->GetIndexOf(foo1));
2901  ASSERT_EQ(1, child->GetIndexOf(foo2));
2902  ASSERT_EQ(2, child->GetIndexOf(foo3));
2903  ASSERT_EQ(foo2, foo1->GetNextFocusableView());
2904  ASSERT_EQ(foo3, foo2->GetNextFocusableView());
2905  ASSERT_EQ(NULL, foo3->GetNextFocusableView());
2906
2907  // Move |foo2| at the end.
2908  child->ReorderChildView(foo2, -1);
2909  ASSERT_EQ(0, child->GetIndexOf(foo1));
2910  ASSERT_EQ(1, child->GetIndexOf(foo3));
2911  ASSERT_EQ(2, child->GetIndexOf(foo2));
2912  ASSERT_EQ(foo3, foo1->GetNextFocusableView());
2913  ASSERT_EQ(foo2, foo3->GetNextFocusableView());
2914  ASSERT_EQ(NULL, foo2->GetNextFocusableView());
2915
2916  // Move |foo1| at the end.
2917  child->ReorderChildView(foo1, -1);
2918  ASSERT_EQ(0, child->GetIndexOf(foo3));
2919  ASSERT_EQ(1, child->GetIndexOf(foo2));
2920  ASSERT_EQ(2, child->GetIndexOf(foo1));
2921  ASSERT_EQ(NULL, foo1->GetNextFocusableView());
2922  ASSERT_EQ(foo2, foo1->GetPreviousFocusableView());
2923  ASSERT_EQ(foo2, foo3->GetNextFocusableView());
2924  ASSERT_EQ(foo1, foo2->GetNextFocusableView());
2925
2926  // Move |foo2| to the front.
2927  child->ReorderChildView(foo2, 0);
2928  ASSERT_EQ(0, child->GetIndexOf(foo2));
2929  ASSERT_EQ(1, child->GetIndexOf(foo3));
2930  ASSERT_EQ(2, child->GetIndexOf(foo1));
2931  ASSERT_EQ(NULL, foo1->GetNextFocusableView());
2932  ASSERT_EQ(foo3, foo1->GetPreviousFocusableView());
2933  ASSERT_EQ(foo3, foo2->GetNextFocusableView());
2934  ASSERT_EQ(foo1, foo3->GetNextFocusableView());
2935}
2936
2937// Verifies that GetViewByID returns the correctly child view from the specified
2938// ID.
2939// The tree looks like this:
2940// v1
2941// +-- v2
2942//     +-- v3
2943//     +-- v4
2944TEST_F(ViewTest, GetViewByID) {
2945  View v1;
2946  const int kV1ID = 1;
2947  v1.set_id(kV1ID);
2948
2949  View v2;
2950  const int kV2ID = 2;
2951  v2.set_id(kV2ID);
2952
2953  View v3;
2954  const int kV3ID = 3;
2955  v3.set_id(kV3ID);
2956
2957  View v4;
2958  const int kV4ID = 4;
2959  v4.set_id(kV4ID);
2960
2961  const int kV5ID = 5;
2962
2963  v1.AddChildView(&v2);
2964  v2.AddChildView(&v3);
2965  v2.AddChildView(&v4);
2966
2967  EXPECT_EQ(&v1, v1.GetViewByID(kV1ID));
2968  EXPECT_EQ(&v2, v1.GetViewByID(kV2ID));
2969  EXPECT_EQ(&v4, v1.GetViewByID(kV4ID));
2970
2971  EXPECT_EQ(NULL, v1.GetViewByID(kV5ID));  // No V5 exists.
2972  EXPECT_EQ(NULL, v2.GetViewByID(kV1ID));  // It can get only from child views.
2973
2974  const int kGroup = 1;
2975  v3.SetGroup(kGroup);
2976  v4.SetGroup(kGroup);
2977
2978  View::Views views;
2979  v1.GetViewsInGroup(kGroup, &views);
2980  EXPECT_EQ(2U, views.size());
2981
2982  View::Views::const_iterator i(std::find(views.begin(), views.end(), &v3));
2983  EXPECT_NE(views.end(), i);
2984
2985  i = std::find(views.begin(), views.end(), &v4);
2986  EXPECT_NE(views.end(), i);
2987}
2988
2989TEST_F(ViewTest, AddExistingChild) {
2990  View v1, v2, v3;
2991
2992  v1.AddChildView(&v2);
2993  v1.AddChildView(&v3);
2994  EXPECT_EQ(0, v1.GetIndexOf(&v2));
2995  EXPECT_EQ(1, v1.GetIndexOf(&v3));
2996
2997  // Check that there's no change in order when adding at same index.
2998  v1.AddChildViewAt(&v2, 0);
2999  EXPECT_EQ(0, v1.GetIndexOf(&v2));
3000  EXPECT_EQ(1, v1.GetIndexOf(&v3));
3001  v1.AddChildViewAt(&v3, 1);
3002  EXPECT_EQ(0, v1.GetIndexOf(&v2));
3003  EXPECT_EQ(1, v1.GetIndexOf(&v3));
3004
3005  // Add it at a different index and check for change in order.
3006  v1.AddChildViewAt(&v2, 1);
3007  EXPECT_EQ(1, v1.GetIndexOf(&v2));
3008  EXPECT_EQ(0, v1.GetIndexOf(&v3));
3009  v1.AddChildViewAt(&v2, 0);
3010  EXPECT_EQ(0, v1.GetIndexOf(&v2));
3011  EXPECT_EQ(1, v1.GetIndexOf(&v3));
3012
3013  // Check that calling |AddChildView()| does not change the order.
3014  v1.AddChildView(&v2);
3015  EXPECT_EQ(0, v1.GetIndexOf(&v2));
3016  EXPECT_EQ(1, v1.GetIndexOf(&v3));
3017  v1.AddChildView(&v3);
3018  EXPECT_EQ(0, v1.GetIndexOf(&v2));
3019  EXPECT_EQ(1, v1.GetIndexOf(&v3));
3020}
3021
3022////////////////////////////////////////////////////////////////////////////////
3023// Layers
3024////////////////////////////////////////////////////////////////////////////////
3025
3026namespace {
3027
3028// Test implementation of LayerAnimator.
3029class TestLayerAnimator : public ui::LayerAnimator {
3030 public:
3031  TestLayerAnimator();
3032
3033  const gfx::Rect& last_bounds() const { return last_bounds_; }
3034
3035  // LayerAnimator.
3036  virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
3037
3038 protected:
3039  virtual ~TestLayerAnimator() { }
3040
3041 private:
3042  gfx::Rect last_bounds_;
3043
3044  DISALLOW_COPY_AND_ASSIGN(TestLayerAnimator);
3045};
3046
3047TestLayerAnimator::TestLayerAnimator()
3048    : ui::LayerAnimator(base::TimeDelta::FromMilliseconds(0)) {
3049}
3050
3051void TestLayerAnimator::SetBounds(const gfx::Rect& bounds) {
3052  last_bounds_ = bounds;
3053}
3054
3055}  // namespace
3056
3057class ViewLayerTest : public ViewsTestBase {
3058 public:
3059  ViewLayerTest() : widget_(NULL) {}
3060
3061  virtual ~ViewLayerTest() {
3062  }
3063
3064  // Returns the Layer used by the RootView.
3065  ui::Layer* GetRootLayer() {
3066    return widget()->GetLayer();
3067  }
3068
3069  virtual void SetUp() OVERRIDE {
3070    ViewTest::SetUp();
3071    widget_ = new Widget;
3072    Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3073    params.bounds = gfx::Rect(50, 50, 200, 200);
3074    widget_->Init(params);
3075    widget_->Show();
3076    widget_->GetRootView()->SetBounds(0, 0, 200, 200);
3077  }
3078
3079  virtual void TearDown() OVERRIDE {
3080    widget_->CloseNow();
3081    ViewsTestBase::TearDown();
3082  }
3083
3084  Widget* widget() { return widget_; }
3085
3086 private:
3087  Widget* widget_;
3088};
3089
3090
3091TEST_F(ViewLayerTest, LayerToggling) {
3092  // Because we lazily create textures the calls to DrawTree are necessary to
3093  // ensure we trigger creation of textures.
3094  ui::Layer* root_layer = widget()->GetLayer();
3095  View* content_view = new View;
3096  widget()->SetContentsView(content_view);
3097
3098  // Create v1, give it a bounds and verify everything is set up correctly.
3099  View* v1 = new View;
3100  v1->SetPaintToLayer(true);
3101  EXPECT_TRUE(v1->layer() != NULL);
3102  v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
3103  content_view->AddChildView(v1);
3104  ASSERT_TRUE(v1->layer() != NULL);
3105  EXPECT_EQ(root_layer, v1->layer()->parent());
3106  EXPECT_EQ(gfx::Rect(20, 30, 140, 150), v1->layer()->bounds());
3107
3108  // Create v2 as a child of v1 and do basic assertion testing.
3109  View* v2 = new View;
3110  v1->AddChildView(v2);
3111  EXPECT_TRUE(v2->layer() == NULL);
3112  v2->SetBoundsRect(gfx::Rect(10, 20, 30, 40));
3113  v2->SetPaintToLayer(true);
3114  ASSERT_TRUE(v2->layer() != NULL);
3115  EXPECT_EQ(v1->layer(), v2->layer()->parent());
3116  EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds());
3117
3118  // Turn off v1s layer. v2 should still have a layer but its parent should have
3119  // changed.
3120  v1->SetPaintToLayer(false);
3121  EXPECT_TRUE(v1->layer() == NULL);
3122  EXPECT_TRUE(v2->layer() != NULL);
3123  EXPECT_EQ(root_layer, v2->layer()->parent());
3124  ASSERT_EQ(1u, root_layer->children().size());
3125  EXPECT_EQ(root_layer->children()[0], v2->layer());
3126  // The bounds of the layer should have changed to be relative to the root view
3127  // now.
3128  EXPECT_EQ(gfx::Rect(30, 50, 30, 40), v2->layer()->bounds());
3129
3130  // Make v1 have a layer again and verify v2s layer is wired up correctly.
3131  gfx::Transform transform;
3132  transform.Scale(2.0, 2.0);
3133  v1->SetTransform(transform);
3134  EXPECT_TRUE(v1->layer() != NULL);
3135  EXPECT_TRUE(v2->layer() != NULL);
3136  EXPECT_EQ(root_layer, v1->layer()->parent());
3137  EXPECT_EQ(v1->layer(), v2->layer()->parent());
3138  ASSERT_EQ(1u, root_layer->children().size());
3139  EXPECT_EQ(root_layer->children()[0], v1->layer());
3140  ASSERT_EQ(1u, v1->layer()->children().size());
3141  EXPECT_EQ(v1->layer()->children()[0], v2->layer());
3142  EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds());
3143}
3144
3145// Verifies turning on a layer wires up children correctly.
3146TEST_F(ViewLayerTest, NestedLayerToggling) {
3147  View* content_view = new View;
3148  widget()->SetContentsView(content_view);
3149
3150  // Create v1, give it a bounds and verify everything is set up correctly.
3151  View* v1 = new View;
3152  content_view->AddChildView(v1);
3153  v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
3154
3155  View* v2 = new View;
3156  v1->AddChildView(v2);
3157
3158  View* v3 = new View;
3159  v3->SetPaintToLayer(true);
3160  v2->AddChildView(v3);
3161  ASSERT_TRUE(v3->layer() != NULL);
3162
3163  // At this point we have v1-v2-v3. v3 has a layer, v1 and v2 don't.
3164
3165  v1->SetPaintToLayer(true);
3166  EXPECT_EQ(v1->layer(), v3->layer()->parent());
3167}
3168
3169TEST_F(ViewLayerTest, LayerAnimator) {
3170  View* content_view = new View;
3171  widget()->SetContentsView(content_view);
3172
3173  View* v1 = new View;
3174  content_view->AddChildView(v1);
3175  v1->SetPaintToLayer(true);
3176  EXPECT_TRUE(v1->layer() != NULL);
3177
3178  TestLayerAnimator* animator = new TestLayerAnimator();
3179  v1->layer()->SetAnimator(animator);
3180
3181  gfx::Rect bounds(1, 2, 3, 4);
3182  v1->SetBoundsRect(bounds);
3183  EXPECT_EQ(bounds, animator->last_bounds());
3184  // TestLayerAnimator doesn't update the layer.
3185  EXPECT_NE(bounds, v1->layer()->bounds());
3186}
3187
3188// Verifies the bounds of a layer are updated if the bounds of ancestor that
3189// doesn't have a layer change.
3190TEST_F(ViewLayerTest, BoundsChangeWithLayer) {
3191  View* content_view = new View;
3192  widget()->SetContentsView(content_view);
3193
3194  View* v1 = new View;
3195  content_view->AddChildView(v1);
3196  v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
3197
3198  View* v2 = new View;
3199  v2->SetBoundsRect(gfx::Rect(10, 11, 40, 50));
3200  v1->AddChildView(v2);
3201  v2->SetPaintToLayer(true);
3202  ASSERT_TRUE(v2->layer() != NULL);
3203  EXPECT_EQ(gfx::Rect(30, 41, 40, 50), v2->layer()->bounds());
3204
3205  v1->SetPosition(gfx::Point(25, 36));
3206  EXPECT_EQ(gfx::Rect(35, 47, 40, 50), v2->layer()->bounds());
3207
3208  v2->SetPosition(gfx::Point(11, 12));
3209  EXPECT_EQ(gfx::Rect(36, 48, 40, 50), v2->layer()->bounds());
3210
3211  // Bounds of the layer should change even if the view is not invisible.
3212  v1->SetVisible(false);
3213  v1->SetPosition(gfx::Point(20, 30));
3214  EXPECT_EQ(gfx::Rect(31, 42, 40, 50), v2->layer()->bounds());
3215
3216  v2->SetVisible(false);
3217  v2->SetBoundsRect(gfx::Rect(10, 11, 20, 30));
3218  EXPECT_EQ(gfx::Rect(30, 41, 20, 30), v2->layer()->bounds());
3219}
3220
3221// Make sure layers are positioned correctly in RTL.
3222TEST_F(ViewLayerTest, BoundInRTL) {
3223  std::string locale = l10n_util::GetApplicationLocale(std::string());
3224  base::i18n::SetICUDefaultLocale("he");
3225
3226  View* view = new View;
3227  widget()->SetContentsView(view);
3228
3229  int content_width = view->width();
3230
3231  // |v1| is initially not attached to anything. So its layer will have the same
3232  // bounds as the view.
3233  View* v1 = new View;
3234  v1->SetPaintToLayer(true);
3235  v1->SetBounds(10, 10, 20, 10);
3236  EXPECT_EQ(gfx::Rect(10, 10, 20, 10),
3237            v1->layer()->bounds());
3238
3239  // Once |v1| is attached to the widget, its layer will get RTL-appropriate
3240  // bounds.
3241  view->AddChildView(v1);
3242  EXPECT_EQ(gfx::Rect(content_width - 30, 10, 20, 10),
3243            v1->layer()->bounds());
3244  gfx::Rect l1bounds = v1->layer()->bounds();
3245
3246  // Now attach a View to the widget first, then create a layer for it. Make
3247  // sure the bounds are correct.
3248  View* v2 = new View;
3249  v2->SetBounds(50, 10, 30, 10);
3250  EXPECT_FALSE(v2->layer());
3251  view->AddChildView(v2);
3252  v2->SetPaintToLayer(true);
3253  EXPECT_EQ(gfx::Rect(content_width - 80, 10, 30, 10),
3254            v2->layer()->bounds());
3255  gfx::Rect l2bounds = v2->layer()->bounds();
3256
3257  view->SetPaintToLayer(true);
3258  EXPECT_EQ(l1bounds, v1->layer()->bounds());
3259  EXPECT_EQ(l2bounds, v2->layer()->bounds());
3260
3261  // Move one of the views. Make sure the layer is positioned correctly
3262  // afterwards.
3263  v1->SetBounds(v1->x() - 5, v1->y(), v1->width(), v1->height());
3264  l1bounds.set_x(l1bounds.x() + 5);
3265  EXPECT_EQ(l1bounds, v1->layer()->bounds());
3266
3267  view->SetPaintToLayer(false);
3268  EXPECT_EQ(l1bounds, v1->layer()->bounds());
3269  EXPECT_EQ(l2bounds, v2->layer()->bounds());
3270
3271  // Move a view again.
3272  v2->SetBounds(v2->x() + 5, v2->y(), v2->width(), v2->height());
3273  l2bounds.set_x(l2bounds.x() - 5);
3274  EXPECT_EQ(l2bounds, v2->layer()->bounds());
3275
3276  // Reset locale.
3277  base::i18n::SetICUDefaultLocale(locale);
3278}
3279
3280// Makes sure a transform persists after toggling the visibility.
3281TEST_F(ViewLayerTest, ToggleVisibilityWithTransform) {
3282  View* view = new View;
3283  gfx::Transform transform;
3284  transform.Scale(2.0, 2.0);
3285  view->SetTransform(transform);
3286  widget()->SetContentsView(view);
3287  EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
3288
3289  view->SetVisible(false);
3290  EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
3291
3292  view->SetVisible(true);
3293  EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
3294}
3295
3296// Verifies a transform persists after removing/adding a view with a transform.
3297TEST_F(ViewLayerTest, ResetTransformOnLayerAfterAdd) {
3298  View* view = new View;
3299  gfx::Transform transform;
3300  transform.Scale(2.0, 2.0);
3301  view->SetTransform(transform);
3302  widget()->SetContentsView(view);
3303  EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
3304  ASSERT_TRUE(view->layer() != NULL);
3305  EXPECT_EQ(2.0f, view->layer()->transform().matrix().get(0, 0));
3306
3307  View* parent = view->parent();
3308  parent->RemoveChildView(view);
3309  parent->AddChildView(view);
3310
3311  EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0));
3312  ASSERT_TRUE(view->layer() != NULL);
3313  EXPECT_EQ(2.0f, view->layer()->transform().matrix().get(0, 0));
3314}
3315
3316// Makes sure that layer visibility is correct after toggling View visibility.
3317TEST_F(ViewLayerTest, ToggleVisibilityWithLayer) {
3318  View* content_view = new View;
3319  widget()->SetContentsView(content_view);
3320
3321  // The view isn't attached to a widget or a parent view yet. But it should
3322  // still have a layer, but the layer should not be attached to the root
3323  // layer.
3324  View* v1 = new View;
3325  v1->SetPaintToLayer(true);
3326  EXPECT_TRUE(v1->layer());
3327  EXPECT_FALSE(LayerIsAncestor(widget()->GetCompositor()->root_layer(),
3328                               v1->layer()));
3329
3330  // Once the view is attached to a widget, its layer should be attached to the
3331  // root layer and visible.
3332  content_view->AddChildView(v1);
3333  EXPECT_TRUE(LayerIsAncestor(widget()->GetCompositor()->root_layer(),
3334                              v1->layer()));
3335  EXPECT_TRUE(v1->layer()->IsDrawn());
3336
3337  v1->SetVisible(false);
3338  EXPECT_FALSE(v1->layer()->IsDrawn());
3339
3340  v1->SetVisible(true);
3341  EXPECT_TRUE(v1->layer()->IsDrawn());
3342
3343  widget()->Hide();
3344  EXPECT_FALSE(v1->layer()->IsDrawn());
3345
3346  widget()->Show();
3347  EXPECT_TRUE(v1->layer()->IsDrawn());
3348}
3349
3350// Tests that the layers in the subtree are orphaned after a View is removed
3351// from the parent.
3352TEST_F(ViewLayerTest, OrphanLayerAfterViewRemove) {
3353  View* content_view = new View;
3354  widget()->SetContentsView(content_view);
3355
3356  View* v1 = new View;
3357  content_view->AddChildView(v1);
3358
3359  View* v2 = new View;
3360  v1->AddChildView(v2);
3361  v2->SetPaintToLayer(true);
3362  EXPECT_TRUE(LayerIsAncestor(widget()->GetCompositor()->root_layer(),
3363                              v2->layer()));
3364  EXPECT_TRUE(v2->layer()->IsDrawn());
3365
3366  content_view->RemoveChildView(v1);
3367
3368  EXPECT_FALSE(LayerIsAncestor(widget()->GetCompositor()->root_layer(),
3369                               v2->layer()));
3370
3371  // Reparent |v2|.
3372  content_view->AddChildView(v2);
3373  delete v1;
3374  v1 = NULL;
3375  EXPECT_TRUE(LayerIsAncestor(widget()->GetCompositor()->root_layer(),
3376                              v2->layer()));
3377  EXPECT_TRUE(v2->layer()->IsDrawn());
3378}
3379
3380class PaintTrackingView : public View {
3381 public:
3382  PaintTrackingView() : painted_(false) {
3383  }
3384
3385  bool painted() const { return painted_; }
3386  void set_painted(bool value) { painted_ = value; }
3387
3388  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
3389    painted_ = true;
3390  }
3391
3392 private:
3393  bool painted_;
3394
3395  DISALLOW_COPY_AND_ASSIGN(PaintTrackingView);
3396};
3397
3398// Makes sure child views with layers aren't painted when paint starts at an
3399// ancestor.
3400TEST_F(ViewLayerTest, DontPaintChildrenWithLayers) {
3401  PaintTrackingView* content_view = new PaintTrackingView;
3402  widget()->SetContentsView(content_view);
3403  content_view->SetPaintToLayer(true);
3404  GetRootLayer()->GetCompositor()->ScheduleDraw();
3405  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3406  GetRootLayer()->SchedulePaint(gfx::Rect(0, 0, 10, 10));
3407  content_view->set_painted(false);
3408  // content_view no longer has a dirty rect. Paint from the root and make sure
3409  // PaintTrackingView isn't painted.
3410  GetRootLayer()->GetCompositor()->ScheduleDraw();
3411  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3412  EXPECT_FALSE(content_view->painted());
3413
3414  // Make content_view have a dirty rect, paint the layers and make sure
3415  // PaintTrackingView is painted.
3416  content_view->layer()->SchedulePaint(gfx::Rect(0, 0, 10, 10));
3417  GetRootLayer()->GetCompositor()->ScheduleDraw();
3418  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3419  EXPECT_TRUE(content_view->painted());
3420}
3421
3422// Tests that the visibility of child layers are updated correctly when a View's
3423// visibility changes.
3424TEST_F(ViewLayerTest, VisibilityChildLayers) {
3425  View* v1 = new View;
3426  v1->SetPaintToLayer(true);
3427  widget()->SetContentsView(v1);
3428
3429  View* v2 = new View;
3430  v1->AddChildView(v2);
3431
3432  View* v3 = new View;
3433  v2->AddChildView(v3);
3434  v3->SetVisible(false);
3435
3436  View* v4 = new View;
3437  v4->SetPaintToLayer(true);
3438  v3->AddChildView(v4);
3439
3440  EXPECT_TRUE(v1->layer()->IsDrawn());
3441  EXPECT_FALSE(v4->layer()->IsDrawn());
3442
3443  v2->SetVisible(false);
3444  EXPECT_TRUE(v1->layer()->IsDrawn());
3445  EXPECT_FALSE(v4->layer()->IsDrawn());
3446
3447  v2->SetVisible(true);
3448  EXPECT_TRUE(v1->layer()->IsDrawn());
3449  EXPECT_FALSE(v4->layer()->IsDrawn());
3450
3451  v2->SetVisible(false);
3452  EXPECT_TRUE(v1->layer()->IsDrawn());
3453  EXPECT_FALSE(v4->layer()->IsDrawn());
3454  EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer()));
3455
3456  v3->SetVisible(true);
3457  EXPECT_TRUE(v1->layer()->IsDrawn());
3458  EXPECT_FALSE(v4->layer()->IsDrawn());
3459  EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer()));
3460
3461  // Reparent |v3| to |v1|.
3462  v1->AddChildView(v3);
3463  EXPECT_TRUE(v1->layer()->IsDrawn());
3464  EXPECT_TRUE(v4->layer()->IsDrawn());
3465  EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer()));
3466}
3467
3468// This test creates a random View tree, and then randomly reorders child views,
3469// reparents views etc. Unrelated changes can appear to break this test. So
3470// marking this as FLAKY.
3471TEST_F(ViewLayerTest, DISABLED_ViewLayerTreesInSync) {
3472  View* content = new View;
3473  content->SetPaintToLayer(true);
3474  widget()->SetContentsView(content);
3475  widget()->Show();
3476
3477  ConstructTree(content, 5);
3478  EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
3479
3480  ScrambleTree(content);
3481  EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
3482
3483  ScrambleTree(content);
3484  EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
3485
3486  ScrambleTree(content);
3487  EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer()));
3488}
3489
3490// Verifies when views are reordered the layer is also reordered. The widget is
3491// providing the parent layer.
3492TEST_F(ViewLayerTest, ReorderUnderWidget) {
3493  View* content = new View;
3494  widget()->SetContentsView(content);
3495  View* c1 = new View;
3496  c1->SetPaintToLayer(true);
3497  content->AddChildView(c1);
3498  View* c2 = new View;
3499  c2->SetPaintToLayer(true);
3500  content->AddChildView(c2);
3501
3502  ui::Layer* parent_layer = c1->layer()->parent();
3503  ASSERT_TRUE(parent_layer);
3504  ASSERT_EQ(2u, parent_layer->children().size());
3505  EXPECT_EQ(c1->layer(), parent_layer->children()[0]);
3506  EXPECT_EQ(c2->layer(), parent_layer->children()[1]);
3507
3508  // Move c1 to the front. The layers should have moved too.
3509  content->ReorderChildView(c1, -1);
3510  EXPECT_EQ(c1->layer(), parent_layer->children()[1]);
3511  EXPECT_EQ(c2->layer(), parent_layer->children()[0]);
3512}
3513
3514// Verifies that the layer of a view can be acquired properly.
3515TEST_F(ViewLayerTest, AcquireLayer) {
3516  View* content = new View;
3517  widget()->SetContentsView(content);
3518  scoped_ptr<View> c1(new View);
3519  c1->SetPaintToLayer(true);
3520  EXPECT_TRUE(c1->layer());
3521  content->AddChildView(c1.get());
3522
3523  scoped_ptr<ui::Layer> layer(c1->AcquireLayer());
3524  EXPECT_EQ(layer.get(), c1->layer());
3525
3526  scoped_ptr<ui::Layer> layer2(c1->RecreateLayer());
3527  EXPECT_NE(c1->layer(), layer2.get());
3528
3529  // Destroy view before destroying layer.
3530  c1.reset();
3531}
3532
3533// Verify the z-order of the layers as a result of calling RecreateLayer().
3534TEST_F(ViewLayerTest, RecreateLayerZOrder) {
3535  scoped_ptr<View> v(new View());
3536  v->SetPaintToLayer(true);
3537
3538  View* v1 = new View();
3539  v1->SetPaintToLayer(true);
3540  v->AddChildView(v1);
3541  View* v2 = new View();
3542  v2->SetPaintToLayer(true);
3543  v->AddChildView(v2);
3544
3545  // Test the initial z-order.
3546  const std::vector<ui::Layer*>& child_layers_pre = v->layer()->children();
3547  ASSERT_EQ(2u, child_layers_pre.size());
3548  EXPECT_EQ(v1->layer(), child_layers_pre[0]);
3549  EXPECT_EQ(v2->layer(), child_layers_pre[1]);
3550
3551  scoped_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer());
3552
3553  // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|.
3554  // for |v1| and |v2|.
3555  const std::vector<ui::Layer*>& child_layers_post = v->layer()->children();
3556  ASSERT_EQ(3u, child_layers_post.size());
3557  EXPECT_EQ(v1->layer(), child_layers_post[0]);
3558  EXPECT_EQ(v1_old_layer, child_layers_post[1]);
3559  EXPECT_EQ(v2->layer(), child_layers_post[2]);
3560}
3561
3562// Verify the z-order of the layers as a result of calling RecreateLayer when
3563// the widget is the parent with the layer.
3564TEST_F(ViewLayerTest, RecreateLayerZOrderWidgetParent) {
3565  View* v = new View();
3566  widget()->SetContentsView(v);
3567
3568  View* v1 = new View();
3569  v1->SetPaintToLayer(true);
3570  v->AddChildView(v1);
3571  View* v2 = new View();
3572  v2->SetPaintToLayer(true);
3573  v->AddChildView(v2);
3574
3575  ui::Layer* root_layer = GetRootLayer();
3576
3577  // Test the initial z-order.
3578  const std::vector<ui::Layer*>& child_layers_pre = root_layer->children();
3579  ASSERT_EQ(2u, child_layers_pre.size());
3580  EXPECT_EQ(v1->layer(), child_layers_pre[0]);
3581  EXPECT_EQ(v2->layer(), child_layers_pre[1]);
3582
3583  scoped_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer());
3584
3585  // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|.
3586  const std::vector<ui::Layer*>& child_layers_post = root_layer->children();
3587  ASSERT_EQ(3u, child_layers_post.size());
3588  EXPECT_EQ(v1->layer(), child_layers_post[0]);
3589  EXPECT_EQ(v1_old_layer, child_layers_post[1]);
3590  EXPECT_EQ(v2->layer(), child_layers_post[2]);
3591}
3592
3593// Verifies RecreateLayer() moves all Layers over, even those that don't have
3594// a View.
3595TEST_F(ViewLayerTest, RecreateLayerMovesNonViewChildren) {
3596  View v;
3597  v.SetPaintToLayer(true);
3598  View child;
3599  child.SetPaintToLayer(true);
3600  v.AddChildView(&child);
3601  ASSERT_TRUE(v.layer() != NULL);
3602  ASSERT_EQ(1u, v.layer()->children().size());
3603  EXPECT_EQ(v.layer()->children()[0], child.layer());
3604
3605  ui::Layer layer(ui::LAYER_NOT_DRAWN);
3606  v.layer()->Add(&layer);
3607  v.layer()->StackAtBottom(&layer);
3608
3609  scoped_ptr<ui::Layer> old_layer(v.RecreateLayer());
3610
3611  // All children should be moved from old layer to new layer.
3612  ASSERT_TRUE(old_layer.get() != NULL);
3613  EXPECT_TRUE(old_layer->children().empty());
3614
3615  // And new layer should have the two children.
3616  ASSERT_TRUE(v.layer() != NULL);
3617  ASSERT_EQ(2u, v.layer()->children().size());
3618  EXPECT_EQ(v.layer()->children()[0], &layer);
3619  EXPECT_EQ(v.layer()->children()[1], child.layer());
3620}
3621
3622class BoundsTreeTestView : public View {
3623 public:
3624  BoundsTreeTestView() {}
3625
3626  virtual void PaintChildren(gfx::Canvas* canvas,
3627                             const CullSet& cull_set) OVERRIDE {
3628    // Save out a copy of the cull_set before calling the base implementation.
3629    last_cull_set_.clear();
3630    if (cull_set.cull_set_) {
3631      for (base::hash_set<intptr_t>::iterator it = cull_set.cull_set_->begin();
3632           it != cull_set.cull_set_->end();
3633           ++it) {
3634        last_cull_set_.insert(reinterpret_cast<View*>(*it));
3635      }
3636    }
3637    View::PaintChildren(canvas, cull_set);
3638  }
3639
3640  std::set<View*> last_cull_set_;
3641};
3642
3643TEST_F(ViewLayerTest, BoundsTreePaintUpdatesCullSet) {
3644  BoundsTreeTestView* test_view = new BoundsTreeTestView;
3645  widget()->SetContentsView(test_view);
3646
3647  View* v1 = new View();
3648  v1->SetBoundsRect(gfx::Rect(10, 15, 150, 151));
3649  test_view->AddChildView(v1);
3650
3651  View* v2 = new View();
3652  v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
3653  v1->AddChildView(v2);
3654
3655  // Schedule a full-view paint to get everyone's rectangles updated.
3656  test_view->SchedulePaintInRect(test_view->bounds());
3657  GetRootLayer()->GetCompositor()->ScheduleDraw();
3658  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3659
3660  // Now we have test_view - v1 - v2. Damage to only test_view should only
3661  // return root_view and test_view.
3662  test_view->SchedulePaintInRect(gfx::Rect(0, 0, 1, 1));
3663  GetRootLayer()->GetCompositor()->ScheduleDraw();
3664  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3665  EXPECT_EQ(2U, test_view->last_cull_set_.size());
3666  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3667  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3668
3669  // Damage to v1 only should only return root_view, test_view, and v1.
3670  test_view->SchedulePaintInRect(gfx::Rect(11, 16, 1, 1));
3671  GetRootLayer()->GetCompositor()->ScheduleDraw();
3672  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3673  EXPECT_EQ(3U, test_view->last_cull_set_.size());
3674  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3675  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3676  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
3677
3678  // A Damage rect inside v2 should get all 3 views back in the |last_cull_set_|
3679  // on call to TestView::Paint(), along with the widget root view.
3680  test_view->SchedulePaintInRect(gfx::Rect(31, 49, 1, 1));
3681  GetRootLayer()->GetCompositor()->ScheduleDraw();
3682  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3683  EXPECT_EQ(4U, test_view->last_cull_set_.size());
3684  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3685  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3686  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
3687  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
3688}
3689
3690TEST_F(ViewLayerTest, BoundsTreeWithRTL) {
3691  std::string locale = l10n_util::GetApplicationLocale(std::string());
3692  base::i18n::SetICUDefaultLocale("ar");
3693
3694  BoundsTreeTestView* test_view = new BoundsTreeTestView;
3695  widget()->SetContentsView(test_view);
3696
3697  // Add child views, which should be in RTL coordinate space of parent view.
3698  View* v1 = new View;
3699  v1->SetBoundsRect(gfx::Rect(10, 12, 25, 26));
3700  test_view->AddChildView(v1);
3701
3702  View* v2 = new View;
3703  v2->SetBoundsRect(gfx::Rect(5, 6, 7, 8));
3704  v1->AddChildView(v2);
3705
3706  // Schedule a full-view paint to get everyone's rectangles updated.
3707  test_view->SchedulePaintInRect(test_view->bounds());
3708  GetRootLayer()->GetCompositor()->ScheduleDraw();
3709  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3710
3711  // Damage to the right side of the parent view should touch both child views.
3712  gfx::Rect rtl_damage(test_view->bounds().width() - 16, 18, 1, 1);
3713  test_view->SchedulePaintInRect(rtl_damage);
3714  GetRootLayer()->GetCompositor()->ScheduleDraw();
3715  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3716  EXPECT_EQ(4U, test_view->last_cull_set_.size());
3717  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3718  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3719  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
3720  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
3721
3722  // Damage to the left side of the parent view should only touch the
3723  // container views.
3724  gfx::Rect ltr_damage(16, 18, 1, 1);
3725  test_view->SchedulePaintInRect(ltr_damage);
3726  GetRootLayer()->GetCompositor()->ScheduleDraw();
3727  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3728  EXPECT_EQ(2U, test_view->last_cull_set_.size());
3729  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3730  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3731
3732  // Reset locale.
3733  base::i18n::SetICUDefaultLocale(locale);
3734}
3735
3736TEST_F(ViewLayerTest, BoundsTreeSetBoundsChangesCullSet) {
3737  BoundsTreeTestView* test_view = new BoundsTreeTestView;
3738  widget()->SetContentsView(test_view);
3739
3740  View* v1 = new View;
3741  v1->SetBoundsRect(gfx::Rect(5, 6, 100, 101));
3742  test_view->AddChildView(v1);
3743
3744  View* v2 = new View;
3745  v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
3746  v1->AddChildView(v2);
3747
3748  // Schedule a full-view paint to get everyone's rectangles updated.
3749  test_view->SchedulePaintInRect(test_view->bounds());
3750  GetRootLayer()->GetCompositor()->ScheduleDraw();
3751  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3752
3753  // Move v1 to a new origin out of the way of our next query.
3754  v1->SetBoundsRect(gfx::Rect(50, 60, 100, 101));
3755  // The move will force a repaint.
3756  GetRootLayer()->GetCompositor()->ScheduleDraw();
3757  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3758
3759  // Schedule a paint with damage rect where v1 used to be.
3760  test_view->SchedulePaintInRect(gfx::Rect(5, 6, 10, 11));
3761  GetRootLayer()->GetCompositor()->ScheduleDraw();
3762  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3763
3764  // Should only have picked up root_view and test_view.
3765  EXPECT_EQ(2U, test_view->last_cull_set_.size());
3766  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3767  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3768}
3769
3770TEST_F(ViewLayerTest, BoundsTreeLayerChangeMakesNewTree) {
3771  BoundsTreeTestView* test_view = new BoundsTreeTestView;
3772  widget()->SetContentsView(test_view);
3773
3774  View* v1 = new View;
3775  v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
3776  test_view->AddChildView(v1);
3777
3778  View* v2 = new View;
3779  v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
3780  v1->AddChildView(v2);
3781
3782  // Schedule a full-view paint to get everyone's rectangles updated.
3783  test_view->SchedulePaintInRect(test_view->bounds());
3784  GetRootLayer()->GetCompositor()->ScheduleDraw();
3785  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3786
3787  // Set v1 to paint to its own layer, it should remove itself from the
3788  // test_view heiarchy and no longer intersect with damage rects in that cull
3789  // set.
3790  v1->SetPaintToLayer(true);
3791
3792  // Schedule another full-view paint.
3793  test_view->SchedulePaintInRect(test_view->bounds());
3794  GetRootLayer()->GetCompositor()->ScheduleDraw();
3795  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3796  // v1 and v2 should no longer be present in the test_view cull_set.
3797  EXPECT_EQ(2U, test_view->last_cull_set_.size());
3798  EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
3799  EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
3800
3801  // Now set v1 back to not painting to a layer.
3802  v1->SetPaintToLayer(false);
3803  // Schedule another full-view paint.
3804  test_view->SchedulePaintInRect(test_view->bounds());
3805  GetRootLayer()->GetCompositor()->ScheduleDraw();
3806  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3807  // We should be back to the full cull set including v1 and v2.
3808  EXPECT_EQ(4U, test_view->last_cull_set_.size());
3809  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3810  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3811  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
3812  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
3813}
3814
3815TEST_F(ViewLayerTest, BoundsTreeRemoveChildRemovesBounds) {
3816  BoundsTreeTestView* test_view = new BoundsTreeTestView;
3817  widget()->SetContentsView(test_view);
3818
3819  View* v1 = new View;
3820  v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
3821  test_view->AddChildView(v1);
3822
3823  View* v2 = new View;
3824  v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
3825  v1->AddChildView(v2);
3826
3827  // Schedule a full-view paint to get everyone's rectangles updated.
3828  test_view->SchedulePaintInRect(test_view->bounds());
3829  GetRootLayer()->GetCompositor()->ScheduleDraw();
3830  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3831
3832  // Now remove v1 from the root view.
3833  test_view->RemoveChildView(v1);
3834
3835  // Schedule another full-view paint.
3836  test_view->SchedulePaintInRect(test_view->bounds());
3837  GetRootLayer()->GetCompositor()->ScheduleDraw();
3838  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3839  // v1 and v2 should no longer be present in the test_view cull_set.
3840  EXPECT_EQ(2U, test_view->last_cull_set_.size());
3841  EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
3842  EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
3843
3844  // View v1 and v2 are no longer part of view hierarchy and therefore won't be
3845  // deleted with that hierarchy.
3846  delete v1;
3847}
3848
3849TEST_F(ViewLayerTest, BoundsTreeMoveViewMovesBounds) {
3850  BoundsTreeTestView* test_view = new BoundsTreeTestView;
3851  widget()->SetContentsView(test_view);
3852
3853  // Build hierarchy v1 - v2 - v3.
3854  View* v1 = new View;
3855  v1->SetBoundsRect(gfx::Rect(20, 30, 150, 160));
3856  test_view->AddChildView(v1);
3857
3858  View* v2 = new View;
3859  v2->SetBoundsRect(gfx::Rect(5, 10, 40, 50));
3860  v1->AddChildView(v2);
3861
3862  View* v3 = new View;
3863  v3->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
3864  v2->AddChildView(v3);
3865
3866  // Schedule a full-view paint and ensure all views are present in the cull.
3867  test_view->SchedulePaintInRect(test_view->bounds());
3868  GetRootLayer()->GetCompositor()->ScheduleDraw();
3869  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3870  EXPECT_EQ(5U, test_view->last_cull_set_.size());
3871  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3872  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3873  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
3874  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
3875  EXPECT_EQ(1U, test_view->last_cull_set_.count(v3));
3876
3877  // Build an unrelated view hierarchy and move v2 in to it.
3878  scoped_ptr<Widget> test_widget(new Widget);
3879  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
3880  params.bounds = gfx::Rect(10, 10, 500, 500);
3881  params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3882  test_widget->Init(params);
3883  test_widget->Show();
3884  BoundsTreeTestView* widget_view = new BoundsTreeTestView;
3885  test_widget->SetContentsView(widget_view);
3886  widget_view->AddChildView(v2);
3887
3888  // Now schedule full-view paints in both widgets.
3889  test_view->SchedulePaintInRect(test_view->bounds());
3890  widget_view->SchedulePaintInRect(widget_view->bounds());
3891  GetRootLayer()->GetCompositor()->ScheduleDraw();
3892  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
3893
3894  // Only v1 should be present in the first cull set.
3895  EXPECT_EQ(3U, test_view->last_cull_set_.size());
3896  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
3897  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
3898  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
3899
3900  // We should find v2 and v3 in the widget_view cull_set.
3901  EXPECT_EQ(4U, widget_view->last_cull_set_.size());
3902  EXPECT_EQ(1U, widget_view->last_cull_set_.count(test_widget->GetRootView()));
3903  EXPECT_EQ(1U, widget_view->last_cull_set_.count(widget_view));
3904  EXPECT_EQ(1U, widget_view->last_cull_set_.count(v2));
3905  EXPECT_EQ(1U, widget_view->last_cull_set_.count(v3));
3906}
3907
3908TEST_F(ViewTest, FocusableAssertions) {
3909  // View subclasses may change insets based on whether they are focusable,
3910  // which effects the preferred size. To avoid preferred size changing around
3911  // these Views need to key off the last value set to SetFocusable(), not
3912  // whether the View is focusable right now. For this reason it's important
3913  // that focusable() return the last value passed to SetFocusable and not
3914  // whether the View is focusable right now.
3915  TestView view;
3916  view.SetFocusable(true);
3917  EXPECT_TRUE(view.focusable());
3918  view.SetEnabled(false);
3919  EXPECT_TRUE(view.focusable());
3920  view.SetFocusable(false);
3921  EXPECT_FALSE(view.focusable());
3922}
3923
3924// Verifies when a view is deleted it is removed from ViewStorage.
3925TEST_F(ViewTest, UpdateViewStorageOnDelete) {
3926  ViewStorage* view_storage = ViewStorage::GetInstance();
3927  const int storage_id = view_storage->CreateStorageID();
3928  {
3929    View view;
3930    view_storage->StoreView(storage_id, &view);
3931  }
3932  EXPECT_TRUE(view_storage->RetrieveView(storage_id) == NULL);
3933}
3934
3935////////////////////////////////////////////////////////////////////////////////
3936// NativeTheme
3937////////////////////////////////////////////////////////////////////////////////
3938
3939void TestView::OnNativeThemeChanged(const ui::NativeTheme* native_theme) {
3940  native_theme_ = native_theme;
3941}
3942
3943TEST_F(ViewTest, OnNativeThemeChanged) {
3944  TestView* test_view = new TestView();
3945  EXPECT_FALSE(test_view->native_theme_);
3946  TestView* test_view_child = new TestView();
3947  EXPECT_FALSE(test_view_child->native_theme_);
3948
3949  // Child view added before the widget hierarchy exists should get the
3950  // new native theme notification.
3951  test_view->AddChildView(test_view_child);
3952
3953  scoped_ptr<Widget> widget(new Widget);
3954  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
3955  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
3956  widget->Init(params);
3957
3958  widget->GetRootView()->AddChildView(test_view);
3959  EXPECT_TRUE(test_view->native_theme_);
3960  EXPECT_EQ(widget->GetNativeTheme(), test_view->native_theme_);
3961  EXPECT_TRUE(test_view_child->native_theme_);
3962  EXPECT_EQ(widget->GetNativeTheme(), test_view_child->native_theme_);
3963
3964  // Child view added after the widget hierarchy exists should also get the
3965  // notification.
3966  TestView* test_view_child_2 = new TestView();
3967  test_view->AddChildView(test_view_child_2);
3968  EXPECT_TRUE(test_view_child_2->native_theme_);
3969  EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_);
3970
3971  widget->CloseNow();
3972}
3973
3974}  // namespace views
3975