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 "base/run_loop.h" | 5 #include "base/run_loop.h" |
| 6 #include "ui/base/hit_test.h" |
6 #include "ui/views/bubble/bubble_delegate.h" | 7 #include "ui/views/bubble/bubble_delegate.h" |
7 #include "ui/views/bubble/bubble_frame_view.h" | 8 #include "ui/views/bubble/bubble_frame_view.h" |
8 #include "ui/views/test/test_widget_observer.h" | 9 #include "ui/views/test/test_widget_observer.h" |
9 #include "ui/views/test/views_test_base.h" | 10 #include "ui/views/test/views_test_base.h" |
10 #include "ui/views/widget/widget.h" | 11 #include "ui/views/widget/widget.h" |
11 #include "ui/views/widget/widget_observer.h" | 12 #include "ui/views/widget/widget_observer.h" |
12 | 13 |
13 #if defined(USE_AURA) | 14 #if defined(USE_AURA) |
14 #include "ui/aura/env.h" | 15 #include "ui/aura/env.h" |
15 #endif | 16 #endif |
16 | 17 |
17 namespace views { | 18 namespace views { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 class TestBubbleDelegateView : public BubbleDelegateView { | 22 class TestBubbleDelegateView : public BubbleDelegateView { |
22 public: | 23 public: |
23 TestBubbleDelegateView(View* anchor_view); | 24 TestBubbleDelegateView(View* anchor_view) |
24 virtual ~TestBubbleDelegateView(); | 25 : BubbleDelegateView(anchor_view, BubbleBorder::TOP_LEFT), |
| 26 view_(new View()) { |
| 27 view_->set_focusable(true); |
| 28 AddChildView(view_); |
| 29 } |
| 30 virtual ~TestBubbleDelegateView() {} |
25 | 31 |
26 virtual View* GetInitiallyFocusedView() OVERRIDE; | 32 // BubbleDelegateView overrides: |
27 | 33 virtual View* GetInitiallyFocusedView() OVERRIDE { return view_; } |
28 protected: | 34 virtual gfx::Size GetPreferredSize() OVERRIDE { return gfx::Size(200, 200); } |
29 // BubbleDelegateView overrides. | 35 virtual int GetFadeDuration() OVERRIDE { return 1; } |
30 virtual int GetFadeDuration() OVERRIDE; | |
31 | 36 |
32 private: | 37 private: |
33 View* view_; | 38 View* view_; |
| 39 |
| 40 DISALLOW_COPY_AND_ASSIGN(TestBubbleDelegateView); |
34 }; | 41 }; |
35 | 42 |
36 TestBubbleDelegateView::TestBubbleDelegateView(View* anchor_view) | 43 class BubbleDelegateTest : public ViewsTestBase { |
37 : BubbleDelegateView(anchor_view, BubbleBorder::TOP_LEFT), | 44 public: |
38 view_(new View()) { | 45 BubbleDelegateTest() {} |
39 view_->set_focusable(true); | 46 virtual ~BubbleDelegateTest() {} |
40 AddChildView(view_); | |
41 } | |
42 | 47 |
43 TestBubbleDelegateView::~TestBubbleDelegateView() {} | 48 // Creates a test widget that owns its native widget. |
| 49 Widget* CreateTestWidget() { |
| 50 Widget* widget = new Widget(); |
| 51 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
| 52 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 53 widget->Init(params); |
| 54 return widget; |
| 55 } |
44 | 56 |
45 View* TestBubbleDelegateView::GetInitiallyFocusedView() { | 57 private: |
46 return view_; | 58 DISALLOW_COPY_AND_ASSIGN(BubbleDelegateTest); |
47 } | 59 }; |
48 | |
49 int TestBubbleDelegateView::GetFadeDuration() { | |
50 // We cannot return 0 as that causes the animation to never complete. | |
51 return 1; | |
52 } | |
53 | 60 |
54 } // namespace | 61 } // namespace |
55 | 62 |
56 typedef ViewsTestBase BubbleDelegateTest; | |
57 | |
58 TEST_F(BubbleDelegateTest, CreateDelegate) { | 63 TEST_F(BubbleDelegateTest, CreateDelegate) { |
59 // Create the anchor and parent widgets. | 64 scoped_ptr<Widget> anchor_widget(CreateTestWidget()); |
60 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | 65 BubbleDelegateView* bubble_delegate = new BubbleDelegateView( |
61 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 66 anchor_widget->GetContentsView(), BubbleBorder::NONE); |
62 scoped_ptr<Widget> anchor_widget(new Widget); | |
63 anchor_widget->Init(params); | |
64 anchor_widget->Show(); | |
65 | |
66 BubbleDelegateView* bubble_delegate = | |
67 new BubbleDelegateView(anchor_widget->GetContentsView(), | |
68 BubbleBorder::NONE); | |
69 bubble_delegate->set_color(SK_ColorGREEN); | 67 bubble_delegate->set_color(SK_ColorGREEN); |
70 Widget* bubble_widget( | 68 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); |
71 BubbleDelegateView::CreateBubble(bubble_delegate)); | |
72 EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); | 69 EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); |
73 EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); | 70 EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); |
74 test::TestWidgetObserver bubble_observer(bubble_widget); | 71 test::TestWidgetObserver bubble_observer(bubble_widget); |
75 EXPECT_FALSE(bubble_observer.widget_closed()); | 72 bubble_widget->Show(); |
76 | 73 |
77 BubbleBorder* border = bubble_delegate->GetBubbleFrameView()->bubble_border(); | 74 BubbleBorder* border = bubble_delegate->GetBubbleFrameView()->bubble_border(); |
78 EXPECT_EQ(bubble_delegate->arrow(), border->arrow()); | 75 EXPECT_EQ(bubble_delegate->arrow(), border->arrow()); |
79 EXPECT_EQ(bubble_delegate->color(), border->background_color()); | 76 EXPECT_EQ(bubble_delegate->color(), border->background_color()); |
80 | 77 |
| 78 EXPECT_FALSE(bubble_observer.widget_closed()); |
81 bubble_widget->CloseNow(); | 79 bubble_widget->CloseNow(); |
82 RunPendingMessages(); | |
83 EXPECT_TRUE(bubble_observer.widget_closed()); | 80 EXPECT_TRUE(bubble_observer.widget_closed()); |
84 } | 81 } |
85 | 82 |
86 TEST_F(BubbleDelegateTest, CloseAnchorWidget) { | 83 TEST_F(BubbleDelegateTest, CloseAnchorWidget) { |
87 // Create the anchor widget. | 84 scoped_ptr<Widget> anchor_widget(CreateTestWidget()); |
88 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
89 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
90 scoped_ptr<Widget> anchor_widget(new Widget); | |
91 anchor_widget->Init(params); | |
92 anchor_widget->Show(); | |
93 | |
94 BubbleDelegateView* bubble_delegate = new BubbleDelegateView( | 85 BubbleDelegateView* bubble_delegate = new BubbleDelegateView( |
95 anchor_widget->GetContentsView(), BubbleBorder::NONE); | 86 anchor_widget->GetContentsView(), BubbleBorder::NONE); |
96 // Preventing close on deactivate should not prevent closing with the anchor. | 87 // Preventing close on deactivate should not prevent closing with the anchor. |
97 bubble_delegate->set_close_on_deactivate(false); | 88 bubble_delegate->set_close_on_deactivate(false); |
98 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); | 89 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); |
99 EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); | 90 EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); |
100 EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); | 91 EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); |
101 EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget()); | 92 EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget()); |
102 test::TestWidgetObserver bubble_observer(bubble_widget); | 93 test::TestWidgetObserver bubble_observer(bubble_widget); |
103 EXPECT_FALSE(bubble_observer.widget_closed()); | 94 EXPECT_FALSE(bubble_observer.widget_closed()); |
104 | 95 |
105 bubble_widget->Show(); | 96 bubble_widget->Show(); |
106 RunPendingMessages(); | 97 EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget()); |
107 EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget()); | |
108 EXPECT_FALSE(bubble_observer.widget_closed()); | 98 EXPECT_FALSE(bubble_observer.widget_closed()); |
109 | 99 |
110 #if defined(USE_AURA) | 100 #if defined(USE_AURA) |
111 // TODO(msw): Remove activation hack to prevent bookkeeping errors in: | 101 // TODO(msw): Remove activation hack to prevent bookkeeping errors in: |
112 // aura::test::TestActivationClient::OnWindowDestroyed(). | 102 // aura::test::TestActivationClient::OnWindowDestroyed(). |
113 scoped_ptr<Widget> smoke_and_mirrors_widget(new Widget); | 103 scoped_ptr<Widget> smoke_and_mirrors_widget(CreateTestWidget()); |
114 smoke_and_mirrors_widget->Init(params); | |
115 smoke_and_mirrors_widget->Show(); | |
116 EXPECT_FALSE(bubble_observer.widget_closed()); | 104 EXPECT_FALSE(bubble_observer.widget_closed()); |
117 #endif | 105 #endif |
118 | 106 |
119 // Ensure that closing the anchor widget also closes the bubble itself. | 107 // Ensure that closing the anchor widget also closes the bubble itself. |
120 anchor_widget->CloseNow(); | 108 anchor_widget->CloseNow(); |
121 RunPendingMessages(); | |
122 EXPECT_TRUE(bubble_observer.widget_closed()); | 109 EXPECT_TRUE(bubble_observer.widget_closed()); |
123 } | 110 } |
124 | 111 |
125 TEST_F(BubbleDelegateTest, ResetAnchorWidget) { | 112 TEST_F(BubbleDelegateTest, ResetAnchorWidget) { |
126 // Create the anchor and parent widgets. | 113 scoped_ptr<Widget> anchor_widget(CreateTestWidget()); |
127 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | 114 BubbleDelegateView* bubble_delegate = new BubbleDelegateView( |
128 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 115 anchor_widget->GetContentsView(), BubbleBorder::NONE); |
129 scoped_ptr<Widget> anchor_widget(new Widget); | |
130 anchor_widget->Init(params); | |
131 anchor_widget->Show(); | |
132 scoped_ptr<Widget> parent_widget(new Widget); | |
133 parent_widget->Init(params); | |
134 parent_widget->Show(); | |
135 | 116 |
136 // Make sure the bubble widget is parented to a widget other than the anchor | 117 // Make sure the bubble widget is parented to a widget other than the anchor |
137 // widget so that closing the anchor widget does not close the bubble widget. | 118 // widget so that closing the anchor widget does not close the bubble widget. |
138 BubbleDelegateView* bubble_delegate = new BubbleDelegateView( | 119 scoped_ptr<Widget> parent_widget(CreateTestWidget()); |
139 anchor_widget->GetContentsView(), BubbleBorder::NONE); | |
140 bubble_delegate->set_parent_window(parent_widget->GetNativeView()); | 120 bubble_delegate->set_parent_window(parent_widget->GetNativeView()); |
141 // Preventing close on deactivate should not prevent closing with the parent. | 121 // Preventing close on deactivate should not prevent closing with the parent. |
142 bubble_delegate->set_close_on_deactivate(false); | 122 bubble_delegate->set_close_on_deactivate(false); |
143 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); | 123 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); |
144 EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); | 124 EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate()); |
145 EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); | 125 EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget()); |
146 EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget()); | 126 EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget()); |
147 test::TestWidgetObserver bubble_observer(bubble_widget); | 127 test::TestWidgetObserver bubble_observer(bubble_widget); |
148 EXPECT_FALSE(bubble_observer.widget_closed()); | 128 EXPECT_FALSE(bubble_observer.widget_closed()); |
149 | 129 |
150 // Showing and hiding the bubble widget should have no effect on its anchor. | 130 // Showing and hiding the bubble widget should have no effect on its anchor. |
151 bubble_widget->Show(); | 131 bubble_widget->Show(); |
152 RunPendingMessages(); | 132 EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget()); |
153 EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget()); | |
154 bubble_widget->Hide(); | 133 bubble_widget->Hide(); |
155 RunPendingMessages(); | 134 EXPECT_EQ(anchor_widget, bubble_delegate->anchor_widget()); |
156 EXPECT_EQ(anchor_widget.get(), bubble_delegate->anchor_widget()); | |
157 | 135 |
158 // Ensure that closing the anchor widget clears the bubble's reference to that | 136 // Ensure that closing the anchor widget clears the bubble's reference to that |
159 // anchor widget, but the bubble itself does not close. | 137 // anchor widget, but the bubble itself does not close. |
160 anchor_widget->CloseNow(); | 138 anchor_widget->CloseNow(); |
161 RunPendingMessages(); | 139 EXPECT_NE(anchor_widget, bubble_delegate->anchor_widget()); |
162 EXPECT_NE(anchor_widget.get(), bubble_delegate->anchor_widget()); | |
163 EXPECT_FALSE(bubble_observer.widget_closed()); | 140 EXPECT_FALSE(bubble_observer.widget_closed()); |
164 | 141 |
165 #if defined(USE_AURA) | 142 #if defined(USE_AURA) |
166 // TODO(msw): Remove activation hack to prevent bookkeeping errors in: | 143 // TODO(msw): Remove activation hack to prevent bookkeeping errors in: |
167 // aura::test::TestActivationClient::OnWindowDestroyed(). | 144 // aura::test::TestActivationClient::OnWindowDestroyed(). |
168 scoped_ptr<Widget> smoke_and_mirrors_widget(new Widget); | 145 scoped_ptr<Widget> smoke_and_mirrors_widget(CreateTestWidget()); |
169 smoke_and_mirrors_widget->Init(params); | |
170 smoke_and_mirrors_widget->Show(); | |
171 EXPECT_FALSE(bubble_observer.widget_closed()); | 146 EXPECT_FALSE(bubble_observer.widget_closed()); |
172 #endif | 147 #endif |
173 | 148 |
174 // Ensure that closing the parent widget also closes the bubble itself. | 149 // Ensure that closing the parent widget also closes the bubble itself. |
175 parent_widget->CloseNow(); | 150 parent_widget->CloseNow(); |
176 RunPendingMessages(); | |
177 EXPECT_TRUE(bubble_observer.widget_closed()); | 151 EXPECT_TRUE(bubble_observer.widget_closed()); |
178 } | 152 } |
179 | 153 |
180 // TODO(msw): test relies on focus and belongs in interactive_ui_tests. | 154 TEST_F(BubbleDelegateTest, InitiallyFocusedView) { |
181 TEST_F(BubbleDelegateTest, DISABLED_InitiallyFocusedView) { | 155 scoped_ptr<Widget> anchor_widget(CreateTestWidget()); |
182 // Create the anchor and parent widgets. | 156 BubbleDelegateView* bubble_delegate = new BubbleDelegateView( |
183 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | 157 anchor_widget->GetContentsView(), BubbleBorder::NONE); |
184 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
185 scoped_ptr<Widget> anchor_widget(new Widget); | |
186 anchor_widget->Init(params); | |
187 anchor_widget->Show(); | |
188 | |
189 TestBubbleDelegateView* bubble_delegate = | |
190 new TestBubbleDelegateView(anchor_widget->GetContentsView()); | |
191 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); | 158 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); |
192 bubble_widget->Show(); | |
193 | |
194 EXPECT_EQ(bubble_delegate->GetInitiallyFocusedView(), | 159 EXPECT_EQ(bubble_delegate->GetInitiallyFocusedView(), |
195 bubble_widget->GetFocusManager()->GetFocusedView()); | 160 bubble_widget->GetFocusManager()->GetFocusedView()); |
196 bubble_widget->CloseNow(); | 161 bubble_widget->CloseNow(); |
197 } | 162 } |
198 | 163 |
| 164 TEST_F(BubbleDelegateTest, NonClientHitTest) { |
| 165 scoped_ptr<Widget> anchor_widget(CreateTestWidget()); |
| 166 TestBubbleDelegateView* bubble_delegate = |
| 167 new TestBubbleDelegateView(anchor_widget->GetContentsView()); |
| 168 BubbleDelegateView::CreateBubble(bubble_delegate); |
| 169 BubbleFrameView* frame = bubble_delegate->GetBubbleFrameView(); |
| 170 const int border = frame->bubble_border()->GetBorderThickness(); |
| 171 |
| 172 struct { |
| 173 const int point; |
| 174 const int hit; |
| 175 } cases[] = { |
| 176 { border, HTNOWHERE }, |
| 177 { border + 5, HTNOWHERE }, |
| 178 { border + 6, HTCLIENT }, |
| 179 { border + 50, HTCLIENT }, |
| 180 { 1000, HTNOWHERE }, |
| 181 }; |
| 182 |
| 183 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { |
| 184 gfx::Point point(cases[i].point, cases[i].point); |
| 185 EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) |
| 186 << " with border: " << border << ", at point " << cases[i].point; |
| 187 } |
| 188 } |
| 189 |
199 // This class provides functionality to verify that the BubbleView shows up | 190 // This class provides functionality to verify that the BubbleView shows up |
200 // when we call BubbleDelegateView::StartFade(true) and is destroyed when we | 191 // when we call BubbleDelegateView::StartFade(true) and is destroyed when we |
201 // call BubbleDelegateView::StartFade(false). | 192 // call BubbleDelegateView::StartFade(false). |
202 class BubbleWidgetClosingTest : public BubbleDelegateTest, | 193 class BubbleWidgetClosingTest : public BubbleDelegateTest, |
203 public views::WidgetObserver { | 194 public views::WidgetObserver { |
204 public: | 195 public: |
205 BubbleWidgetClosingTest() | 196 BubbleWidgetClosingTest() : bubble_destroyed_(false) { |
206 : bubble_destroyed_(false) { | |
207 #if defined(USE_AURA) | 197 #if defined(USE_AURA) |
208 loop_.set_dispatcher(aura::Env::GetInstance()->GetDispatcher()); | 198 loop_.set_dispatcher(aura::Env::GetInstance()->GetDispatcher()); |
209 #endif | 199 #endif |
210 } | 200 } |
211 | 201 |
212 virtual ~BubbleWidgetClosingTest() {} | 202 virtual ~BubbleWidgetClosingTest() {} |
213 | 203 |
214 void Observe(views::Widget* widget) { | 204 void Observe(views::Widget* widget) { |
215 widget->AddObserver(this); | 205 widget->AddObserver(this); |
216 } | 206 } |
(...skipping 12 matching lines...) Expand all Loading... |
229 } | 219 } |
230 | 220 |
231 private: | 221 private: |
232 bool bubble_destroyed_; | 222 bool bubble_destroyed_; |
233 base::RunLoop loop_; | 223 base::RunLoop loop_; |
234 | 224 |
235 DISALLOW_COPY_AND_ASSIGN(BubbleWidgetClosingTest); | 225 DISALLOW_COPY_AND_ASSIGN(BubbleWidgetClosingTest); |
236 }; | 226 }; |
237 | 227 |
238 TEST_F(BubbleWidgetClosingTest, TestBubbleVisibilityAndClose) { | 228 TEST_F(BubbleWidgetClosingTest, TestBubbleVisibilityAndClose) { |
239 // Create the anchor and parent widgets. | 229 scoped_ptr<Widget> anchor_widget(CreateTestWidget()); |
240 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
241 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
242 scoped_ptr<Widget> anchor_widget(new Widget); | |
243 anchor_widget->Init(params); | |
244 anchor_widget->Show(); | |
245 | |
246 TestBubbleDelegateView* bubble_delegate = | 230 TestBubbleDelegateView* bubble_delegate = |
247 new TestBubbleDelegateView(anchor_widget->GetContentsView()); | 231 new TestBubbleDelegateView(anchor_widget->GetContentsView()); |
248 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); | 232 Widget* bubble_widget = BubbleDelegateView::CreateBubble(bubble_delegate); |
249 EXPECT_FALSE(bubble_widget->IsVisible()); | 233 EXPECT_FALSE(bubble_widget->IsVisible()); |
250 | 234 |
251 bubble_delegate->StartFade(true); | 235 bubble_delegate->StartFade(true); |
252 EXPECT_TRUE(bubble_widget->IsVisible()); | 236 EXPECT_TRUE(bubble_widget->IsVisible()); |
253 | 237 |
254 EXPECT_EQ(bubble_delegate->GetInitiallyFocusedView(), | 238 EXPECT_EQ(bubble_delegate->GetInitiallyFocusedView(), |
255 bubble_widget->GetFocusManager()->GetFocusedView()); | 239 bubble_widget->GetFocusManager()->GetFocusedView()); |
256 | 240 |
257 Observe(bubble_widget); | 241 Observe(bubble_widget); |
258 | 242 |
259 bubble_delegate->StartFade(false); | 243 bubble_delegate->StartFade(false); |
260 RunNestedLoop(); | 244 RunNestedLoop(); |
261 EXPECT_TRUE(bubble_destroyed()); | 245 EXPECT_TRUE(bubble_destroyed()); |
262 } | 246 } |
263 | 247 |
264 } // namespace views | 248 } // namespace views |
OLD | NEW |