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 "chrome/browser/ui/window_sizer/window_sizer_common_unittest.h" 6 7 #include "ash/wm/window_resizer.h" 8 #include "base/compiler_specific.h" 9 #include "chrome/browser/ui/browser.h" 10 #include "chrome/common/chrome_switches.h" 11 #include "chrome/test/base/testing_profile.h" 12 #include "testing/gtest/include/gtest/gtest.h" 13 14 TestMonitorInfoProvider::TestMonitorInfoProvider() {}; 15 16 TestMonitorInfoProvider::~TestMonitorInfoProvider() {}; 17 18 void TestMonitorInfoProvider::AddMonitor(const gfx::Rect& bounds, 19 const gfx::Rect& work_area) { 20 DCHECK(bounds.Contains(work_area)); 21 monitor_bounds_.push_back(bounds); 22 work_areas_.push_back(work_area); 23 } 24 25 // Overridden from WindowSizer::MonitorInfoProvider: 26 gfx::Rect TestMonitorInfoProvider::GetPrimaryDisplayWorkArea() const { 27 return work_areas_[0]; 28 } 29 30 gfx::Rect TestMonitorInfoProvider::GetPrimaryDisplayBounds() const { 31 return monitor_bounds_[0]; 32 } 33 34 gfx::Rect TestMonitorInfoProvider::GetMonitorWorkAreaMatching( 35 const gfx::Rect& match_rect) const { 36 return work_areas_[GetMonitorIndexMatchingBounds(match_rect)]; 37 } 38 39 size_t TestMonitorInfoProvider::GetMonitorIndexMatchingBounds( 40 const gfx::Rect& match_rect) const { 41 int max_area = 0; 42 size_t max_area_index = 0; 43 // Loop through all the monitors, finding the one that intersects the 44 // largest area of the supplied match rect. 45 for (size_t i = 0; i < work_areas_.size(); ++i) { 46 gfx::Rect overlap = work_areas_[i]; 47 overlap.Intersect(match_rect); 48 int area = overlap.width() * overlap.height(); 49 if (area > max_area) { 50 max_area = area; 51 max_area_index = i; 52 } 53 } 54 return max_area_index; 55 } 56 57 TestStateProvider::TestStateProvider(): 58 has_persistent_data_(false), 59 persistent_show_state_(ui::SHOW_STATE_DEFAULT), 60 has_last_active_data_(false), 61 last_active_show_state_(ui::SHOW_STATE_DEFAULT) { 62 } 63 64 void TestStateProvider::SetPersistentState(const gfx::Rect& bounds, 65 const gfx::Rect& work_area, 66 ui::WindowShowState show_state, 67 bool has_persistent_data) { 68 persistent_bounds_ = bounds; 69 persistent_work_area_ = work_area; 70 persistent_show_state_ = show_state; 71 has_persistent_data_ = has_persistent_data; 72 } 73 74 void TestStateProvider::SetLastActiveState(const gfx::Rect& bounds, 75 ui::WindowShowState show_state, 76 bool has_last_active_data) { 77 last_active_bounds_ = bounds; 78 last_active_show_state_ = show_state; 79 has_last_active_data_ = has_last_active_data; 80 } 81 82 bool TestStateProvider::GetPersistentState( 83 gfx::Rect* bounds, 84 gfx::Rect* saved_work_area, 85 ui::WindowShowState* show_state) const { 86 DCHECK(show_state); 87 *bounds = persistent_bounds_; 88 *saved_work_area = persistent_work_area_; 89 if (*show_state == ui::SHOW_STATE_DEFAULT) 90 *show_state = persistent_show_state_; 91 return has_persistent_data_; 92 } 93 94 bool TestStateProvider::GetLastActiveWindowState( 95 gfx::Rect* bounds, 96 ui::WindowShowState* show_state) const { 97 DCHECK(show_state); 98 *bounds = last_active_bounds_; 99 if (*show_state == ui::SHOW_STATE_DEFAULT) 100 *show_state = last_active_show_state_; 101 return has_last_active_data_; 102 } 103 104 int kWindowTilePixels = WindowSizer::kWindowTilePixels; 105 106 // The window sizer commonly used test functions. 107 void GetWindowBoundsAndShowState( 108 const gfx::Rect& monitor1_bounds, 109 const gfx::Rect& monitor1_work_area, 110 const gfx::Rect& monitor2_bounds, 111 const gfx::Rect& bounds, 112 const gfx::Rect& work_area, 113 ui::WindowShowState show_state_persisted, 114 ui::WindowShowState show_state_last, 115 Source source, 116 const Browser* browser, 117 const gfx::Rect& passed_in, 118 gfx::Rect* out_bounds, 119 ui::WindowShowState* out_show_state) { 120 DCHECK(out_show_state); 121 TestMonitorInfoProvider* mip = new TestMonitorInfoProvider; 122 mip->AddMonitor(monitor1_bounds, monitor1_work_area); 123 if (!monitor2_bounds.IsEmpty()) 124 mip->AddMonitor(monitor2_bounds, monitor2_bounds); 125 TestStateProvider* sp = new TestStateProvider; 126 if (source == PERSISTED || source == BOTH) 127 sp->SetPersistentState(bounds, work_area, show_state_persisted, true); 128 if (source == LAST_ACTIVE || source == BOTH) 129 sp->SetLastActiveState(bounds, show_state_last, true); 130 131 WindowSizer sizer(sp, mip, browser); 132 sizer.DetermineWindowBoundsAndShowState(passed_in, 133 out_bounds, 134 out_show_state); 135 } 136 137 void GetWindowBounds(const gfx::Rect& monitor1_bounds, 138 const gfx::Rect& monitor1_work_area, 139 const gfx::Rect& monitor2_bounds, 140 const gfx::Rect& bounds, 141 const gfx::Rect& work_area, 142 Source source, 143 const Browser* browser, 144 const gfx::Rect& passed_in, 145 gfx::Rect* out_bounds) { 146 ui::WindowShowState out_show_state = ui::SHOW_STATE_DEFAULT; 147 GetWindowBoundsAndShowState( 148 monitor1_bounds, monitor1_work_area, monitor2_bounds, bounds, work_area, 149 ui::SHOW_STATE_DEFAULT, ui::SHOW_STATE_DEFAULT, source, browser, 150 passed_in, out_bounds, &out_show_state); 151 } 152 153 ui::WindowShowState GetWindowShowState( 154 ui::WindowShowState show_state_persisted, 155 ui::WindowShowState show_state_last, 156 Source source, 157 const Browser* browser, 158 const gfx::Rect& display_config) { 159 gfx::Rect bounds = display_config; 160 gfx::Rect work_area = display_config; 161 TestMonitorInfoProvider* mip = new TestMonitorInfoProvider; 162 mip->AddMonitor(display_config, display_config); 163 TestStateProvider* sp = new TestStateProvider; 164 if (source == PERSISTED || source == BOTH) 165 sp->SetPersistentState(bounds, work_area, show_state_persisted, true); 166 if (source == LAST_ACTIVE || source == BOTH) 167 sp->SetLastActiveState(bounds, show_state_last, true); 168 169 WindowSizer sizer(sp, mip, browser); 170 171 ui::WindowShowState out_show_state = ui::SHOW_STATE_DEFAULT; 172 gfx::Rect out_bounds; 173 sizer.DetermineWindowBoundsAndShowState( 174 gfx::Rect(), 175 &out_bounds, 176 &out_show_state); 177 return out_show_state; 178 } 179 180 #if !defined(OS_MACOSX) 181 TEST(WindowSizerTestCommon, PersistedWindowOffscreenWithNonAggressiveRepositioning) { 182 { // off the left but the minimum visibility condition is barely satisfied 183 // without relocaiton. 184 gfx::Rect initial_bounds(-470, 50, 500, 400); 185 186 gfx::Rect window_bounds; 187 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 188 initial_bounds, gfx::Rect(), PERSISTED, 189 NULL, gfx::Rect(), &window_bounds); 190 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString()); 191 } 192 193 { // off the left and the minimum visibility condition is satisfied by 194 // relocation. 195 gfx::Rect window_bounds; 196 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 197 gfx::Rect(-471, 50, 500, 400), gfx::Rect(), PERSISTED, 198 NULL, gfx::Rect(), &window_bounds); 199 EXPECT_EQ(gfx::Rect(-470 /* not -471 */, 50, 500, 400).ToString(), 200 window_bounds.ToString()); 201 } 202 203 { // off the top 204 gfx::Rect initial_bounds(50, -370, 500, 400); 205 206 gfx::Rect window_bounds; 207 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 208 gfx::Rect(50, -370, 500, 400), gfx::Rect(), PERSISTED, 209 NULL, gfx::Rect(), &window_bounds); 210 EXPECT_EQ("50,0 500x400", window_bounds.ToString()); 211 } 212 213 { // off the right but the minimum visibility condition is barely satisified 214 // without relocation. 215 gfx::Rect initial_bounds(994, 50, 500, 400); 216 217 gfx::Rect window_bounds; 218 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 219 initial_bounds, gfx::Rect(), PERSISTED, 220 NULL, gfx::Rect(), &window_bounds); 221 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString()); 222 } 223 224 { // off the right and the minimum visibility condition is satisified by 225 // relocation. 226 gfx::Rect window_bounds; 227 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 228 gfx::Rect(995, 50, 500, 400), gfx::Rect(), PERSISTED, 229 NULL, gfx::Rect(), &window_bounds); 230 EXPECT_EQ(gfx::Rect(994 /* not 995 */, 50, 500, 400).ToString(), 231 window_bounds.ToString()); 232 } 233 234 { // off the bottom but the minimum visibility condition is barely satisified 235 // without relocation. 236 gfx::Rect initial_bounds(50, 738, 500, 400); 237 238 gfx::Rect window_bounds; 239 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 240 initial_bounds, gfx::Rect(), PERSISTED, 241 NULL, gfx::Rect(), &window_bounds); 242 EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString()); 243 } 244 245 { // off the bottom and the minimum visibility condition is satisified by 246 // relocation. 247 gfx::Rect window_bounds; 248 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 249 gfx::Rect(50, 739, 500, 400), gfx::Rect(), PERSISTED, 250 NULL, gfx::Rect(), &window_bounds); 251 EXPECT_EQ(gfx::Rect(50, 738 /* not 739 */, 500, 400).ToString(), 252 window_bounds.ToString()); 253 } 254 255 { // off the topleft 256 gfx::Rect window_bounds; 257 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 258 gfx::Rect(-471, -371, 500, 400), gfx::Rect(), PERSISTED, 259 NULL, gfx::Rect(), &window_bounds); 260 EXPECT_EQ(gfx::Rect(-470 /* not -471 */, 0, 500, 400).ToString(), 261 window_bounds.ToString()); 262 } 263 264 { // off the topright and the minimum visibility condition is satisified by 265 // relocation. 266 gfx::Rect window_bounds; 267 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 268 gfx::Rect(995, -371, 500, 400), gfx::Rect(), PERSISTED, 269 NULL, gfx::Rect(), &window_bounds); 270 EXPECT_EQ(gfx::Rect(994 /* not 995 */, 0, 500, 400).ToString(), 271 window_bounds.ToString()); 272 } 273 274 { // off the bottomleft and the minimum visibility condition is satisified by 275 // relocation. 276 gfx::Rect window_bounds; 277 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 278 gfx::Rect(-471, 739, 500, 400), gfx::Rect(), PERSISTED, 279 NULL, gfx::Rect(), &window_bounds); 280 EXPECT_EQ(gfx::Rect(-470 /* not -471 */, 281 738 /* not 739 */, 282 500, 283 400).ToString(), 284 window_bounds.ToString()); 285 } 286 287 { // off the bottomright and the minimum visibility condition is satisified by 288 // relocation. 289 gfx::Rect window_bounds; 290 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 291 gfx::Rect(995, 739, 500, 400), gfx::Rect(), PERSISTED, 292 NULL, gfx::Rect(), &window_bounds); 293 EXPECT_EQ(gfx::Rect(994 /* not 995 */, 294 738 /* not 739 */, 295 500, 296 400).ToString(), 297 window_bounds.ToString()); 298 } 299 300 { // entirely off left 301 gfx::Rect window_bounds; 302 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 303 gfx::Rect(-700, 50, 500, 400), gfx::Rect(), PERSISTED, 304 NULL, gfx::Rect(), &window_bounds); 305 EXPECT_EQ(gfx::Rect(-470 /* not -700 */, 50, 500, 400).ToString(), 306 window_bounds.ToString()); 307 } 308 309 { // entirely off left (monitor was detached since last run) 310 gfx::Rect window_bounds; 311 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 312 gfx::Rect(-700, 50, 500, 400), left_s1024x768, PERSISTED, 313 NULL, gfx::Rect(), &window_bounds); 314 EXPECT_EQ("0,50 500x400", window_bounds.ToString()); 315 } 316 317 { // entirely off top 318 gfx::Rect window_bounds; 319 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 320 gfx::Rect(50, -500, 500, 400), gfx::Rect(), PERSISTED, 321 NULL, gfx::Rect(), &window_bounds); 322 EXPECT_EQ("50,0 500x400", window_bounds.ToString()); 323 } 324 325 { // entirely off top (monitor was detached since last run) 326 gfx::Rect window_bounds; 327 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 328 gfx::Rect(50, -500, 500, 400), top_s1024x768, 329 PERSISTED, NULL, gfx::Rect(), &window_bounds); 330 EXPECT_EQ("50,0 500x400", window_bounds.ToString()); 331 } 332 333 { // entirely off right 334 gfx::Rect window_bounds; 335 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 336 gfx::Rect(1200, 50, 500, 400), gfx::Rect(), PERSISTED, 337 NULL, gfx::Rect(), &window_bounds); 338 EXPECT_EQ(gfx::Rect(994 /* not 1200 */, 50, 500, 400).ToString(), 339 window_bounds.ToString()); 340 } 341 342 { // entirely off right (monitor was detached since last run) 343 gfx::Rect window_bounds; 344 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 345 gfx::Rect(1200, 50, 500, 400), right_s1024x768, 346 PERSISTED, NULL, gfx::Rect(), &window_bounds); 347 EXPECT_EQ("524,50 500x400", window_bounds.ToString()); 348 } 349 350 { // entirely off bottom 351 gfx::Rect window_bounds; 352 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 353 gfx::Rect(50, 800, 500, 400), gfx::Rect(), PERSISTED, 354 NULL, gfx::Rect(), &window_bounds); 355 EXPECT_EQ(gfx::Rect(50, 738 /* not 800 */, 500, 400).ToString(), 356 window_bounds.ToString()); 357 } 358 359 { // entirely off bottom (monitor was detached since last run) 360 gfx::Rect window_bounds; 361 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), 362 gfx::Rect(50, 800, 500, 400), bottom_s1024x768, 363 PERSISTED, NULL, gfx::Rect(), &window_bounds); 364 EXPECT_EQ("50,368 500x400", window_bounds.ToString()); 365 } 366 } 367 368 // Test that the window is sized appropriately for the first run experience 369 // where the default window bounds calculation is invoked. 370 TEST(WindowSizerTestCommon, AdjustFitSize) { 371 { // Check that the window gets resized to the screen. 372 gfx::Rect window_bounds; 373 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), gfx::Rect(), 374 gfx::Rect(), DEFAULT, NULL, 375 gfx::Rect(-10, -10, 1024 + 20, 768 + 20), &window_bounds); 376 EXPECT_EQ("0,0 1024x768", window_bounds.ToString()); 377 } 378 379 { // Check that a window which hangs out of the screen get moved back in. 380 gfx::Rect window_bounds; 381 GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), gfx::Rect(), 382 gfx::Rect(), DEFAULT, NULL, 383 gfx::Rect(1020, 700, 100, 100), &window_bounds); 384 EXPECT_EQ("924,668 100x100", window_bounds.ToString()); 385 } 386 } 387 388 #endif // defined(OS_MACOSX) 389