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 "ash/scoped_target_root_window.h"
6 #include "ash/screen_util.h"
8 #include "ash/test/ash_test_base.h"
9 #include "ash/test/test_shell_delegate.h"
10 #include "ash/wm/window_positioner.h"
11 #include "ash/wm/window_resizer.h"
12 #include "ash/wm/window_state.h"
13 #include "base/compiler_specific.h"
14 #include "chrome/browser/ui/ash/ash_init.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/window_sizer/window_sizer_common_unittest.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "content/public/test/render_view_test.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/aura/client/aura_constants.h"
22 #include "ui/aura/env.h"
23 #include "ui/aura/test/test_windows.h"
24 #include "ui/aura/window_event_dispatcher.h"
25 #include "ui/gfx/screen.h"
26 #include "ui/wm/public/activation_client.h"
28 typedef ash::test::AshTestBase WindowSizerAshTest
;
32 // A browser window proxy which is able to associate an aura native window with
34 class TestBrowserWindowAura
: public TestBrowserWindow
{
36 // |native_window| will still be owned by the caller after the constructor
38 explicit TestBrowserWindowAura(aura::Window
* native_window
)
39 : native_window_(native_window
) {
41 virtual ~TestBrowserWindowAura() {}
43 // TestBrowserWindow overrides:
44 virtual void Show() OVERRIDE
{
45 native_window_
->Show();
48 virtual void Hide() OVERRIDE
{
49 native_window_
->Hide();
51 virtual void Activate() OVERRIDE
{
52 aura::client::GetActivationClient(
53 native_window_
->GetRootWindow())->ActivateWindow(native_window_
.get());
55 virtual gfx::NativeWindow
GetNativeWindow() OVERRIDE
{
56 return native_window_
.get();
58 virtual gfx::Rect
GetBounds() const OVERRIDE
{
59 return native_window_
->bounds();
62 Browser
* browser() { return browser_
.get(); }
64 void CreateBrowser(const Browser::CreateParams
& params
) {
65 Browser::CreateParams create_params
= params
;
66 create_params
.window
= this;
67 browser_
.reset(new Browser(create_params
));
68 if (browser_
->is_type_tabbed() || browser_
->is_app()) {
69 ash::wm::GetWindowState(native_window_
.get())->
70 set_window_position_managed(true);
75 scoped_ptr
<Browser
> browser_
;
76 scoped_ptr
<aura::Window
> native_window_
;
78 DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura
);
81 scoped_ptr
<TestBrowserWindowAura
> CreateTestBrowserWindow(
83 const gfx::Rect
& bounds
,
84 const Browser::CreateParams
& params
) {
85 if (!bounds
.IsEmpty())
86 window
->SetBounds(bounds
);
87 scoped_ptr
<TestBrowserWindowAura
> browser_window(
88 new TestBrowserWindowAura(window
));
89 browser_window
->CreateBrowser(params
);
90 return browser_window
.Pass();
95 // Test that the window is sized appropriately for the first run experience
96 // where the default window bounds calculation is invoked.
97 TEST_F(WindowSizerAshTest
, DefaultSizeCase
) {
99 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kOpenAsh
);
101 { // 4:3 monitor case, 1024x768, no taskbar
102 gfx::Rect window_bounds
;
103 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(), gfx::Rect(),
104 gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(), &window_bounds
);
105 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
106 ash::WindowPositioner::kDesktopBorderSize
,
107 1024 - ash::WindowPositioner::kDesktopBorderSize
* 2,
108 768 - ash::WindowPositioner::kDesktopBorderSize
),
112 { // 4:3 monitor case, 1024x768, taskbar on bottom
113 gfx::Rect window_bounds
;
114 GetWindowBounds(p1024x768
, taskbar_bottom_work_area
, gfx::Rect(),
115 gfx::Rect(), gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(),
117 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
118 ash::WindowPositioner::kDesktopBorderSize
,
119 1024 - ash::WindowPositioner::kDesktopBorderSize
* 2,
120 taskbar_bottom_work_area
.height() -
121 ash::WindowPositioner::kDesktopBorderSize
),
125 { // 4:3 monitor case, 1024x768, taskbar on right
126 gfx::Rect window_bounds
;
127 GetWindowBounds(p1024x768
, taskbar_right_work_area
, gfx::Rect(),
128 gfx::Rect(), gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(),
130 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
131 ash::WindowPositioner::kDesktopBorderSize
,
132 taskbar_right_work_area
.width() -
133 ash::WindowPositioner::kDesktopBorderSize
* 2,
134 768 - ash::WindowPositioner::kDesktopBorderSize
),
138 { // 4:3 monitor case, 1024x768, taskbar on left
139 gfx::Rect window_bounds
;
140 GetWindowBounds(p1024x768
, taskbar_left_work_area
, gfx::Rect(),
141 gfx::Rect(), gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(),
143 EXPECT_EQ(gfx::Rect(taskbar_left_work_area
.x() +
144 ash::WindowPositioner::kDesktopBorderSize
,
145 ash::WindowPositioner::kDesktopBorderSize
,
146 taskbar_left_work_area
.width() -
147 ash::WindowPositioner::kDesktopBorderSize
* 2,
148 taskbar_left_work_area
.height() -
149 ash::WindowPositioner::kDesktopBorderSize
),
153 { // 4:3 monitor case, 1024x768, taskbar on top
154 gfx::Rect window_bounds
;
155 GetWindowBounds(p1024x768
, taskbar_top_work_area
, gfx::Rect(),
156 gfx::Rect(), gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(),
158 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
159 taskbar_top_work_area
.y() +
160 ash::WindowPositioner::kDesktopBorderSize
,
161 1024 - ash::WindowPositioner::kDesktopBorderSize
* 2,
162 taskbar_top_work_area
.height() -
163 ash::WindowPositioner::kDesktopBorderSize
),
167 { // 4:3 monitor case, 1280x1024
168 gfx::Rect window_bounds
;
169 GetWindowBounds(p1280x1024
, p1280x1024
, gfx::Rect(), gfx::Rect(),
170 gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(), &window_bounds
);
171 EXPECT_EQ(gfx::Rect((1280 - ash::WindowPositioner::kMaximumWindowWidth
) / 2,
172 ash::WindowPositioner::kDesktopBorderSize
,
173 ash::WindowPositioner::kMaximumWindowWidth
,
174 1024 - ash::WindowPositioner::kDesktopBorderSize
),
178 { // 4:3 monitor case, 1600x1200
179 gfx::Rect window_bounds
;
180 GetWindowBounds(p1600x1200
, p1600x1200
, gfx::Rect(), gfx::Rect(),
181 gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(), &window_bounds
);
182 EXPECT_EQ(gfx::Rect((1600 - ash::WindowPositioner::kMaximumWindowWidth
) / 2,
183 ash::WindowPositioner::kDesktopBorderSize
,
184 ash::WindowPositioner::kMaximumWindowWidth
,
185 1200 - ash::WindowPositioner::kDesktopBorderSize
),
189 { // 16:10 monitor case, 1680x1050
190 gfx::Rect window_bounds
;
191 GetWindowBounds(p1680x1050
, p1680x1050
, gfx::Rect(), gfx::Rect(),
192 gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(), &window_bounds
);
193 EXPECT_EQ(gfx::Rect((1680 - ash::WindowPositioner::kMaximumWindowWidth
) / 2,
194 ash::WindowPositioner::kDesktopBorderSize
,
195 ash::WindowPositioner::kMaximumWindowWidth
,
196 1050 - ash::WindowPositioner::kDesktopBorderSize
),
200 { // 16:10 monitor case, 1920x1200
201 gfx::Rect window_bounds
;
202 GetWindowBounds(p1920x1200
, p1920x1200
, gfx::Rect(), gfx::Rect(),
203 gfx::Rect(), DEFAULT
, NULL
, gfx::Rect(), &window_bounds
);
204 EXPECT_EQ(gfx::Rect((1920 - ash::WindowPositioner::kMaximumWindowWidth
) / 2,
205 ash::WindowPositioner::kDesktopBorderSize
,
206 ash::WindowPositioner::kMaximumWindowWidth
,
207 1200 - ash::WindowPositioner::kDesktopBorderSize
),
212 // Test that the next opened window is positioned appropriately given the
213 // bounds of an existing window of the same type.
214 TEST_F(WindowSizerAshTest
, LastWindowBoundsCase
) {
215 { // normal, in the middle of the screen somewhere.
216 gfx::Rect window_bounds
;
218 p1024x768
, p1024x768
, gfx::Rect(),
219 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
220 ash::WindowPositioner::kDesktopBorderSize
, 500, 400),
221 gfx::Rect(), LAST_ACTIVE
, NULL
, gfx::Rect(),
224 gfx::Rect(kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
225 kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
226 500, 400).ToString(),
227 window_bounds
.ToString());
231 gfx::Rect window_bounds
;
233 p1024x768
, taskbar_top_work_area
, gfx::Rect(),
234 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
235 ash::WindowPositioner::kDesktopBorderSize
, 500, 400),
236 gfx::Rect(), LAST_ACTIVE
, NULL
, gfx::Rect(),
239 gfx::Rect(kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
240 std::max(kWindowTilePixels
+
241 ash::WindowPositioner::kDesktopBorderSize
,
242 34 /* toolbar height */),
243 500, 400).ToString(),
244 window_bounds
.ToString());
247 { // Too small to satisify the minimum visibility condition.
248 gfx::Rect window_bounds
;
250 p1024x768
, p1024x768
, gfx::Rect(),
251 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
252 ash::WindowPositioner::kDesktopBorderSize
, 29, 29),
253 gfx::Rect(), LAST_ACTIVE
, NULL
, gfx::Rect(),
256 gfx::Rect(kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
257 kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
259 30 /* not 29 */).ToString(),
260 window_bounds
.ToString());
265 gfx::Rect window_bounds
;
267 p1024x768
, p1024x768
, gfx::Rect(),
268 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
269 ash::WindowPositioner::kDesktopBorderSize
, 500, 400),
270 gfx::Rect(), LAST_ACTIVE
, NULL
, gfx::Rect(),
273 gfx::Rect(kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
274 kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
275 500, 400).ToString(),
276 window_bounds
.ToString());
280 // Test that the window opened is sized appropriately given persisted sizes.
281 TEST_F(WindowSizerAshTest
, PersistedBoundsCase
) {
282 { // normal, in the middle of the screen somewhere.
283 gfx::Rect
initial_bounds(
284 ash::WindowPositioner::kDesktopBorderSize
,
285 ash::WindowPositioner::kDesktopBorderSize
, 500, 400);
287 gfx::Rect window_bounds
;
288 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(), initial_bounds
,
289 gfx::Rect(), PERSISTED
, NULL
, gfx::Rect(), &window_bounds
);
290 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
294 gfx::Rect
initial_bounds(0, 0, 1024, 768);
296 gfx::Rect window_bounds
;
297 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(), initial_bounds
,
298 gfx::Rect(), PERSISTED
, NULL
, gfx::Rect(), &window_bounds
);
299 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
302 { // normal, on non-primary monitor in negative coords.
303 gfx::Rect
initial_bounds(-600, 10, 500, 400);
305 gfx::Rect window_bounds
;
306 GetWindowBounds(p1024x768
, p1024x768
, left_s1024x768
,
307 initial_bounds
, gfx::Rect(), PERSISTED
, NULL
, gfx::Rect(),
309 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
312 { // normal, on non-primary monitor in negative coords.
313 gfx::Rect
initial_bounds(-1024, 0, 1024, 768);
315 gfx::Rect window_bounds
;
316 GetWindowBounds(p1024x768
, p1024x768
, left_s1024x768
,
317 initial_bounds
, gfx::Rect(), PERSISTED
, NULL
, gfx::Rect(),
319 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
322 { // Non-primary monitor resoultion has changed, but the monitor still
323 // completely contains the window.
325 gfx::Rect
initial_bounds(1074, 50, 600, 500);
327 gfx::Rect window_bounds
;
328 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(1024, 0, 800, 600),
329 initial_bounds
, right_s1024x768
, PERSISTED
, NULL
,
330 gfx::Rect(), &window_bounds
);
331 EXPECT_EQ(initial_bounds
.ToString(), window_bounds
.ToString());
334 { // Non-primary monitor resoultion has changed, and the window is partially
337 gfx::Rect
initial_bounds(1274, 50, 600, 500);
339 gfx::Rect window_bounds
;
340 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(1024, 0, 800, 600),
341 initial_bounds
, right_s1024x768
, PERSISTED
,
342 NULL
, gfx::Rect(), &window_bounds
);
343 EXPECT_EQ("1224,50 600x500", window_bounds
.ToString());
346 { // Non-primary monitor resoultion has changed, and the window is now too
347 // large for the monitor.
349 gfx::Rect
initial_bounds(1274, 50, 900, 700);
351 gfx::Rect window_bounds
;
352 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(1024, 0, 800, 600),
353 initial_bounds
, right_s1024x768
, PERSISTED
,
354 NULL
, gfx::Rect(), &window_bounds
);
355 EXPECT_EQ("1024,0 800x600", window_bounds
.ToString());
358 { // width and height too small
359 gfx::Rect window_bounds
;
361 p1024x768
, p1024x768
, gfx::Rect(),
362 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
363 ash::WindowPositioner::kDesktopBorderSize
, 29, 29),
364 gfx::Rect(), PERSISTED
, NULL
, gfx::Rect(), &window_bounds
);
365 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
366 ash::WindowPositioner::kDesktopBorderSize
,
367 30 /* not 29 */, 30 /* not 29 */).ToString(),
368 window_bounds
.ToString());
372 //////////////////////////////////////////////////////////////////////////////
373 // The following unittests have different results on Mac/non-Mac because we
374 // reposition windows aggressively on Mac. The *WithAggressiveReposition tests
375 // are run on Mac, and the *WithNonAggressiveRepositioning tests are run on
378 TEST_F(WindowSizerAshTest
, LastWindowOffscreenWithNonAggressiveRepositioning
) {
379 { // taskbar on left.
380 gfx::Rect window_bounds
;
382 p1024x768
, taskbar_left_work_area
, gfx::Rect(),
383 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize
,
384 ash::WindowPositioner::kDesktopBorderSize
, 500, 400),
385 gfx::Rect(), LAST_ACTIVE
, NULL
, gfx::Rect(),
388 gfx::Rect(kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
389 kWindowTilePixels
+ ash::WindowPositioner::kDesktopBorderSize
,
390 500, 400).ToString(),
391 window_bounds
.ToString());
394 { // offset would put the new window offscreen at the bottom but the minimum
395 // visibility condition is barely satisfied without relocation.
396 gfx::Rect window_bounds
;
397 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
398 gfx::Rect(10, 728, 500, 400), gfx::Rect(), LAST_ACTIVE
,
399 NULL
, gfx::Rect(), &window_bounds
);
400 EXPECT_EQ(gfx::Rect(10 + kWindowTilePixels
, 738, 500, 400).ToString(),
401 window_bounds
.ToString());
404 { // offset would put the new window offscreen at the bottom and the minimum
405 // visibility condition is satisified by relocation.
406 gfx::Rect window_bounds
;
407 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
408 gfx::Rect(10, 729, 500, 400), gfx::Rect(), LAST_ACTIVE
,
409 NULL
, gfx::Rect(), &window_bounds
);
410 EXPECT_EQ(gfx::Rect(10 + kWindowTilePixels
,
414 window_bounds
.ToString());
417 { // offset would put the new window offscreen at the right but the minimum
418 // visibility condition is barely satisfied without relocation.
419 gfx::Rect window_bounds
;
420 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
421 gfx::Rect(984, 10, 500, 400), gfx::Rect(), LAST_ACTIVE
,
422 NULL
, gfx::Rect(), &window_bounds
);
423 EXPECT_EQ(gfx::Rect(994, 10 + kWindowTilePixels
, 500, 400).ToString(),
424 window_bounds
.ToString());
427 { // offset would put the new window offscreen at the right and the minimum
428 // visibility condition is satisified by relocation.
429 gfx::Rect window_bounds
;
430 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
431 gfx::Rect(985, 10, 500, 400), gfx::Rect(), LAST_ACTIVE
,
432 NULL
, gfx::Rect(), &window_bounds
);
433 EXPECT_EQ(gfx::Rect(994 /* not 995 */,
434 10 + kWindowTilePixels
,
437 window_bounds
.ToString());
440 { // offset would put the new window offscreen at the bottom right and the
441 // minimum visibility condition is satisified by relocation.
442 gfx::Rect window_bounds
;
443 GetWindowBounds(p1024x768
, p1024x768
, gfx::Rect(),
444 gfx::Rect(985, 729, 500, 400), gfx::Rect(), LAST_ACTIVE
,
445 NULL
, gfx::Rect(), &window_bounds
);
446 EXPECT_EQ(gfx::Rect(994 /* not 995 */,
450 window_bounds
.ToString());
454 // Test the placement of newly created windows.
455 TEST_F(WindowSizerAshTest
, PlaceNewWindows
) {
456 // Create a browser which we can use to pass into the GetWindowBounds
458 scoped_ptr
<TestingProfile
> profile(new TestingProfile());
459 // Creating a popup handler here to make sure it does not interfere with the
461 Browser::CreateParams
native_params(profile
.get(),
462 chrome::HOST_DESKTOP_TYPE_ASH
);
463 scoped_ptr
<Browser
> browser(
464 chrome::CreateBrowserWithTestWindowForParams(&native_params
));
466 // Creating a popup handler here to make sure it does not interfere with the
468 scoped_ptr
<BrowserWindow
> browser_window(CreateTestBrowserWindow(
469 CreateTestWindowInShellWithId(0),
470 gfx::Rect(16, 32, 640, 320),
471 Browser::CreateParams(profile
.get(), chrome::HOST_DESKTOP_TYPE_ASH
)));
473 // Creating a popup to make sure it does not interfere with the positioning.
474 scoped_ptr
<TestBrowserWindowAura
> browser_popup(CreateTestBrowserWindow(
475 CreateTestWindowInShellWithId(1),
476 gfx::Rect(16, 32, 128, 256),
477 Browser::CreateParams(Browser::TYPE_POPUP
, profile
.get(),
478 chrome::HOST_DESKTOP_TYPE_ASH
)));
480 // Creating a panel to make sure it does not interfere with the positioning.
481 scoped_ptr
<BrowserWindow
> browser_panel(CreateTestBrowserWindow(
482 CreateTestWindowInShellWithId(2),
483 gfx::Rect(32, 48, 256, 512),
484 Browser::CreateParams(Browser::TYPE_POPUP
, profile
.get(),
485 chrome::HOST_DESKTOP_TYPE_ASH
)));
486 browser_window
->Show();
487 { // Make sure that popups do not get changed.
488 gfx::Rect window_bounds
;
489 GetWindowBounds(p1600x1200
, p1600x1200
, gfx::Rect(),
490 gfx::Rect(50, 100, 300, 150), bottom_s1600x1200
,
491 PERSISTED
, browser_popup
->browser(),
492 gfx::Rect(), &window_bounds
);
493 EXPECT_EQ("50,100 300x150", window_bounds
.ToString());
496 browser_window
->Hide();
497 { // If a window is there but not shown the persisted default should be used.
498 gfx::Rect window_bounds
;
499 GetWindowBounds(p1600x1200
, p1600x1200
, gfx::Rect(),
500 gfx::Rect(50, 100, 300, 150), bottom_s1600x1200
,
501 PERSISTED
, browser
.get(), gfx::Rect(), &window_bounds
);
502 EXPECT_EQ("50,100 300x150", window_bounds
.ToString());
505 { // If a window is there but not shown the default should be returned.
506 gfx::Rect window_bounds
;
507 GetWindowBounds(p1600x1200
, p1600x1200
, gfx::Rect(),
508 gfx::Rect(), bottom_s1600x1200
,
509 DEFAULT
, browser
.get(), gfx::Rect(), &window_bounds
);
510 // Note: We need to also take the defaults maximum width into account here
511 // since that might get used if the resolution is too big.
514 std::max(ash::WindowPositioner::kDesktopBorderSize
,
515 (1600 - ash::WindowPositioner::kMaximumWindowWidth
) / 2),
516 ash::WindowPositioner::kDesktopBorderSize
,
517 std::min(ash::WindowPositioner::kMaximumWindowWidth
,
518 1600 - 2 * ash::WindowPositioner::kDesktopBorderSize
),
519 1200 - ash::WindowPositioner::kDesktopBorderSize
).ToString(),
520 window_bounds
.ToString());
524 // Test the placement of newly created windows on an empty desktop.
525 // This test supplements "PlaceNewWindows" by testing the creation of a newly
526 // created browser window on an empty desktop.
527 TEST_F(WindowSizerAshTest
, PlaceNewBrowserWindowOnEmptyDesktop
) {
528 // Create a browser which we can use to pass into the GetWindowBounds
530 scoped_ptr
<TestingProfile
> profile(new TestingProfile());
531 Browser::CreateParams
native_params(profile
.get(),
532 chrome::HOST_DESKTOP_TYPE_ASH
);
533 scoped_ptr
<Browser
> browser(
534 chrome::CreateBrowserWithTestWindowForParams(&native_params
));
536 // A common screen size for Chrome OS devices where this behavior is
538 const gfx::Rect
p1366x768(0, 0, 1366, 768);
540 // If there is no previous state the window should get maximized if the
541 // screen is less than or equal to our limit (1366 pixels width).
542 gfx::Rect window_bounds
;
543 ui::WindowShowState out_show_state1
= ui::SHOW_STATE_DEFAULT
;
544 GetWindowBoundsAndShowState(
545 p1366x768
, // The screen resolution.
546 p1366x768
, // The monitor work area.
547 gfx::Rect(), // The second monitor.
548 gfx::Rect(), // The (persisted) bounds.
549 p1366x768
, // The overall work area.
550 ui::SHOW_STATE_NORMAL
, // The persisted show state.
551 ui::SHOW_STATE_DEFAULT
, // The last show state.
552 DEFAULT
, // No persisted values.
553 browser
.get(), // Use this browser.
554 gfx::Rect(), // Don't request valid bounds.
557 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED
, out_show_state1
);
559 // If there is a stored coordinate however, that should be taken instead.
560 ui::WindowShowState out_show_state2
= ui::SHOW_STATE_DEFAULT
;
561 GetWindowBoundsAndShowState(
562 p1366x768
, // The screen resolution.
563 p1366x768
, // The monitor work area.
564 gfx::Rect(), // The second monitor.
565 gfx::Rect(50, 100, 300, 150), // The (persisted) bounds.
566 p1366x768
, // The overall work area.
567 ui::SHOW_STATE_NORMAL
, // The persisted show state.
568 ui::SHOW_STATE_DEFAULT
, // The last show state.
569 PERSISTED
, // Set the persisted values.
570 browser
.get(), // Use this browser.
571 gfx::Rect(), // Don't request valid bounds.
574 EXPECT_EQ(ui::SHOW_STATE_NORMAL
, out_show_state2
);
575 EXPECT_EQ("50,100 300x150", window_bounds
.ToString());
577 // A larger monitor should not trigger auto-maximize.
578 ui::WindowShowState out_show_state3
= ui::SHOW_STATE_DEFAULT
;
579 GetWindowBoundsAndShowState(
580 p1600x1200
, // The screen resolution.
581 p1600x1200
, // The monitor work area.
582 gfx::Rect(), // The second monitor.
583 gfx::Rect(), // The (persisted) bounds.
584 p1600x1200
, // The overall work area.
585 ui::SHOW_STATE_NORMAL
, // The persisted show state.
586 ui::SHOW_STATE_DEFAULT
, // The last show state.
587 DEFAULT
, // No persisted values.
588 browser
.get(), // Use this browser.
589 gfx::Rect(), // Don't request valid bounds.
593 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED
, out_show_state3
);
595 EXPECT_EQ(ui::SHOW_STATE_DEFAULT
, out_show_state3
);
599 #if defined(OS_CHROMEOS)
600 #define MAYBE_PlaceNewWindowsOnMultipleDisplays PlaceNewWindowsOnMultipleDisplays
602 // No multiple displays on windows ash.
603 #define MAYBE_PlaceNewWindowsOnMultipleDisplays DISABLED_PlaceNewWindowsOnMultipleDisplays
606 // Test the placement of newly created windows on multiple dislays.
607 TEST_F(WindowSizerAshTest
, MAYBE_PlaceNewWindowsOnMultipleDisplays
) {
608 UpdateDisplay("1600x1200,1600x1200");
609 gfx::Rect primary_bounds
= ash::Shell::GetInstance()->GetScreen()->
610 GetPrimaryDisplay().bounds();
611 gfx::Rect secondary_bounds
= ash::ScreenUtil::GetSecondaryDisplay().bounds();
613 ash::Shell::GetInstance()->set_target_root_window(
614 ash::Shell::GetPrimaryRootWindow());
616 scoped_ptr
<TestingProfile
> profile(new TestingProfile());
618 // Create browser windows that are used as reference.
619 scoped_ptr
<BrowserWindow
> browser_window(CreateTestBrowserWindow(
620 CreateTestWindowInShellWithId(0),
621 gfx::Rect(10, 10, 200, 200),
622 Browser::CreateParams(profile
.get(), chrome::HOST_DESKTOP_TYPE_ASH
)));
623 browser_window
->Show();
624 EXPECT_EQ(browser_window
->GetNativeWindow()->GetRootWindow(),
625 ash::Shell::GetTargetRootWindow());
627 scoped_ptr
<BrowserWindow
> another_browser_window(CreateTestBrowserWindow(
628 CreateTestWindowInShellWithId(1),
629 gfx::Rect(400, 10, 300, 300),
630 Browser::CreateParams(profile
.get(), chrome::HOST_DESKTOP_TYPE_ASH
)));
631 another_browser_window
->Show();
633 // Creating a new window to verify the new placement.
634 scoped_ptr
<TestBrowserWindowAura
> new_browser_window(CreateTestBrowserWindow(
635 CreateTestWindowInShellWithId(0),
637 Browser::CreateParams(profile
.get(),
638 chrome::HOST_DESKTOP_TYPE_ASH
)));
640 // Make sure the primary root is active.
641 ASSERT_EQ(ash::Shell::GetPrimaryRootWindow(),
642 ash::Shell::GetTargetRootWindow());
644 // First new window should be in the primary.
646 gfx::Rect window_bounds
;
647 GetWindowBounds(p1600x1200
, p1600x1200
, secondary_bounds
,
648 gfx::Rect(), secondary_bounds
,
649 PERSISTED
, new_browser_window
->browser(),
650 gfx::Rect(), &window_bounds
);
651 // TODO(oshima): Use exact bounds when the window_sizer_ash is
652 // moved to ash and changed to include the result from
653 // RearrangeVisibleWindowOnShow.
654 EXPECT_TRUE(primary_bounds
.Contains(window_bounds
));
657 // Move the window to the right side of the secondary display and create a new
658 // window. It should be opened then on the secondary display.
660 gfx::Display second_display
= ash::Shell::GetScreen()->
661 GetDisplayNearestPoint(gfx::Point(1600 + 100,10));
662 browser_window
->GetNativeWindow()->SetBoundsInScreen(
663 gfx::Rect(secondary_bounds
.CenterPoint().x() - 100, 10, 200, 200),
665 browser_window
->Activate();
666 EXPECT_NE(ash::Shell::GetPrimaryRootWindow(),
667 ash::Shell::GetTargetRootWindow());
668 gfx::Rect window_bounds
;
669 GetWindowBounds(p1600x1200
, p1600x1200
, secondary_bounds
,
670 gfx::Rect(), secondary_bounds
,
671 PERSISTED
, new_browser_window
->browser(),
672 gfx::Rect(), &window_bounds
);
673 // TODO(oshima): Use exact bounds when the window_sizer_ash is
674 // moved to ash and changed to include the result from
675 // RearrangeVisibleWindowOnShow.
676 EXPECT_TRUE(secondary_bounds
.Contains(window_bounds
));
679 // Activate another window in the primary display and create a new window.
680 // It should be created in the primary display.
682 another_browser_window
->Activate();
683 EXPECT_EQ(ash::Shell::GetPrimaryRootWindow(),
684 ash::Shell::GetTargetRootWindow());
686 gfx::Rect window_bounds
;
687 GetWindowBounds(p1600x1200
, p1600x1200
, secondary_bounds
,
688 gfx::Rect(), secondary_bounds
,
689 PERSISTED
, new_browser_window
->browser(),
690 gfx::Rect(), &window_bounds
);
691 // TODO(oshima): Use exact bounds when the window_sizer_ash is
692 // moved to ash and changed to include the result from
693 // RearrangeVisibleWindowOnShow.
694 EXPECT_TRUE(primary_bounds
.Contains(window_bounds
));
698 // Test that the show state is properly returned for non default cases.
699 TEST_F(WindowSizerAshTest
, TestShowState
) {
700 scoped_ptr
<TestingProfile
> profile(new TestingProfile());
702 // Creating a browser & window to play with.
703 scoped_ptr
<TestBrowserWindowAura
> browser_window(CreateTestBrowserWindow(
704 CreateTestWindowInShellWithId(0),
705 gfx::Rect(16, 32, 640, 320),
706 Browser::CreateParams(Browser::TYPE_TABBED
, profile
.get(),
707 chrome::HOST_DESKTOP_TYPE_ASH
)));
709 // Create also a popup browser since that behaves different.
710 scoped_ptr
<TestBrowserWindowAura
> browser_popup(CreateTestBrowserWindow(
711 CreateTestWindowInShellWithId(1),
712 gfx::Rect(16, 32, 640, 320),
713 Browser::CreateParams(Browser::TYPE_POPUP
, profile
.get(),
714 chrome::HOST_DESKTOP_TYPE_ASH
)));
716 // Tabbed windows should retrieve the saved window state - since there is a
718 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED
,
719 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
720 ui::SHOW_STATE_NORMAL
,
722 browser_window
->browser(),
724 EXPECT_EQ(ui::SHOW_STATE_DEFAULT
,
725 GetWindowShowState(ui::SHOW_STATE_DEFAULT
,
726 ui::SHOW_STATE_NORMAL
,
728 browser_window
->browser(),
730 // Non tabbed windows should always follow the window saved visibility state.
731 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED
,
732 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
733 ui::SHOW_STATE_NORMAL
,
735 browser_popup
->browser(),
737 // The non tabbed window will take the status of the last active of its kind.
738 EXPECT_EQ(ui::SHOW_STATE_NORMAL
,
739 GetWindowShowState(ui::SHOW_STATE_DEFAULT
,
740 ui::SHOW_STATE_NORMAL
,
742 browser_popup
->browser(),
745 // Now create a top level window and check again for both. Only the tabbed
746 // window should follow the top level window's state.
747 // Creating a browser & window to play with.
748 scoped_ptr
<TestBrowserWindowAura
> browser_window2(CreateTestBrowserWindow(
749 CreateTestWindowInShellWithId(3),
750 gfx::Rect(16, 32, 640, 320),
751 Browser::CreateParams(Browser::TYPE_TABBED
, profile
.get(),
752 chrome::HOST_DESKTOP_TYPE_ASH
)));
754 // A tabbed window should now take the top level window state.
755 EXPECT_EQ(ui::SHOW_STATE_DEFAULT
,
756 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
757 ui::SHOW_STATE_DEFAULT
,
759 browser_window
->browser(),
761 // Non tabbed windows should always follow the window saved visibility state.
762 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED
,
763 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
764 ui::SHOW_STATE_MINIMIZED
,
766 browser_popup
->browser(),
769 // In smaller screen resolutions we default to maximized if there is no other
771 int min_size
= ash::WindowPositioner::GetForceMaximizedWidthLimit() / 2;
773 const gfx::Rect
tiny_screen(0, 0, min_size
, min_size
);
774 EXPECT_EQ(ui::SHOW_STATE_DEFAULT
,
775 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
776 ui::SHOW_STATE_DEFAULT
,
778 browser_window
->browser(),
780 browser_window
->Hide();
781 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED
,
782 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
783 ui::SHOW_STATE_DEFAULT
,
785 browser_window2
->browser(),
791 // Test that the default show state override behavior is properly handled.
792 TEST_F(WindowSizerAshTest
, TestShowStateDefaults
) {
793 // Creating a browser & window to play with.
794 scoped_ptr
<TestingProfile
> profile(new TestingProfile());
796 scoped_ptr
<TestBrowserWindowAura
> browser_window(CreateTestBrowserWindow(
797 CreateTestWindowInShellWithId(0),
798 gfx::Rect(16, 32, 640, 320),
799 Browser::CreateParams(Browser::TYPE_TABBED
, profile
.get(),
800 chrome::HOST_DESKTOP_TYPE_ASH
)));
802 // Create also a popup browser since that behaves slightly different for
804 scoped_ptr
<TestBrowserWindowAura
> browser_popup(CreateTestBrowserWindow(
805 CreateTestWindowInShellWithId(1),
806 gfx::Rect(16, 32, 128, 256),
807 Browser::CreateParams(Browser::TYPE_POPUP
, profile
.get(),
808 chrome::HOST_DESKTOP_TYPE_ASH
)));
810 // Check that a browser creation state always get used if not given as
811 // SHOW_STATE_DEFAULT. On Windows ASH it should be SHOW_STATE_MAXIMIZED.
812 ui::WindowShowState window_show_state
=
813 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
814 ui::SHOW_STATE_MAXIMIZED
,
816 browser_window
->browser(),
819 EXPECT_EQ(window_show_state
, ui::SHOW_STATE_MAXIMIZED
);
821 EXPECT_EQ(window_show_state
, ui::SHOW_STATE_DEFAULT
);
824 browser_window
->browser()->set_initial_show_state(ui::SHOW_STATE_MINIMIZED
);
825 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
826 ui::SHOW_STATE_MAXIMIZED
,
828 browser_window
->browser(),
829 p1600x1200
), ui::SHOW_STATE_MINIMIZED
);
830 browser_window
->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL
);
831 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED
,
832 ui::SHOW_STATE_MAXIMIZED
,
834 browser_window
->browser(),
835 p1600x1200
), ui::SHOW_STATE_NORMAL
);
836 browser_window
->browser()->set_initial_show_state(ui::SHOW_STATE_MAXIMIZED
);
837 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL
,
838 ui::SHOW_STATE_NORMAL
,
840 browser_window
->browser(),
841 p1600x1200
), ui::SHOW_STATE_MAXIMIZED
);
843 // Check that setting the maximized command line option is forcing the
845 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kStartMaximized
);
847 browser_window
->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL
);
848 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL
,
849 ui::SHOW_STATE_NORMAL
,
851 browser_window
->browser(),
852 p1600x1200
), ui::SHOW_STATE_MAXIMIZED
);
854 // The popup should favor the initial show state over the command line.
855 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL
,
856 ui::SHOW_STATE_NORMAL
,
858 browser_popup
->browser(),
859 p1600x1200
), ui::SHOW_STATE_NORMAL
);
862 // Test that the target root window is used as the destionation of
863 // the non browser window. This differ from PersistedBoundsCase
864 // in that this uses real ash shell implementations + StateProvider
865 // TargetDisplayProvider, rather than mocks.
866 TEST_F(WindowSizerAshTest
, DefaultBoundsInTargetDisplay
) {
867 if (!SupportsMultipleDisplays() || !chrome::ShouldOpenAshOnStartup())
869 UpdateDisplay("500x500,600x600");
871 aura::Window
* first_root
=
872 ash::Shell::GetAllRootWindows()[0];
873 ash::internal::ScopedTargetRootWindow
tmp(
876 ui::WindowShowState show_state
;
877 WindowSizer::GetBrowserWindowBoundsAndShowState(
883 EXPECT_TRUE(first_root
->GetBoundsInScreen().Contains(bounds
));
886 aura::Window
* second_root
=
887 ash::Shell::GetAllRootWindows()[1];
888 ash::internal::ScopedTargetRootWindow
tmp(
891 ui::WindowShowState show_state
;
892 WindowSizer::GetBrowserWindowBoundsAndShowState(
898 EXPECT_TRUE(second_root
->GetBoundsInScreen().Contains(bounds
));