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 // On desktop linux aura, we currently don't use the ash frame, breaking some
96 // tests which expect ash sizes: http://crbug.com/303862
97 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
98 #define MAYBE_DefaultSizeCase DISABLED_DefaultSizeCase
100 #define MAYBE_DefaultSizeCase DefaultSizeCase
103 // Test that the window is sized appropriately for the first run experience
104 // where the default window bounds calculation is invoked.
105 TEST_F(WindowSizerAshTest, MAYBE_DefaultSizeCase) {
107 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kOpenAsh);
109 { // 4:3 monitor case, 1024x768, no taskbar
110 gfx::Rect window_bounds;
111 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), gfx::Rect(),
112 gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
113 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
114 ash::WindowPositioner::kDesktopBorderSize,
115 1024 - ash::WindowPositioner::kDesktopBorderSize * 2,
116 768 - ash::WindowPositioner::kDesktopBorderSize),
120 { // 4:3 monitor case, 1024x768, taskbar on bottom
121 gfx::Rect window_bounds;
122 GetWindowBounds(p1024x768, taskbar_bottom_work_area, gfx::Rect(),
123 gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
125 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
126 ash::WindowPositioner::kDesktopBorderSize,
127 1024 - ash::WindowPositioner::kDesktopBorderSize * 2,
128 taskbar_bottom_work_area.height() -
129 ash::WindowPositioner::kDesktopBorderSize),
133 { // 4:3 monitor case, 1024x768, taskbar on right
134 gfx::Rect window_bounds;
135 GetWindowBounds(p1024x768, taskbar_right_work_area, gfx::Rect(),
136 gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
138 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
139 ash::WindowPositioner::kDesktopBorderSize,
140 taskbar_right_work_area.width() -
141 ash::WindowPositioner::kDesktopBorderSize * 2,
142 768 - ash::WindowPositioner::kDesktopBorderSize),
146 { // 4:3 monitor case, 1024x768, taskbar on left
147 gfx::Rect window_bounds;
148 GetWindowBounds(p1024x768, taskbar_left_work_area, gfx::Rect(),
149 gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
151 EXPECT_EQ(gfx::Rect(taskbar_left_work_area.x() +
152 ash::WindowPositioner::kDesktopBorderSize,
153 ash::WindowPositioner::kDesktopBorderSize,
154 taskbar_left_work_area.width() -
155 ash::WindowPositioner::kDesktopBorderSize * 2,
156 taskbar_left_work_area.height() -
157 ash::WindowPositioner::kDesktopBorderSize),
161 { // 4:3 monitor case, 1024x768, taskbar on top
162 gfx::Rect window_bounds;
163 GetWindowBounds(p1024x768, taskbar_top_work_area, gfx::Rect(),
164 gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
166 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
167 taskbar_top_work_area.y() +
168 ash::WindowPositioner::kDesktopBorderSize,
169 1024 - ash::WindowPositioner::kDesktopBorderSize * 2,
170 taskbar_top_work_area.height() -
171 ash::WindowPositioner::kDesktopBorderSize),
175 { // 4:3 monitor case, 1280x1024
176 gfx::Rect window_bounds;
177 GetWindowBounds(p1280x1024, p1280x1024, gfx::Rect(), gfx::Rect(),
178 gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
179 EXPECT_EQ(gfx::Rect((1280 - ash::WindowPositioner::kMaximumWindowWidth) / 2,
180 ash::WindowPositioner::kDesktopBorderSize,
181 ash::WindowPositioner::kMaximumWindowWidth,
182 1024 - ash::WindowPositioner::kDesktopBorderSize),
186 { // 4:3 monitor case, 1600x1200
187 gfx::Rect window_bounds;
188 GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(), gfx::Rect(),
189 gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
190 EXPECT_EQ(gfx::Rect((1600 - ash::WindowPositioner::kMaximumWindowWidth) / 2,
191 ash::WindowPositioner::kDesktopBorderSize,
192 ash::WindowPositioner::kMaximumWindowWidth,
193 1200 - ash::WindowPositioner::kDesktopBorderSize),
197 { // 16:10 monitor case, 1680x1050
198 gfx::Rect window_bounds;
199 GetWindowBounds(p1680x1050, p1680x1050, gfx::Rect(), gfx::Rect(),
200 gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
201 EXPECT_EQ(gfx::Rect((1680 - ash::WindowPositioner::kMaximumWindowWidth) / 2,
202 ash::WindowPositioner::kDesktopBorderSize,
203 ash::WindowPositioner::kMaximumWindowWidth,
204 1050 - ash::WindowPositioner::kDesktopBorderSize),
208 { // 16:10 monitor case, 1920x1200
209 gfx::Rect window_bounds;
210 GetWindowBounds(p1920x1200, p1920x1200, gfx::Rect(), gfx::Rect(),
211 gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
212 EXPECT_EQ(gfx::Rect((1920 - ash::WindowPositioner::kMaximumWindowWidth) / 2,
213 ash::WindowPositioner::kDesktopBorderSize,
214 ash::WindowPositioner::kMaximumWindowWidth,
215 1200 - ash::WindowPositioner::kDesktopBorderSize),
220 // Test that the next opened window is positioned appropriately given the
221 // bounds of an existing window of the same type.
222 TEST_F(WindowSizerAshTest, LastWindowBoundsCase) {
223 { // normal, in the middle of the screen somewhere.
224 gfx::Rect window_bounds;
226 p1024x768, p1024x768, gfx::Rect(),
227 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
228 ash::WindowPositioner::kDesktopBorderSize, 500, 400),
229 gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
232 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
233 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
234 500, 400).ToString(),
235 window_bounds.ToString());
239 gfx::Rect window_bounds;
241 p1024x768, taskbar_top_work_area, gfx::Rect(),
242 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
243 ash::WindowPositioner::kDesktopBorderSize, 500, 400),
244 gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
247 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
248 std::max(kWindowTilePixels +
249 ash::WindowPositioner::kDesktopBorderSize,
250 34 /* toolbar height */),
251 500, 400).ToString(),
252 window_bounds.ToString());
255 { // Too small to satisify the minimum visibility condition.
256 gfx::Rect window_bounds;
258 p1024x768, p1024x768, gfx::Rect(),
259 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
260 ash::WindowPositioner::kDesktopBorderSize, 29, 29),
261 gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
264 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
265 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
267 30 /* not 29 */).ToString(),
268 window_bounds.ToString());
273 gfx::Rect window_bounds;
275 p1024x768, p1024x768, gfx::Rect(),
276 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
277 ash::WindowPositioner::kDesktopBorderSize, 500, 400),
278 gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
281 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
282 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
283 500, 400).ToString(),
284 window_bounds.ToString());
288 // Test that the window opened is sized appropriately given persisted sizes.
289 TEST_F(WindowSizerAshTest, PersistedBoundsCase) {
290 { // normal, in the middle of the screen somewhere.
291 gfx::Rect initial_bounds(
292 ash::WindowPositioner::kDesktopBorderSize,
293 ash::WindowPositioner::kDesktopBorderSize, 500, 400);
295 gfx::Rect window_bounds;
296 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), initial_bounds,
297 gfx::Rect(), PERSISTED, NULL, gfx::Rect(), &window_bounds);
298 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
302 gfx::Rect initial_bounds(0, 0, 1024, 768);
304 gfx::Rect window_bounds;
305 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), initial_bounds,
306 gfx::Rect(), PERSISTED, NULL, gfx::Rect(), &window_bounds);
307 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
310 { // normal, on non-primary monitor in negative coords.
311 gfx::Rect initial_bounds(-600, 10, 500, 400);
313 gfx::Rect window_bounds;
314 GetWindowBounds(p1024x768, p1024x768, left_s1024x768,
315 initial_bounds, gfx::Rect(), PERSISTED, NULL, gfx::Rect(),
317 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
320 { // normal, on non-primary monitor in negative coords.
321 gfx::Rect initial_bounds(-1024, 0, 1024, 768);
323 gfx::Rect window_bounds;
324 GetWindowBounds(p1024x768, p1024x768, left_s1024x768,
325 initial_bounds, gfx::Rect(), PERSISTED, NULL, gfx::Rect(),
327 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
330 { // Non-primary monitor resoultion has changed, but the monitor still
331 // completely contains the window.
333 gfx::Rect initial_bounds(1074, 50, 600, 500);
335 gfx::Rect window_bounds;
336 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(1024, 0, 800, 600),
337 initial_bounds, right_s1024x768, PERSISTED, NULL,
338 gfx::Rect(), &window_bounds);
339 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
342 { // Non-primary monitor resoultion has changed, and the window is partially
345 gfx::Rect initial_bounds(1274, 50, 600, 500);
347 gfx::Rect window_bounds;
348 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(1024, 0, 800, 600),
349 initial_bounds, right_s1024x768, PERSISTED,
350 NULL, gfx::Rect(), &window_bounds);
351 EXPECT_EQ("1224,50 600x500", window_bounds.ToString());
354 { // Non-primary monitor resoultion has changed, and the window is now too
355 // large for the monitor.
357 gfx::Rect initial_bounds(1274, 50, 900, 700);
359 gfx::Rect window_bounds;
360 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(1024, 0, 800, 600),
361 initial_bounds, right_s1024x768, PERSISTED,
362 NULL, gfx::Rect(), &window_bounds);
363 EXPECT_EQ("1024,0 800x600", window_bounds.ToString());
366 { // width and height too small
367 gfx::Rect window_bounds;
369 p1024x768, p1024x768, gfx::Rect(),
370 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
371 ash::WindowPositioner::kDesktopBorderSize, 29, 29),
372 gfx::Rect(), PERSISTED, NULL, gfx::Rect(), &window_bounds);
373 EXPECT_EQ(gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
374 ash::WindowPositioner::kDesktopBorderSize,
375 30 /* not 29 */, 30 /* not 29 */).ToString(),
376 window_bounds.ToString());
380 //////////////////////////////////////////////////////////////////////////////
381 // The following unittests have different results on Mac/non-Mac because we
382 // reposition windows aggressively on Mac. The *WithAggressiveReposition tests
383 // are run on Mac, and the *WithNonAggressiveRepositioning tests are run on
386 TEST_F(WindowSizerAshTest, LastWindowOffscreenWithNonAggressiveRepositioning) {
387 { // taskbar on left.
388 gfx::Rect window_bounds;
390 p1024x768, taskbar_left_work_area, gfx::Rect(),
391 gfx::Rect(ash::WindowPositioner::kDesktopBorderSize,
392 ash::WindowPositioner::kDesktopBorderSize, 500, 400),
393 gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
396 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
397 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize,
398 500, 400).ToString(),
399 window_bounds.ToString());
402 { // offset would put the new window offscreen at the bottom but the minimum
403 // visibility condition is barely satisfied without relocation.
404 gfx::Rect window_bounds;
405 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
406 gfx::Rect(10, 728, 500, 400), gfx::Rect(), LAST_ACTIVE,
407 NULL, gfx::Rect(), &window_bounds);
408 EXPECT_EQ(gfx::Rect(10 + kWindowTilePixels, 738, 500, 400).ToString(),
409 window_bounds.ToString());
412 { // offset would put the new window offscreen at the bottom and the minimum
413 // visibility condition is satisified by relocation.
414 gfx::Rect window_bounds;
415 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
416 gfx::Rect(10, 729, 500, 400), gfx::Rect(), LAST_ACTIVE,
417 NULL, gfx::Rect(), &window_bounds);
418 EXPECT_EQ(gfx::Rect(10 + kWindowTilePixels,
422 window_bounds.ToString());
425 { // offset would put the new window offscreen at the right but the minimum
426 // visibility condition is barely satisfied without relocation.
427 gfx::Rect window_bounds;
428 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
429 gfx::Rect(984, 10, 500, 400), gfx::Rect(), LAST_ACTIVE,
430 NULL, gfx::Rect(), &window_bounds);
431 EXPECT_EQ(gfx::Rect(994, 10 + kWindowTilePixels, 500, 400).ToString(),
432 window_bounds.ToString());
435 { // offset would put the new window offscreen at the right and the minimum
436 // visibility condition is satisified by relocation.
437 gfx::Rect window_bounds;
438 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
439 gfx::Rect(985, 10, 500, 400), gfx::Rect(), LAST_ACTIVE,
440 NULL, gfx::Rect(), &window_bounds);
441 EXPECT_EQ(gfx::Rect(994 /* not 995 */,
442 10 + kWindowTilePixels,
445 window_bounds.ToString());
448 { // offset would put the new window offscreen at the bottom right and the
449 // minimum visibility condition is satisified by relocation.
450 gfx::Rect window_bounds;
451 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
452 gfx::Rect(985, 729, 500, 400), gfx::Rect(), LAST_ACTIVE,
453 NULL, gfx::Rect(), &window_bounds);
454 EXPECT_EQ(gfx::Rect(994 /* not 995 */,
458 window_bounds.ToString());
462 // On desktop linux aura, we currently don't use the ash frame, breaking some
463 // tests which expect ash sizes: http://crbug.com/303862
464 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
465 #define MAYBE_PlaceNewWindows DISABLED_PlaceNewWindows
467 #define MAYBE_PlaceNewWindows PlaceNewWindows
470 // Test the placement of newly created windows.
471 TEST_F(WindowSizerAshTest, MAYBE_PlaceNewWindows) {
472 // Create a browser to pass into the GetWindowBounds function.
473 scoped_ptr<TestingProfile> profile(new TestingProfile());
474 // Creating a popup handler here to make sure it does not interfere with the
476 Browser::CreateParams native_params(profile.get(),
477 chrome::HOST_DESKTOP_TYPE_ASH);
478 scoped_ptr<Browser> browser(
479 chrome::CreateBrowserWithTestWindowForParams(&native_params));
481 // Creating a popup handler here to make sure it does not interfere with the
483 scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow(
484 CreateTestWindowInShellWithId(0),
485 gfx::Rect(16, 32, 640, 320),
486 Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH)));
488 // Creating a popup to make sure it does not interfere with the positioning.
489 scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow(
490 CreateTestWindowInShellWithId(1),
491 gfx::Rect(16, 32, 128, 256),
492 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
493 chrome::HOST_DESKTOP_TYPE_ASH)));
495 // Creating a panel to make sure it does not interfere with the positioning.
496 scoped_ptr<BrowserWindow> browser_panel(CreateTestBrowserWindow(
497 CreateTestWindowInShellWithId(2),
498 gfx::Rect(32, 48, 256, 512),
499 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
500 chrome::HOST_DESKTOP_TYPE_ASH)));
501 browser_window->Show();
502 { // Make sure that popups do not get changed.
503 gfx::Rect window_bounds;
504 GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(),
505 gfx::Rect(50, 100, 300, 150), bottom_s1600x1200,
506 PERSISTED, browser_popup->browser(),
507 gfx::Rect(), &window_bounds);
508 EXPECT_EQ("50,100 300x150", window_bounds.ToString());
511 browser_window->Hide();
512 { // If a window is there but not shown the persisted default should be used.
513 gfx::Rect window_bounds;
514 GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(),
515 gfx::Rect(50, 100, 300, 150), bottom_s1600x1200,
516 PERSISTED, browser.get(), gfx::Rect(), &window_bounds);
517 EXPECT_EQ("50,100 300x150", window_bounds.ToString());
520 { // If a window is there but not shown the default should be returned.
521 gfx::Rect window_bounds;
522 GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(),
523 gfx::Rect(), bottom_s1600x1200,
524 DEFAULT, browser.get(), gfx::Rect(), &window_bounds);
525 // Note: We need to also take the defaults maximum width into account here
526 // since that might get used if the resolution is too big.
529 std::max(ash::WindowPositioner::kDesktopBorderSize,
530 (1600 - ash::WindowPositioner::kMaximumWindowWidth) / 2),
531 ash::WindowPositioner::kDesktopBorderSize,
532 std::min(ash::WindowPositioner::kMaximumWindowWidth,
533 1600 - 2 * ash::WindowPositioner::kDesktopBorderSize),
534 1200 - ash::WindowPositioner::kDesktopBorderSize).ToString(),
535 window_bounds.ToString());
539 // On desktop linux aura, we currently don't use the ash frame, breaking some
540 // tests which expect ash sizes: http://crbug.com/303862
541 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
542 #define MAYBE_PlaceNewBrowserWindowOnEmptyDesktop DISABLED_PlaceNewBrowserWindowOnEmptyDesktop
544 #define MAYBE_PlaceNewBrowserWindowOnEmptyDesktop PlaceNewBrowserWindowOnEmptyDesktop
547 // Test the placement of newly created windows on an empty desktop.
548 // This test supplements "PlaceNewWindows" by testing the creation of a newly
549 // created browser window on an empty desktop.
550 TEST_F(WindowSizerAshTest, MAYBE_PlaceNewBrowserWindowOnEmptyDesktop) {
551 // Create a browser to pass into the GetWindowBoundsAndShowState function.
552 scoped_ptr<TestingProfile> profile(new TestingProfile());
553 Browser::CreateParams native_params(profile.get(),
554 chrome::HOST_DESKTOP_TYPE_ASH);
555 scoped_ptr<Browser> browser(
556 chrome::CreateBrowserWithTestWindowForParams(&native_params));
558 // A common screen size for Chrome OS devices where this behavior is
560 const gfx::Rect p1366x768(0, 0, 1366, 768);
562 // If there is no previous state the window should get maximized if the
563 // screen is less than or equal to our limit (1366 pixels width).
564 gfx::Rect window_bounds;
565 ui::WindowShowState out_show_state1 = ui::SHOW_STATE_DEFAULT;
566 GetWindowBoundsAndShowState(
567 p1366x768, // The screen resolution.
568 p1366x768, // The monitor work area.
569 gfx::Rect(), // The second monitor.
570 gfx::Rect(), // The (persisted) bounds.
571 p1366x768, // The overall work area.
572 ui::SHOW_STATE_NORMAL, // The persisted show state.
573 ui::SHOW_STATE_DEFAULT, // The last show state.
574 DEFAULT, // No persisted values.
575 browser.get(), // Use this browser.
576 gfx::Rect(), // Don't request valid bounds.
579 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, out_show_state1);
581 // If there is a stored coordinate however, that should be taken instead.
582 ui::WindowShowState out_show_state2 = ui::SHOW_STATE_DEFAULT;
583 GetWindowBoundsAndShowState(
584 p1366x768, // The screen resolution.
585 p1366x768, // The monitor work area.
586 gfx::Rect(), // The second monitor.
587 gfx::Rect(50, 100, 300, 150), // The (persisted) bounds.
588 p1366x768, // The overall work area.
589 ui::SHOW_STATE_NORMAL, // The persisted show state.
590 ui::SHOW_STATE_DEFAULT, // The last show state.
591 PERSISTED, // Set the persisted values.
592 browser.get(), // Use this browser.
593 gfx::Rect(), // Don't request valid bounds.
596 EXPECT_EQ(ui::SHOW_STATE_NORMAL, out_show_state2);
597 EXPECT_EQ("50,100 300x150", window_bounds.ToString());
599 // A larger monitor should not trigger auto-maximize.
600 ui::WindowShowState out_show_state3 = ui::SHOW_STATE_DEFAULT;
601 GetWindowBoundsAndShowState(
602 p1600x1200, // The screen resolution.
603 p1600x1200, // The monitor work area.
604 gfx::Rect(), // The second monitor.
605 gfx::Rect(), // The (persisted) bounds.
606 p1600x1200, // The overall work area.
607 ui::SHOW_STATE_NORMAL, // The persisted show state.
608 ui::SHOW_STATE_DEFAULT, // The last show state.
609 DEFAULT, // No persisted values.
610 browser.get(), // Use this browser.
611 gfx::Rect(), // Don't request valid bounds.
615 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, out_show_state3);
617 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, out_show_state3);
621 #if defined(OS_CHROMEOS)
622 #define MAYBE_PlaceNewWindowsOnMultipleDisplays PlaceNewWindowsOnMultipleDisplays
624 // No multiple displays on windows ash.
625 #define MAYBE_PlaceNewWindowsOnMultipleDisplays DISABLED_PlaceNewWindowsOnMultipleDisplays
628 // Test the placement of newly created windows on multiple dislays.
629 TEST_F(WindowSizerAshTest, MAYBE_PlaceNewWindowsOnMultipleDisplays) {
630 UpdateDisplay("1600x1200,1600x1200");
631 gfx::Rect primary_bounds = ash::Shell::GetInstance()->GetScreen()->
632 GetPrimaryDisplay().bounds();
633 gfx::Rect secondary_bounds = ash::ScreenUtil::GetSecondaryDisplay().bounds();
635 ash::Shell::GetInstance()->set_target_root_window(
636 ash::Shell::GetPrimaryRootWindow());
638 scoped_ptr<TestingProfile> profile(new TestingProfile());
640 // Create browser windows that are used as reference.
641 scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow(
642 CreateTestWindowInShellWithId(0),
643 gfx::Rect(10, 10, 200, 200),
644 Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH)));
645 browser_window->Show();
646 EXPECT_EQ(browser_window->GetNativeWindow()->GetRootWindow(),
647 ash::Shell::GetTargetRootWindow());
649 scoped_ptr<BrowserWindow> another_browser_window(CreateTestBrowserWindow(
650 CreateTestWindowInShellWithId(1),
651 gfx::Rect(400, 10, 300, 300),
652 Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH)));
653 another_browser_window->Show();
655 // Creating a new window to verify the new placement.
656 scoped_ptr<TestBrowserWindowAura> new_browser_window(CreateTestBrowserWindow(
657 CreateTestWindowInShellWithId(0),
659 Browser::CreateParams(profile.get(),
660 chrome::HOST_DESKTOP_TYPE_ASH)));
662 // Make sure the primary root is active.
663 ASSERT_EQ(ash::Shell::GetPrimaryRootWindow(),
664 ash::Shell::GetTargetRootWindow());
666 // First new window should be in the primary.
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(primary_bounds.Contains(window_bounds));
679 // Move the window to the right side of the secondary display and create a new
680 // window. It should be opened then on the secondary display.
682 gfx::Display second_display = ash::Shell::GetScreen()->
683 GetDisplayNearestPoint(gfx::Point(1600 + 100,10));
684 browser_window->GetNativeWindow()->SetBoundsInScreen(
685 gfx::Rect(secondary_bounds.CenterPoint().x() - 100, 10, 200, 200),
687 browser_window->Activate();
688 EXPECT_NE(ash::Shell::GetPrimaryRootWindow(),
689 ash::Shell::GetTargetRootWindow());
690 gfx::Rect window_bounds;
691 GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds,
692 gfx::Rect(), secondary_bounds,
693 PERSISTED, new_browser_window->browser(),
694 gfx::Rect(), &window_bounds);
695 // TODO(oshima): Use exact bounds when the window_sizer_ash is
696 // moved to ash and changed to include the result from
697 // RearrangeVisibleWindowOnShow.
698 EXPECT_TRUE(secondary_bounds.Contains(window_bounds));
701 // Activate another window in the primary display and create a new window.
702 // It should be created in the primary display.
704 another_browser_window->Activate();
705 EXPECT_EQ(ash::Shell::GetPrimaryRootWindow(),
706 ash::Shell::GetTargetRootWindow());
708 gfx::Rect window_bounds;
709 GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds,
710 gfx::Rect(), secondary_bounds,
711 PERSISTED, new_browser_window->browser(),
712 gfx::Rect(), &window_bounds);
713 // TODO(oshima): Use exact bounds when the window_sizer_ash is
714 // moved to ash and changed to include the result from
715 // RearrangeVisibleWindowOnShow.
716 EXPECT_TRUE(primary_bounds.Contains(window_bounds));
720 // On desktop linux aura, we currently don't use the ash frame, breaking some
721 // tests which expect ash sizes: http://crbug.com/303862
722 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
723 #define MAYBE_TestShowState DISABLED_TestShowState
725 #define MAYBE_TestShowState TestShowState
728 // Test that the show state is properly returned for non default cases.
729 TEST_F(WindowSizerAshTest, MAYBE_TestShowState) {
730 scoped_ptr<TestingProfile> profile(new TestingProfile());
732 // Creating a browser & window to play with.
733 scoped_ptr<TestBrowserWindowAura> browser_window(CreateTestBrowserWindow(
734 CreateTestWindowInShellWithId(0),
735 gfx::Rect(16, 32, 640, 320),
736 Browser::CreateParams(Browser::TYPE_TABBED, profile.get(),
737 chrome::HOST_DESKTOP_TYPE_ASH)));
739 // Create also a popup browser since that behaves different.
740 scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow(
741 CreateTestWindowInShellWithId(1),
742 gfx::Rect(16, 32, 640, 320),
743 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
744 chrome::HOST_DESKTOP_TYPE_ASH)));
746 // Tabbed windows should retrieve the saved window state - since there is a
748 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
749 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
750 ui::SHOW_STATE_NORMAL,
752 browser_window->browser(),
755 // A window that is smaller than the whole work area is set to default state.
756 EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
757 GetWindowShowState(ui::SHOW_STATE_DEFAULT,
758 ui::SHOW_STATE_NORMAL,
760 browser_window->browser(),
763 // A window that is sized to occupy the whole work area is maximized.
764 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
765 GetWindowShowState(ui::SHOW_STATE_DEFAULT,
766 ui::SHOW_STATE_NORMAL,
768 browser_window->browser(),
771 // Non tabbed windows should always follow the window saved visibility state.
772 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
773 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
774 ui::SHOW_STATE_NORMAL,
776 browser_popup->browser(),
779 // The non tabbed window will take the status of the last active of its kind.
780 EXPECT_EQ(ui::SHOW_STATE_NORMAL,
781 GetWindowShowState(ui::SHOW_STATE_DEFAULT,
782 ui::SHOW_STATE_NORMAL,
784 browser_popup->browser(),
788 // Now create a top level window and check again for both. Only the tabbed
789 // window should follow the top level window's state.
790 // Creating a browser & window to play with.
791 scoped_ptr<TestBrowserWindowAura> browser_window2(CreateTestBrowserWindow(
792 CreateTestWindowInShellWithId(3),
793 gfx::Rect(16, 32, 640, 320),
794 Browser::CreateParams(Browser::TYPE_TABBED, profile.get(),
795 chrome::HOST_DESKTOP_TYPE_ASH)));
797 // A tabbed window should now take the top level window state.
798 EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
799 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
800 ui::SHOW_STATE_DEFAULT,
802 browser_window->browser(),
805 // Non tabbed windows should always follow the window saved visibility state.
806 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
807 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
808 ui::SHOW_STATE_MINIMIZED,
810 browser_popup->browser(),
814 // In smaller screen resolutions we default to maximized if there is no other
816 int min_size = ash::WindowPositioner::GetForceMaximizedWidthLimit() / 2;
818 const gfx::Rect tiny_screen(0, 0, min_size, min_size);
819 EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
820 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
821 ui::SHOW_STATE_DEFAULT,
823 browser_window->browser(),
826 browser_window->Hide();
827 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
828 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
829 ui::SHOW_STATE_DEFAULT,
831 browser_window2->browser(),
838 // Test that the default show state override behavior is properly handled.
839 TEST_F(WindowSizerAshTest, TestShowStateDefaults) {
840 // Creating a browser & window to play with.
841 scoped_ptr<TestingProfile> profile(new TestingProfile());
843 scoped_ptr<TestBrowserWindowAura> browser_window(CreateTestBrowserWindow(
844 CreateTestWindowInShellWithId(0),
845 gfx::Rect(16, 32, 640, 320),
846 Browser::CreateParams(Browser::TYPE_TABBED, profile.get(),
847 chrome::HOST_DESKTOP_TYPE_ASH)));
849 // Create also a popup browser since that behaves slightly different for
851 scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow(
852 CreateTestWindowInShellWithId(1),
853 gfx::Rect(16, 32, 128, 256),
854 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
855 chrome::HOST_DESKTOP_TYPE_ASH)));
857 // Check that a browser creation state always get used if not given as
858 // SHOW_STATE_DEFAULT. On Windows ASH it should be SHOW_STATE_MAXIMIZED.
859 ui::WindowShowState window_show_state =
860 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
861 ui::SHOW_STATE_MAXIMIZED,
863 browser_window->browser(),
867 EXPECT_EQ(window_show_state, ui::SHOW_STATE_MAXIMIZED);
869 EXPECT_EQ(window_show_state, ui::SHOW_STATE_DEFAULT);
872 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_MINIMIZED);
873 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
874 ui::SHOW_STATE_MAXIMIZED,
876 browser_window->browser(),
878 p1600x1200), ui::SHOW_STATE_MINIMIZED);
879 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL);
880 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
881 ui::SHOW_STATE_MAXIMIZED,
883 browser_window->browser(),
885 p1600x1200), ui::SHOW_STATE_NORMAL);
886 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_MAXIMIZED);
887 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL,
888 ui::SHOW_STATE_NORMAL,
890 browser_window->browser(),
892 p1600x1200), ui::SHOW_STATE_MAXIMIZED);
894 // Check that setting the maximized command line option is forcing the
896 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kStartMaximized);
898 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL);
899 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL,
900 ui::SHOW_STATE_NORMAL,
902 browser_window->browser(),
904 p1600x1200), ui::SHOW_STATE_MAXIMIZED);
906 // The popup should favor the initial show state over the command line.
907 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL,
908 ui::SHOW_STATE_NORMAL,
910 browser_popup->browser(),
912 p1600x1200), ui::SHOW_STATE_NORMAL);
915 TEST_F(WindowSizerAshTest, DefaultStateBecomesMaximized) {
916 // Create a browser to pass into the GetWindowBounds function.
917 scoped_ptr<TestingProfile> profile(new TestingProfile());
918 Browser::CreateParams native_params(profile.get(),
919 chrome::HOST_DESKTOP_TYPE_ASH);
920 scoped_ptr<Browser> browser(
921 chrome::CreateBrowserWithTestWindowForParams(&native_params));
923 gfx::Rect display_bounds = ash::Shell::GetInstance()->GetScreen()->
924 GetPrimaryDisplay().bounds();
925 gfx::Rect specified_bounds = display_bounds;
927 // Make a window bigger than the display work area.
928 specified_bounds.Inset(-20, -20);
929 ui::WindowShowState show_state = ui::SHOW_STATE_DEFAULT;
931 WindowSizer::GetBrowserWindowBoundsAndShowState(
932 std::string(), specified_bounds, browser.get(), &bounds, &show_state);
933 // The window should start maximized with its restore bounds shrunken.
934 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, show_state);
935 EXPECT_NE(display_bounds.ToString(), bounds.ToString());
936 EXPECT_TRUE(display_bounds.Contains(bounds));
938 // Make a window smaller than the display work area.
939 specified_bounds.Inset(100, 100);
940 show_state = ui::SHOW_STATE_DEFAULT;
941 WindowSizer::GetBrowserWindowBoundsAndShowState(
942 std::string(), specified_bounds, browser.get(), &bounds, &show_state);
943 // The window should start in default state.
944 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, show_state);
945 EXPECT_EQ(specified_bounds.ToString(), bounds.ToString());
948 // Test that the target root window is used as the destination of
949 // the non browser window. This differ from PersistedBoundsCase
950 // in that this uses real ash shell implementations + StateProvider
951 // TargetDisplayProvider, rather than mocks.
952 TEST_F(WindowSizerAshTest, DefaultBoundsInTargetDisplay) {
953 if (!SupportsMultipleDisplays() || !chrome::ShouldOpenAshOnStartup())
955 UpdateDisplay("500x500,600x600");
957 aura::Window* first_root =
958 ash::Shell::GetAllRootWindows()[0];
959 ash::ScopedTargetRootWindow tmp(first_root);
961 ui::WindowShowState show_state;
962 WindowSizer::GetBrowserWindowBoundsAndShowState(
968 EXPECT_TRUE(first_root->GetBoundsInScreen().Contains(bounds));
971 aura::Window* second_root =
972 ash::Shell::GetAllRootWindows()[1];
973 ash::ScopedTargetRootWindow tmp(second_root);
975 ui::WindowShowState show_state;
976 WindowSizer::GetBrowserWindowBoundsAndShowState(
982 EXPECT_TRUE(second_root->GetBoundsInScreen().Contains(bounds));
986 TEST_F(WindowSizerAshTest, TrustedPopupBehavior) {
987 scoped_ptr<TestingProfile> profile(new TestingProfile());
988 Browser::CreateParams trusted_popup_create_params(
989 Browser::TYPE_POPUP, profile.get(), chrome::HOST_DESKTOP_TYPE_ASH);
990 trusted_popup_create_params.trusted_source = true;
992 scoped_ptr<TestBrowserWindowAura> trusted_popup(CreateTestBrowserWindow(
993 CreateTestWindowInShellWithId(1),
994 gfx::Rect(16, 32, 640, 320),
995 trusted_popup_create_params));
996 // Trusted popup windows should follow the saved show state and ignore the
998 EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
999 GetWindowShowState(ui::SHOW_STATE_DEFAULT,
1000 ui::SHOW_STATE_NORMAL,
1002 trusted_popup->browser(),
1005 // A popup that is sized to occupy the whole work area has default state.
1006 EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
1007 GetWindowShowState(ui::SHOW_STATE_DEFAULT,
1008 ui::SHOW_STATE_NORMAL,
1010 trusted_popup->browser(),