| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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_aura.h" | 5 #include "ui/views/controls/native/native_view_host_aura.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/client/aura_constants.h" | |
| 10 #include "ui/aura/window.h" | 9 #include "ui/aura/window.h" |
| 11 #include "ui/base/cursor/cursor.h" | 10 #include "ui/base/cursor/cursor.h" |
| 12 #include "ui/views/controls/native/native_view_host.h" | 11 #include "ui/views/controls/native/native_view_host.h" |
| 13 #include "ui/views/test/views_test_base.h" | 12 #include "ui/views/test/views_test_base.h" |
| 14 #include "ui/views/view.h" | 13 #include "ui/views/view.h" |
| 15 #include "ui/views/view_constants_aura.h" | 14 #include "ui/views/view_constants_aura.h" |
| 16 #include "ui/views/widget/widget.h" | 15 #include "ui/views/widget/widget.h" |
| 17 | 16 |
| 18 namespace views { | 17 namespace views { |
| 19 | 18 |
| 20 // Testing wrapper of the NativeViewHost | |
| 21 class NativeViewHostTesting : public NativeViewHost { | |
| 22 public: | |
| 23 NativeViewHostTesting() {} | |
| 24 virtual ~NativeViewHostTesting() { destroyed_count_++; } | |
| 25 | |
| 26 static void ResetDestroyedCount() { destroyed_count_ = 0; } | |
| 27 | |
| 28 static int destroyed_count() { return destroyed_count_; } | |
| 29 | |
| 30 private: | |
| 31 static int destroyed_count_; | |
| 32 | |
| 33 DISALLOW_COPY_AND_ASSIGN(NativeViewHostTesting); | |
| 34 }; | |
| 35 int NativeViewHostTesting::destroyed_count_ = 0; | |
| 36 | |
| 37 class NativeViewHostAuraTest : public ViewsTestBase { | 19 class NativeViewHostAuraTest : public ViewsTestBase { |
| 38 public: | 20 public: |
| 39 NativeViewHostAuraTest() { | 21 NativeViewHostAuraTest() { |
| 40 } | 22 } |
| 41 | 23 |
| 42 NativeViewHostAura* native_host() { | 24 NativeViewHostAura* native_host() { |
| 43 return static_cast<NativeViewHostAura*>(host_->native_wrapper_.get()); | 25 return static_cast<NativeViewHostAura*>(host_->native_wrapper_.get()); |
| 44 } | 26 } |
| 45 | 27 |
| 46 Widget* toplevel() { | 28 Widget* toplevel() { |
| 47 return toplevel_.get(); | 29 return toplevel_.get(); |
| 48 } | 30 } |
| 49 | 31 |
| 50 NativeViewHost* host() { | 32 NativeViewHost* host() { |
| 51 return host_.get(); | 33 return host_.get(); |
| 52 } | 34 } |
| 53 | 35 |
| 54 Widget* child() { | 36 Widget* child() { |
| 55 return child_.get(); | 37 return child_.get(); |
| 56 } | 38 } |
| 57 | 39 |
| 58 aura::Window* clipping_window() { return &(native_host()->clipping_window_); } | |
| 59 | |
| 60 void CreateHost() { | 40 void CreateHost() { |
| 61 // Create the top level widget. | 41 // Create the top level widget. |
| 62 toplevel_.reset(new Widget); | 42 toplevel_.reset(new Widget); |
| 63 Widget::InitParams toplevel_params = | 43 Widget::InitParams toplevel_params = |
| 64 CreateParams(Widget::InitParams::TYPE_WINDOW); | 44 CreateParams(Widget::InitParams::TYPE_WINDOW); |
| 65 toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 45 toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 66 toplevel_->Init(toplevel_params); | 46 toplevel_->Init(toplevel_params); |
| 67 | 47 |
| 68 // And the child widget. | 48 // And the child widget. |
| 69 View* test_view = new View; | 49 View* test_view = new View; |
| 70 child_.reset(new Widget); | 50 child_.reset(new Widget); |
| 71 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); | 51 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); |
| 72 child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 52 child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 73 child_params.parent = toplevel_->GetNativeView(); | 53 child_params.parent = toplevel_->GetNativeView(); |
| 74 child_->Init(child_params); | 54 child_->Init(child_params); |
| 75 child_->SetContentsView(test_view); | 55 child_->SetContentsView(test_view); |
| 76 | 56 |
| 77 // Owned by |toplevel|. | 57 // Owned by |toplevel|. |
| 78 host_.reset(new NativeViewHostTesting); | 58 host_.reset(new NativeViewHost); |
| 79 toplevel_->GetRootView()->AddChildView(host_.get()); | 59 toplevel_->GetRootView()->AddChildView(host_.get()); |
| 80 host_->Attach(child_->GetNativeView()); | 60 host_->Attach(child_->GetNativeView()); |
| 81 } | 61 } |
| 82 | 62 |
| 83 void DestroyHost() { | 63 void DestroyHost() { |
| 84 host_.reset(); | 64 host_.reset(); |
| 85 } | 65 } |
| 86 | 66 |
| 87 NativeViewHostTesting* ReleaseHost() { return host_.release(); } | |
| 88 | |
| 89 void DestroyTopLevel() { toplevel_.reset(); } | |
| 90 | |
| 91 private: | 67 private: |
| 92 scoped_ptr<Widget> toplevel_; | 68 scoped_ptr<Widget> toplevel_; |
| 93 scoped_ptr<NativeViewHostTesting> host_; | 69 scoped_ptr<NativeViewHost> host_; |
| 94 scoped_ptr<Widget> child_; | 70 scoped_ptr<Widget> child_; |
| 95 | 71 |
| 96 DISALLOW_COPY_AND_ASSIGN(NativeViewHostAuraTest); | 72 DISALLOW_COPY_AND_ASSIGN(NativeViewHostAuraTest); |
| 97 }; | 73 }; |
| 98 | 74 |
| 99 // Verifies NativeViewHostAura stops observing native view on destruction. | 75 // Verifies NativeViewHostAura stops observing native view on destruction. |
| 100 TEST_F(NativeViewHostAuraTest, StopObservingNativeViewOnDestruct) { | 76 TEST_F(NativeViewHostAuraTest, StopObservingNativeViewOnDestruct) { |
| 101 CreateHost(); | 77 CreateHost(); |
| 102 aura::Window* child_win = child()->GetNativeView(); | 78 aura::Window* child_win = child()->GetNativeView(); |
| 103 NativeViewHostAura* aura_host = native_host(); | 79 NativeViewHostAura* aura_host = native_host(); |
| 104 | 80 |
| 105 EXPECT_TRUE(child_win->HasObserver(aura_host)); | 81 EXPECT_TRUE(child_win->HasObserver(aura_host)); |
| 106 DestroyHost(); | 82 DestroyHost(); |
| 107 EXPECT_FALSE(child_win->HasObserver(aura_host)); | 83 EXPECT_FALSE(child_win->HasObserver(aura_host)); |
| 108 } | 84 } |
| 109 | 85 |
| 110 // Tests that the kHostViewKey is correctly set and cleared. | 86 // Tests that the kHostViewKey is correctly set and cleared. |
| 111 TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) { | 87 TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) { |
| 112 // Create the NativeViewHost and attach a NativeView. | 88 // Create the NativeViewHost and attach a NativeView. |
| 113 CreateHost(); | 89 CreateHost(); |
| 114 aura::Window* child_win = child()->GetNativeView(); | 90 aura::Window* child_win = child()->GetNativeView(); |
| 115 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); | 91 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); |
| 116 EXPECT_EQ(host()->GetWidget()->GetNativeView(), | |
| 117 child_win->GetProperty(aura::client::kHostWindowKey)); | |
| 118 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey)); | |
| 119 | 92 |
| 120 host()->Detach(); | 93 host()->Detach(); |
| 121 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); | 94 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); |
| 122 EXPECT_FALSE(child_win->GetProperty(aura::client::kHostWindowKey)); | |
| 123 EXPECT_TRUE(clipping_window()->GetProperty(views::kHostViewKey)); | |
| 124 | 95 |
| 125 host()->Attach(child_win); | 96 host()->Attach(child_win); |
| 126 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); | 97 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); |
| 127 EXPECT_EQ(host()->GetWidget()->GetNativeView(), | |
| 128 child_win->GetProperty(aura::client::kHostWindowKey)); | |
| 129 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey)); | |
| 130 | 98 |
| 131 DestroyHost(); | 99 DestroyHost(); |
| 132 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); | 100 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); |
| 133 EXPECT_FALSE(child_win->GetProperty(aura::client::kHostWindowKey)); | |
| 134 } | 101 } |
| 135 | 102 |
| 136 // Tests that the NativeViewHost reports the cursor set on its native view. | 103 // Tests that the NativeViewHost reports the cursor set on its native view. |
| 137 TEST_F(NativeViewHostAuraTest, CursorForNativeView) { | 104 TEST_F(NativeViewHostAuraTest, CursorForNativeView) { |
| 138 CreateHost(); | 105 CreateHost(); |
| 139 | 106 |
| 140 toplevel()->SetCursor(ui::kCursorHand); | 107 toplevel()->SetCursor(ui::kCursorHand); |
| 141 child()->SetCursor(ui::kCursorWait); | 108 child()->SetCursor(ui::kCursorWait); |
| 142 ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0), | 109 ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0), |
| 143 gfx::Point(0, 0), 0, 0); | 110 gfx::Point(0, 0), 0, 0); |
| 144 | 111 |
| 145 EXPECT_EQ(ui::kCursorWait, host()->GetCursor(move_event).native_type()); | 112 EXPECT_EQ(ui::kCursorWait, host()->GetCursor(move_event).native_type()); |
| 146 | 113 |
| 147 DestroyHost(); | 114 DestroyHost(); |
| 148 } | 115 } |
| 149 | 116 |
| 150 // Test that destroying the top level widget before destroying the attached | |
| 151 // NativeViewHost works correctly. Specifically the associated NVH should be | |
| 152 // destroyed and there shouldn't be any errors. | |
| 153 TEST_F(NativeViewHostAuraTest, DestroyWidget) { | |
| 154 NativeViewHostTesting::ResetDestroyedCount(); | |
| 155 CreateHost(); | |
| 156 ReleaseHost(); | |
| 157 EXPECT_EQ(0, NativeViewHostTesting::destroyed_count()); | |
| 158 DestroyTopLevel(); | |
| 159 EXPECT_EQ(1, NativeViewHostTesting::destroyed_count()); | |
| 160 } | |
| 161 | |
| 162 // Test that the fast resize path places the clipping and content windows were | |
| 163 // they are supposed to be. | |
| 164 TEST_F(NativeViewHostAuraTest, FastResizePath) { | |
| 165 CreateHost(); | |
| 166 toplevel()->SetBounds(gfx::Rect(20, 20, 100, 100)); | |
| 167 | |
| 168 // Without fast resize, the clipping window should size to the native view | |
| 169 // with the native view positioned at the origin of the clipping window and | |
| 170 // the clipping window positioned where the native view was requested. | |
| 171 host()->set_fast_resize(false); | |
| 172 native_host()->ShowWidget(5, 10, 100, 100); | |
| 173 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
| 174 host()->native_view()->bounds().ToString()); | |
| 175 EXPECT_EQ(gfx::Rect(5, 10, 100, 100).ToString(), | |
| 176 clipping_window()->bounds().ToString()); | |
| 177 | |
| 178 // With fast resize, the native view should remain the same size but be | |
| 179 // clipped the requested size. | |
| 180 host()->set_fast_resize(true); | |
| 181 native_host()->ShowWidget(10, 25, 50, 50); | |
| 182 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
| 183 host()->native_view()->bounds().ToString()); | |
| 184 EXPECT_EQ(gfx::Rect(10, 25, 50, 50).ToString(), | |
| 185 clipping_window()->bounds().ToString()); | |
| 186 | |
| 187 // Turning off fast resize should make the native view start resizing again. | |
| 188 host()->set_fast_resize(false); | |
| 189 native_host()->ShowWidget(10, 25, 50, 50); | |
| 190 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), | |
| 191 host()->native_view()->bounds().ToString()); | |
| 192 EXPECT_EQ(gfx::Rect(10, 25, 50, 50).ToString(), | |
| 193 clipping_window()->bounds().ToString()); | |
| 194 | |
| 195 DestroyHost(); | |
| 196 } | |
| 197 | |
| 198 // Test installing and uninstalling a clip. | |
| 199 TEST_F(NativeViewHostAuraTest, InstallClip) { | |
| 200 CreateHost(); | |
| 201 toplevel()->SetBounds(gfx::Rect(20, 20, 100, 100)); | |
| 202 | |
| 203 // Without a clip, the clipping window should always be positioned at the | |
| 204 // requested coordinates with the native view positioned at the origin of the | |
| 205 // clipping window. | |
| 206 native_host()->ShowWidget(10, 20, 100, 100); | |
| 207 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
| 208 host()->native_view()->bounds().ToString()); | |
| 209 EXPECT_EQ(gfx::Rect(10, 20, 100, 100).ToString(), | |
| 210 clipping_window()->bounds().ToString()); | |
| 211 | |
| 212 // Clip to the bottom right quarter of the native view. | |
| 213 native_host()->InstallClip(60, 70, 50, 50); | |
| 214 native_host()->ShowWidget(10, 20, 100, 100); | |
| 215 EXPECT_EQ(gfx::Rect(-50, -50, 100, 100).ToString(), | |
| 216 host()->native_view()->bounds().ToString()); | |
| 217 EXPECT_EQ(gfx::Rect(60, 70, 50, 50).ToString(), | |
| 218 clipping_window()->bounds().ToString()); | |
| 219 | |
| 220 // Clip to the center of the native view. | |
| 221 native_host()->InstallClip(35, 45, 50, 50); | |
| 222 native_host()->ShowWidget(10, 20, 100, 100); | |
| 223 EXPECT_EQ(gfx::Rect(-25, -25, 100, 100).ToString(), | |
| 224 host()->native_view()->bounds().ToString()); | |
| 225 EXPECT_EQ(gfx::Rect(35, 45, 50, 50).ToString(), | |
| 226 clipping_window()->bounds().ToString()); | |
| 227 | |
| 228 // Uninstalling the clip should make the clipping window match the native view | |
| 229 // again. | |
| 230 native_host()->UninstallClip(); | |
| 231 native_host()->ShowWidget(10, 20, 100, 100); | |
| 232 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
| 233 host()->native_view()->bounds().ToString()); | |
| 234 EXPECT_EQ(gfx::Rect(10, 20, 100, 100).ToString(), | |
| 235 clipping_window()->bounds().ToString()); | |
| 236 | |
| 237 DestroyHost(); | |
| 238 } | |
| 239 | |
| 240 } // namespace views | 117 } // namespace views |
| OLD | NEW |