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
3 // found in the LICENSE file.
5 #include "ui/gfx/insets.h"
6 #include "ui/views/bubble/bubble_border.h"
7 #include "ui/views/bubble/bubble_frame_view.h"
8 #include "ui/views/test/views_test_base.h"
9 #include "ui/views/widget/widget.h"
13 typedef ViewsTestBase BubbleFrameViewTest
;
17 const BubbleBorder::Arrow kArrow
= BubbleBorder::TOP_LEFT
;
18 const SkColor kColor
= SK_ColorRED
;
19 const int kMargin
= 6;
21 class TestBubbleFrameView
: public BubbleFrameView
{
24 : BubbleFrameView(gfx::Insets(kMargin
, kMargin
, kMargin
, kMargin
)),
25 available_bounds_(gfx::Rect(0, 0, 1000, 1000)) {
26 SetBubbleBorder(scoped_ptr
<views::BubbleBorder
>(
27 new BubbleBorder(kArrow
, BubbleBorder::NO_SHADOW
, kColor
)));
29 virtual ~TestBubbleFrameView() {}
31 // BubbleFrameView overrides:
32 virtual gfx::Rect
GetAvailableScreenBounds(const gfx::Rect
& rect
) OVERRIDE
{
33 return available_bounds_
;
37 gfx::Rect available_bounds_
;
39 DISALLOW_COPY_AND_ASSIGN(TestBubbleFrameView
);
44 TEST_F(BubbleFrameViewTest
, GetBoundsForClientView
) {
45 TestBubbleFrameView frame
;
46 EXPECT_EQ(kArrow
, frame
.bubble_border()->arrow());
47 EXPECT_EQ(kColor
, frame
.bubble_border()->background_color());
49 int margin_x
= frame
.content_margins().left();
50 int margin_y
= frame
.content_margins().top();
51 gfx::Insets insets
= frame
.bubble_border()->GetInsets();
52 EXPECT_EQ(insets
.left() + margin_x
, frame
.GetBoundsForClientView().x());
53 EXPECT_EQ(insets
.top() + margin_y
, frame
.GetBoundsForClientView().y());
56 // Tests that the arrow is mirrored as needed to better fit the screen.
57 TEST_F(BubbleFrameViewTest
, GetUpdatedWindowBounds
) {
58 TestBubbleFrameView frame
;
59 gfx::Rect window_bounds
;
61 gfx::Insets insets
= frame
.bubble_border()->GetInsets();
62 int xposition
= 95 - insets
.width();
64 // Test that the info bubble displays normally when it fits.
65 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT
);
66 window_bounds
= frame
.GetUpdatedWindowBounds(
67 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
68 gfx::Size(500, 500), // |client_size|
69 true); // |adjust_if_offscreen|
70 EXPECT_EQ(BubbleBorder::TOP_LEFT
, frame
.bubble_border()->arrow());
71 EXPECT_GT(window_bounds
.x(), xposition
);
72 EXPECT_GT(window_bounds
.y(), 100 + 50 - 10); // -10 to roughly compensate for
75 // Test bubble not fitting on left.
76 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT
);
77 window_bounds
= frame
.GetUpdatedWindowBounds(
78 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
79 gfx::Size(500, 500), // |client_size|
80 true); // |adjust_if_offscreen|
81 EXPECT_EQ(BubbleBorder::TOP_LEFT
, frame
.bubble_border()->arrow());
82 EXPECT_GT(window_bounds
.x(), xposition
);
83 EXPECT_GT(window_bounds
.y(), 100 + 50 - 10); // -10 to roughly compensate for
86 // Test bubble not fitting on left or top.
87 frame
.bubble_border()->set_arrow(BubbleBorder::BOTTOM_RIGHT
);
88 window_bounds
= frame
.GetUpdatedWindowBounds(
89 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
90 gfx::Size(500, 500), // |client_size|
91 true); // |adjust_if_offscreen|
92 EXPECT_EQ(BubbleBorder::TOP_LEFT
, frame
.bubble_border()->arrow());
93 EXPECT_GT(window_bounds
.x(), xposition
);
94 EXPECT_GT(window_bounds
.y(), 100 + 50 - 10); // -10 to roughly compensate for
97 // Test bubble not fitting on top.
98 frame
.bubble_border()->set_arrow(BubbleBorder::BOTTOM_LEFT
);
99 window_bounds
= frame
.GetUpdatedWindowBounds(
100 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
101 gfx::Size(500, 500), // |client_size|
102 true); // |adjust_if_offscreen|
103 EXPECT_EQ(BubbleBorder::TOP_LEFT
, frame
.bubble_border()->arrow());
104 EXPECT_GT(window_bounds
.x(), xposition
);
105 EXPECT_GT(window_bounds
.y(), 100 + 50 - 10); // -10 to roughly compensate for
108 // Test bubble not fitting on top and right.
109 frame
.bubble_border()->set_arrow(BubbleBorder::BOTTOM_LEFT
);
110 window_bounds
= frame
.GetUpdatedWindowBounds(
111 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
112 gfx::Size(500, 500), // |client_size|
113 true); // |adjust_if_offscreen|
114 EXPECT_EQ(BubbleBorder::TOP_RIGHT
, frame
.bubble_border()->arrow());
115 EXPECT_LT(window_bounds
.x(), 900 + 50 - 500);
116 EXPECT_GT(window_bounds
.y(), 100 + 50 - 10); // -10 to roughly compensate for
119 // Test bubble not fitting on right.
120 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT
);
121 window_bounds
= frame
.GetUpdatedWindowBounds(
122 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
123 gfx::Size(500, 500), // |client_size|
124 true); // |adjust_if_offscreen|
125 EXPECT_EQ(BubbleBorder::TOP_RIGHT
, frame
.bubble_border()->arrow());
126 EXPECT_LT(window_bounds
.x(), 900 + 50 - 500);
127 EXPECT_GT(window_bounds
.y(), 100 + 50 - 10); // -10 to roughly compensate for
130 // Test bubble not fitting on bottom and right.
131 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT
);
132 window_bounds
= frame
.GetUpdatedWindowBounds(
133 gfx::Rect(900, 900, 50, 50), // |anchor_rect|
134 gfx::Size(500, 500), // |client_size|
135 true); // |adjust_if_offscreen|
136 EXPECT_EQ(BubbleBorder::BOTTOM_RIGHT
, frame
.bubble_border()->arrow());
137 EXPECT_LT(window_bounds
.x(), 900 + 50 - 500);
138 EXPECT_LT(window_bounds
.y(), 900 - 500 - 15); // -15 to roughly compensate
141 // Test bubble not fitting at the bottom.
142 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT
);
143 window_bounds
= frame
.GetUpdatedWindowBounds(
144 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
145 gfx::Size(500, 500), // |client_size|
146 true); // |adjust_if_offscreen|
147 EXPECT_EQ(BubbleBorder::BOTTOM_LEFT
, frame
.bubble_border()->arrow());
148 // The window should be right aligned with the anchor_rect.
149 EXPECT_LT(window_bounds
.x(), 900 + 50 - 500);
150 EXPECT_LT(window_bounds
.y(), 900 - 500 - 15); // -15 to roughly compensate
153 // Test bubble not fitting at the bottom and left.
154 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT
);
155 window_bounds
= frame
.GetUpdatedWindowBounds(
156 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
157 gfx::Size(500, 500), // |client_size|
158 true); // |adjust_if_offscreen|
159 EXPECT_EQ(BubbleBorder::BOTTOM_LEFT
, frame
.bubble_border()->arrow());
160 // The window should be right aligned with the anchor_rect.
161 EXPECT_LT(window_bounds
.x(), 900 + 50 - 500);
162 EXPECT_LT(window_bounds
.y(), 900 - 500 - 15); // -15 to roughly compensate
166 // Tests that the arrow is not moved when the info-bubble does not fit the
167 // screen but moving it would make matter worse.
168 TEST_F(BubbleFrameViewTest
, GetUpdatedWindowBoundsMirroringFails
) {
169 TestBubbleFrameView frame
;
170 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT
);
171 gfx::Rect window_bounds
= frame
.GetUpdatedWindowBounds(
172 gfx::Rect(400, 100, 50, 50), // |anchor_rect|
173 gfx::Size(500, 700), // |client_size|
174 true); // |adjust_if_offscreen|
175 EXPECT_EQ(BubbleBorder::TOP_LEFT
, frame
.bubble_border()->arrow());
178 TEST_F(BubbleFrameViewTest
, TestMirroringForCenteredArrow
) {
179 TestBubbleFrameView frame
;
181 // Test bubble not fitting above the anchor.
182 frame
.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER
);
183 gfx::Rect window_bounds
= frame
.GetUpdatedWindowBounds(
184 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
185 gfx::Size(500, 700), // |client_size|
186 true); // |adjust_if_offscreen|
187 EXPECT_EQ(BubbleBorder::TOP_CENTER
, frame
.bubble_border()->arrow());
189 // Test bubble not fitting below the anchor.
190 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER
);
191 window_bounds
= frame
.GetUpdatedWindowBounds(
192 gfx::Rect(300, 800, 50, 50), // |anchor_rect|
193 gfx::Size(500, 200), // |client_size|
194 true); // |adjust_if_offscreen|
195 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER
, frame
.bubble_border()->arrow());
197 // Test bubble not fitting to the right of the anchor.
198 frame
.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER
);
199 window_bounds
= frame
.GetUpdatedWindowBounds(
200 gfx::Rect(800, 300, 50, 50), // |anchor_rect|
201 gfx::Size(200, 500), // |client_size|
202 true); // |adjust_if_offscreen|
203 EXPECT_EQ(BubbleBorder::RIGHT_CENTER
, frame
.bubble_border()->arrow());
205 // Test bubble not fitting to the left of the anchor.
206 frame
.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER
);
207 window_bounds
= frame
.GetUpdatedWindowBounds(
208 gfx::Rect(100, 300, 50, 50), // |anchor_rect|
209 gfx::Size(500, 500), // |client_size|
210 true); // |adjust_if_offscreen|
211 EXPECT_EQ(BubbleBorder::LEFT_CENTER
, frame
.bubble_border()->arrow());
214 // Test that the arrow will not be mirrored when |adjust_if_offscreen| is false.
215 TEST_F(BubbleFrameViewTest
, GetUpdatedWindowBoundsDontTryMirror
) {
216 TestBubbleFrameView frame
;
217 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT
);
218 gfx::Rect window_bounds
= frame
.GetUpdatedWindowBounds(
219 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
220 gfx::Size(500, 500), // |client_size|
221 false); // |adjust_if_offscreen|
222 EXPECT_EQ(BubbleBorder::TOP_RIGHT
, frame
.bubble_border()->arrow());
223 // The coordinates should be pointing to anchor_rect from TOP_RIGHT.
224 EXPECT_LT(window_bounds
.x(), 100 + 50 - 500);
225 EXPECT_GT(window_bounds
.y(), 900 + 50 - 10); // -10 to roughly compensate for
229 // Test that the center arrow is moved as needed to fit the screen.
230 TEST_F(BubbleFrameViewTest
, GetUpdatedWindowBoundsCenterArrows
) {
231 TestBubbleFrameView frame
;
232 gfx::Rect window_bounds
;
234 // Test that the bubble displays normally when it fits.
235 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER
);
236 window_bounds
= frame
.GetUpdatedWindowBounds(
237 gfx::Rect(500, 100, 50, 50), // |anchor_rect|
238 gfx::Size(500, 500), // |client_size|
239 true); // |adjust_if_offscreen|
240 EXPECT_EQ(BubbleBorder::TOP_CENTER
, frame
.bubble_border()->arrow());
241 EXPECT_EQ(window_bounds
.x() + window_bounds
.width() / 2, 525);
243 frame
.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER
);
244 window_bounds
= frame
.GetUpdatedWindowBounds(
245 gfx::Rect(500, 900, 50, 50), // |anchor_rect|
246 gfx::Size(500, 500), // |client_size|
247 true); // |adjust_if_offscreen|
248 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER
, frame
.bubble_border()->arrow());
249 EXPECT_EQ(window_bounds
.x() + window_bounds
.width() / 2, 525);
251 frame
.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER
);
252 window_bounds
= frame
.GetUpdatedWindowBounds(
253 gfx::Rect(100, 400, 50, 50), // |anchor_rect|
254 gfx::Size(500, 500), // |client_size|
255 true); // |adjust_if_offscreen|
256 EXPECT_EQ(BubbleBorder::LEFT_CENTER
, frame
.bubble_border()->arrow());
257 EXPECT_EQ(window_bounds
.y() + window_bounds
.height() / 2, 425);
259 frame
.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER
);
260 window_bounds
= frame
.GetUpdatedWindowBounds(
261 gfx::Rect(900, 400, 50, 50), // |anchor_rect|
262 gfx::Size(500, 500), // |client_size|
263 true); // |adjust_if_offscreen|
264 EXPECT_EQ(BubbleBorder::RIGHT_CENTER
, frame
.bubble_border()->arrow());
265 EXPECT_EQ(window_bounds
.y() + window_bounds
.height() / 2, 425);
267 // Test bubble not fitting left screen edge.
268 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER
);
269 window_bounds
= frame
.GetUpdatedWindowBounds(
270 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
271 gfx::Size(500, 500), // |client_size|
272 true); // |adjust_if_offscreen|
273 EXPECT_EQ(BubbleBorder::TOP_CENTER
, frame
.bubble_border()->arrow());
274 EXPECT_EQ(window_bounds
.x(), 0);
275 EXPECT_EQ(window_bounds
.x() +
276 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 125);
278 frame
.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER
);
279 window_bounds
= frame
.GetUpdatedWindowBounds(
280 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
281 gfx::Size(500, 500), // |client_size|
282 true); // |adjust_if_offscreen|
283 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER
, frame
.bubble_border()->arrow());
284 EXPECT_EQ(window_bounds
.x(), 0);
285 EXPECT_EQ(window_bounds
.x() +
286 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 125);
288 // Test bubble not fitting right screen edge.
289 frame
.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER
);
290 window_bounds
= frame
.GetUpdatedWindowBounds(
291 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
292 gfx::Size(500, 500), // |client_size|
293 true); // |adjust_if_offscreen|
294 EXPECT_EQ(BubbleBorder::TOP_CENTER
, frame
.bubble_border()->arrow());
295 EXPECT_EQ(window_bounds
.right(), 1000);
296 EXPECT_EQ(window_bounds
.x() +
297 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 925);
299 frame
.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER
);
300 window_bounds
= frame
.GetUpdatedWindowBounds(
301 gfx::Rect(900, 900, 50, 50), // |anchor_rect|
302 gfx::Size(500, 500), // |client_size|
303 true); // |adjust_if_offscreen|
304 EXPECT_EQ(BubbleBorder::BOTTOM_CENTER
, frame
.bubble_border()->arrow());
305 EXPECT_EQ(window_bounds
.right(), 1000);
306 EXPECT_EQ(window_bounds
.x() +
307 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 925);
309 // Test bubble not fitting top screen edge.
310 frame
.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER
);
311 window_bounds
= frame
.GetUpdatedWindowBounds(
312 gfx::Rect(100, 100, 50, 50), // |anchor_rect|
313 gfx::Size(500, 500), // |client_size|
314 true); // |adjust_if_offscreen|
315 EXPECT_EQ(BubbleBorder::LEFT_CENTER
, frame
.bubble_border()->arrow());
316 EXPECT_EQ(window_bounds
.y(), 0);
317 EXPECT_EQ(window_bounds
.y() +
318 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 125);
320 frame
.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER
);
321 window_bounds
= frame
.GetUpdatedWindowBounds(
322 gfx::Rect(900, 100, 50, 50), // |anchor_rect|
323 gfx::Size(500, 500), // |client_size|
324 true); // |adjust_if_offscreen|
325 EXPECT_EQ(BubbleBorder::RIGHT_CENTER
, frame
.bubble_border()->arrow());
326 EXPECT_EQ(window_bounds
.y(), 0);
327 EXPECT_EQ(window_bounds
.y() +
328 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 125);
330 // Test bubble not fitting bottom screen edge.
331 frame
.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER
);
332 window_bounds
= frame
.GetUpdatedWindowBounds(
333 gfx::Rect(100, 900, 50, 50), // |anchor_rect|
334 gfx::Size(500, 500), // |client_size|
335 true); // |adjust_if_offscreen|
336 EXPECT_EQ(BubbleBorder::LEFT_CENTER
, frame
.bubble_border()->arrow());
337 EXPECT_EQ(window_bounds
.bottom(), 1000);
338 EXPECT_EQ(window_bounds
.y() +
339 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 925);
341 frame
.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER
);
342 window_bounds
= frame
.GetUpdatedWindowBounds(
343 gfx::Rect(900, 900, 50, 50), // |anchor_rect|
344 gfx::Size(500, 500), // |client_size|
345 true); // |adjust_if_offscreen|
346 EXPECT_EQ(BubbleBorder::RIGHT_CENTER
, frame
.bubble_border()->arrow());
347 EXPECT_EQ(window_bounds
.bottom(), 1000);
348 EXPECT_EQ(window_bounds
.y() +
349 frame
.bubble_border()->GetArrowOffset(window_bounds
.size()), 925);