Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / views / view_unittest.cc
index d681114..7bcef0e 100644 (file)
@@ -7,25 +7,21 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/rand_util.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "grit/ui_strings.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
-#include "ui/compositor/layer_tree_owner.h"
 #include "ui/compositor/test/draw_waiter_for_test.h"
-#include "ui/compositor/test/test_layers.h"
 #include "ui/events/event.h"
-#include "ui/events/gestures/gesture_recognizer.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/path.h"
 #include "ui/gfx/transform.h"
+#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/native/native_view_host.h"
 #include "ui/views/controls/scroll_view.h"
 #include "ui/views/focus/view_storage.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/view.h"
-#include "ui/views/view_constants_aura.h"
 #include "ui/views/views_delegate.h"
 #include "ui/views/widget/native_widget.h"
 #include "ui/views/widget/root_view.h"
 #include "ui/views/window/dialog_client_view.h"
 #include "ui/views/window/dialog_delegate.h"
-#include "ui/wm/core/window_util.h"
 
 using base::ASCIIToUTF16;
 
@@ -182,18 +176,6 @@ void ScrambleTree(views::View* view) {
     view->SetVisible(!view->visible());
 }
 
-// Convenience to make constructing a GestureEvent simpler.
-class GestureEventForTest : public ui::GestureEvent {
- public:
-  GestureEventForTest(ui::EventType type, int x, int y, int flags)
-      : GestureEvent(type, x, y, flags, base::TimeDelta(),
-                     ui::GestureEventDetails(type, 0.0f, 0.0f), 0) {
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GestureEventForTest);
-};
-
 }  // namespace
 
 namespace views {
@@ -203,7 +185,11 @@ typedef ViewsTestBase ViewTest;
 // A derived class for testing purpose.
 class TestView : public View {
  public:
-  TestView() : View(), delete_on_pressed_(false), in_touch_sequence_(false) {}
+  TestView()
+      : View(),
+        delete_on_pressed_(false),
+        native_theme_(NULL),
+        can_process_events_within_subtree_(true) {}
   virtual ~TestView() {}
 
   // Reset all test state
@@ -213,12 +199,9 @@ class TestView : public View {
     location_.SetPoint(0, 0);
     received_mouse_enter_ = false;
     received_mouse_exit_ = false;
-    last_touch_event_type_ = 0;
-    last_touch_event_was_handled_ = false;
-    last_gesture_event_type_ = 0;
-    last_gesture_event_was_handled_ = false;
     last_clip_.setEmpty();
     accelerator_count_map_.clear();
+    can_process_events_within_subtree_ = true;
   }
 
   // Exposed as public for testing.
@@ -232,6 +215,14 @@ class TestView : public View {
 
   bool focusable() const { return View::focusable(); }
 
+  void set_can_process_events_within_subtree(bool can_process) {
+    can_process_events_within_subtree_ = can_process;
+  }
+
+  virtual bool CanProcessEventsWithinSubtree() const OVERRIDE {
+    return can_process_events_within_subtree_;
+  }
+
   virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
   virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
@@ -239,14 +230,13 @@ class TestView : public View {
   virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
   virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
 
-  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
-  // Ignores GestureEvent by default.
-  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
-
-  virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
+  virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set) OVERRIDE;
   virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE;
   virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
 
+  virtual void OnNativeThemeChanged(const ui::NativeTheme* native_theme)
+      OVERRIDE;
+
   // OnBoundsChanged.
   bool did_change_bounds_;
   gfx::Rect new_bounds_;
@@ -261,77 +251,17 @@ class TestView : public View {
   // Painting.
   std::vector<gfx::Rect> scheduled_paint_rects_;
 
-  // GestureEvent
-  int last_gesture_event_type_;
-  bool last_gesture_event_was_handled_;
-
-  // TouchEvent.
-  int last_touch_event_type_;
-  bool last_touch_event_was_handled_;
-  bool in_touch_sequence_;
-
   // Painting.
   SkRect last_clip_;
 
   // Accelerators.
   std::map<ui::Accelerator, int> accelerator_count_map_;
-};
-
-// A view subclass that ignores all touch events for testing purposes.
-class TestViewIgnoreTouch : public TestView {
- public:
-  TestViewIgnoreTouch() : TestView() {}
-  virtual ~TestViewIgnoreTouch() {}
-
- private:
-  virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE;
-};
-
-// A view subclass that consumes all Gesture events for testing purposes.
-class TestViewConsumeGesture : public TestView {
- public:
-  TestViewConsumeGesture() : TestView() {}
-  virtual ~TestViewConsumeGesture() {}
-
- protected:
-  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
-    last_gesture_event_type_ = event->type();
-    location_.SetPoint(event->x(), event->y());
-    event->StopPropagation();
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TestViewConsumeGesture);
-};
-
-// A view subclass that ignores all Gesture events.
-class TestViewIgnoreGesture: public TestView {
- public:
-  TestViewIgnoreGesture() : TestView() {}
-  virtual ~TestViewIgnoreGesture() {}
 
- private:
-  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
-  }
+  // Native theme.
+  const ui::NativeTheme* native_theme_;
 
-  DISALLOW_COPY_AND_ASSIGN(TestViewIgnoreGesture);
-};
-
-// A view subclass that ignores all scroll-gesture events, but consume all other
-// gesture events.
-class TestViewIgnoreScrollGestures : public TestViewConsumeGesture {
- public:
-  TestViewIgnoreScrollGestures() {}
-  virtual ~TestViewIgnoreScrollGestures() {}
-
- private:
-  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
-    if (event->IsScrollGestureEvent())
-      return;
-    TestViewConsumeGesture::OnGestureEvent(event);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(TestViewIgnoreScrollGestures);
+  // Value to return from CanProcessEventsWithinSubtree().
+  bool can_process_events_within_subtree_;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -480,342 +410,10 @@ TEST_F(ViewTest, DeleteOnPressed) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// TouchEvent
-////////////////////////////////////////////////////////////////////////////////
-void TestView::OnTouchEvent(ui::TouchEvent* event) {
-  last_touch_event_type_ = event->type();
-  location_.SetPoint(event->x(), event->y());
-  if (!in_touch_sequence_) {
-    if (event->type() == ui::ET_TOUCH_PRESSED) {
-      in_touch_sequence_ = true;
-      event->StopPropagation();
-      return;
-    }
-  } else {
-    if (event->type() == ui::ET_TOUCH_RELEASED) {
-      in_touch_sequence_ = false;
-      event->SetHandled();
-      return;
-    }
-    event->StopPropagation();
-    return;
-  }
-
-  if (last_touch_event_was_handled_)
-   event->StopPropagation();
-}
-
-void TestViewIgnoreTouch::OnTouchEvent(ui::TouchEvent* event) {
-}
-
-TEST_F(ViewTest, TouchEvent) {
-  TestView* v1 = new TestView();
-  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
-
-  TestView* v2 = new TestView();
-  v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
-
-  TestView* v3 = new TestViewIgnoreTouch();
-  v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
-
-  scoped_ptr<Widget> widget(new Widget());
-  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
-  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-  params.bounds = gfx::Rect(50, 50, 650, 650);
-  widget->Init(params);
-  internal::RootView* root =
-      static_cast<internal::RootView*>(widget->GetRootView());
-  ui::EventDispatchDetails details;
-
-  root->AddChildView(v1);
-  v1->AddChildView(v2);
-  v2->AddChildView(v3);
-
-  // |v3| completely obscures |v2|, but all the touch events on |v3| should
-  // reach |v2| because |v3| doesn't process any touch events.
-
-  // Make sure if none of the views handle the touch event, the gesture manager
-  // does.
-  v1->Reset();
-  v2->Reset();
-
-  ui::TouchEvent unhandled(ui::ET_TOUCH_MOVED,
-                           gfx::Point(400, 400),
-                           0, /* no flags */
-                           0, /* first finger touch */
-                           base::TimeDelta(),
-                           1.0, 0.0, 1.0, 0.0);
-  details = root->OnEventFromSource(&unhandled);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(v1->last_touch_event_type_, 0);
-  EXPECT_EQ(v2->last_touch_event_type_, 0);
-
-  // Test press, drag, release touch sequence.
-  v1->Reset();
-  v2->Reset();
-
-  ui::TouchEvent pressed(ui::ET_TOUCH_PRESSED,
-                         gfx::Point(110, 120),
-                         0, /* no flags */
-                         0, /* first finger touch */
-                         base::TimeDelta(),
-                         1.0, 0.0, 1.0, 0.0);
-  v2->last_touch_event_was_handled_ = true;
-  details = root->OnEventFromSource(&pressed);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(v2->last_touch_event_type_, ui::ET_TOUCH_PRESSED);
-  EXPECT_EQ(v2->location_.x(), 10);
-  EXPECT_EQ(v2->location_.y(), 20);
-  // Make sure v1 did not receive the event
-  EXPECT_EQ(v1->last_touch_event_type_, 0);
-
-  // Drag event out of bounds. Should still go to v2
-  v1->Reset();
-  v2->Reset();
-  ui::TouchEvent dragged(ui::ET_TOUCH_MOVED,
-                         gfx::Point(50, 40),
-                         0, /* no flags */
-                         0, /* first finger touch */
-                         base::TimeDelta(),
-                         1.0, 0.0, 1.0, 0.0);
-
-  details = root->OnEventFromSource(&dragged);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(v2->last_touch_event_type_, ui::ET_TOUCH_MOVED);
-  EXPECT_EQ(v2->location_.x(), -50);
-  EXPECT_EQ(v2->location_.y(), -60);
-  // Make sure v1 did not receive the event
-  EXPECT_EQ(v1->last_touch_event_type_, 0);
-
-  // Released event out of bounds. Should still go to v2
-  v1->Reset();
-  v2->Reset();
-  ui::TouchEvent released(ui::ET_TOUCH_RELEASED, gfx::Point(),
-                          0, /* no flags */
-                          0, /* first finger */
-                          base::TimeDelta(),
-                          1.0, 0.0, 1.0, 0.0);
-  v2->last_touch_event_was_handled_ = true;
-
-  details = root->OnEventFromSource(&released);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(v2->last_touch_event_type_, ui::ET_TOUCH_RELEASED);
-  EXPECT_EQ(v2->location_.x(), -100);
-  EXPECT_EQ(v2->location_.y(), -100);
-  // Make sure v1 did not receive the event
-  EXPECT_EQ(v1->last_touch_event_type_, 0);
-
-  widget->CloseNow();
-}
-
-void TestView::OnGestureEvent(ui::GestureEvent* event) {
-}
-
-TEST_F(ViewTest, GestureEvent) {
-  // Views hierarchy for non delivery of GestureEvent.
-  TestView* v1 = new TestViewConsumeGesture();
-  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
-
-  TestView* v2 = new TestViewConsumeGesture();
-  v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
-
-  TestView* v3 = new TestViewIgnoreGesture();
-  v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
-
-  scoped_ptr<Widget> widget(new Widget());
-  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
-  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-  params.bounds = gfx::Rect(50, 50, 650, 650);
-  widget->Init(params);
-  internal::RootView* root =
-      static_cast<internal::RootView*>(widget->GetRootView());
-  ui::EventDispatchDetails details;
-
-  root->AddChildView(v1);
-  v1->AddChildView(v2);
-  v2->AddChildView(v3);
-
-  // |v3| completely obscures |v2|, but all the gesture events on |v3| should
-  // reach |v2| because |v3| doesn't process any gesture events. However, since
-  // |v2| does process gesture events, gesture events on |v3| or |v2| should not
-  // reach |v1|.
-
-  v1->Reset();
-  v2->Reset();
-  v3->Reset();
-
-  // Gesture on |v3|
-  GestureEventForTest g1(ui::ET_GESTURE_TAP, 110, 110, 0);
-  details = root->OnEventFromSource(&g1);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
-  EXPECT_EQ(gfx::Point(10, 10), v2->location_);
-  EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
-
-  // Simulate an up so that RootView is no longer targetting |v3|.
-  GestureEventForTest g1_up(ui::ET_GESTURE_END, 110, 110, 0);
-  details = root->OnEventFromSource(&g1_up);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  v1->Reset();
-  v2->Reset();
-  v3->Reset();
-
-  // Gesture on |v1|
-  GestureEventForTest g2(ui::ET_GESTURE_TAP, 80, 80, 0);
-  details = root->OnEventFromSource(&g2);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
-  EXPECT_EQ(gfx::Point(80, 80), v1->location_);
-  EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
-
-  // Send event |g1| again. Even though the coordinates target |v3| it should go
-  // to |v1| as that is the view the touch was initially down on.
-  v1->last_gesture_event_type_ = ui::ET_UNKNOWN;
-  v3->last_gesture_event_type_ = ui::ET_UNKNOWN;
-  details = root->OnEventFromSource(&g1);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
-  EXPECT_EQ(ui::ET_UNKNOWN, v3->last_gesture_event_type_);
-  EXPECT_EQ("110,110", v1->location_.ToString());
-
-  widget->CloseNow();
-}
-
-TEST_F(ViewTest, ScrollGestureEvent) {
-  // Views hierarchy for non delivery of GestureEvent.
-  TestView* v1 = new TestViewConsumeGesture();
-  v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
-
-  TestView* v2 = new TestViewIgnoreScrollGestures();
-  v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100));
-
-  TestView* v3 = new TestViewIgnoreGesture();
-  v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
-
-  scoped_ptr<Widget> widget(new Widget());
-  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
-  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-  params.bounds = gfx::Rect(50, 50, 650, 650);
-  widget->Init(params);
-  internal::RootView* root =
-      static_cast<internal::RootView*>(widget->GetRootView());
-  ui::EventDispatchDetails details;
-
-  root->AddChildView(v1);
-  v1->AddChildView(v2);
-  v2->AddChildView(v3);
-
-  // |v3| completely obscures |v2|, but all the gesture events on |v3| should
-  // reach |v2| because |v3| doesn't process any gesture events. However, since
-  // |v2| does process gesture events, gesture events on |v3| or |v2| should not
-  // reach |v1|.
-
-  v1->Reset();
-  v2->Reset();
-  v3->Reset();
-
-  // Gesture on |v3|
-  GestureEventForTest g1(ui::ET_GESTURE_TAP, 110, 110, 0);
-  details = root->OnEventFromSource(&g1);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
-  EXPECT_EQ(gfx::Point(10, 10), v2->location_);
-  EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
-
-  v2->Reset();
-
-  // Send scroll gestures on |v3|. The gesture should reach |v2|, however,
-  // since it does not process scroll-gesture events, these events should reach
-  // |v1|.
-  GestureEventForTest gscroll_begin(ui::ET_GESTURE_SCROLL_BEGIN, 115, 115, 0);
-  details = root->OnEventFromSource(&gscroll_begin);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
-  EXPECT_EQ(ui::ET_GESTURE_SCROLL_BEGIN, v1->last_gesture_event_type_);
-  v1->Reset();
-
-  // Send a second tap on |v1|. The event should reach |v2| since it is the
-  // default gesture handler, and not |v1| (even though it is the view under the
-  // point, and is the scroll event handler).
-  GestureEventForTest second_tap(ui::ET_GESTURE_TAP, 70, 70, 0);
-  details = root->OnEventFromSource(&second_tap);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_TAP, v2->last_gesture_event_type_);
-  EXPECT_EQ(ui::ET_UNKNOWN, v1->last_gesture_event_type_);
-  v2->Reset();
-
-  GestureEventForTest gscroll_end(ui::ET_GESTURE_SCROLL_END, 50, 50, 0);
-  details = root->OnEventFromSource(&gscroll_end);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_SCROLL_END, v1->last_gesture_event_type_);
-  v1->Reset();
-
-  // Simulate an up so that RootView is no longer targetting |v3|.
-  GestureEventForTest g1_up(ui::ET_GESTURE_END, 110, 110, 0);
-  details = root->OnEventFromSource(&g1_up);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_END, v2->last_gesture_event_type_);
-
-  v1->Reset();
-  v2->Reset();
-  v3->Reset();
-
-  // Gesture on |v1|
-  GestureEventForTest g2(ui::ET_GESTURE_TAP, 80, 80, 0);
-  details = root->OnEventFromSource(&g2);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
-  EXPECT_EQ(gfx::Point(80, 80), v1->location_);
-  EXPECT_EQ(ui::ET_UNKNOWN, v2->last_gesture_event_type_);
-
-  // Send event |g1| again. Even though the coordinates target |v3| it should go
-  // to |v1| as that is the view the touch was initially down on.
-  v1->last_gesture_event_type_ = ui::ET_UNKNOWN;
-  v3->last_gesture_event_type_ = ui::ET_UNKNOWN;
-  details = root->OnEventFromSource(&g1);
-  EXPECT_FALSE(details.dispatcher_destroyed);
-  EXPECT_FALSE(details.target_destroyed);
-
-  EXPECT_EQ(ui::ET_GESTURE_TAP, v1->last_gesture_event_type_);
-  EXPECT_EQ(ui::ET_UNKNOWN, v3->last_gesture_event_type_);
-  EXPECT_EQ("110,110", v1->location_.ToString());
-
-  widget->CloseNow();
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // Painting
 ////////////////////////////////////////////////////////////////////////////////
 
-void TestView::Paint(gfx::Canvas* canvas) {
+void TestView::Paint(gfx::Canvas* canvas, const CullSet& cull_set) {
   canvas->sk_canvas()->getClipBounds(&last_clip_);
 }
 
@@ -920,50 +518,6 @@ TEST_F(ViewTest, RemoveNotification) {
 }
 
 namespace {
-class HitTestView : public View {
- public:
-  explicit HitTestView(bool has_hittest_mask)
-      : has_hittest_mask_(has_hittest_mask) {
-  }
-  virtual ~HitTestView() {}
-
- protected:
-  // Overridden from View:
-  virtual bool HasHitTestMask() const OVERRIDE {
-    return has_hittest_mask_;
-  }
-  virtual void GetHitTestMask(HitTestSource source,
-                              gfx::Path* mask) const OVERRIDE {
-    DCHECK(has_hittest_mask_);
-    DCHECK(mask);
-
-    SkScalar w = SkIntToScalar(width());
-    SkScalar h = SkIntToScalar(height());
-
-    // Create a triangular mask within the bounds of this View.
-    mask->moveTo(w / 2, 0);
-    mask->lineTo(w, h);
-    mask->lineTo(0, h);
-    mask->close();
-  }
-
- private:
-  bool has_hittest_mask_;
-
-  DISALLOW_COPY_AND_ASSIGN(HitTestView);
-};
-
-gfx::Point ConvertPointToView(View* view, const gfx::Point& p) {
-  gfx::Point tmp(p);
-  View::ConvertPointToTarget(view->GetWidget()->GetRootView(), view, &tmp);
-  return tmp;
-}
-
-gfx::Rect ConvertRectToView(View* view, const gfx::Rect& r) {
-  gfx::Rect tmp(r);
-  tmp.set_origin(ConvertPointToView(view, r.origin()));
-  return tmp;
-}
 
 void RotateCounterclockwise(gfx::Transform* transform) {
   transform->matrix().set3x3(0, -1, 0,
@@ -979,72 +533,6 @@ void RotateClockwise(gfx::Transform* transform) {
 
 }  // namespace
 
-TEST_F(ViewTest, HitTestMasks) {
-  Widget* widget = new Widget;
-  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
-  widget->Init(params);
-  View* root_view = widget->GetRootView();
-  root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
-
-  gfx::Rect v1_bounds = gfx::Rect(0, 0, 100, 100);
-  HitTestView* v1 = new HitTestView(false);
-  v1->SetBoundsRect(v1_bounds);
-  root_view->AddChildView(v1);
-
-  gfx::Rect v2_bounds = gfx::Rect(105, 0, 100, 100);
-  HitTestView* v2 = new HitTestView(true);
-  v2->SetBoundsRect(v2_bounds);
-  root_view->AddChildView(v2);
-
-  gfx::Point v1_centerpoint = v1_bounds.CenterPoint();
-  gfx::Point v2_centerpoint = v2_bounds.CenterPoint();
-  gfx::Point v1_origin = v1_bounds.origin();
-  gfx::Point v2_origin = v2_bounds.origin();
-
-  gfx::Rect r1(10, 10, 110, 15);
-  gfx::Rect r2(106, 1, 98, 98);
-  gfx::Rect r3(0, 0, 300, 300);
-  gfx::Rect r4(115, 342, 200, 10);
-
-  // Test HitTestPoint
-  EXPECT_TRUE(v1->HitTestPoint(ConvertPointToView(v1, v1_centerpoint)));
-  EXPECT_TRUE(v2->HitTestPoint(ConvertPointToView(v2, v2_centerpoint)));
-
-  EXPECT_TRUE(v1->HitTestPoint(ConvertPointToView(v1, v1_origin)));
-  EXPECT_FALSE(v2->HitTestPoint(ConvertPointToView(v2, v2_origin)));
-
-  // Test HitTestRect
-  EXPECT_TRUE(v1->HitTestRect(ConvertRectToView(v1, r1)));
-  EXPECT_FALSE(v2->HitTestRect(ConvertRectToView(v2, r1)));
-
-  EXPECT_FALSE(v1->HitTestRect(ConvertRectToView(v1, r2)));
-  EXPECT_TRUE(v2->HitTestRect(ConvertRectToView(v2, r2)));
-
-  EXPECT_TRUE(v1->HitTestRect(ConvertRectToView(v1, r3)));
-  EXPECT_TRUE(v2->HitTestRect(ConvertRectToView(v2, r3)));
-
-  EXPECT_FALSE(v1->HitTestRect(ConvertRectToView(v1, r4)));
-  EXPECT_FALSE(v2->HitTestRect(ConvertRectToView(v2, r4)));
-
-  // Test GetEventHandlerForPoint
-  EXPECT_EQ(v1, root_view->GetEventHandlerForPoint(v1_centerpoint));
-  EXPECT_EQ(v2, root_view->GetEventHandlerForPoint(v2_centerpoint));
-
-  EXPECT_EQ(v1, root_view->GetEventHandlerForPoint(v1_origin));
-  EXPECT_EQ(root_view, root_view->GetEventHandlerForPoint(v2_origin));
-
-  // Test GetTooltipHandlerForPoint
-  EXPECT_EQ(v1, root_view->GetTooltipHandlerForPoint(v1_centerpoint));
-  EXPECT_EQ(v2, root_view->GetTooltipHandlerForPoint(v2_centerpoint));
-
-  EXPECT_EQ(v1, root_view->GetTooltipHandlerForPoint(v1_origin));
-  EXPECT_EQ(root_view, root_view->GetTooltipHandlerForPoint(v2_origin));
-
-  EXPECT_FALSE(v1->GetTooltipHandlerForPoint(v2_origin));
-
-  widget->CloseNow();
-}
-
 // Tests the correctness of the rect-based targeting algorithm implemented in
 // View::GetEventHandlerForRect(). See http://goo.gl/3Jp2BD for a description
 // of rect-based targeting.
@@ -1357,6 +845,163 @@ TEST_F(ViewTest, GetEventHandlerForRect) {
   widget->CloseNow();
 }
 
+// Tests that GetEventHandlerForRect() and GetTooltipHandlerForPoint() behave
+// as expected when different views in the view hierarchy return false
+// when CanProcessEventsWithinSubtree() is called.
+TEST_F(ViewTest, CanProcessEventsWithinSubtree) {
+  Widget* widget = new Widget;
+  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+  widget->Init(params);
+  View* root_view = widget->GetRootView();
+  root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500));
+
+  // Have this hierarchy of views (the coords here are in the coordinate
+  // space of the root view):
+  // v (0, 0, 100, 100)
+  //  - v_child (0, 0, 20, 30)
+  //    - v_grandchild (5, 5, 5, 15)
+
+  TestView* v = new TestView;
+  v->SetBounds(0, 0, 100, 100);
+  root_view->AddChildView(v);
+  v->set_notify_enter_exit_on_child(true);
+
+  TestView* v_child = new TestView;
+  v_child->SetBounds(0, 0, 20, 30);
+  v->AddChildView(v_child);
+
+  TestView* v_grandchild = new TestView;
+  v_grandchild->SetBounds(5, 5, 5, 15);
+  v_child->AddChildView(v_grandchild);
+
+  v->Reset();
+  v_child->Reset();
+  v_grandchild->Reset();
+
+  // Define rects and points within the views in the hierarchy.
+  gfx::Rect rect_in_v_grandchild(7, 7, 3, 3);
+  gfx::Point point_in_v_grandchild(rect_in_v_grandchild.origin());
+  gfx::Rect rect_in_v_child(12, 3, 5, 5);
+  gfx::Point point_in_v_child(rect_in_v_child.origin());
+  gfx::Rect rect_in_v(50, 50, 25, 30);
+  gfx::Point point_in_v(rect_in_v.origin());
+
+  // When all three views return true when CanProcessEventsWithinSubtree()
+  // is called, targeting should behave as expected.
+
+  View* result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+  EXPECT_EQ(v_grandchild, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+  EXPECT_EQ(v_grandchild, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+  EXPECT_EQ(v_child, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+  EXPECT_EQ(v_child, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+
+  // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
+  // is called, then |v_grandchild| cannot be returned as a target.
+
+  v_grandchild->set_can_process_events_within_subtree(false);
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+  EXPECT_EQ(v_child, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+  EXPECT_EQ(v_child, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+  EXPECT_EQ(v_child, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+  EXPECT_EQ(v_child, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+  EXPECT_EQ(v, result_view);
+
+  // When |v_grandchild| returns false when CanProcessEventsWithinSubtree()
+  // is called, then NULL should be returned as a target if we call
+  // GetTooltipHandlerForPoint() with |v_grandchild| as the root of the
+  // views tree. Note that the location must be in the coordinate space
+  // of the root view (|v_grandchild| in this case), so use (1, 1).
+
+  result_view = v_grandchild;
+  result_view = v_grandchild->GetTooltipHandlerForPoint(gfx::Point(1, 1));
+  EXPECT_EQ(NULL, result_view);
+  result_view = NULL;
+
+  // When |v_child| returns false when CanProcessEventsWithinSubtree()
+  // is called, then neither |v_child| nor |v_grandchild| can be returned
+  // as a target (|v| should be returned as the target for each case).
+
+  v_grandchild->Reset();
+  v_child->set_can_process_events_within_subtree(false);
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+  EXPECT_EQ(v, result_view);
+  result_view = NULL;
+
+  // When |v| returns false when CanProcessEventsWithinSubtree()
+  // is called, then none of |v|, |v_child|, and |v_grandchild| can be returned
+  // as a target (|root_view| should be returned as the target for each case).
+
+  v_child->Reset();
+  v->set_can_process_events_within_subtree(false);
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild);
+  EXPECT_EQ(root_view, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild);
+  EXPECT_EQ(root_view, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v_child);
+  EXPECT_EQ(root_view, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child);
+  EXPECT_EQ(root_view, result_view);
+  result_view = NULL;
+
+  result_view = root_view->GetEventHandlerForRect(rect_in_v);
+  EXPECT_EQ(root_view, result_view);
+  result_view = NULL;
+  result_view = root_view->GetTooltipHandlerForPoint(point_in_v);
+  EXPECT_EQ(root_view, result_view);
+}
+
 TEST_F(ViewTest, NotifyEnterExitOnChild) {
   Widget* widget = new Widget;
   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -1492,7 +1137,6 @@ TEST_F(ViewTest, Textfield) {
   const base::string16 kText = ASCIIToUTF16(
       "Reality is that which, when you stop believing it, doesn't go away.");
   const base::string16 kExtraText = ASCIIToUTF16("Pretty deep, Philip!");
-  const base::string16 kEmptyString;
 
   Widget* widget = new Widget;
   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -1509,15 +1153,15 @@ TEST_F(ViewTest, Textfield) {
   textfield->AppendText(kExtraText);
   EXPECT_EQ(kText + kExtraText, textfield->text());
   textfield->SetText(base::string16());
-  EXPECT_EQ(kEmptyString, textfield->text());
+  EXPECT_TRUE(textfield->text().empty());
 
   // Test selection related methods.
   textfield->SetText(kText);
-  EXPECT_EQ(kEmptyString, textfield->GetSelectedText());
+  EXPECT_TRUE(textfield->GetSelectedText().empty());
   textfield->SelectAll(false);
   EXPECT_EQ(kText, textfield->text());
   textfield->ClearSelection();
-  EXPECT_EQ(kEmptyString, textfield->GetSelectedText());
+  EXPECT_TRUE(textfield->GetSelectedText().empty());
 
   widget->CloseNow();
 }
@@ -1632,7 +1276,7 @@ bool TestView::AcceleratorPressed(const ui::Accelerator& accelerator) {
 
 // TODO: these tests were initially commented out when getting aura to
 // run. Figure out if still valuable and either nuke or fix.
-#if defined(false)
+#if 0
 TEST_F(ViewTest, ActivateAccelerator) {
   // Register a keyboard accelerator before the view is added to a window.
   ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
@@ -1837,7 +1481,7 @@ TEST_F(ViewTest, DISABLED_RerouteMouseWheelTest) {
   window1->CloseNow();
   window2->CloseNow();
 }
-#endif  // false
+#endif  // 0
 
 ////////////////////////////////////////////////////////////////////////////////
 // Native view hierachy
@@ -2164,7 +1808,7 @@ class VisibleBoundsView : public View {
 
  private:
   // Overridden from View:
-  virtual bool NeedsNotificationWhenVisibleBoundsChange() const OVERRIDE {
+  virtual bool GetNeedsNotificationWhenVisibleBoundsChange() const OVERRIDE {
      return true;
   }
   virtual void OnVisibleBoundsChanged() OVERRIDE {
@@ -2511,7 +2155,7 @@ TEST_F(ViewTest, ConversionsToFromScreen) {
   child->SetTransform(t);
 
   gfx::Point point_in_screen(100, 90);
-  gfx::Point point_in_child(80,60);
+  gfx::Point point_in_child(80, 60);
 
   gfx::Point point = point_in_screen;
   View::ConvertPointFromScreen(child, &point);
@@ -2998,6 +2642,69 @@ TEST_F(ViewTest, AddExistingChild) {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// FocusManager
+////////////////////////////////////////////////////////////////////////////////
+
+// A widget that always claims to be active, regardless of its real activation
+// status.
+class ActiveWidget : public Widget {
+ public:
+  ActiveWidget() {}
+  virtual ~ActiveWidget() {}
+
+  virtual bool IsActive() const OVERRIDE {
+    return true;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ActiveWidget);
+};
+
+TEST_F(ViewTest, AdvanceFocusIfNecessaryForUnfocusableView) {
+  // Create a widget with two views and give the first one focus.
+  ActiveWidget widget;
+  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+  params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  widget.Init(params);
+
+  View* view1 = new View();
+  view1->SetFocusable(true);
+  widget.GetRootView()->AddChildView(view1);
+  View* view2 = new View();
+  view2->SetFocusable(true);
+  widget.GetRootView()->AddChildView(view2);
+
+  FocusManager* focus_manager = widget.GetFocusManager();
+  ASSERT_TRUE(focus_manager);
+
+  focus_manager->SetFocusedView(view1);
+  EXPECT_EQ(view1, focus_manager->GetFocusedView());
+
+  // Disable the focused view and check if the next view gets focused.
+  view1->SetEnabled(false);
+  EXPECT_EQ(view2, focus_manager->GetFocusedView());
+
+  // Re-enable and re-focus.
+  view1->SetEnabled(true);
+  focus_manager->SetFocusedView(view1);
+  EXPECT_EQ(view1, focus_manager->GetFocusedView());
+
+  // Hide the focused view and check it the next view gets focused.
+  view1->SetVisible(false);
+  EXPECT_EQ(view2, focus_manager->GetFocusedView());
+
+  // Re-show and re-focus.
+  view1->SetVisible(true);
+  focus_manager->SetFocusedView(view1);
+  EXPECT_EQ(view1, focus_manager->GetFocusedView());
+
+  // Set the focused view as not focusable and check if the next view gets
+  // focused.
+  view1->SetFocusable(false);
+  EXPECT_EQ(view2, focus_manager->GetFocusedView());
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // Layers
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -3508,17 +3215,6 @@ TEST_F(ViewLayerTest, AcquireLayer) {
   c1.reset();
 }
 
-// Verify that new layer scales content only if the old layer does.
-TEST_F(ViewLayerTest, RecreateLayerScaling) {
-  scoped_ptr<View> v(new View());
-  v->SetPaintToLayer(true);
-  // Set to non default value.
-  v->layer()->set_scale_content(false);
-  scoped_ptr<ui::Layer> old_layer(v->RecreateLayer());
-  ui::Layer* new_layer = v->layer();
-  EXPECT_FALSE(new_layer->scale_content());
-}
-
 // Verify the z-order of the layers as a result of calling RecreateLayer().
 TEST_F(ViewLayerTest, RecreateLayerZOrder) {
   scoped_ptr<View> v(new View());
@@ -3608,6 +3304,340 @@ TEST_F(ViewLayerTest, RecreateLayerMovesNonViewChildren) {
   EXPECT_EQ(v.layer()->children()[1], child.layer());
 }
 
+class BoundsTreeTestView : public View {
+ public:
+  BoundsTreeTestView() {}
+
+  virtual void PaintChildren(gfx::Canvas* canvas,
+                             const CullSet& cull_set) OVERRIDE {
+    // Save out a copy of the cull_set before calling the base implementation.
+    last_cull_set_.clear();
+    if (cull_set.cull_set_) {
+      for (base::hash_set<intptr_t>::iterator it = cull_set.cull_set_->begin();
+           it != cull_set.cull_set_->end();
+           ++it) {
+        last_cull_set_.insert(reinterpret_cast<View*>(*it));
+      }
+    }
+    View::PaintChildren(canvas, cull_set);
+  }
+
+  std::set<View*> last_cull_set_;
+};
+
+TEST_F(ViewLayerTest, BoundsTreePaintUpdatesCullSet) {
+  BoundsTreeTestView* test_view = new BoundsTreeTestView;
+  widget()->SetContentsView(test_view);
+
+  View* v1 = new View();
+  v1->SetBoundsRect(gfx::Rect(10, 15, 150, 151));
+  test_view->AddChildView(v1);
+
+  View* v2 = new View();
+  v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
+  v1->AddChildView(v2);
+
+  // Schedule a full-view paint to get everyone's rectangles updated.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Now we have test_view - v1 - v2. Damage to only test_view should only
+  // return root_view and test_view.
+  test_view->SchedulePaintInRect(gfx::Rect(0, 0, 1, 1));
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  EXPECT_EQ(2U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+
+  // Damage to v1 only should only return root_view, test_view, and v1.
+  test_view->SchedulePaintInRect(gfx::Rect(11, 16, 1, 1));
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  EXPECT_EQ(3U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+
+  // A Damage rect inside v2 should get all 3 views back in the |last_cull_set_|
+  // on call to TestView::Paint(), along with the widget root view.
+  test_view->SchedulePaintInRect(gfx::Rect(31, 49, 1, 1));
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  EXPECT_EQ(4U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
+}
+
+TEST_F(ViewLayerTest, BoundsTreeWithRTL) {
+  std::string locale = l10n_util::GetApplicationLocale(std::string());
+  base::i18n::SetICUDefaultLocale("ar");
+
+  BoundsTreeTestView* test_view = new BoundsTreeTestView;
+  widget()->SetContentsView(test_view);
+
+  // Add child views, which should be in RTL coordinate space of parent view.
+  View* v1 = new View;
+  v1->SetBoundsRect(gfx::Rect(10, 12, 25, 26));
+  test_view->AddChildView(v1);
+
+  View* v2 = new View;
+  v2->SetBoundsRect(gfx::Rect(5, 6, 7, 8));
+  v1->AddChildView(v2);
+
+  // Schedule a full-view paint to get everyone's rectangles updated.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Damage to the right side of the parent view should touch both child views.
+  gfx::Rect rtl_damage(test_view->bounds().width() - 16, 18, 1, 1);
+  test_view->SchedulePaintInRect(rtl_damage);
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  EXPECT_EQ(4U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
+
+  // Damage to the left side of the parent view should only touch the
+  // container views.
+  gfx::Rect ltr_damage(16, 18, 1, 1);
+  test_view->SchedulePaintInRect(ltr_damage);
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  EXPECT_EQ(2U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+
+  // Reset locale.
+  base::i18n::SetICUDefaultLocale(locale);
+}
+
+TEST_F(ViewLayerTest, BoundsTreeSetBoundsChangesCullSet) {
+  BoundsTreeTestView* test_view = new BoundsTreeTestView;
+  widget()->SetContentsView(test_view);
+
+  View* v1 = new View;
+  v1->SetBoundsRect(gfx::Rect(5, 6, 100, 101));
+  test_view->AddChildView(v1);
+
+  View* v2 = new View;
+  v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50));
+  v1->AddChildView(v2);
+
+  // Schedule a full-view paint to get everyone's rectangles updated.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Move v1 to a new origin out of the way of our next query.
+  v1->SetBoundsRect(gfx::Rect(50, 60, 100, 101));
+  // The move will force a repaint.
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Schedule a paint with damage rect where v1 used to be.
+  test_view->SchedulePaintInRect(gfx::Rect(5, 6, 10, 11));
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Should only have picked up root_view and test_view.
+  EXPECT_EQ(2U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+}
+
+TEST_F(ViewLayerTest, BoundsTreeLayerChangeMakesNewTree) {
+  BoundsTreeTestView* test_view = new BoundsTreeTestView;
+  widget()->SetContentsView(test_view);
+
+  View* v1 = new View;
+  v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
+  test_view->AddChildView(v1);
+
+  View* v2 = new View;
+  v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
+  v1->AddChildView(v2);
+
+  // Schedule a full-view paint to get everyone's rectangles updated.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Set v1 to paint to its own layer, it should remove itself from the
+  // test_view heiarchy and no longer intersect with damage rects in that cull
+  // set.
+  v1->SetPaintToLayer(true);
+
+  // Schedule another full-view paint.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  // v1 and v2 should no longer be present in the test_view cull_set.
+  EXPECT_EQ(2U, test_view->last_cull_set_.size());
+  EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
+  EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
+
+  // Now set v1 back to not painting to a layer.
+  v1->SetPaintToLayer(false);
+  // Schedule another full-view paint.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  // We should be back to the full cull set including v1 and v2.
+  EXPECT_EQ(4U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
+}
+
+TEST_F(ViewLayerTest, BoundsTreeRemoveChildRemovesBounds) {
+  BoundsTreeTestView* test_view = new BoundsTreeTestView;
+  widget()->SetContentsView(test_view);
+
+  View* v1 = new View;
+  v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20));
+  test_view->AddChildView(v1);
+
+  View* v2 = new View;
+  v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
+  v1->AddChildView(v2);
+
+  // Schedule a full-view paint to get everyone's rectangles updated.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Now remove v1 from the root view.
+  test_view->RemoveChildView(v1);
+
+  // Schedule another full-view paint.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  // v1 and v2 should no longer be present in the test_view cull_set.
+  EXPECT_EQ(2U, test_view->last_cull_set_.size());
+  EXPECT_EQ(0U, test_view->last_cull_set_.count(v1));
+  EXPECT_EQ(0U, test_view->last_cull_set_.count(v2));
+
+  // View v1 and v2 are no longer part of view hierarchy and therefore won't be
+  // deleted with that hierarchy.
+  delete v1;
+}
+
+TEST_F(ViewLayerTest, BoundsTreeMoveViewMovesBounds) {
+  BoundsTreeTestView* test_view = new BoundsTreeTestView;
+  widget()->SetContentsView(test_view);
+
+  // Build hierarchy v1 - v2 - v3.
+  View* v1 = new View;
+  v1->SetBoundsRect(gfx::Rect(20, 30, 150, 160));
+  test_view->AddChildView(v1);
+
+  View* v2 = new View;
+  v2->SetBoundsRect(gfx::Rect(5, 10, 40, 50));
+  v1->AddChildView(v2);
+
+  View* v3 = new View;
+  v3->SetBoundsRect(gfx::Rect(1, 2, 3, 4));
+  v2->AddChildView(v3);
+
+  // Schedule a full-view paint and ensure all views are present in the cull.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+  EXPECT_EQ(5U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v2));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v3));
+
+  // Build an unrelated view hierarchy and move v2 in to it.
+  scoped_ptr<Widget> test_widget(new Widget);
+  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+  params.bounds = gfx::Rect(10, 10, 500, 500);
+  params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  test_widget->Init(params);
+  test_widget->Show();
+  BoundsTreeTestView* widget_view = new BoundsTreeTestView;
+  test_widget->SetContentsView(widget_view);
+  widget_view->AddChildView(v2);
+
+  // Now schedule full-view paints in both widgets.
+  test_view->SchedulePaintInRect(test_view->bounds());
+  widget_view->SchedulePaintInRect(widget_view->bounds());
+  GetRootLayer()->GetCompositor()->ScheduleDraw();
+  ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor());
+
+  // Only v1 should be present in the first cull set.
+  EXPECT_EQ(3U, test_view->last_cull_set_.size());
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView()));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view));
+  EXPECT_EQ(1U, test_view->last_cull_set_.count(v1));
+
+  // We should find v2 and v3 in the widget_view cull_set.
+  EXPECT_EQ(4U, widget_view->last_cull_set_.size());
+  EXPECT_EQ(1U, widget_view->last_cull_set_.count(test_widget->GetRootView()));
+  EXPECT_EQ(1U, widget_view->last_cull_set_.count(widget_view));
+  EXPECT_EQ(1U, widget_view->last_cull_set_.count(v2));
+  EXPECT_EQ(1U, widget_view->last_cull_set_.count(v3));
+}
+
+namespace {
+
+std::string ToString(const gfx::Vector2dF& vector) {
+  return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y());
+}
+
+}  // namespace
+
+TEST_F(ViewLayerTest, SnapLayerToPixel) {
+  View* v1 = new View;
+
+  View* v11 = new View;
+  v1->AddChildView(v11);
+
+  widget()->SetContentsView(v1);
+
+  const gfx::Size& size = GetRootLayer()->GetCompositor()->size();
+  GetRootLayer()->GetCompositor()->SetScaleAndSize(1.25f, size);
+
+  v11->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
+  v1->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
+  v11->SetPaintToLayer(true);
+
+  EXPECT_EQ("0.40 0.40", ToString(v11->layer()->subpixel_position_offset()));
+
+  // Creating a layer in parent should update the child view's layer offset.
+  v1->SetPaintToLayer(true);
+  EXPECT_EQ("-0.20 -0.20", ToString(v1->layer()->subpixel_position_offset()));
+  EXPECT_EQ("-0.20 -0.20", ToString(v11->layer()->subpixel_position_offset()));
+
+  // DSF change should get propagated and update offsets.
+  GetRootLayer()->GetCompositor()->SetScaleAndSize(1.5f, size);
+  EXPECT_EQ("0.33 0.33", ToString(v1->layer()->subpixel_position_offset()));
+  EXPECT_EQ("0.33 0.33", ToString(v11->layer()->subpixel_position_offset()));
+
+  // Deleting parent's layer should update the child view's layer's offset.
+  v1->SetPaintToLayer(false);
+  EXPECT_EQ("0.00 0.00", ToString(v11->layer()->subpixel_position_offset()));
+
+  // Setting parent view should update the child view's layer's offset.
+  v1->SetBoundsRect(gfx::Rect(2, 2, 10, 10));
+  EXPECT_EQ("0.33 0.33", ToString(v11->layer()->subpixel_position_offset()));
+
+  // Setting integral DSF should reset the offset.
+  GetRootLayer()->GetCompositor()->SetScaleAndSize(2.0f, size);
+  EXPECT_EQ("0.00 0.00", ToString(v11->layer()->subpixel_position_offset()));
+}
+
 TEST_F(ViewTest, FocusableAssertions) {
   // View subclasses may change insets based on whether they are focusable,
   // which effects the preferred size. To avoid preferred size changing around
@@ -3624,141 +3654,6 @@ TEST_F(ViewTest, FocusableAssertions) {
   EXPECT_FALSE(view.focusable());
 }
 
-// Creates a widget of TYPE_CONTROL.
-// The caller takes ownership of the returned widget.
-Widget* CreateControlWidget(aura::Window* parent, const gfx::Rect& bounds) {
-  Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
-  params.parent = parent;
-  params.bounds = bounds;
-  Widget* widget = new Widget();
-  widget->Init(params);
-  return widget;
-}
-
-// Returns a view with a layer with the passed in |bounds| and |layer_name|.
-// The caller takes ownership of the returned view.
-View* CreateViewWithLayer(const gfx::Rect& bounds,
-                          const char* layer_name) {
-  View* view = new View();
-  view->SetBoundsRect(bounds);
-  view->SetPaintToLayer(true);
-  view->layer()->set_name(layer_name);
-  return view;
-}
-
-// Test that RecreateWindowLayers() recreates the layers for all child windows
-// and all child views and that the z-order of the recreated layers matches that
-// of the original layers.
-// Test hierarchy:
-// w1
-// +-- v1
-// +-- v2 (no layer)
-//     +-- v3 (no layer)
-//     +-- v4
-// +-- w2
-//     +-- v5
-//         +-- v6
-// +-- v7
-//     +-- v8
-//     +-- v9
-TEST_F(ViewTest, RecreateLayers) {
-  Widget* w1 = CreateControlWidget(GetContext(), gfx::Rect(0, 0, 100, 100));
-  w1->GetNativeView()->layer()->set_name("w1");
-
-  View* v2 = new View();
-  v2->SetBounds(0, 1, 100, 101);
-  View* v3 = new View();
-  v3->SetBounds(0, 2, 100, 102);
-  View* w2_host_view = new View();
-
-  View* v1 = CreateViewWithLayer(gfx::Rect(0, 3, 100, 103), "v1");
-  ui::Layer* v1_layer = v1->layer();
-  w1->GetRootView()->AddChildView(v1);
-  w1->GetRootView()->AddChildView(v2);
-  v2->AddChildView(v3);
-  View* v4 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v4");
-  ui::Layer* v4_layer = v4->layer();
-  v2->AddChildView(v4);
-
-  w1->GetRootView()->AddChildView(w2_host_view);
-  View* v7 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v7");
-  ui::Layer* v7_layer = v7->layer();
-  w1->GetRootView()->AddChildView(v7);
-
-  View* v8 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v8");
-  ui::Layer* v8_layer = v8->layer();
-  v7->AddChildView(v8);
-
-  View* v9 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v9");
-  ui::Layer* v9_layer = v9->layer();
-  v7->AddChildView(v9);
-
-  Widget* w2 = CreateControlWidget(w1->GetNativeView(),
-                                          gfx::Rect(0, 5, 100, 105));
-  w2->GetNativeView()->layer()->set_name("w2");
-  w2->GetNativeView()->SetProperty(kHostViewKey, w2_host_view);
-
-  View* v5 = CreateViewWithLayer(gfx::Rect(0, 6, 100, 106), "v5");
-  w2->GetRootView()->AddChildView(v5);
-  View* v6 = CreateViewWithLayer(gfx::Rect(0, 7, 100, 107), "v6");
-  ui::Layer* v6_layer = v6->layer();
-  v5->AddChildView(v6);
-
-  // Test the initial order of the layers.
-  ui::Layer* w1_layer = w1->GetNativeView()->layer();
-  ASSERT_EQ("w1", w1_layer->name());
-  ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
-  ui::Layer* w2_layer = w1_layer->children()[2];
-  ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
-  ui::Layer* v5_layer = w2_layer->children()[0];
-  ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
-
-  {
-    scoped_ptr<ui::LayerTreeOwner> cloned_owner(
-        wm::RecreateLayers(w1->GetNativeView()));
-    EXPECT_EQ(w1_layer, cloned_owner->root());
-    EXPECT_NE(w1_layer, w1->GetNativeView()->layer());
-
-    // The old layers should still exist and have the same hierarchy.
-    ASSERT_EQ("w1", w1_layer->name());
-    ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
-    ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
-    ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
-    EXPECT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_layer));
-
-    ASSERT_EQ(4u, w1_layer->children().size());
-    EXPECT_EQ(v1_layer, w1_layer->children()[0]);
-    EXPECT_EQ(v4_layer, w1_layer->children()[1]);
-    EXPECT_EQ(w2_layer, w1_layer->children()[2]);
-    EXPECT_EQ(v7_layer, w1_layer->children()[3]);
-
-    ASSERT_EQ(1u, w2_layer->children().size());
-    EXPECT_EQ(v5_layer, w2_layer->children()[0]);
-
-    ASSERT_EQ(1u, v5_layer->children().size());
-    EXPECT_EQ(v6_layer, v5_layer->children()[0]);
-
-    ASSERT_EQ(0u, v6_layer->children().size());
-
-    EXPECT_EQ(2u, v7_layer->children().size());
-    EXPECT_EQ(v8_layer, v7_layer->children()[0]);
-    EXPECT_EQ(v9_layer, v7_layer->children()[1]);
-
-    // The cloned layers should have the same hierarchy as old.
-    ui::Layer* w1_new_layer = w1->GetNativeView()->layer();
-    EXPECT_EQ("w1", w1_new_layer->name());
-    ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_new_layer));
-    ui::Layer* w2_new_layer = w1_new_layer->children()[2];
-    ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_new_layer));
-    ui::Layer* v5_new_layer = w2_new_layer->children()[0];
-    ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_new_layer));
-    ui::Layer* v7_new_layer = w1_new_layer->children()[3];
-    ASSERT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_new_layer));
-  }
-  // The views and the widgets are destroyed when AuraTestHelper::TearDown()
-  // destroys root_window().
-}
-
 // Verifies when a view is deleted it is removed from ViewStorage.
 TEST_F(ViewTest, UpdateViewStorageOnDelete) {
   ViewStorage* view_storage = ViewStorage::GetInstance();
@@ -3770,4 +3665,43 @@ TEST_F(ViewTest, UpdateViewStorageOnDelete) {
   EXPECT_TRUE(view_storage->RetrieveView(storage_id) == NULL);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// NativeTheme
+////////////////////////////////////////////////////////////////////////////////
+
+void TestView::OnNativeThemeChanged(const ui::NativeTheme* native_theme) {
+  native_theme_ = native_theme;
+}
+
+TEST_F(ViewTest, OnNativeThemeChanged) {
+  TestView* test_view = new TestView();
+  EXPECT_FALSE(test_view->native_theme_);
+  TestView* test_view_child = new TestView();
+  EXPECT_FALSE(test_view_child->native_theme_);
+
+  // Child view added before the widget hierarchy exists should get the
+  // new native theme notification.
+  test_view->AddChildView(test_view_child);
+
+  scoped_ptr<Widget> widget(new Widget);
+  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  widget->Init(params);
+
+  widget->GetRootView()->AddChildView(test_view);
+  EXPECT_TRUE(test_view->native_theme_);
+  EXPECT_EQ(widget->GetNativeTheme(), test_view->native_theme_);
+  EXPECT_TRUE(test_view_child->native_theme_);
+  EXPECT_EQ(widget->GetNativeTheme(), test_view_child->native_theme_);
+
+  // Child view added after the widget hierarchy exists should also get the
+  // notification.
+  TestView* test_view_child_2 = new TestView();
+  test_view->AddChildView(test_view_child_2);
+  EXPECT_TRUE(test_view_child_2->native_theme_);
+  EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_);
+
+  widget->CloseNow();
+}
+
 }  // namespace views