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.
5 #include "ash/wm/window_positioner.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 "base/logging.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/host_desktop.h"
15 #include "chrome/test/base/test_browser_window_aura.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "content/public/test/render_view_test.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/aura/env.h"
20 #include "ui/aura/test/test_windows.h"
21 #include "ui/aura/window_event_dispatcher.h"
22 #include "ui/gfx/screen.h"
27 // A test class for preparing window positioner tests - it creates a testing
28 // base by adding a window and a popup which can be independently
29 // positioned to see where the positioner will place the window.
30 class WindowPositionerTest
: public AshTestBase
{
32 WindowPositionerTest();
34 void SetUp() override
;
35 void TearDown() override
;
38 aura::Window
* window() { return browser_
->window()->GetNativeWindow(); }
39 aura::Window
* popup() { return browser_popup_
->window()->GetNativeWindow(); }
41 WindowPositioner
* window_positioner() { return window_positioner_
.get(); }
43 // The positioner & desktop's used grid alignment size.
47 scoped_ptr
<WindowPositioner
> window_positioner_
;
49 TestingProfile profile_
;
51 scoped_ptr
<Browser
> browser_
;
52 scoped_ptr
<Browser
> browser_popup_
;
54 DISALLOW_COPY_AND_ASSIGN(WindowPositionerTest
);
57 WindowPositionerTest::WindowPositionerTest()
58 : grid_size_(WindowPositioner::kMinimumWindowOffset
) {}
60 void WindowPositionerTest::SetUp() {
62 // Create some default dummy windows.
63 scoped_ptr
<aura::Window
> dummy_window(CreateTestWindowInShellWithId(0));
64 dummy_window
->SetBounds(gfx::Rect(16, 32, 640, 320));
65 scoped_ptr
<aura::Window
> dummy_popup(CreateTestWindowInShellWithId(1));
66 dummy_popup
->SetBounds(gfx::Rect(16, 32, 128, 256));
68 // Create a browser for the window.
69 Browser::CreateParams
window_params(&profile_
,
70 chrome::HOST_DESKTOP_TYPE_ASH
);
71 browser_
= chrome::CreateBrowserWithAuraTestWindowForParams(
72 dummy_window
.Pass(), &window_params
);
74 // Creating a browser for the popup.
75 Browser::CreateParams
popup_params(Browser::TYPE_POPUP
, &profile_
,
76 chrome::HOST_DESKTOP_TYPE_ASH
);
77 browser_popup_
= chrome::CreateBrowserWithAuraTestWindowForParams(
78 dummy_popup
.Pass(), &popup_params
);
80 // We hide all windows upon start - each user is required to set it up
84 window_positioner_
.reset(new WindowPositioner());
87 void WindowPositionerTest::TearDown() {
88 // Since the AuraTestBase is needed to create our assets, we have to
89 // also delete them before we tear it down.
91 browser_popup_
.reset();
92 window_positioner_
.reset();
93 AshTestBase::TearDown();
96 int AlignToGridRoundDown(int location
, int grid_size
) {
97 if (grid_size
<= 1 || location
% grid_size
== 0)
99 return location
/ grid_size
* grid_size
;
102 TEST_F(WindowPositionerTest
, cascading
) {
103 const gfx::Rect work_area
=
104 Shell::GetScreen()->GetPrimaryDisplay().work_area();
106 // First see that the window will cascade down when there is no space.
107 window()->SetBounds(work_area
);
110 gfx::Rect
popup_position(0, 0, 200, 200);
111 // Check that it gets cascaded.
112 gfx::Rect cascade_1
= window_positioner()->GetPopupPosition(popup_position
);
113 EXPECT_EQ(gfx::Rect(work_area
.x() + grid_size_
, work_area
.y() + grid_size_
,
114 popup_position
.width(), popup_position
.height()),
117 gfx::Rect cascade_2
= window_positioner()->GetPopupPosition(popup_position
);
118 EXPECT_EQ(gfx::Rect(work_area
.x() + 2 * grid_size_
,
119 work_area
.y() + 2 * grid_size_
,
120 popup_position
.width(), popup_position
.height()),
123 // Check that if there is even only a pixel missing it will cascade.
124 window()->SetBounds(gfx::Rect(work_area
.x() + popup_position
.width() - 1,
125 work_area
.y() + popup_position
.height() - 1,
127 2 * (popup_position
.width() - 1),
129 2 * (popup_position
.height() - 1)));
131 gfx::Rect cascade_3
= window_positioner()->GetPopupPosition(popup_position
);
132 EXPECT_EQ(gfx::Rect(work_area
.x() + 3 * grid_size_
,
133 work_area
.y() + 3 * grid_size_
,
134 popup_position
.width(), popup_position
.height()),
137 // Check that we overflow into the next line when we do not fit anymore in Y.
138 gfx::Rect
popup_position_4(0, 0, 200,
140 (cascade_3
.y() - work_area
.y()));
141 gfx::Rect cascade_4
=
142 window_positioner()->GetPopupPosition(popup_position_4
);
143 EXPECT_EQ(gfx::Rect(work_area
.x() + 2 * grid_size_
,
144 work_area
.y() + grid_size_
,
145 popup_position_4
.width(), popup_position_4
.height()),
148 // Check that we overflow back to the first possible location if we overflow
150 gfx::Rect
popup_position_5(0, 0,
151 work_area
.width() + 1 -
152 (cascade_4
.x() - work_area
.x()),
154 (2 * grid_size_
- work_area
.y()));
155 gfx::Rect cascade_5
=
156 window_positioner()->GetPopupPosition(popup_position_5
);
157 EXPECT_EQ(gfx::Rect(work_area
.x() + grid_size_
,
158 work_area
.y() + grid_size_
,
159 popup_position_5
.width(), popup_position_5
.height()),
163 TEST_F(WindowPositionerTest
, filling
) {
164 const gfx::Rect work_area
=
165 Shell::GetScreen()->GetPrimaryDisplay().work_area();
166 gfx::Rect
popup_position(0, 0, 256, 128);
167 // Leave space on the left and the right and see if we fill top to bottom.
168 window()->SetBounds(gfx::Rect(work_area
.x() + popup_position
.width(),
170 work_area
.width() - 2 * popup_position
.width(),
171 work_area
.height()));
173 // Check that we are positioned in the top left corner.
174 gfx::Rect top_left
= window_positioner()->GetPopupPosition(popup_position
);
175 EXPECT_EQ(gfx::Rect(work_area
.x(), work_area
.y(),
176 popup_position
.width(), popup_position
.height()),
179 // Now block the found location.
180 popup()->SetBounds(top_left
);
182 gfx::Rect mid_left
= window_positioner()->GetPopupPosition(popup_position
);
183 EXPECT_EQ(gfx::Rect(work_area
.x(),
184 AlignToGridRoundDown(
185 work_area
.y() + top_left
.height(), grid_size_
),
186 popup_position
.width(), popup_position
.height()),
189 // Block now everything so that we can only put the popup on the bottom
191 // Note: We need to keep one "grid spacing free" if the window does not
192 // fit into the grid (which is true for 200 height).`
193 popup()->SetBounds(gfx::Rect(work_area
.x(), work_area
.y(),
194 popup_position
.width(),
195 work_area
.height() - popup_position
.height() -
197 gfx::Rect bottom_left
= window_positioner()->GetPopupPosition(
199 EXPECT_EQ(gfx::Rect(work_area
.x(),
200 work_area
.bottom() - popup_position
.height(),
201 popup_position
.width(), popup_position
.height()),
204 // Block now enough to force the right side.
205 popup()->SetBounds(gfx::Rect(work_area
.x(), work_area
.y(),
206 popup_position
.width(),
207 work_area
.height() - popup_position
.height() +
209 gfx::Rect top_right
= window_positioner()->GetPopupPosition(
211 EXPECT_EQ(gfx::Rect(AlignToGridRoundDown(work_area
.right() -
212 popup_position
.width(), grid_size_
),
214 popup_position
.width(), popup_position
.height()),
218 TEST_F(WindowPositionerTest
, biggerThenBorder
) {
219 const gfx::Rect work_area
=
220 Shell::GetScreen()->GetPrimaryDisplay().work_area();
222 gfx::Rect
pop_position(0, 0, work_area
.width(), work_area
.height());
224 // Check that the popup is placed full screen.
225 gfx::Rect full
= window_positioner()->GetPopupPosition(pop_position
);
226 EXPECT_EQ(gfx::Rect(work_area
.x(), work_area
.y(),
227 pop_position
.width(), pop_position
.height()),