| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/controls/native/native_view_host.h" | 5 #include "ui/views/controls/native/native_view_host.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "ui/aura/window.h" | |
| 10 #include "ui/views/test/views_test_base.h" | 9 #include "ui/views/test/views_test_base.h" |
| 11 #include "ui/views/widget/widget.h" | 10 #include "ui/views/widget/widget.h" |
| 12 | 11 |
| 12 #if defined(USE_AURA) |
| 13 #include "ui/aura/window.h" |
| 14 #endif |
| 15 |
| 13 namespace views { | 16 namespace views { |
| 14 | 17 |
| 15 class NativeViewHostTest : public ViewsTestBase { | 18 class NativeViewHostTest : public ViewsTestBase { |
| 16 public: | 19 public: |
| 17 NativeViewHostTest() { | 20 NativeViewHostTest() { |
| 18 } | 21 } |
| 19 | 22 |
| 20 virtual void SetUp() OVERRIDE { | 23 virtual void SetUp() OVERRIDE { |
| 21 ViewsTestBase::SetUp(); | 24 ViewsTestBase::SetUp(); |
| 22 | 25 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 46 parent_view->AddChildView(host); | 49 parent_view->AddChildView(host); |
| 47 host->Attach(child->GetNativeView()); | 50 host->Attach(child->GetNativeView()); |
| 48 | 51 |
| 49 return child; | 52 return child; |
| 50 } | 53 } |
| 51 | 54 |
| 52 Widget* toplevel() { | 55 Widget* toplevel() { |
| 53 return toplevel_.get(); | 56 return toplevel_.get(); |
| 54 } | 57 } |
| 55 | 58 |
| 56 private: | 59 protected: |
| 57 scoped_ptr<Widget> toplevel_; | 60 scoped_ptr<Widget> toplevel_; |
| 58 | 61 |
| 62 private: |
| 59 DISALLOW_COPY_AND_ASSIGN(NativeViewHostTest); | 63 DISALLOW_COPY_AND_ASSIGN(NativeViewHostTest); |
| 60 }; | 64 }; |
| 61 | 65 |
| 62 namespace { | 66 namespace { |
| 63 | 67 |
| 64 // View implementation used by NativeViewHierarchyChanged to count number of | 68 // View implementation used by NativeViewHierarchyChanged to count number of |
| 65 // times NativeViewHierarchyChanged() is invoked. | 69 // times NativeViewHierarchyChanged() is invoked. |
| 66 class NativeViewHierarchyChangedTestView : public View { | 70 class NativeViewHierarchyChangedTestView : public View { |
| 67 public: | 71 public: |
| 68 NativeViewHierarchyChangedTestView() : notification_count_(0) { | 72 NativeViewHierarchyChangedTestView() : notification_count_(0) { |
| 69 } | 73 } |
| 70 | 74 |
| 75 virtual ~NativeViewHierarchyChangedTestView() { |
| 76 if (g_expect_destroy) |
| 77 EXPECT_EQ(g_expect_destroy_object, this); |
| 78 g_expect_destroy_object = NULL; |
| 79 } |
| 80 |
| 71 void ResetCount() { | 81 void ResetCount() { |
| 72 notification_count_ = 0; | 82 notification_count_ = 0; |
| 73 } | 83 } |
| 74 | 84 |
| 85 void ExpectDestroy() { |
| 86 DCHECK(!g_expect_destroy); |
| 87 g_expect_destroy = true; |
| 88 g_expect_destroy_object = this; |
| 89 } |
| 90 |
| 91 static bool PopExpectDestroy() { |
| 92 DCHECK(g_expect_destroy); |
| 93 g_expect_destroy = false; |
| 94 return g_expect_destroy_object == NULL; |
| 95 } |
| 96 |
| 75 int notification_count() const { return notification_count_; } | 97 int notification_count() const { return notification_count_; } |
| 76 | 98 |
| 77 // Overriden from View: | 99 // Overriden from View: |
| 78 virtual void NativeViewHierarchyChanged() OVERRIDE { | 100 virtual void NativeViewHierarchyChanged() OVERRIDE { |
| 79 ++notification_count_; | 101 ++notification_count_; |
| 80 View::NativeViewHierarchyChanged(); | 102 View::NativeViewHierarchyChanged(); |
| 81 } | 103 } |
| 82 | 104 |
| 83 private: | 105 private: |
| 106 static bool g_expect_destroy; |
| 107 static NativeViewHierarchyChangedTestView* g_expect_destroy_object; |
| 108 |
| 84 int notification_count_; | 109 int notification_count_; |
| 85 | 110 |
| 86 DISALLOW_COPY_AND_ASSIGN(NativeViewHierarchyChangedTestView); | 111 DISALLOW_COPY_AND_ASSIGN(NativeViewHierarchyChangedTestView); |
| 87 }; | 112 }; |
| 88 | 113 |
| 114 bool NativeViewHierarchyChangedTestView::g_expect_destroy = false; |
| 115 NativeViewHierarchyChangedTestView* |
| 116 NativeViewHierarchyChangedTestView::g_expect_destroy_object = NULL; |
| 117 |
| 118 #if defined(USE_AURA) |
| 89 aura::Window* GetNativeParent(aura::Window* window) { | 119 aura::Window* GetNativeParent(aura::Window* window) { |
| 90 return window->parent(); | 120 return window->parent(); |
| 91 } | 121 } |
| 122 #else |
| 123 gfx::NativeView GetNativeParent(gfx::NativeView native_view) { |
| 124 Widget* widget = Widget::GetWidgetForNativeView(native_view); |
| 125 return widget ? widget->GetNativeView() : NULL; |
| 126 } |
| 127 #endif |
| 92 | 128 |
| 93 class ViewHierarchyChangedTestHost : public NativeViewHost { | 129 class ViewHierarchyChangedTestHost : public NativeViewHost { |
| 94 public: | 130 public: |
| 95 ViewHierarchyChangedTestHost() | 131 ViewHierarchyChangedTestHost() |
| 96 : num_parent_changes_(0) { | 132 : num_parent_changes_(0) { |
| 97 } | 133 } |
| 98 | 134 |
| 99 void ResetParentChanges() { | 135 void ResetParentChanges() { |
| 100 num_parent_changes_ = 0; | 136 num_parent_changes_ = 0; |
| 101 } | 137 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 119 private: | 155 private: |
| 120 int num_parent_changes_; | 156 int num_parent_changes_; |
| 121 | 157 |
| 122 DISALLOW_COPY_AND_ASSIGN(ViewHierarchyChangedTestHost); | 158 DISALLOW_COPY_AND_ASSIGN(ViewHierarchyChangedTestHost); |
| 123 }; | 159 }; |
| 124 | 160 |
| 125 } // namespace | 161 } // namespace |
| 126 | 162 |
| 127 // Verifies NativeViewHierarchyChanged is sent. | 163 // Verifies NativeViewHierarchyChanged is sent. |
| 128 TEST_F(NativeViewHostTest, NativeViewHierarchyChanged) { | 164 TEST_F(NativeViewHostTest, NativeViewHierarchyChanged) { |
| 165 // Put a test view in the parent widget to track changes. |
| 166 views::View* parent_view = toplevel()->GetRootView(); |
| 167 NativeViewHierarchyChangedTestView* test_view_in_parent = |
| 168 new NativeViewHierarchyChangedTestView; |
| 169 parent_view->AddChildView(test_view_in_parent); |
| 170 |
| 129 // Create a child widget. | 171 // Create a child widget. |
| 130 NativeViewHierarchyChangedTestView* test_view = | 172 NativeViewHierarchyChangedTestView* test_view_in_child = |
| 131 new NativeViewHierarchyChangedTestView; | 173 new NativeViewHierarchyChangedTestView; |
| 174 |
| 132 NativeViewHost* host = new NativeViewHost; | 175 NativeViewHost* host = new NativeViewHost; |
| 133 scoped_ptr<Widget> child(CreateChildForHost(toplevel()->GetNativeView(), | 176 scoped_ptr<Widget> child(CreateChildForHost( |
| 134 toplevel()->GetRootView(), | 177 toplevel()->GetNativeView(), parent_view, test_view_in_child, host)); |
| 135 test_view, | |
| 136 host)); | |
| 137 #if defined(USE_AURA) | 178 #if defined(USE_AURA) |
| 138 // Two notifications are generated from inserting the native view into the | 179 // Two notifications are generated from inserting the native view into the |
| 139 // clipping window and then inserting the clipping window into the root | 180 // clipping window and then inserting the clipping window into the root |
| 140 // window. | 181 // window. |
| 141 EXPECT_EQ(2, test_view->notification_count()); | 182 EXPECT_EQ(2, test_view_in_child->notification_count()); |
| 142 #else | 183 #else |
| 143 EXPECT_EQ(0, test_view->notification_count()); | 184 // One notification results from inserting the native contents view of the |
| 185 // Widget created in CreateChildForHost() into the toplevel Widget's native |
| 186 // hierarchy. |
| 187 EXPECT_EQ(1, test_view_in_child->notification_count()); |
| 188 EXPECT_EQ(1, test_view_in_parent->notification_count()); |
| 144 #endif | 189 #endif |
| 145 test_view->ResetCount(); | 190 test_view_in_child->ResetCount(); |
| 191 test_view_in_parent->ResetCount(); |
| 146 | 192 |
| 147 // Detaching should send a NativeViewHierarchyChanged() notification and | 193 // Detaching should send a NativeViewHierarchyChanged() notification and |
| 148 // change the parent. | 194 // change the parent. |
| 149 host->Detach(); | 195 host->Detach(); |
| 150 #if defined(USE_AURA) | 196 #if defined(USE_AURA) |
| 151 // Two notifications are generated from removing the native view from the | 197 // Two notifications are generated from removing the native view from the |
| 152 // clipping window and then reparenting it to the root window. | 198 // clipping window and then reparenting it to the root window. |
| 153 EXPECT_EQ(2, test_view->notification_count()); | 199 EXPECT_EQ(2, test_view_in_child->notification_count()); |
| 154 #else | 200 #else |
| 155 EXPECT_EQ(1, test_view->notification_count()); | 201 // There are no notifications in the child view because it is not associated |
| 202 // with a Widget after being detached. The parent gets one change. |
| 203 EXPECT_EQ(0, test_view_in_child->notification_count()); |
| 204 EXPECT_EQ(1, test_view_in_parent->notification_count()); |
| 156 #endif | 205 #endif |
| 157 EXPECT_NE(toplevel()->GetNativeView(), | 206 EXPECT_NE(toplevel()->GetNativeView(), |
| 158 GetNativeParent(child->GetNativeView())); | 207 GetNativeParent(child->GetNativeView())); |
| 159 test_view->ResetCount(); | 208 test_view_in_child->ResetCount(); |
| 209 test_view_in_parent->ResetCount(); |
| 160 | 210 |
| 161 // Attaching should send a NativeViewHierarchyChanged() notification and | 211 // Attaching should send a NativeViewHierarchyChanged() notification and |
| 162 // reset the parent. | 212 // reset the parent. |
| 163 host->Attach(child->GetNativeView()); | 213 host->Attach(child->GetNativeView()); |
| 164 #if defined(USE_AURA) | 214 #if defined(USE_AURA) |
| 165 // There is a clipping window inserted above the native view that needs to be | 215 // There is a clipping window inserted above the native view that needs to be |
| 166 // accounted for when looking at the relationship between the native views. | 216 // accounted for when looking at the relationship between the native views. |
| 167 EXPECT_EQ(2, test_view->notification_count()); | 217 EXPECT_EQ(2, test_view_in_child->notification_count()); |
| 168 EXPECT_EQ(toplevel()->GetNativeView(), | 218 EXPECT_EQ(toplevel()->GetNativeView(), |
| 169 GetNativeParent(GetNativeParent(child->GetNativeView()))); | 219 GetNativeParent(GetNativeParent(child->GetNativeView()))); |
| 170 #else | 220 #else |
| 171 EXPECT_EQ(1, test_view->notification_count()); | 221 EXPECT_EQ(0, test_view_in_child->notification_count()); |
| 222 EXPECT_EQ(1, test_view_in_parent->notification_count()); |
| 172 EXPECT_EQ(toplevel()->GetNativeView(), | 223 EXPECT_EQ(toplevel()->GetNativeView(), |
| 173 GetNativeParent(child->GetNativeView())); | 224 GetNativeParent(child->GetNativeView())); |
| 174 #endif | 225 #endif |
| 226 |
| 227 // Ownership of the views should still rest with the original Widgets. |
| 228 test_view_in_child->ExpectDestroy(); |
| 229 child.reset(); |
| 230 EXPECT_TRUE(NativeViewHierarchyChangedTestView::PopExpectDestroy()); |
| 231 |
| 232 test_view_in_parent->ExpectDestroy(); |
| 233 toplevel_.reset(); |
| 234 EXPECT_TRUE(NativeViewHierarchyChangedTestView::PopExpectDestroy()); |
| 175 } | 235 } |
| 176 | 236 |
| 177 // Verifies ViewHierarchyChanged handles NativeViewHost remove, add and move | 237 // Verifies ViewHierarchyChanged handles NativeViewHost remove, add and move |
| 178 // (reparent) operations with correct parent changes. | 238 // (reparent) operations with correct parent changes. |
| 179 // This exercises the non-recursive code paths in | 239 // This exercises the non-recursive code paths in |
| 180 // View::PropagateRemoveNotifications() and View::PropagateAddNotifications(). | 240 // View::PropagateRemoveNotifications() and View::PropagateAddNotifications(). |
| 181 TEST_F(NativeViewHostTest, ViewHierarchyChangedForHost) { | 241 TEST_F(NativeViewHostTest, ViewHierarchyChangedForHost) { |
| 182 // Original tree: | 242 // Original tree: |
| 183 // toplevel | 243 // toplevel |
| 184 // +-- host0 (NativeViewHost) | 244 // +-- host0 (NativeViewHost) |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 296 host0->ResetParentChanges(); | 356 host0->ResetParentChanges(); |
| 297 host1->ResetParentChanges(); | 357 host1->ResetParentChanges(); |
| 298 EXPECT_EQ(0, host0->num_parent_changes()); | 358 EXPECT_EQ(0, host0->num_parent_changes()); |
| 299 EXPECT_EQ(0, host1->num_parent_changes()); | 359 EXPECT_EQ(0, host1->num_parent_changes()); |
| 300 child0->GetContentsView()->AddChildView(view1); | 360 child0->GetContentsView()->AddChildView(view1); |
| 301 EXPECT_EQ(0, host0->num_parent_changes()); | 361 EXPECT_EQ(0, host0->num_parent_changes()); |
| 302 EXPECT_EQ(2, host1->num_parent_changes()); | 362 EXPECT_EQ(2, host1->num_parent_changes()); |
| 303 } | 363 } |
| 304 | 364 |
| 305 } // namespace views | 365 } // namespace views |
| OLD | NEW |