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 28typedef ash::test::AshTestBase WindowSizerAshTest; 29 30namespace { 31 32// A browser window proxy which is able to associate an aura native window with 33// it. 34class 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 81scoped_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. 105TEST_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. 222TEST_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. 289TEST_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 386TEST_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. 471TEST_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 475 // existing windows. 476 Browser::CreateParams native_params(profile.get(), 477 chrome::HOST_DESKTOP_TYPE_ASH); 478 scoped_ptr<Browser> browser( 479 chrome::CreateBrowserWithTestWindowForParams(&native_params)); 480 481 // Creating a popup handler here to make sure it does not interfere with the 482 // existing windows. 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))); 487 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))); 494 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()); 509 } 510 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()); 518 } 519 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. 527 EXPECT_EQ( 528 gfx::Rect( 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()); 536 } 537} 538 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 543#else 544#define MAYBE_PlaceNewBrowserWindowOnEmptyDesktop PlaceNewBrowserWindowOnEmptyDesktop 545#endif 546 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. 550TEST_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)); 557 558 // A common screen size for Chrome OS devices where this behavior is 559 // desirable. 560 const gfx::Rect p1366x768(0, 0, 1366, 768); 561 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. 577 &window_bounds, 578 &out_show_state1); 579 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, out_show_state1); 580 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. 594 &window_bounds, 595 &out_show_state2); 596 EXPECT_EQ(ui::SHOW_STATE_NORMAL, out_show_state2); 597 EXPECT_EQ("50,100 300x150", window_bounds.ToString()); 598 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. 612 &window_bounds, 613 &out_show_state3); 614#if defined(OS_WIN) 615 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, out_show_state3); 616#else 617 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, out_show_state3); 618#endif 619} 620 621#if defined(OS_CHROMEOS) 622#define MAYBE_PlaceNewWindowsOnMultipleDisplays PlaceNewWindowsOnMultipleDisplays 623#else 624// No multiple displays on windows ash. 625#define MAYBE_PlaceNewWindowsOnMultipleDisplays DISABLED_PlaceNewWindowsOnMultipleDisplays 626#endif 627 628// Test the placement of newly created windows on multiple dislays. 629TEST_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(); 634 635 ash::Shell::GetInstance()->set_target_root_window( 636 ash::Shell::GetPrimaryRootWindow()); 637 638 scoped_ptr<TestingProfile> profile(new TestingProfile()); 639 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()); 648 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(); 654 655 // Creating a new window to verify the new placement. 656 scoped_ptr<TestBrowserWindowAura> new_browser_window(CreateTestBrowserWindow( 657 CreateTestWindowInShellWithId(0), 658 gfx::Rect(), 659 Browser::CreateParams(profile.get(), 660 chrome::HOST_DESKTOP_TYPE_ASH))); 661 662 // Make sure the primary root is active. 663 ASSERT_EQ(ash::Shell::GetPrimaryRootWindow(), 664 ash::Shell::GetTargetRootWindow()); 665 666 // First new window should be in the primary. 667 { 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)); 677 } 678 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. 681 { 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), 686 second_display); 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)); 699 } 700 701 // Activate another window in the primary display and create a new window. 702 // It should be created in the primary display. 703 { 704 another_browser_window->Activate(); 705 EXPECT_EQ(ash::Shell::GetPrimaryRootWindow(), 706 ash::Shell::GetTargetRootWindow()); 707 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)); 717 } 718} 719 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 724#else 725#define MAYBE_TestShowState TestShowState 726#endif 727 728// Test that the show state is properly returned for non default cases. 729TEST_F(WindowSizerAshTest, MAYBE_TestShowState) { 730 scoped_ptr<TestingProfile> profile(new TestingProfile()); 731 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))); 738 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))); 745 746 // Tabbed windows should retrieve the saved window state - since there is a 747 // top window. 748 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, 749 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 750 ui::SHOW_STATE_NORMAL, 751 BOTH, 752 browser_window->browser(), 753 p1600x1200, 754 p1600x1200)); 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, 759 BOTH, 760 browser_window->browser(), 761 p1280x1024, 762 p1600x1200)); 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, 767 BOTH, 768 browser_window->browser(), 769 p1600x1200, 770 p1600x1200)); 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, 775 BOTH, 776 browser_popup->browser(), 777 p1600x1200, 778 p1600x1200)); 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, 783 BOTH, 784 browser_popup->browser(), 785 p1600x1200, 786 p1600x1200)); 787 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))); 796 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, 801 BOTH, 802 browser_window->browser(), 803 p1600x1200, 804 p1600x1200)); 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, 809 BOTH, 810 browser_popup->browser(), 811 p1600x1200, 812 p1600x1200)); 813 814 // In smaller screen resolutions we default to maximized if there is no other 815 // window visible. 816 int min_size = ash::WindowPositioner::GetForceMaximizedWidthLimit() / 2; 817 if (min_size > 0) { 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, 822 BOTH, 823 browser_window->browser(), 824 tiny_screen, 825 tiny_screen)); 826 browser_window->Hide(); 827 EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, 828 GetWindowShowState(ui::SHOW_STATE_MAXIMIZED, 829 ui::SHOW_STATE_DEFAULT, 830 BOTH, 831 browser_window2->browser(), 832 tiny_screen, 833 tiny_screen)); 834 835 } 836} 837 838// Test that the default show state override behavior is properly handled. 839TEST_F(WindowSizerAshTest, TestShowStateDefaults) { 840 // Creating a browser & window to play with. 841 scoped_ptr<TestingProfile> profile(new TestingProfile()); 842 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))); 848 849 // Create also a popup browser since that behaves slightly different for 850 // defaults. 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))); 856 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, 862 DEFAULT, 863 browser_window->browser(), 864 p1600x1200, 865 p1600x1200); 866#if defined(OS_WIN) 867 EXPECT_EQ(window_show_state, ui::SHOW_STATE_MAXIMIZED); 868#else 869 EXPECT_EQ(window_show_state, ui::SHOW_STATE_DEFAULT); 870#endif 871 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, 875 BOTH, 876 browser_window->browser(), 877 p1600x1200, 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, 882 BOTH, 883 browser_window->browser(), 884 p1600x1200, 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, 889 BOTH, 890 browser_window->browser(), 891 p1600x1200, 892 p1600x1200), ui::SHOW_STATE_MAXIMIZED); 893 894 // Check that setting the maximized command line option is forcing the 895 // maximized state. 896 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kStartMaximized); 897 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, 901 BOTH, 902 browser_window->browser(), 903 p1600x1200, 904 p1600x1200), ui::SHOW_STATE_MAXIMIZED); 905 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, 909 BOTH, 910 browser_popup->browser(), 911 p1600x1200, 912 p1600x1200), ui::SHOW_STATE_NORMAL); 913} 914 915TEST_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)); 922 923 gfx::Rect display_bounds = ash::Shell::GetInstance()->GetScreen()-> 924 GetPrimaryDisplay().bounds(); 925 gfx::Rect specified_bounds = display_bounds; 926 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; 930 gfx::Rect bounds; 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)); 937 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()); 946} 947 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. 952TEST_F(WindowSizerAshTest, DefaultBoundsInTargetDisplay) { 953 if (!SupportsMultipleDisplays() || !chrome::ShouldOpenAshOnStartup()) 954 return; 955 UpdateDisplay("500x500,600x600"); 956 { 957 aura::Window* first_root = 958 ash::Shell::GetAllRootWindows()[0]; 959 ash::ScopedTargetRootWindow tmp(first_root); 960 gfx::Rect bounds; 961 ui::WindowShowState show_state; 962 WindowSizer::GetBrowserWindowBoundsAndShowState( 963 std::string(), 964 gfx::Rect(), 965 NULL, 966 &bounds, 967 &show_state); 968 EXPECT_TRUE(first_root->GetBoundsInScreen().Contains(bounds)); 969 } 970 { 971 aura::Window* second_root = 972 ash::Shell::GetAllRootWindows()[1]; 973 ash::ScopedTargetRootWindow tmp(second_root); 974 gfx::Rect bounds; 975 ui::WindowShowState show_state; 976 WindowSizer::GetBrowserWindowBoundsAndShowState( 977 std::string(), 978 gfx::Rect(), 979 NULL, 980 &bounds, 981 &show_state); 982 EXPECT_TRUE(second_root->GetBoundsInScreen().Contains(bounds)); 983 } 984} 985 986TEST_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; 991 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 997 // last show state. 998 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, 999 GetWindowShowState(ui::SHOW_STATE_DEFAULT, 1000 ui::SHOW_STATE_NORMAL, 1001 BOTH, 1002 trusted_popup->browser(), 1003 p1280x1024, 1004 p1600x1200)); 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, 1009 BOTH, 1010 trusted_popup->browser(), 1011 p1600x1200, 1012 p1600x1200)); 1013} 1014