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 |