window_sizer_ash_unittest.cc revision 424c4d7b64af9d0d8fd9624f381f469654d5e3d2
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/screen_ash.h"
6#include "ash/shell.h"
7#include "ash/test/ash_test_base.h"
8#include "ash/test/test_shell_delegate.h"
9#include "ash/wm/window_resizer.h"
10#include "ash/wm/window_util.h"
11#include "base/compiler_specific.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/window_sizer/window_sizer_common_unittest.h"
14#include "chrome/common/chrome_switches.h"
15#include "chrome/test/base/testing_profile.h"
16#include "content/public/test/render_view_test.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "ui/aura/client/activation_client.h"
19#include "ui/aura/client/aura_constants.h"
20#include "ui/aura/env.h"
21#include "ui/aura/root_window.h"
22#include "ui/aura/test/test_windows.h"
23
24typedef ash::test::AshTestBase WindowSizerAshTest;
25
26namespace {
27
28// A browser window proxy which is able to associate an aura native window with
29// it.
30class TestBrowserWindowAura : public TestBrowserWindow {
31 public:
32  // |native_window| will still be owned by the caller after the constructor
33  // was called.
34  explicit TestBrowserWindowAura(aura::Window* native_window)
35      : native_window_(native_window) {
36  }
37  virtual ~TestBrowserWindowAura() {}
38
39  // TestBrowserWindow overrides:
40  virtual void Show() OVERRIDE {
41    native_window_->Show();
42    Activate();
43  }
44  virtual void Hide() OVERRIDE {
45    native_window_->Hide();
46  }
47  virtual void Activate() OVERRIDE {
48    GetActivationClient(
49        native_window_->GetRootWindow())->ActivateWindow(native_window_.get());
50  }
51  virtual gfx::NativeWindow GetNativeWindow() OVERRIDE {
52    return native_window_.get();
53  }
54  virtual gfx::Rect GetBounds() const OVERRIDE {
55    return native_window_->bounds();
56  }
57
58  Browser* browser() { return browser_.get(); }
59
60  void CreateBrowser(const Browser::CreateParams& params) {
61    Browser::CreateParams create_params = params;
62    create_params.window = this;
63    browser_.reset(new Browser(create_params));
64    if (browser_->is_type_tabbed() || browser_->is_app())
65      ash::wm::SetWindowPositionManaged(native_window_.get(), true);
66  }
67
68 private:
69  scoped_ptr<Browser> browser_;
70  scoped_ptr<aura::Window> native_window_;
71
72  DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura);
73};
74
75int AlignToGridRoundDown(int location, int grid_size) {
76  if (grid_size <= 1 || location % grid_size == 0)
77    return location;
78  return location / grid_size * grid_size;
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// Test that the window is sized appropriately for the first run experience
96// where the default window bounds calculation is invoked.
97TEST_F(WindowSizerAshTest, DefaultSizeCase) {
98  int grid = WindowSizer::kDesktopBorderSize;
99  { // 4:3 monitor case, 1024x768, no taskbar
100    gfx::Rect window_bounds;
101    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), gfx::Rect(),
102                    gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
103    EXPECT_EQ(gfx::Rect(WindowSizer::kDesktopBorderSize,
104                        WindowSizer::kDesktopBorderSize,
105                        1024 - WindowSizer::kDesktopBorderSize * 2,
106                        768 - WindowSizer::kDesktopBorderSize),
107              window_bounds);
108  }
109
110  { // 4:3 monitor case, 1024x768, taskbar on bottom
111    gfx::Rect window_bounds;
112    GetWindowBounds(p1024x768, taskbar_bottom_work_area, gfx::Rect(),
113                    gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
114                    &window_bounds);
115    EXPECT_EQ(gfx::Rect(WindowSizer::kDesktopBorderSize,
116                        WindowSizer::kDesktopBorderSize,
117                        1024 - WindowSizer::kDesktopBorderSize * 2,
118                        AlignToGridRoundDown(
119                            taskbar_bottom_work_area.height() -
120                            WindowSizer::kDesktopBorderSize, grid)),
121                        window_bounds);
122  }
123
124  { // 4:3 monitor case, 1024x768, taskbar on right
125    gfx::Rect window_bounds;
126    GetWindowBounds(p1024x768, taskbar_right_work_area, gfx::Rect(),
127                    gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
128                    &window_bounds);
129    EXPECT_EQ(gfx::Rect(WindowSizer::kDesktopBorderSize,
130                        WindowSizer::kDesktopBorderSize,
131                        AlignToGridRoundDown(
132                            taskbar_right_work_area.width() -
133                            WindowSizer::kDesktopBorderSize * 2, grid),
134                        768 - WindowSizer::kDesktopBorderSize),
135              window_bounds);
136  }
137
138  { // 4:3 monitor case, 1024x768, taskbar on left
139    gfx::Rect window_bounds;
140    GetWindowBounds(p1024x768, taskbar_left_work_area, gfx::Rect(),
141                    gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
142                    &window_bounds);
143    EXPECT_EQ(gfx::Rect(taskbar_left_work_area.x() +
144                          WindowSizer::kDesktopBorderSize,
145                        WindowSizer::kDesktopBorderSize,
146                        AlignToGridRoundDown(
147                            taskbar_left_work_area.width() -
148                        WindowSizer::kDesktopBorderSize * 2, grid),
149                            AlignToGridRoundDown(
150                            taskbar_left_work_area.height() -
151                            WindowSizer::kDesktopBorderSize, grid)),
152              window_bounds);
153  }
154
155  { // 4:3 monitor case, 1024x768, taskbar on top
156    gfx::Rect window_bounds;
157    GetWindowBounds(p1024x768, taskbar_top_work_area, gfx::Rect(),
158                    gfx::Rect(), gfx::Rect(), DEFAULT, NULL, gfx::Rect(),
159                    &window_bounds);
160    EXPECT_EQ(gfx::Rect(WindowSizer::kDesktopBorderSize,
161                        taskbar_top_work_area.y() +
162                          WindowSizer::kDesktopBorderSize,
163                        1024 - WindowSizer::kDesktopBorderSize * 2,
164                        AlignToGridRoundDown(
165                            taskbar_top_work_area.height() -
166                            WindowSizer::kDesktopBorderSize, grid)),
167              window_bounds);
168  }
169
170  { // 4:3 monitor case, 1280x1024
171    gfx::Rect window_bounds;
172    GetWindowBounds(p1280x1024, p1280x1024, gfx::Rect(), gfx::Rect(),
173                    gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
174    EXPECT_EQ(gfx::Rect((1280 - WindowSizer::kMaximumWindowWidth) / 2,
175                        WindowSizer::kDesktopBorderSize,
176                        WindowSizer::kMaximumWindowWidth,
177                        1024 - WindowSizer::kDesktopBorderSize),
178              window_bounds);
179  }
180
181  { // 4:3 monitor case, 1600x1200
182    gfx::Rect window_bounds;
183    GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(), gfx::Rect(),
184                    gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
185    EXPECT_EQ(gfx::Rect((1600 - WindowSizer::kMaximumWindowWidth) / 2,
186                        WindowSizer::kDesktopBorderSize,
187                        WindowSizer::kMaximumWindowWidth,
188                        1200 - WindowSizer::kDesktopBorderSize),
189              window_bounds);
190  }
191
192  { // 16:10 monitor case, 1680x1050
193    gfx::Rect window_bounds;
194    GetWindowBounds(p1680x1050, p1680x1050, gfx::Rect(), gfx::Rect(),
195                    gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
196    EXPECT_EQ(gfx::Rect((1680 - WindowSizer::kMaximumWindowWidth) / 2,
197                        WindowSizer::kDesktopBorderSize,
198                        WindowSizer::kMaximumWindowWidth,
199                        AlignToGridRoundDown(
200                            1050 - WindowSizer::kDesktopBorderSize,
201                            grid)),
202              window_bounds);
203  }
204
205  { // 16:10 monitor case, 1920x1200
206    gfx::Rect window_bounds;
207    GetWindowBounds(p1920x1200, p1920x1200, gfx::Rect(), gfx::Rect(),
208                    gfx::Rect(), DEFAULT, NULL, gfx::Rect(), &window_bounds);
209    EXPECT_EQ(gfx::Rect((1920 - WindowSizer::kMaximumWindowWidth) / 2,
210                        WindowSizer::kDesktopBorderSize,
211                        WindowSizer::kMaximumWindowWidth,
212                        1200 - WindowSizer::kDesktopBorderSize),
213              window_bounds);
214  }
215}
216
217// Test that the next opened window is positioned appropriately given the
218// bounds of an existing window of the same type.
219TEST_F(WindowSizerAshTest, LastWindowBoundsCase) {
220  { // normal, in the middle of the screen somewhere.
221    gfx::Rect window_bounds;
222    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
223                    gfx::Rect(WindowSizer::kDesktopBorderSize,
224                              WindowSizer::kDesktopBorderSize, 500, 400),
225                    gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
226                    &window_bounds);
227    EXPECT_EQ(gfx::Rect(kWindowTilePixels + WindowSizer::kDesktopBorderSize,
228                        kWindowTilePixels + WindowSizer::kDesktopBorderSize,
229                        500, 400).ToString(),
230              window_bounds.ToString());
231  }
232
233  { // taskbar on top.
234    gfx::Rect window_bounds;
235    GetWindowBounds(p1024x768, taskbar_top_work_area, gfx::Rect(),
236                    gfx::Rect(WindowSizer::kDesktopBorderSize,
237                              WindowSizer::kDesktopBorderSize, 500, 400),
238                    gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
239                    &window_bounds);
240    EXPECT_EQ(gfx::Rect(kWindowTilePixels + WindowSizer::kDesktopBorderSize,
241                        std::max(kWindowTilePixels +
242                                 WindowSizer::kDesktopBorderSize,
243                                 34 /* toolbar height */),
244                        500, 400).ToString(), window_bounds.ToString());
245  }
246
247  { // Too small to satisify the minimum visibility condition.
248    gfx::Rect window_bounds;
249    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
250                    gfx::Rect(WindowSizer::kDesktopBorderSize,
251                              WindowSizer::kDesktopBorderSize, 29, 29),
252                    gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
253                    &window_bounds);
254    EXPECT_EQ(gfx::Rect(kWindowTilePixels + WindowSizer::kDesktopBorderSize,
255                        kWindowTilePixels + WindowSizer::kDesktopBorderSize,
256                        30 /* not 29 */,
257                        30 /* not 29 */).ToString(),
258              window_bounds.ToString());
259  }
260
261
262  { // Normal.
263    gfx::Rect window_bounds;
264    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
265                    gfx::Rect(WindowSizer::kDesktopBorderSize,
266                              WindowSizer::kDesktopBorderSize, 500, 400),
267                    gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
268                    &window_bounds);
269    EXPECT_EQ(gfx::Rect(kWindowTilePixels + WindowSizer::kDesktopBorderSize,
270                        kWindowTilePixels + WindowSizer::kDesktopBorderSize,
271                        500, 400).ToString(),
272              window_bounds.ToString());
273  }
274}
275
276// Test that the window opened is sized appropriately given persisted sizes.
277TEST_F(WindowSizerAshTest, PersistedBoundsCase) {
278  { // normal, in the middle of the screen somewhere.
279    gfx::Rect initial_bounds(WindowSizer::kDesktopBorderSize,
280                             WindowSizer::kDesktopBorderSize, 500, 400);
281
282    gfx::Rect window_bounds;
283    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), initial_bounds,
284                    gfx::Rect(), PERSISTED, NULL, gfx::Rect(), &window_bounds);
285    EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
286  }
287
288  { // Normal.
289    gfx::Rect initial_bounds(0, 0, 1024, 768);
290
291    gfx::Rect window_bounds;
292    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(), initial_bounds,
293                    gfx::Rect(), PERSISTED, NULL, gfx::Rect(), &window_bounds);
294    EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
295  }
296
297  { // normal, on non-primary monitor in negative coords.
298    gfx::Rect initial_bounds(-600, 10, 500, 400);
299
300    gfx::Rect window_bounds;
301    GetWindowBounds(p1024x768, p1024x768, left_s1024x768,
302                    initial_bounds, gfx::Rect(), PERSISTED, NULL, gfx::Rect(),
303                    &window_bounds);
304    EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
305  }
306
307  { // normal, on non-primary monitor in negative coords.
308    gfx::Rect initial_bounds(-1024, 0, 1024, 768);
309
310    gfx::Rect window_bounds;
311    GetWindowBounds(p1024x768, p1024x768, left_s1024x768,
312                    initial_bounds, gfx::Rect(), PERSISTED, NULL, gfx::Rect(),
313                    &window_bounds);
314    EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
315  }
316
317  { // Non-primary monitor resoultion has changed, but the monitor still
318    // completely contains the window.
319
320    gfx::Rect initial_bounds(1074, 50, 600, 500);
321
322    gfx::Rect window_bounds;
323    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(1024, 0, 800, 600),
324                    initial_bounds, right_s1024x768, PERSISTED, NULL,
325                    gfx::Rect(), &window_bounds);
326    EXPECT_EQ(initial_bounds.ToString(), window_bounds.ToString());
327  }
328
329  { // Non-primary monitor resoultion has changed, and the window is partially
330    // off-screen.
331
332    gfx::Rect initial_bounds(1274, 50, 600, 500);
333
334    gfx::Rect window_bounds;
335    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(1024, 0, 800, 600),
336                    initial_bounds, right_s1024x768, PERSISTED,
337                    NULL, gfx::Rect(), &window_bounds);
338    EXPECT_EQ("1224,50 600x500", window_bounds.ToString());
339  }
340
341  { // Non-primary monitor resoultion has changed, and the window is now too
342    // large for the monitor.
343
344    gfx::Rect initial_bounds(1274, 50, 900, 700);
345
346    gfx::Rect window_bounds;
347    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(1024, 0, 800, 600),
348                    initial_bounds, right_s1024x768, PERSISTED,
349                    NULL, gfx::Rect(), &window_bounds);
350    EXPECT_EQ("1024,0 800x600", window_bounds.ToString());
351  }
352
353  { // width and height too small
354    gfx::Rect window_bounds;
355    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
356                    gfx::Rect(WindowSizer::kDesktopBorderSize,
357                              WindowSizer::kDesktopBorderSize, 29, 29),
358                    gfx::Rect(), PERSISTED, NULL, gfx::Rect(), &window_bounds);
359    EXPECT_EQ(gfx::Rect(WindowSizer::kDesktopBorderSize,
360                        WindowSizer::kDesktopBorderSize,
361                        30 /* not 29 */, 30 /* not 29 */).ToString(),
362              window_bounds.ToString());
363  }
364}
365
366//////////////////////////////////////////////////////////////////////////////
367// The following unittests have different results on Mac/non-Mac because we
368// reposition windows aggressively on Mac.  The *WithAggressiveReposition tests
369// are run on Mac, and the *WithNonAggressiveRepositioning tests are run on
370// other platforms.
371
372TEST_F(WindowSizerAshTest, LastWindowOffscreenWithNonAggressiveRepositioning) {
373  { // taskbar on left.
374    gfx::Rect window_bounds;
375    GetWindowBounds(p1024x768, taskbar_left_work_area, gfx::Rect(),
376                    gfx::Rect(WindowSizer::kDesktopBorderSize,
377                              WindowSizer::kDesktopBorderSize, 500, 400),
378                    gfx::Rect(), LAST_ACTIVE, NULL, gfx::Rect(),
379                    &window_bounds);
380    EXPECT_EQ(gfx::Rect(kWindowTilePixels + WindowSizer::kDesktopBorderSize,
381                        kWindowTilePixels + WindowSizer::kDesktopBorderSize,
382                        500, 400).ToString(),
383              window_bounds.ToString());
384  }
385
386  { // offset would put the new window offscreen at the bottom but the minimum
387    // visibility condition is barely satisfied without relocation.
388    gfx::Rect window_bounds;
389    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
390                    gfx::Rect(10, 728, 500, 400), gfx::Rect(), LAST_ACTIVE,
391                    NULL, gfx::Rect(), &window_bounds);
392    EXPECT_EQ(gfx::Rect(10 + kWindowTilePixels, 738, 500, 400).ToString(),
393              window_bounds.ToString());
394  }
395
396  { // offset would put the new window offscreen at the bottom and the minimum
397    // visibility condition is satisified by relocation.
398    gfx::Rect window_bounds;
399    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
400                    gfx::Rect(10, 729, 500, 400), gfx::Rect(), LAST_ACTIVE,
401                    NULL, gfx::Rect(), &window_bounds);
402    EXPECT_EQ(gfx::Rect(10 + kWindowTilePixels,
403                        738 /* not 739 */,
404                        500,
405                        400).ToString(),
406              window_bounds.ToString());
407  }
408
409  { // offset would put the new window offscreen at the right but the minimum
410    // visibility condition is barely satisfied without relocation.
411    gfx::Rect window_bounds;
412    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
413                    gfx::Rect(984, 10, 500, 400), gfx::Rect(), LAST_ACTIVE,
414                    NULL, gfx::Rect(), &window_bounds);
415    EXPECT_EQ(gfx::Rect(994, 10 + kWindowTilePixels, 500, 400).ToString(),
416              window_bounds.ToString());
417  }
418
419  { // offset would put the new window offscreen at the right and the minimum
420    // visibility condition is satisified by relocation.
421    gfx::Rect window_bounds;
422    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
423                    gfx::Rect(985, 10, 500, 400), gfx::Rect(), LAST_ACTIVE,
424                    NULL, gfx::Rect(), &window_bounds);
425    EXPECT_EQ(gfx::Rect(994 /* not 995 */,
426                        10 + kWindowTilePixels,
427                        500,
428                        400).ToString(),
429              window_bounds.ToString());
430  }
431
432  { // offset would put the new window offscreen at the bottom right and the
433    // minimum visibility condition is satisified by relocation.
434    gfx::Rect window_bounds;
435    GetWindowBounds(p1024x768, p1024x768, gfx::Rect(),
436                    gfx::Rect(985, 729, 500, 400), gfx::Rect(), LAST_ACTIVE,
437                    NULL, gfx::Rect(), &window_bounds);
438    EXPECT_EQ(gfx::Rect(994 /* not 995 */,
439                        738 /* not 739 */,
440                        500,
441                        400).ToString(),
442              window_bounds.ToString());
443  }
444}
445
446// Test the placement of newly created windows.
447TEST_F(WindowSizerAshTest, PlaceNewWindows) {
448  // Create a browser which we can use to pass into the GetWindowBounds
449  // function.
450  scoped_ptr<TestingProfile> profile(new TestingProfile());
451  // Creating a popup handler here to make sure it does not interfere with the
452  // existing windows.
453  Browser::CreateParams native_params(profile.get(),
454                                      chrome::HOST_DESKTOP_TYPE_ASH);
455  scoped_ptr<Browser> browser(
456      chrome::CreateBrowserWithTestWindowForParams(&native_params));
457
458  // Creating a popup handler here to make sure it does not interfere with the
459  // existing windows.
460  scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow(
461      CreateTestWindowInShellWithId(0),
462      gfx::Rect(16, 32, 640, 320),
463      Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH)));
464
465  // Creating a popup to make sure it does not interfere with the positioning.
466  scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow(
467      CreateTestWindowInShellWithId(1),
468      gfx::Rect(16, 32, 128, 256),
469      Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
470                            chrome::HOST_DESKTOP_TYPE_ASH)));
471
472  // Creating a panel to make sure it does not interfere with the positioning.
473  scoped_ptr<BrowserWindow> browser_panel(CreateTestBrowserWindow(
474      CreateTestWindowInShellWithId(2),
475      gfx::Rect(32, 48, 256, 512),
476      Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
477                            chrome::HOST_DESKTOP_TYPE_ASH)));
478  browser_window->Show();
479  { // Make sure that popups do not get changed.
480    gfx::Rect window_bounds;
481    GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(),
482                    gfx::Rect(50, 100, 300, 150), bottom_s1600x1200,
483                    PERSISTED, browser_popup->browser(),
484                    gfx::Rect(), &window_bounds);
485    EXPECT_EQ("50,100 300x150", window_bounds.ToString());
486  }
487
488  browser_window->Hide();
489  { // If a window is there but not shown the persisted default should be used.
490    gfx::Rect window_bounds;
491    GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(),
492                    gfx::Rect(50, 100, 300, 150), bottom_s1600x1200,
493                    PERSISTED, browser.get(), gfx::Rect(), &window_bounds);
494    EXPECT_EQ("50,100 300x150", window_bounds.ToString());
495  }
496
497  { // If a window is there but not shown the default should be returned.
498    gfx::Rect window_bounds;
499    GetWindowBounds(p1600x1200, p1600x1200, gfx::Rect(),
500                    gfx::Rect(), bottom_s1600x1200,
501                    DEFAULT, browser.get(), gfx::Rect(), &window_bounds);
502    // Note: We need to also take the defaults maximum width into account here
503    // since that might get used if the resolution is too big.
504    EXPECT_EQ(gfx::Rect(std::max(WindowSizer::kDesktopBorderSize,
505                                 (1600 - WindowSizer::kMaximumWindowWidth) / 2),
506                        WindowSizer::kDesktopBorderSize,
507                        std::min(WindowSizer::kMaximumWindowWidth,
508                                 1600 - 2 * WindowSizer::kDesktopBorderSize),
509                        1200 - WindowSizer::kDesktopBorderSize).ToString(),
510              window_bounds.ToString());
511  }
512}
513
514// Test the placement of newly created windows on an empty desktop.
515// This test supplements "PlaceNewWindows" by testing the creation of a newly
516// created browser window on an empty desktop.
517TEST_F(WindowSizerAshTest, PlaceNewBrowserWindowOnEmptyDesktop) {
518  // Create a browser which we can use to pass into the GetWindowBounds
519  // function.
520  scoped_ptr<TestingProfile> profile(new TestingProfile());
521  Browser::CreateParams native_params(profile.get(),
522                                      chrome::HOST_DESKTOP_TYPE_ASH);
523  scoped_ptr<Browser> browser(
524      chrome::CreateBrowserWithTestWindowForParams(&native_params));
525
526  // A common screen size for Chrome OS devices where this behavior is
527  // desirable.
528  const gfx::Rect p1366x768(0, 0, 1366, 768);
529
530  // If there is no previous state the window should get maximized if the
531  // screen is less than or equal to our limit (1366 pixels width).
532  gfx::Rect window_bounds;
533  ui::WindowShowState out_show_state1 = ui::SHOW_STATE_DEFAULT;
534  GetWindowBoundsAndShowState(
535      p1366x768,                    // The screen resolution.
536      p1366x768,                    // The monitor work area.
537      gfx::Rect(),                  // The second monitor.
538      gfx::Rect(),                  // The (persisted) bounds.
539      p1366x768,                    // The overall work area.
540      ui::SHOW_STATE_NORMAL,        // The persisted show state.
541      ui::SHOW_STATE_DEFAULT,       // The last show state.
542      DEFAULT,                      // No persisted values.
543      browser.get(),                // Use this browser.
544      gfx::Rect(),                  // Don't request valid bounds.
545      &window_bounds,
546      &out_show_state1);
547  EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, out_show_state1);
548
549  // If there is a stored coordinate however, that should be taken instead.
550  ui::WindowShowState out_show_state2 = ui::SHOW_STATE_DEFAULT;
551  GetWindowBoundsAndShowState(
552      p1366x768,                    // The screen resolution.
553      p1366x768,                    // The monitor work area.
554      gfx::Rect(),                  // The second monitor.
555      gfx::Rect(50, 100, 300, 150), // The (persisted) bounds.
556      p1366x768,                    // The overall work area.
557      ui::SHOW_STATE_NORMAL,        // The persisted show state.
558      ui::SHOW_STATE_DEFAULT,       // The last show state.
559      PERSISTED,                    // Set the persisted values.
560      browser.get(),                // Use this browser.
561      gfx::Rect(),                  // Don't request valid bounds.
562      &window_bounds,
563      &out_show_state2);
564  EXPECT_EQ(ui::SHOW_STATE_NORMAL, out_show_state2);
565  EXPECT_EQ("50,100 300x150", window_bounds.ToString());
566
567  // A larger monitor should not trigger auto-maximize.
568  ui::WindowShowState out_show_state3 = ui::SHOW_STATE_DEFAULT;
569  GetWindowBoundsAndShowState(
570      p1600x1200,                   // The screen resolution.
571      p1600x1200,                   // The monitor work area.
572      gfx::Rect(),                  // The second monitor.
573      gfx::Rect(),                  // The (persisted) bounds.
574      p1600x1200,                   // The overall work area.
575      ui::SHOW_STATE_NORMAL,        // The persisted show state.
576      ui::SHOW_STATE_DEFAULT,       // The last show state.
577      DEFAULT,                      // No persisted values.
578      browser.get(),                // Use this browser.
579      gfx::Rect(),                  // Don't request valid bounds.
580      &window_bounds,
581      &out_show_state3);
582  EXPECT_EQ(ui::SHOW_STATE_DEFAULT, out_show_state3);
583}
584
585#if defined(OS_CHROMEOS)
586#define MAYBE_PlaceNewWindowsOnMultipleDisplays PlaceNewWindowsOnMultipleDisplays
587#else
588// No multiple displays on windows ash.
589#define MAYBE_PlaceNewWindowsOnMultipleDisplays DISABLED_PlaceNewWindowsOnMultipleDisplays
590#endif
591
592// Test the placement of newly created windows on multiple dislays.
593TEST_F(WindowSizerAshTest, MAYBE_PlaceNewWindowsOnMultipleDisplays) {
594  UpdateDisplay("1600x1200,1600x1200");
595  gfx::Rect primary_bounds = ash::Shell::GetInstance()->GetScreen()->
596      GetPrimaryDisplay().bounds();
597  gfx::Rect secondary_bounds = ash::ScreenAsh::GetSecondaryDisplay().bounds();
598
599  ash::Shell::GetInstance()->set_active_root_window(
600      ash::Shell::GetPrimaryRootWindow());
601
602  scoped_ptr<TestingProfile> profile(new TestingProfile());
603
604  // Create browser windows that are used as reference.
605  scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow(
606      CreateTestWindowInShellWithId(0),
607      gfx::Rect(10, 10, 200, 200),
608      Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH)));
609  browser_window->Show();
610  EXPECT_EQ(browser_window->GetNativeWindow()->GetRootWindow(),
611            ash::Shell::GetActiveRootWindow());
612
613  scoped_ptr<BrowserWindow> another_browser_window(CreateTestBrowserWindow(
614      CreateTestWindowInShellWithId(1),
615      gfx::Rect(400, 10, 300, 300),
616      Browser::CreateParams(profile.get(), chrome::HOST_DESKTOP_TYPE_ASH)));
617  another_browser_window->Show();
618
619  // Creating a new window to verify the new placement.
620  scoped_ptr<TestBrowserWindowAura> new_browser_window(CreateTestBrowserWindow(
621      CreateTestWindowInShellWithId(0),
622      gfx::Rect(),
623      Browser::CreateParams(profile.get(),
624                            chrome::HOST_DESKTOP_TYPE_ASH)));
625
626  // Make sure the primary root is active.
627  ASSERT_EQ(ash::Shell::GetPrimaryRootWindow(),
628            ash::Shell::GetActiveRootWindow());
629
630  // First new window should be in the primary.
631  {
632    gfx::Rect window_bounds;
633    GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds,
634                    gfx::Rect(), secondary_bounds,
635                    PERSISTED, new_browser_window->browser(),
636                    gfx::Rect(), &window_bounds);
637    // TODO(oshima): Use exact bounds when the window_sizer_ash is
638    // moved to ash and changed to include the result from
639    // RearrangeVisibleWindowOnShow.
640    EXPECT_TRUE(primary_bounds.Contains(window_bounds));
641  }
642
643  // Move the window to the right side of the secondary display and create a new
644  // window. It should be opened then on the secondary display.
645  {
646    gfx::Display second_display = ash::Shell::GetScreen()->
647        GetDisplayNearestPoint(gfx::Point(1600 + 100,10));
648    browser_window->GetNativeWindow()->SetBoundsInScreen(
649        gfx::Rect(secondary_bounds.CenterPoint().x() - 100, 10, 200, 200),
650        second_display);
651    browser_window->Activate();
652    EXPECT_NE(ash::Shell::GetPrimaryRootWindow(),
653              ash::Shell::GetActiveRootWindow());
654    gfx::Rect window_bounds;
655    GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds,
656                    gfx::Rect(), secondary_bounds,
657                    PERSISTED, new_browser_window->browser(),
658                    gfx::Rect(), &window_bounds);
659    // TODO(oshima): Use exact bounds when the window_sizer_ash is
660    // moved to ash and changed to include the result from
661    // RearrangeVisibleWindowOnShow.
662    EXPECT_TRUE(secondary_bounds.Contains(window_bounds));
663  }
664
665  // Activate another window in the primary display and create a new window.
666  // It should be created in the primary display.
667  {
668    another_browser_window->Activate();
669    EXPECT_EQ(ash::Shell::GetPrimaryRootWindow(),
670              ash::Shell::GetActiveRootWindow());
671
672    gfx::Rect window_bounds;
673    GetWindowBounds(p1600x1200, p1600x1200, secondary_bounds,
674                    gfx::Rect(), secondary_bounds,
675                    PERSISTED, new_browser_window->browser(),
676                    gfx::Rect(), &window_bounds);
677    // TODO(oshima): Use exact bounds when the window_sizer_ash is
678    // moved to ash and changed to include the result from
679    // RearrangeVisibleWindowOnShow.
680    EXPECT_TRUE(primary_bounds.Contains(window_bounds));
681  }
682}
683
684// Test that the show state is properly returned for non default cases.
685TEST_F(WindowSizerAshTest, TestShowState) {
686  scoped_ptr<TestingProfile> profile(new TestingProfile());
687
688  // Creating a browser & window to play with.
689  scoped_ptr<TestBrowserWindowAura> browser_window(CreateTestBrowserWindow(
690      CreateTestWindowInShellWithId(0),
691      gfx::Rect(16, 32, 640, 320),
692      Browser::CreateParams(Browser::TYPE_TABBED, profile.get(),
693                            chrome::HOST_DESKTOP_TYPE_ASH)));
694
695  // Create also a popup browser since that behaves different.
696  scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow(
697      CreateTestWindowInShellWithId(1),
698      gfx::Rect(16, 32, 640, 320),
699      Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
700                            chrome::HOST_DESKTOP_TYPE_ASH)));
701
702  // Tabbed windows should retrieve the saved window state - since there is a
703  // top window.
704  EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
705            GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
706                               ui::SHOW_STATE_NORMAL,
707                               BOTH,
708                               browser_window->browser(),
709                               p1600x1200));
710  EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
711            GetWindowShowState(ui::SHOW_STATE_DEFAULT,
712                               ui::SHOW_STATE_NORMAL,
713                               BOTH,
714                               browser_window->browser(),
715                               p1600x1200));
716  // Non tabbed windows should always follow the window saved visibility state.
717  EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
718            GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
719                               ui::SHOW_STATE_NORMAL,
720                               BOTH,
721                               browser_popup->browser(),
722                               p1600x1200));
723  // The non tabbed window will take the status of the last active of its kind.
724  EXPECT_EQ(ui::SHOW_STATE_NORMAL,
725            GetWindowShowState(ui::SHOW_STATE_DEFAULT,
726                               ui::SHOW_STATE_NORMAL,
727                               BOTH,
728                               browser_popup->browser(),
729                               p1600x1200));
730
731  // Now create a top level window and check again for both. Only the tabbed
732  // window should follow the top level window's state.
733  // Creating a browser & window to play with.
734  scoped_ptr<TestBrowserWindowAura> browser_window2(CreateTestBrowserWindow(
735      CreateTestWindowInShellWithId(3),
736      gfx::Rect(16, 32, 640, 320),
737      Browser::CreateParams(Browser::TYPE_TABBED, profile.get(),
738                            chrome::HOST_DESKTOP_TYPE_ASH)));
739
740  // A tabbed window should now take the top level window state.
741  EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
742            GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
743                               ui::SHOW_STATE_DEFAULT,
744                               BOTH,
745                               browser_window->browser(),
746                               p1600x1200));
747  // Non tabbed windows should always follow the window saved visibility state.
748  EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
749            GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
750                               ui::SHOW_STATE_MINIMIZED,
751                               BOTH,
752                               browser_popup->browser(),
753                               p1600x1200));
754
755  // In smaller screen resolutions we default to maximized if there is no other
756  // window visible.
757  int min_size = WindowSizer::GetForceMaximizedWidthLimit() / 2;
758  if (min_size > 0) {
759    const gfx::Rect tiny_screen(0, 0, min_size, min_size);
760    EXPECT_EQ(ui::SHOW_STATE_DEFAULT,
761              GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
762                                 ui::SHOW_STATE_DEFAULT,
763                                 BOTH,
764                                 browser_window->browser(),
765                                 tiny_screen));
766    browser_window->Hide();
767    EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED,
768              GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
769                                 ui::SHOW_STATE_DEFAULT,
770                                 BOTH,
771                                 browser_window2->browser(),
772                                 tiny_screen));
773
774  }
775}
776
777// Test that the default show state override behavior is properly handled.
778TEST_F(WindowSizerAshTest, TestShowStateDefaults) {
779  // Creating a browser & window to play with.
780  scoped_ptr<TestingProfile> profile(new TestingProfile());
781
782  scoped_ptr<TestBrowserWindowAura> browser_window(CreateTestBrowserWindow(
783      CreateTestWindowInShellWithId(0),
784      gfx::Rect(16, 32, 640, 320),
785      Browser::CreateParams(Browser::TYPE_TABBED, profile.get(),
786                            chrome::HOST_DESKTOP_TYPE_ASH)));
787
788  // Create also a popup browser since that behaves slightly different for
789  // defaults.
790  scoped_ptr<TestBrowserWindowAura> browser_popup(CreateTestBrowserWindow(
791      CreateTestWindowInShellWithId(1),
792      gfx::Rect(16, 32, 128, 256),
793      Browser::CreateParams(Browser::TYPE_POPUP, profile.get(),
794                            chrome::HOST_DESKTOP_TYPE_ASH)));
795
796  // Check that a browser creation state always get used if not given as
797  // SHOW_STATE_DEFAULT.
798  EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
799                               ui::SHOW_STATE_MAXIMIZED,
800                               DEFAULT,
801                               browser_window->browser(),
802                               p1600x1200), ui::SHOW_STATE_DEFAULT);
803  browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_MINIMIZED);
804  EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
805                               ui::SHOW_STATE_MAXIMIZED,
806                               BOTH,
807                               browser_window->browser(),
808                               p1600x1200), ui::SHOW_STATE_MINIMIZED);
809  browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL);
810  EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_MAXIMIZED,
811                               ui::SHOW_STATE_MAXIMIZED,
812                               BOTH,
813                               browser_window->browser(),
814                               p1600x1200), ui::SHOW_STATE_NORMAL);
815  browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_MAXIMIZED);
816  EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL,
817                               ui::SHOW_STATE_NORMAL,
818                               BOTH,
819                               browser_window->browser(),
820                               p1600x1200), ui::SHOW_STATE_MAXIMIZED);
821
822  // Check that setting the maximized command line option is forcing the
823  // maximized state.
824  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kStartMaximized);
825
826  browser_window->browser()->set_initial_show_state(ui::SHOW_STATE_NORMAL);
827  EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL,
828                               ui::SHOW_STATE_NORMAL,
829                               BOTH,
830                               browser_window->browser(),
831                               p1600x1200), ui::SHOW_STATE_MAXIMIZED);
832
833  // The popup should favor the initial show state over the command line.
834  EXPECT_EQ(GetWindowShowState(ui::SHOW_STATE_NORMAL,
835                               ui::SHOW_STATE_NORMAL,
836                               BOTH,
837                               browser_popup->browser(),
838                               p1600x1200), ui::SHOW_STATE_NORMAL);
839}
840