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/window.h" | 9 #include "ui/aura/window.h" |
10 #include "ui/views/controls/native/native_view_host.h" | 10 #include "ui/views/controls/native/native_view_host.h" |
11 #include "ui/views/test/views_test_base.h" | 11 #include "ui/views/test/views_test_base.h" |
12 #include "ui/views/view.h" | 12 #include "ui/views/view.h" |
13 #include "ui/views/view_constants_aura.h" | 13 #include "ui/views/view_constants_aura.h" |
14 #include "ui/views/widget/widget.h" | 14 #include "ui/views/widget/widget.h" |
15 | 15 |
16 namespace views { | 16 namespace views { |
17 | 17 |
18 // Testing wrapper of the NativeViewHost | |
19 class NativeViewHostTesting : public NativeViewHost { | |
20 public: | |
21 NativeViewHostTesting() {} | |
22 virtual ~NativeViewHostTesting() { | |
23 destroyed_count_++; | |
24 } | |
25 | |
26 static void ResetDestroyedCount() { | |
27 destroyed_count_ = 0; | |
28 } | |
29 | |
30 static int destroyed_count() { | |
31 return destroyed_count_; | |
32 } | |
33 | |
34 private: | |
35 static int destroyed_count_; | |
36 }; | |
sky
2013/10/24 18:16:50
nit: DISALLOW_...
rharrison
2013/10/24 19:28:17
Done.
| |
37 int NativeViewHostTesting::destroyed_count_ = 0; | |
38 | |
39 class AuraWindowDestroyedObserver : public aura::WindowObserver { | |
40 public: | |
41 AuraWindowDestroyedObserver(aura::Window *window) : | |
42 destroyed_count_(0) { | |
43 window->AddObserver(this); | |
44 } | |
45 | |
46 virtual ~AuraWindowDestroyedObserver() {} | |
47 | |
48 int destroyed_count() { return destroyed_count_; } | |
49 | |
50 // aura::WindowObserver overrides | |
51 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE { | |
52 destroyed_count_++; | |
53 } | |
54 | |
55 private: | |
56 int destroyed_count_; | |
57 }; | |
sky
2013/10/24 18:16:50
nit: DISALLOW_...
rharrison
2013/10/24 19:28:17
Done.
| |
58 | |
18 class NativeViewHostAuraTest : public ViewsTestBase { | 59 class NativeViewHostAuraTest : public ViewsTestBase { |
19 public: | 60 public: |
20 NativeViewHostAuraTest() { | 61 NativeViewHostAuraTest() { |
21 } | 62 } |
22 | 63 |
23 NativeViewHostAura* native_host() { | 64 NativeViewHostAura* native_host() { |
24 return static_cast<NativeViewHostAura*>(host_->native_wrapper_.get()); | 65 return static_cast<NativeViewHostAura*>(host_->native_wrapper_.get()); |
25 } | 66 } |
26 | 67 |
27 NativeViewHost* host() { | 68 NativeViewHost* host() { |
28 return host_.get(); | 69 return host_.get(); |
29 } | 70 } |
30 | 71 |
31 Widget* child() { | 72 Widget* child() { |
32 return child_.get(); | 73 return child_.get(); |
33 } | 74 } |
34 | 75 |
76 aura::Window* clipping_window() { | |
77 return native_host()->clipping_window_; | |
78 } | |
79 | |
80 Widget* toplevel() { | |
81 return toplevel_.get(); | |
82 } | |
83 | |
35 void CreateHost() { | 84 void CreateHost() { |
36 // Create the top level widget. | 85 // Create the top level widget. |
37 toplevel_.reset(new Widget); | 86 toplevel_.reset(new Widget); |
38 Widget::InitParams toplevel_params = | 87 Widget::InitParams toplevel_params = |
39 CreateParams(Widget::InitParams::TYPE_WINDOW); | 88 CreateParams(Widget::InitParams::TYPE_WINDOW); |
40 toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 89 toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
41 toplevel_->Init(toplevel_params); | 90 toplevel_->Init(toplevel_params); |
42 | 91 |
43 // And the child widget. | 92 // And the child widget. |
44 View* test_view = new View; | 93 View* test_view = new View; |
45 child_.reset(new Widget); | 94 child_.reset(new Widget); |
46 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); | 95 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); |
47 child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 96 child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
48 child_params.parent = toplevel_->GetNativeView(); | 97 child_params.parent = toplevel_->GetNativeView(); |
49 child_->Init(child_params); | 98 child_->Init(child_params); |
50 child_->SetContentsView(test_view); | 99 child_->SetContentsView(test_view); |
51 | 100 |
52 // Owned by |toplevel|. | 101 // Owned by |toplevel|. |
53 host_.reset(new NativeViewHost); | 102 host_.reset(new NativeViewHostTesting); |
54 toplevel_->GetRootView()->AddChildView(host_.get()); | 103 toplevel_->GetRootView()->AddChildView(host_.get()); |
55 host_->Attach(child_->GetNativeView()); | 104 host_->Attach(child_->GetNativeView()); |
56 } | 105 } |
57 | 106 |
58 void DestroyHost() { | 107 void DestroyHost() { |
59 host_.reset(); | 108 host_.reset(); |
60 } | 109 } |
61 | 110 |
111 NativeViewHostTesting* ReleaseHost() { | |
112 return host_.release(); | |
113 } | |
114 | |
115 void DestroyTopLevel() { | |
116 toplevel_.reset(); | |
117 } | |
118 | |
119 gfx::Point CalculateNativeViewOrigin(gfx::Rect input_rect, | |
120 gfx::Rect native_rect) { | |
121 return native_host()->CalculateNativeViewOrigin(input_rect, native_rect); | |
122 } | |
123 | |
62 private: | 124 private: |
63 scoped_ptr<Widget> toplevel_; | 125 scoped_ptr<Widget> toplevel_; |
64 scoped_ptr<NativeViewHost> host_; | 126 scoped_ptr<NativeViewHostTesting> host_; |
65 scoped_ptr<Widget> child_; | 127 scoped_ptr<Widget> child_; |
66 | 128 |
67 DISALLOW_COPY_AND_ASSIGN(NativeViewHostAuraTest); | 129 DISALLOW_COPY_AND_ASSIGN(NativeViewHostAuraTest); |
68 }; | 130 }; |
69 | 131 |
70 // Verifies NativeViewHostAura stops observing native view on destruction. | 132 // Verifies NativeViewHostAura stops observing native view on destruction. |
71 TEST_F(NativeViewHostAuraTest, StopObservingNativeViewOnDestruct) { | 133 TEST_F(NativeViewHostAuraTest, StopObservingNativeViewOnDestruct) { |
72 CreateHost(); | 134 CreateHost(); |
73 aura::Window* child_win = child()->GetNativeView(); | 135 aura::Window* child_win = child()->GetNativeView(); |
74 NativeViewHostAura* aura_host = native_host(); | 136 NativeViewHostAura* aura_host = native_host(); |
75 | 137 |
76 EXPECT_TRUE(child_win->HasObserver(aura_host)); | 138 EXPECT_TRUE(child_win->HasObserver(aura_host)); |
77 DestroyHost(); | 139 DestroyHost(); |
78 EXPECT_FALSE(child_win->HasObserver(aura_host)); | 140 EXPECT_FALSE(child_win->HasObserver(aura_host)); |
79 } | 141 } |
80 | 142 |
81 // Tests that the kHostViewKey is correctly set and cleared. | 143 // Tests that the kHostViewKey is correctly set and cleared. |
82 TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) { | 144 TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) { |
83 // Create the NativeViewHost and attach a NativeView. | 145 // Create the NativeViewHost and attach a NativeView. |
84 CreateHost(); | 146 CreateHost(); |
85 aura::Window* child_win = child()->GetNativeView(); | 147 aura::Window* child_win = child()->GetNativeView(); |
86 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); | 148 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); |
149 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey)); | |
87 | 150 |
88 host()->Detach(); | 151 host()->Detach(); |
89 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); | 152 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); |
90 | 153 |
91 host()->Attach(child_win); | 154 host()->Attach(child_win); |
92 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); | 155 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); |
156 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey)); | |
93 | 157 |
94 DestroyHost(); | 158 DestroyHost(); |
95 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); | 159 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); |
96 } | 160 } |
97 | 161 |
162 // Tests that the values being calculated by CalculateNativeViewOrigin are | |
163 // correct. | |
164 TEST_F(NativeViewHostAuraTest, CalculateNewNativeViewOrigin) { | |
165 CreateHost(); | |
166 | |
167 gfx::Rect clip_rect(0, 0, 50, 50); | |
168 gfx::Rect contents_rect(50, 50, 100, 100); | |
169 | |
170 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTHWEST); | |
171 EXPECT_EQ(gfx::Point(0, 0).ToString(), | |
172 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
173 | |
174 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTH); | |
175 EXPECT_EQ(gfx::Point(-25, 0).ToString(), | |
176 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
177 | |
178 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTHEAST); | |
179 EXPECT_EQ(gfx::Point(-50, 0).ToString(), | |
180 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
181 | |
182 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_EAST); | |
183 EXPECT_EQ(gfx::Point(-50, -25).ToString(), | |
184 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
185 | |
186 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTHEAST); | |
187 EXPECT_EQ(gfx::Point(-50, -50).ToString(), | |
188 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
189 | |
190 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTH); | |
191 EXPECT_EQ(gfx::Point(-25, -50).ToString(), | |
192 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
193 | |
194 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTHWEST); | |
195 EXPECT_EQ(gfx::Point(0, -50).ToString(), | |
196 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
197 | |
198 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_WEST); | |
199 EXPECT_EQ(gfx::Point(0, -25).ToString(), | |
200 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
201 | |
202 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_CENTER); | |
203 EXPECT_EQ(gfx::Point(-25, -25).ToString(), | |
204 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
205 | |
206 DestroyHost(); | |
207 } | |
208 | |
209 // Test that the fast resize path places the clipping and content windows were | |
210 // they are supposed to be. | |
211 TEST_F(NativeViewHostAuraTest, FastResizePath) { | |
212 CreateHost(); | |
213 host()->set_fast_resize(false); | |
214 toplevel()->SetBounds(gfx::Rect(0, 0, 100, 100)); | |
215 native_host()->ShowWidget(0, 0, 100, 100); | |
216 host()->set_fast_resize(true); | |
217 | |
218 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_CENTER); | |
219 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
220 host()->native_view()->layer()->bounds().ToString()); | |
221 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
222 clipping_window()->layer()->bounds().ToString()); | |
223 | |
224 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTHWEST); | |
225 native_host()->ShowWidget(0, 0, 50, 50); | |
226 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
227 host()->native_view()->layer()->bounds().ToString()); | |
228 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), | |
229 clipping_window()->layer()->bounds().ToString()); | |
230 | |
231 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTHEAST); | |
232 native_host()->ShowWidget(0, 0, 50, 50); | |
233 EXPECT_EQ(gfx::Rect(-50, -50, 100, 100).ToString(), | |
234 host()->native_view()->layer()->bounds().ToString()); | |
235 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), | |
236 clipping_window()->layer()->bounds().ToString()); | |
237 | |
238 DestroyHost(); | |
239 } | |
240 | |
241 // Test that destroying the top level widget before destroying the attached | |
242 // NativeViewHost works correctly. Specifically the associated NVH should be | |
243 // destroyed and there shouldn't be any errors. | |
244 TEST_F(NativeViewHostAuraTest, DestroyWidget) { | |
245 NativeViewHostTesting::ResetDestroyedCount(); | |
246 CreateHost(); | |
247 ReleaseHost(); | |
248 EXPECT_EQ(0, NativeViewHostTesting::destroyed_count()); | |
249 DestroyTopLevel(); | |
250 EXPECT_EQ(1, NativeViewHostTesting::destroyed_count()); | |
251 } | |
252 | |
253 // Test that the clipping window and the native view are destroyed when the | |
254 // containing widget for the native view is closed. | |
255 TEST_F(NativeViewHostAuraTest, ClosingWidgetDoesntLeak) { | |
256 CreateHost(); | |
257 AuraWindowDestroyedObserver clipping_observer(clipping_window()); | |
258 AuraWindowDestroyedObserver native_view_observer(child()->GetNativeView()); | |
259 EXPECT_EQ(0, clipping_observer.destroyed_count()); | |
260 EXPECT_EQ(0, native_view_observer.destroyed_count()); | |
261 child()->CloseNow(); | |
262 EXPECT_EQ(1, clipping_observer.destroyed_count()); | |
263 EXPECT_EQ(1, native_view_observer.destroyed_count()); | |
264 DestroyHost(); | |
265 } | |
266 | |
267 // Test that the none fast resize path is clipped and positioned correctly. | |
268 TEST_F(NativeViewHostAuraTest, NonFastResizePath) { | |
269 const gfx::Rect base_rect = gfx::Rect(0, 0, 100, 100); | |
270 CreateHost(); | |
271 toplevel()->SetBounds(base_rect); | |
272 native_host()->ShowWidget(base_rect.x(), base_rect.y(), | |
273 base_rect.width(), base_rect.height()); | |
274 EXPECT_EQ(base_rect.ToString(), | |
275 host()->native_view()->bounds().ToString()); | |
276 EXPECT_EQ(base_rect.ToString(), | |
277 clipping_window()->bounds().ToString()); | |
278 | |
279 const gfx::Rect kTestCases[] = { | |
280 gfx::Rect(-10, -20, 100, 100), | |
281 gfx::Rect(0, -20, 100, 100), | |
282 gfx::Rect(10, -20, 100, 100), | |
283 gfx::Rect(-10, 0, 100, 100), | |
284 gfx::Rect(0, 0, 100, 100), | |
285 gfx::Rect(10, 0, 100, 100), | |
286 gfx::Rect(-10, 20, 100, 100), | |
287 gfx::Rect(0, 20, 100, 100), | |
288 gfx::Rect(10, 20, 100, 100), | |
289 gfx::Rect(0, 0, 200, 300), | |
290 gfx::Rect(-50, -100, 200, 300), | |
291 }; | |
292 | |
293 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | |
294 const gfx::Rect& bounds = kTestCases[i]; | |
295 | |
296 host()->SetBoundsRect(bounds); | |
297 | |
298 gfx::Rect clip_rect = gfx::IntersectRects(bounds, base_rect); | |
299 EXPECT_EQ(clip_rect.ToString(), clipping_window()->bounds().ToString()); | |
300 | |
301 gfx::Rect native_view_bounds = bounds; | |
302 native_view_bounds.Offset(-clip_rect.x(), -clip_rect.y()); | |
303 EXPECT_EQ(native_view_bounds.ToString(), | |
304 host()->native_view()->bounds().ToString()); | |
305 } | |
306 | |
307 DestroyHost(); | |
308 } | |
309 | |
98 } // namespace views | 310 } // namespace views |
OLD | NEW |