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. 4 5 #include "ash/scoped_target_root_window.h" 6 #include "ash/screen_util.h" 7 #include "ash/shell.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" 27 28 typedef ash::test::AshTestBase WindowSizerAshTest; 29 30 namespace { 31 32 // A browser window proxy which is able to associate an aura native window with 33 // it. 34 class TestBrowserWindowAura : public TestBrowserWindow { 35 public: 36 // |native_window| will still be owned by the caller after the constructor 37 // was called. 38 explicit TestBrowserWindowAura(aura::Window* native_window) 39 : native_window_(native_window) { 40 } 41 virtual ~TestBrowserWindowAura() {} 42 43 // TestBrowserWindow overrides: 44 virtual void Show() OVERRIDE { 45 native_window_->Show(); 46 Activate(); 47 } 48 virtual void Hide() OVERRIDE { 49 native_window_->Hide(); 50 } 51 virtual void Activate() OVERRIDE { 52 aura::client::GetActivationClient( 53 native_window_->GetRootWindow())->ActivateWindow(native_window_.get()); 54 } 55 virtual gfx::NativeWindow GetNativeWindow() OVERRIDE { 56 return native_window_.get(); 57 } 58 virtual gfx::Rect GetBounds() const OVERRIDE { 59 return native_window_->bounds(); 60 } 61 62 Browser* browser() { return browser_.get(); } 63 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); 71 } 72 } 73 74 private: 75 scoped_ptr<Browser> browser_; 76 scoped_ptr<aura::Window> native_window_; 77 78 DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura); 79 }; 80 81 scoped_ptr<TestBrowserWindowAura> CreateTestBrowserWindow( 82 aura::Window* window, 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(); 91 } 92 93 } // namespace 94 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 99 #else 100 #define MAYBE_DefaultSizeCase DefaultSizeCase 101 #endif 102 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) { 106 #if defined(OS_WIN) 107 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kOpenAsh); 108 #endif 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), 117 window_bounds); 118 } 119 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(), 124 &window_bounds); 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), 130 window_bounds); 131 } 132 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(), 137 &window_bounds); 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), 143 window_bounds); 144 } 145 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(), 150 &window_bounds); 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), 158 window_bounds); 159 } 160 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(), 165 &window_bounds); 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), 172 window_bounds); 173 } 174 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), 183 window_bounds); 184 } 185 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), 194 window_bounds); 195 } 196 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), 205 window_bounds); 206 } 207 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), 216 window_bounds); 217 } 218 } 219 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; 225 GetWindowBounds( 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(), 230 &window_bounds); 231 EXPECT_EQ( 232 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 233 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 234 500, 400).ToString(), 235 window_bounds.ToString()); 236 } 237 238 { // taskbar on top. 239 gfx::Rect window_bounds; 240 GetWindowBounds( 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(), 245 &window_bounds); 246 EXPECT_EQ( 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()); 253 } 254 255 { // Too small to satisify the minimum visibility condition. 256 gfx::Rect window_bounds; 257 GetWindowBounds( 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(), 262 &window_bounds); 263 EXPECT_EQ( 264 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 265 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 266 30 /* not 29 */, 267 30 /* not 29 */).ToString(), 268 window_bounds.ToString()); 269 } 270 271 272 { // Normal. 273 gfx::Rect window_bounds; 274 GetWindowBounds( 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(), 279 &window_bounds); 280 EXPECT_EQ( 281 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 282 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 283 500, 400).ToString(), 284 window_bounds.ToString()); 285 } 286 } 287 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); 294 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()); 299 } 300 301 { // Normal. 302 gfx::Rect initial_bounds(0, 0, 1024, 768); 303 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()); 308 } 309 310 { // normal, on non-primary monitor in negative coords. 311 gfx::Rect initial_bounds(-600, 10, 500, 400); 312 313 gfx::Rect window_bounds; 314 GetWindowBounds(p1024x768, p1024x768, left_s1024x768, 315 initial_bounds, gfx::Rect(), PERSISTED, NULL, gfx::Rect(), 316 &window_bounds); 317 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString()); 318 } 319 320 { // normal, on non-primary monitor in negative coords. 321 gfx::Rect initial_bounds(-1024, 0, 1024, 768); 322 323 gfx::Rect window_bounds; 324 GetWindowBounds(p1024x768, p1024x768, left_s1024x768, 325 initial_bounds, gfx::Rect(), PERSISTED, NULL, gfx::Rect(), 326 &window_bounds); 327 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString()); 328 } 329 330 { // Non-primary monitor resoultion has changed, but the monitor still 331 // completely contains the window. 332 333 gfx::Rect initial_bounds(1074, 50, 600, 500); 334 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()); 340 } 341 342 { // Non-primary monitor resoultion has changed, and the window is partially 343 // off-screen. 344 345 gfx::Rect initial_bounds(1274, 50, 600, 500); 346 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()); 352 } 353 354 { // Non-primary monitor resoultion has changed, and the window is now too 355 // large for the monitor. 356 357 gfx::Rect initial_bounds(1274, 50, 900, 700); 358 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()); 364 } 365 366 { // width and height too small 367 gfx::Rect window_bounds; 368 GetWindowBounds( 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()); 377 } 378 } 379 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 384 // other platforms. 385 386 TEST_F(WindowSizerAshTest, LastWindowOffscreenWithNonAggressiveRepositioning) { 387 { // taskbar on left. 388 gfx::Rect window_bounds; 389 GetWindowBounds( 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(), 394 &window_bounds); 395 EXPECT_EQ( 396 gfx::Rect(kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 397 kWindowTilePixels + ash::WindowPositioner::kDesktopBorderSize, 398 500, 400).ToString(), 399 window_bounds.ToString()); 400 } 401 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()); 410 } 411 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, 419 738 /* not 739 */, 420 500, 421 400).ToString(), 422 window_bounds.ToString()); 423 } 424 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()); 433 } 434 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, 443 500, 444 400).ToString(), 445 window_bounds.ToString()); 446 } 447 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 */, 455 738 /* not 739 */, 456 500, 457 400).ToString(), 458 window_bounds.ToString()); 459 } 460 } 461 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 466 #else 467 #define MAYBE_PlaceNewWindows PlaceNewWindows 468 #endif 469 470 // Test the placement of newly created windows. 471 TEST_F(WindowSizerAshTest, MAYBE_PlaceNewWindows) { 472 // Create a browser which we can use to pass into the GetWindowBounds 473 // function. 474 scoped_ptr<TestingProfile> profile(new TestingProfile()); 475 // Creating a popup handler here to make sure it does not interfere with the 476 // existing windows. 477 Browser::CreateParams native_params(profile.get(), 478 chrome::HOST_DESKTOP_TYPE_ASH); 479 scoped_ptr<Browser> browser( 480 chrome::CreateBrowserWithTestWindowForParams(&native_params)); 481 482 // Creating a popup handler here to make sure it does not interfere with the 483 // existing windows. 484 scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow( 485 CreateTestWindowInShellWithId(0), 486 gfx::Rect(16, 32, 640, 320), 487 Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH))); 488 489 // Creating a popup to make sure it does not interfere with the positioning. 490 scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow( 491 CreateTestWindowInShellWithId(1), 492 gfx::Rect(16, 32, 128, 256), 493 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(), 494 chrome::HOST_DESKTOP_TYPE_ASH))); 495 496 // Creating a panel to make sure it does not interfere with the positioning. 497 scoped_ptr<BrowserWindow> browser_panel(CreateTestBrowserWindow( 498 CreateTestWindowInShellWithId(2), 499 gfx::Rect(32, 48, 256, 512), 500 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(), 501 chrome::HOST_DESKTOP_TYPE_ASH))); 502 browser_window->Show(); 503 { // Make sure that popups do not get changed. 504 gfx::Rect window_bounds; 505 GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(), 506 gfx::Rect(50, 100, 300, 150), bottom_s1600x1200, 507 PERSISTED, browser_popup->browser(), 508 gfx::Rect(), &window_bounds); 509 EXPECT_EQ("50,100 300x150", window_bounds.ToString()); 510 } 511 512 browser_window->Hide(); 513 { // If a window is there but not shown the persisted default should be used. 514 gfx::Rect window_bounds; 515 GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(), 516 gfx::Rect(50, 100, 300, 150), bottom_s1600x1200, 517 PERSISTED, browser.get(), gfx::Rect(), &window_bounds); 518 EXPECT_EQ("50,100 300x150", window_bounds.ToString()); 519 } 520 521 { // If a window is there but not shown the default should be returned. 522 gfx::Rect window_bounds; 523 GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(), 524 gfx::Rect(), bottom_s1600x1200, 525 DEFAULT, browser.get(), gfx::Rect(), &window_bounds); 526 // Note: We need to also take the defaults maximum width into account here 527 // since that might get used if the resolution is too big. 528 EXPECT_EQ( 529 gfx::Rect( 530 std::max(ash::WindowPositioner::kDesktopBorderSize, 531 (1600 - ash::WindowPositioner::kMaximumWindowWidth) / 2), 532 ash::WindowPositioner::kDesktopBorderSize, 533 std::min(ash::WindowPositioner::kMaximumWindowWidth, 534 1600 - 2 * ash::WindowPositioner::kDesktopBorderSize), 535 1200 - ash::WindowPositioner::kDesktopBorderSize).ToString(), 536 window_bounds.ToString()); 537 } 538 } 539 540 // On desktop linux aura, we currently don't use the ash frame, breaking some 541 // tests which expect ash sizes: http://crbug.com/303862 542 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 543 #define MAYBE_PlaceNewBrowserWindowOnEmptyDesktop DISABLED_PlaceNewBrowserWindowOnEmptyDesktop 544 #else 545 #define MAYBE_PlaceNewBrowserWindowOnEmptyDesktop PlaceNewBrowserWindowOnEmptyDesktop 546 #endif 547 548 // Test the placement of newly created windows on an empty desktop. 549 // This test supplements "PlaceNewWindows" by testing the creation of a newly 550 // created browser window on an empty desktop. 551 TEST_F(WindowSizerAshTest, MAYBE_PlaceNewBrowserWindowOnEmptyDesktop) { 552 // Create a browser which we can use to pass into the GetWindowBounds 553 // function. 554 scoped_ptr<TestingProfile> profile(new TestingProfile()); 555 Browser::CreateParams native_params(profile.get(), 556 chrome::HOST_DESKTOP_TYPE_ASH); 557 scoped_ptr<Browser> browser( 558 chrome::CreateBrowserWithTestWindowForParams(&native_params)); 559 560 // A common screen size for Chrome OS devices where this behavior is 561 // desirable. 562 const gfx::Rect p1366x768(0, 0, 1366, 768); 563 564 // If there is no previous state the window should get maximized if the 565 // screen is less than or equal to our limit (1366 pixels width). 566 gfx::Rect window_bounds; 567 ui::WindowShowState out_show_state1 = ui::SHOW_STATE_DEFAULT; 568 GetWindowBoundsAndShowState( 569 p1366x768, // The screen resolution. 570 p1366x768, // The monitor work area. 571 gfx::Rect(), // The second monitor. 572 gfx::Rect(), // The (persisted) bounds. 573 p1366x768, // The overall work area. 574 ui::SHOW_STATE_NORMAL, // The persisted show state. 575 ui::SHOW_STATE_DEFAULT, // The last show state. 576 DEFAULT, // No persisted values. 577 browser.get(), // Use this browser. 578 gfx::Rect(), // Don't request valid bounds. 579 &window_bounds, 580 &out_show_state1); 581 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, out_show_state1); 582 583 // If there is a stored coordinate however, that should be taken instead. 584 ui::WindowShowState out_show_state2 = ui::SHOW_STATE_DEFAULT; 585 GetWindowBoundsAndShowState( 586 p1366x768, // The screen resolution. 587 p1366x768, // The monitor work area. 588 gfx::Rect(), // The second monitor. 589 gfx::Rect(50, 100, 300, 150), // The (persisted) bounds. 590 p1366x768, // The overall work area. 591 ui::SHOW_STATE_NORMAL, // The persisted show state. 592 ui::SHOW_STATE_DEFAULT, // The last show state. 593 PERSISTED, // Set the persisted values. 594 browser.get(), // Use this browser. 595 gfx::Rect(), // Don't request valid bounds. 596 &window_bounds, 597 &out_show_state2); 598 EXPECT_EQ(ui::SHOW_STATE_NORMAL, out_show_state2); 599 EXPECT_EQ("50,100 300x150", window_bounds.ToString()); 600 601 // A larger monitor should not trigger auto-maximize. 602 ui::WindowShowState out_show_state3 = ui::SHOW_STATE_DEFAULT; 603 GetWindowBoundsAndShowState( 604 p1600x1200, // The screen resolution. 605 p1600x1200, // The monitor work area. 606 gfx::Rect(), // The second monitor. 607 gfx::Rect(), // The (persisted) bounds. 608 p1600x1200, // The overall work area. 609 ui::SHOW_STATE_NORMAL, // The persisted show state. 610 ui::SHOW_STATE_DEFAULT, // The last show state. 611 DEFAULT, // No persisted values. 612 browser.get(), // Use this browser. 613 gfx::Rect(), // Don't request valid bounds. 614 &window_bounds, 615 &out_show_state3); 616 #if defined(OS_WIN) 617 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, out_show_state3); 618 #else 619 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, out_show_state3); 620 #endif 621 } 622 623 #if defined(OS_CHROMEOS) 624 #define MAYBE_PlaceNewWindowsOnMultipleDisplays PlaceNewWindowsOnMultipleDisplays 625 #else 626 // No multiple displays on windows ash. 627 #define MAYBE_PlaceNewWindowsOnMultipleDisplays DISABLED_PlaceNewWindowsOnMultipleDisplays 628 #endif 629 630 // Test the placement of newly created windows on multiple dislays. 631 TEST_F(WindowSizerAshTest, MAYBE_PlaceNewWindowsOnMultipleDisplays) { 632 UpdateDisplay("1600x1200,1600x1200"); 633 gfx::Rect primary_bounds = ash::Shell::GetInstance()->GetScreen()-> 634 GetPrimaryDisplay().bounds(); 635 gfx::Rect secondary_bounds = ash::ScreenUtil::GetSecondaryDisplay().bounds(); 636 637 ash::Shell::GetInstance()->set_target_root_window( 638 ash::Shell::GetPrimaryRootWindow()); 639 640 scoped_ptr<TestingProfile> profile(new TestingProfile()); 641 642 // Create browser windows that are used as reference. 643 scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow( 644 CreateTestWindowInShellWithId(0), 645 gfx::Rect(10, 10, 200, 200), 646 Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH))); 647 browser_window->Show(); 648 EXPECT_EQ(browser_window->GetNativeWindow()->GetRootWindow(), 649 ash::Shell::GetTargetRootWindow()); 650 651 scoped_ptr<BrowserWindow> another_browser_window(CreateTestBrowserWindow( 652 CreateTestWindowInShellWithId(1), 653 gfx::Rect(400, 10, 300, 300), 654 Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH))); 655 another_browser_window->Show(); 656 657 // Creating a new window to verify the new placement. 658 scoped_ptr<TestBrowserWindowAura> new_browser_window(CreateTestBrowserWindow( 659 CreateTestWindowInShellWithId(0), 660 gfx::Rect(), 661 Browser::CreateParams(profile.get(), 662 chrome::HOST_DESKTOP_TYPE_ASH))); 663 664 // Make sure the primary root is active. 665 ASSERT_EQ(ash::Shell::GetPrimaryRootWindow(), 666 ash::Shell::GetTargetRootWindow()); 667 668 // First new window should be in the primary. 669 { 670 gfx::Rect window_bounds; 671 GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds, 672 gfx::Rect(), secondary_bounds, 673 PERSISTED, new_browser_window->browser(), 674 gfx::Rect(), &window_bounds); 675 // TODO(oshima): Use exact bounds when the window_sizer_ash is 676 // moved to ash and changed to include the result from 677 // RearrangeVisibleWindowOnShow. 678 EXPECT_TRUE(primary_bounds.Contains(window_bounds)); 679 } 680 681 // Move the window to the right side of the secondary display and create a new 682 // window. It should be opened then on the secondary display. 683 { 684 gfx::Display second_display = ash::Shell::GetScreen()-> 685 GetDisplayNearestPoint(gfx::Point(1600 + 100,10)); 686 browser_window->GetNativeWindow()->SetBoundsInScreen( 687 gfx::Rect(secondary_bounds.CenterPoint().x() - 100, 10, 200, 200), 688 second_display); 689 browser_window->Activate(); 690 EXPECT_NE(ash::Shell::GetPrimaryRootWindow(), 691 ash::Shell::GetTargetRootWindow()); 692 gfx::Rect window_bounds; 693 GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds, 694 gfx::Rect(), secondary_bounds, 695 PERSISTED, new_browser_window->browser(), 696 gfx::Rect(), &window_bounds); 697 // TODO(oshima): Use exact bounds when the window_sizer_ash is 698 // moved to ash and changed to include the result from 699 // RearrangeVisibleWindowOnShow. 700 EXPECT_TRUE(secondary_bounds.Contains(window_bounds)); 701 } 702 703 // Activate another window in the primary display and create a new window. 704 // It should be created in the primary display. 705 { 706 another_browser_window->Activate(); 707 EXPECT_EQ(ash::Shell::GetPrimaryRootWindow(), 708 ash::Shell::GetTargetRootWindow()); 709 710 gfx::Rect window_bounds; 711 GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds, 712 gfx::Rect(), secondary_bounds, 713 PERSISTED, new_browser_window->browser(), 714 gfx::Rect(), &window_bounds); 715 // TODO(oshima): Use exact bounds when the window_sizer_ash is 716 // moved to ash and changed to include the result from 717 // RearrangeVisibleWindowOnShow. 718 EXPECT_TRUE(primary_bounds.Contains(window_bounds)); 719 } 720 } 721 722 // On desktop linux aura, we currently don't use the ash frame, breaking some 723 // tests which expect ash sizes: http://crbug.com/303862 724 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 725 #define MAYBE_TestShowState DISABLED_TestShowState 726 #else 727 #define MAYBE_TestShowState TestShowState 728 #endif 729 730 // Test that the show state is properly returned for non default cases. 731 TEST_F(WindowSizerAshTest, MAYBE_TestShowState) { 732 scoped_ptr<TestingProfile> profile(new TestingProfile()); 733 734 // Creating a browser & window to play with. 735 scoped_ptr<TestBrowserWindowAura> browser_window(CreateTestBrowserWindow( 736 CreateTestWindowInShellWithId(0), 737 gfx::Rect(16, 32, 640, 320), 738 Browser::CreateParams(Browser::TYPE_TABBED, profile.get(), 739 chrome::HOST_DESKTOP_TYPE_ASH))); 740 741 // Create also a popup browser since that behaves different. 742 scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow( 743 CreateTestWindowInShellWithId(1), 744 gfx::Rect(16, 32, 640, 320), 745 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(), 746 chrome::HOST_DESKTOP_TYPE_ASH))); 747 748 // Tabbed windows should retrieve the saved window state - since there is a 749 // top window. 750 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, 751 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 752 ui::SHOW_STATE_NORMAL, 753 BOTH, 754 browser_window->browser(), 755 p1600x1200)); 756 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, 757 GetWindowShowState(ui::SHOW_STATE_DEFAULT, 758 ui::SHOW_STATE_NORMAL, 759 BOTH, 760 browser_window->browser(), 761 p1600x1200)); 762 // Non tabbed windows should always follow the window saved visibility state. 763 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, 764 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 765 ui::SHOW_STATE_NORMAL, 766 BOTH, 767 browser_popup->browser(), 768 p1600x1200)); 769 // The non tabbed window will take the status of the last active of its kind. 770 EXPECT_EQ(ui::SHOW_STATE_NORMAL, 771 GetWindowShowState(ui::SHOW_STATE_DEFAULT, 772 ui::SHOW_STATE_NORMAL, 773 BOTH, 774 browser_popup->browser(), 775 p1600x1200)); 776 777 // Now create a top level window and check again for both. Only the tabbed 778 // window should follow the top level window's state. 779 // Creating a browser & window to play with. 780 scoped_ptr<TestBrowserWindowAura> browser_window2(CreateTestBrowserWindow( 781 CreateTestWindowInShellWithId(3), 782 gfx::Rect(16, 32, 640, 320), 783 Browser::CreateParams(Browser::TYPE_TABBED, profile.get(), 784 chrome::HOST_DESKTOP_TYPE_ASH))); 785 786 // A tabbed window should now take the top level window state. 787 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, 788 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 789 ui::SHOW_STATE_DEFAULT, 790 BOTH, 791 browser_window->browser(), 792 p1600x1200)); 793 // Non tabbed windows should always follow the window saved visibility state. 794 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, 795 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 796 ui::SHOW_STATE_MINIMIZED, 797 BOTH, 798 browser_popup->browser(), 799 p1600x1200)); 800 801 // In smaller screen resolutions we default to maximized if there is no other 802 // window visible. 803 int min_size = ash::WindowPositioner::GetForceMaximizedWidthLimit() / 2; 804 if (min_size > 0) { 805 const gfx::Rect tiny_screen(0, 0, min_size, min_size); 806 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, 807 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 808 ui::SHOW_STATE_DEFAULT, 809 BOTH, 810 browser_window->browser(), 811 tiny_screen)); 812 browser_window->Hide(); 813 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, 814 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 815 ui::SHOW_STATE_DEFAULT, 816 BOTH, 817 browser_window2->browser(), 818 tiny_screen)); 819 820 } 821 } 822 823 // Test that the default show state override behavior is properly handled. 824 TEST_F(WindowSizerAshTest, TestShowStateDefaults) { 825 // Creating a browser & window to play with. 826 scoped_ptr<TestingProfile> profile(new TestingProfile()); 827 828 scoped_ptr<TestBrowserWindowAura> browser_window(CreateTestBrowserWindow( 829 CreateTestWindowInShellWithId(0), 830 gfx::Rect(16, 32, 640, 320), 831 Browser::CreateParams(Browser::TYPE_TABBED, profile.get(), 832 chrome::HOST_DESKTOP_TYPE_ASH))); 833 834 // Create also a popup browser since that behaves slightly different for 835 // defaults. 836 scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow( 837 CreateTestWindowInShellWithId(1), 838 gfx::Rect(16, 32, 128, 256), 839 Browser::CreateParams(Browser::TYPE_POPUP, profile.get(), 840 chrome::HOST_DESKTOP_TYPE_ASH))); 841 842 // Check that a browser creation state always get used if not given as 843 // SHOW_STATE_DEFAULT. On Windows ASH it should be SHOW_STATE_MAXIMIZED. 844 ui::WindowShowState window_show_state = 845 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 846 ui::SHOW_STATE_MAXIMIZED, 847 DEFAULT, 848 browser_window->browser(), 849 p1600x1200); 850 #if defined(OS_WIN) 851 EXPECT_EQ(window_show_state, ui::SHOW_STATE_MAXIMIZED); 852 #else 853 EXPECT_EQ(window_show_state, ui::SHOW_STATE_DEFAULT); 854 #endif 855 856 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_MINIMIZED); 857 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 858 ui::SHOW_STATE_MAXIMIZED, 859 BOTH, 860 browser_window->browser(), 861 p1600x1200), ui::SHOW_STATE_MINIMIZED); 862 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL); 863 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 864 ui::SHOW_STATE_MAXIMIZED, 865 BOTH, 866 browser_window->browser(), 867 p1600x1200), ui::SHOW_STATE_NORMAL); 868 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_MAXIMIZED); 869 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL, 870 ui::SHOW_STATE_NORMAL, 871 BOTH, 872 browser_window->browser(), 873 p1600x1200), ui::SHOW_STATE_MAXIMIZED); 874 875 // Check that setting the maximized command line option is forcing the 876 // maximized state. 877 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kStartMaximized); 878 879 browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL); 880 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL, 881 ui::SHOW_STATE_NORMAL, 882 BOTH, 883 browser_window->browser(), 884 p1600x1200), ui::SHOW_STATE_MAXIMIZED); 885 886 // The popup should favor the initial show state over the command line. 887 EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL, 888 ui::SHOW_STATE_NORMAL, 889 BOTH, 890 browser_popup->browser(), 891 p1600x1200), ui::SHOW_STATE_NORMAL); 892 } 893 894 // Test that the target root window is used as the destionation of 895 // the non browser window. This differ from PersistedBoundsCase 896 // in that this uses real ash shell implementations + StateProvider 897 // TargetDisplayProvider, rather than mocks. 898 TEST_F(WindowSizerAshTest, DefaultBoundsInTargetDisplay) { 899 if (!SupportsMultipleDisplays() || !chrome::ShouldOpenAshOnStartup()) 900 return; 901 UpdateDisplay("500x500,600x600"); 902 { 903 aura::Window* first_root = 904 ash::Shell::GetAllRootWindows()[0]; 905 ash::ScopedTargetRootWindow tmp(first_root); 906 gfx::Rect bounds; 907 ui::WindowShowState show_state; 908 WindowSizer::GetBrowserWindowBoundsAndShowState( 909 std::string(), 910 gfx::Rect(), 911 NULL, 912 &bounds, 913 &show_state); 914 EXPECT_TRUE(first_root->GetBoundsInScreen().Contains(bounds)); 915 } 916 { 917 aura::Window* second_root = 918 ash::Shell::GetAllRootWindows()[1]; 919 ash::ScopedTargetRootWindow tmp(second_root); 920 gfx::Rect bounds; 921 ui::WindowShowState show_state; 922 WindowSizer::GetBrowserWindowBoundsAndShowState( 923 std::string(), 924 gfx::Rect(), 925 NULL, 926 &bounds, 927 &show_state); 928 EXPECT_TRUE(second_root->GetBoundsInScreen().Contains(bounds)); 929 } 930 } 931 932 TEST_F(WindowSizerAshTest, TrustedPopupBehavior) { 933 scoped_ptr<TestingProfile> profile(new TestingProfile()); 934 Browser::CreateParams trusted_popup_create_params( 935 Browser::TYPE_POPUP, profile.get(), chrome::HOST_DESKTOP_TYPE_ASH); 936 trusted_popup_create_params.trusted_source = true; 937 938 scoped_ptr<TestBrowserWindowAura> trusted_popup(CreateTestBrowserWindow( 939 CreateTestWindowInShellWithId(1), 940 gfx::Rect(16, 32, 640, 320), 941 trusted_popup_create_params)); 942 // Trusted popup windows should follow the saved show state and ignore the 943 // last show state. 944 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, 945 GetWindowShowState(ui::SHOW_STATE_DEFAULT, 946 ui::SHOW_STATE_NORMAL, 947 BOTH, 948 trusted_popup->browser(), 949 p1600x1200)); 950 } 951