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 "chrome/browser/ui/window_sizer/window_sizer_common_unittest.h"
7 #include "ash/wm/window_resizer.h"
8 #include "base/compiler_specific.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/common/chrome_switches.h"
11 #include "chrome/test/base/testing_profile.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/gfx/display.h"
14 #include "ui/gfx/screen.h"
17 #include "ui/aura/window.h"
22 class TestScreen
: public gfx::Screen
{
25 ~TestScreen() override
{}
27 // Overridden from gfx::Screen:
28 gfx::Point
GetCursorScreenPoint() override
{
33 gfx::NativeWindow
GetWindowUnderCursor() override
{
38 gfx::NativeWindow
GetWindowAtScreenPoint(const gfx::Point
& point
) override
{
43 int GetNumDisplays() const override
{ return displays_
.size(); }
45 std::vector
<gfx::Display
> GetAllDisplays() const override
{
49 gfx::Display
GetDisplayNearestWindow(gfx::NativeView view
) const override
{
51 return GetDisplayMatching(view
->GetBoundsInScreen());
54 return gfx::Display();
58 gfx::Display
GetDisplayNearestPoint(const gfx::Point
& point
) const override
{
60 return gfx::Display();
63 gfx::Display
GetDisplayMatching(const gfx::Rect
& match_rect
) const override
{
65 size_t max_area_index
= 0;
67 for (size_t i
= 0; i
< displays_
.size(); ++i
) {
68 gfx::Rect overlap
= displays_
[i
].bounds();
69 overlap
.Intersect(match_rect
);
70 int area
= overlap
.width() * overlap
.height();
71 if (area
> max_area
) {
76 return displays_
[max_area_index
];
79 gfx::Display
GetPrimaryDisplay() const override
{ return displays_
[0]; }
81 void AddObserver(gfx::DisplayObserver
* observer
) override
{ NOTREACHED(); }
83 void RemoveObserver(gfx::DisplayObserver
* observer
) override
{ NOTREACHED(); }
85 void AddDisplay(const gfx::Rect
& bounds
,
86 const gfx::Rect
& work_area
) {
87 gfx::Display
display(displays_
.size(), bounds
);
88 display
.set_work_area(work_area
);
89 displays_
.push_back(display
);
93 std::vector
<gfx::Display
> displays_
;
95 DISALLOW_COPY_AND_ASSIGN(TestScreen
);
98 class TestTargetDisplayProvider
: public WindowSizer::TargetDisplayProvider
{
100 TestTargetDisplayProvider() {}
101 ~TestTargetDisplayProvider() override
{}
103 gfx::Display
GetTargetDisplay(const gfx::Screen
* screen
,
104 const gfx::Rect
& bounds
) const override
{
105 // On ash, the bounds is used as a indicator to specify
106 // the target display.
107 return screen
->GetDisplayMatching(bounds
);
111 DISALLOW_COPY_AND_ASSIGN(TestTargetDisplayProvider
);
116 TestStateProvider::TestStateProvider():
117 has_persistent_data_(false),
118 persistent_show_state_(ui::SHOW_STATE_DEFAULT
),
119 has_last_active_data_(false),
120 last_active_show_state_(ui::SHOW_STATE_DEFAULT
) {
123 void TestStateProvider::SetPersistentState(const gfx::Rect
& bounds
,
124 const gfx::Rect
& work_area
,
125 ui::WindowShowState show_state
,
126 bool has_persistent_data
) {
127 persistent_bounds_
= bounds
;
128 persistent_work_area_
= work_area
;
129 persistent_show_state_
= show_state
;
130 has_persistent_data_
= has_persistent_data
;
133 void TestStateProvider::SetLastActiveState(const gfx::Rect
& bounds
,
134 ui::WindowShowState show_state
,
135 bool has_last_active_data
) {
136 last_active_bounds_
= bounds
;
137 last_active_show_state_
= show_state
;
138 has_last_active_data_
= has_last_active_data
;
141 bool TestStateProvider::GetPersistentState(
143 gfx::Rect
* saved_work_area
,
144 ui::WindowShowState
* show_state
) const {
146 *bounds
= persistent_bounds_
;
147 *saved_work_area
= persistent_work_area_
;
148 if (*show_state
== ui::SHOW_STATE_DEFAULT
)
149 *show_state
= persistent_show_state_
;
150 return has_persistent_data_
;
153 bool TestStateProvider::GetLastActiveWindowState(
155 ui::WindowShowState
* show_state
) const {
157 *bounds
= last_active_bounds_
;
158 if (*show_state
== ui::SHOW_STATE_DEFAULT
)
159 *show_state
= last_active_show_state_
;
160 return has_last_active_data_
;
163 int kWindowTilePixels
= WindowSizer::kWindowTilePixels
;
165 // The window sizer commonly used test functions.
166 void GetWindowBoundsAndShowState(
167 const gfx::Rect
& monitor1_bounds
,
168 const gfx::Rect
& monitor1_work_area
,
169 const gfx::Rect
& monitor2_bounds
,
170 const gfx::Rect
& bounds
,
171 const gfx::Rect
& work_area
,
172 ui::WindowShowState show_state_persisted
,
173 ui::WindowShowState show_state_last
,
175 const Browser
* browser
,
176 const gfx::Rect
& passed_in
,
177 gfx::Rect
* out_bounds
,
178 ui::WindowShowState
* out_show_state
) {
179 DCHECK(out_show_state
);
180 TestScreen test_screen
;
181 test_screen
.AddDisplay(monitor1_bounds
, monitor1_work_area
);
182 if (!monitor2_bounds
.IsEmpty())
183 test_screen
.AddDisplay(monitor2_bounds
, monitor2_bounds
);
184 scoped_ptr
<TestStateProvider
> sp(new TestStateProvider
);
185 if (source
== PERSISTED
|| source
== BOTH
)
186 sp
->SetPersistentState(bounds
, work_area
, show_state_persisted
, true);
187 if (source
== LAST_ACTIVE
|| source
== BOTH
)
188 sp
->SetLastActiveState(bounds
, show_state_last
, true);
189 scoped_ptr
<WindowSizer::TargetDisplayProvider
> tdp(
190 new TestTargetDisplayProvider
);
192 WindowSizer
sizer(sp
.Pass(), tdp
.Pass(), &test_screen
, browser
);
193 sizer
.DetermineWindowBoundsAndShowState(passed_in
,
198 void GetWindowBounds(const gfx::Rect
& monitor1_bounds
,
199 const gfx::Rect
& monitor1_work_area
,
200 const gfx::Rect
& monitor2_bounds
,
201 const gfx::Rect
& bounds
,
202 const gfx::Rect
& work_area
,
204 const Browser
* browser
,
205 const gfx::Rect
& passed_in
,
206 gfx::Rect
* out_bounds
) {
207 ui::WindowShowState out_show_state
= ui::SHOW_STATE_DEFAULT
;
208 GetWindowBoundsAndShowState(
209 monitor1_bounds
, monitor1_work_area
, monitor2_bounds
, bounds
, work_area
,
210 ui::SHOW_STATE_DEFAULT
, ui::SHOW_STATE_DEFAULT
, source
, browser
,
211 passed_in
, out_bounds
, &out_show_state
);
214 ui::WindowShowState
GetWindowShowState(
215 ui::WindowShowState show_state_persisted
,
216 ui::WindowShowState show_state_last
,
218 const Browser
* browser
,
219 const gfx::Rect
& bounds
,
220 const gfx::Rect
& display_config
) {
221 TestScreen test_screen
;
222 test_screen
.AddDisplay(display_config
, display_config
);
223 scoped_ptr
<TestStateProvider
> sp(new TestStateProvider
);
224 if (source
== PERSISTED
|| source
== BOTH
)
225 sp
->SetPersistentState(bounds
, display_config
, show_state_persisted
, true);
226 if (source
== LAST_ACTIVE
|| source
== BOTH
)
227 sp
->SetLastActiveState(bounds
, show_state_last
, true);
228 scoped_ptr
<WindowSizer::TargetDisplayProvider
> tdp(
229 new TestTargetDisplayProvider
);
231 WindowSizer
sizer(sp
.Pass(), tdp
.Pass(), &test_screen
, browser
);
233 ui::WindowShowState out_show_state
= ui::SHOW_STATE_DEFAULT
;
234 gfx::Rect out_bounds
;
235 sizer
.DetermineWindowBoundsAndShowState(
239 return out_show_state
;
242 #if !defined(OS_MACOSX)
243 TEST(WindowSizerTestCommon
,
244 PersistedWindowOffscreenWithNonAggressiveRepositioning
) {
245 { // off the left but the minimum visibility condition is barely satisfied
246 // without relocaiton.
247 gfx::Rect
initial_bounds(-470, 50, 500, 400);
249 gfx::Rect window_bounds
;
250 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
251 initial_bounds
, gfx::Rect(), PERSISTED
,
252 NULL
, gfx::Rect(), &window_bounds
);
253 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
256 { // off the left and the minimum visibility condition is satisfied by
258 gfx::Rect window_bounds
;
259 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
260 gfx::Rect(-471, 50, 500, 400), gfx::Rect(), PERSISTED
,
261 NULL
, gfx::Rect(), &window_bounds
);
262 EXPECT_EQ(gfx::Rect(-470 /* not -471 */, 50, 500, 400).ToString(),
263 window_bounds
.ToString());
267 gfx::Rect
initial_bounds(50, -370, 500, 400);
269 gfx::Rect window_bounds
;
270 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
271 gfx::Rect(50, -370, 500, 400), gfx::Rect(), PERSISTED
,
272 NULL
, gfx::Rect(), &window_bounds
);
273 EXPECT_EQ("50,0 500x400", window_bounds
.ToString());
276 { // off the right but the minimum visibility condition is barely satisified
277 // without relocation.
278 gfx::Rect
initial_bounds(994, 50, 500, 400);
280 gfx::Rect window_bounds
;
281 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
282 initial_bounds
, gfx::Rect(), PERSISTED
,
283 NULL
, gfx::Rect(), &window_bounds
);
284 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
287 { // off the right and the minimum visibility condition is satisified by
289 gfx::Rect window_bounds
;
290 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
291 gfx::Rect(995, 50, 500, 400), gfx::Rect(), PERSISTED
,
292 NULL
, gfx::Rect(), &window_bounds
);
293 EXPECT_EQ(gfx::Rect(994 /* not 995 */, 50, 500, 400).ToString(),
294 window_bounds
.ToString());
297 { // off the bottom but the minimum visibility condition is barely satisified
298 // without relocation.
299 gfx::Rect
initial_bounds(50, 738, 500, 400);
301 gfx::Rect window_bounds
;
302 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
303 initial_bounds
, gfx::Rect(), PERSISTED
,
304 NULL
, gfx::Rect(), &window_bounds
);
305 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
308 { // off the bottom and the minimum visibility condition is satisified by
310 gfx::Rect window_bounds
;
311 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
312 gfx::Rect(50, 739, 500, 400), gfx::Rect(), PERSISTED
,
313 NULL
, gfx::Rect(), &window_bounds
);
314 EXPECT_EQ(gfx::Rect(50, 738 /* not 739 */, 500, 400).ToString(),
315 window_bounds
.ToString());
319 gfx::Rect window_bounds
;
320 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
321 gfx::Rect(-471, -371, 500, 400), gfx::Rect(), PERSISTED
,
322 NULL
, gfx::Rect(), &window_bounds
);
323 EXPECT_EQ(gfx::Rect(-470 /* not -471 */, 0, 500, 400).ToString(),
324 window_bounds
.ToString());
327 { // off the topright and the minimum visibility condition is satisified by
329 gfx::Rect window_bounds
;
330 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
331 gfx::Rect(995, -371, 500, 400), gfx::Rect(), PERSISTED
,
332 NULL
, gfx::Rect(), &window_bounds
);
333 EXPECT_EQ(gfx::Rect(994 /* not 995 */, 0, 500, 400).ToString(),
334 window_bounds
.ToString());
337 { // off the bottomleft and the minimum visibility condition is satisified by
339 gfx::Rect window_bounds
;
340 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
341 gfx::Rect(-471, 739, 500, 400), gfx::Rect(), PERSISTED
,
342 NULL
, gfx::Rect(), &window_bounds
);
343 EXPECT_EQ(gfx::Rect(-470 /* not -471 */,
347 window_bounds
.ToString());
350 { // off the bottomright and the minimum visibility condition is satisified by
352 gfx::Rect window_bounds
;
353 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
354 gfx::Rect(995, 739, 500, 400), gfx::Rect(), PERSISTED
,
355 NULL
, gfx::Rect(), &window_bounds
);
356 EXPECT_EQ(gfx::Rect(994 /* not 995 */,
360 window_bounds
.ToString());
363 { // entirely off left
364 gfx::Rect window_bounds
;
365 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
366 gfx::Rect(-700, 50, 500, 400), gfx::Rect(), PERSISTED
,
367 NULL
, gfx::Rect(), &window_bounds
);
368 EXPECT_EQ(gfx::Rect(-470 /* not -700 */, 50, 500, 400).ToString(),
369 window_bounds
.ToString());
372 { // entirely off left (monitor was detached since last run)
373 gfx::Rect window_bounds
;
374 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
375 gfx::Rect(-700, 50, 500, 400), left_s1024x768
, PERSISTED
,
376 NULL
, gfx::Rect(), &window_bounds
);
377 EXPECT_EQ("0,50 500x400", window_bounds
.ToString());
380 { // entirely off top
381 gfx::Rect window_bounds
;
382 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
383 gfx::Rect(50, -500, 500, 400), gfx::Rect(), PERSISTED
,
384 NULL
, gfx::Rect(), &window_bounds
);
385 EXPECT_EQ("50,0 500x400", window_bounds
.ToString());
388 { // entirely off top (monitor was detached since last run)
389 gfx::Rect window_bounds
;
390 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
391 gfx::Rect(50, -500, 500, 400), top_s1024x768
,
392 PERSISTED
, NULL
, gfx::Rect(), &window_bounds
);
393 EXPECT_EQ("50,0 500x400", window_bounds
.ToString());
396 { // entirely off right
397 gfx::Rect window_bounds
;
398 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
399 gfx::Rect(1200, 50, 500, 400), gfx::Rect(), PERSISTED
,
400 NULL
, gfx::Rect(), &window_bounds
);
401 EXPECT_EQ(gfx::Rect(994 /* not 1200 */, 50, 500, 400).ToString(),
402 window_bounds
.ToString());
405 { // entirely off right (monitor was detached since last run)
406 gfx::Rect window_bounds
;
407 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
408 gfx::Rect(1200, 50, 500, 400), right_s1024x768
,
409 PERSISTED
, NULL
, gfx::Rect(), &window_bounds
);
410 EXPECT_EQ("524,50 500x400", window_bounds
.ToString());
413 { // entirely off bottom
414 gfx::Rect window_bounds
;
415 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
416 gfx::Rect(50, 800, 500, 400), gfx::Rect(), PERSISTED
,
417 NULL
, gfx::Rect(), &window_bounds
);
418 EXPECT_EQ(gfx::Rect(50, 738 /* not 800 */, 500, 400).ToString(),
419 window_bounds
.ToString());
422 { // entirely off bottom (monitor was detached since last run)
423 gfx::Rect window_bounds
;
424 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
425 gfx::Rect(50, 800, 500, 400), bottom_s1024x768
,
426 PERSISTED
, NULL
, gfx::Rect(), &window_bounds
);
427 EXPECT_EQ("50,368 500x400", window_bounds
.ToString());
431 // Test that the window is sized appropriately for the first run experience
432 // where the default window bounds calculation is invoked.
433 TEST(WindowSizerTestCommon
, AdjustFitSize
) {
434 { // Check that the window gets resized to the screen.
435 gfx::Rect window_bounds
;
436 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(), gfx::Rect(),
437 gfx::Rect(), DEFAULT
, NULL
,
438 gfx::Rect(-10, -10, 1024 + 20, 768 + 20), &window_bounds
);
439 EXPECT_EQ("0,0 1024x768", window_bounds
.ToString());
442 { // Check that a window which hangs out of the screen get moved back in.
443 gfx::Rect window_bounds
;
444 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(), gfx::Rect(),
445 gfx::Rect(), DEFAULT
, NULL
,
446 gfx::Rect(1020, 700, 100, 100), &window_bounds
);
447 EXPECT_EQ("924,668 100x100", window_bounds
.ToString());
451 #endif // defined(OS_MACOSX)