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