1 // Copyright 2014 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/display/display_manager.h"
6 #include "ash/root_window_controller.h"
7 #include "ash/screen_util.h"
9 #include "ash/shell_window_ids.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/wm/window_state.h"
12 #include "base/basictypes.h"
13 #include "base/command_line.h"
14 #include "ui/aura/client/aura_constants.h"
15 #include "ui/aura/window.h"
16 #include "ui/gfx/screen.h"
17 #include "ui/keyboard/keyboard_controller.h"
18 #include "ui/keyboard/keyboard_controller_proxy.h"
19 #include "ui/keyboard/keyboard_switches.h"
20 #include "ui/keyboard/keyboard_util.h"
21 #include "ui/views/widget/widget.h"
22 #include "ui/views/widget/widget_delegate.h"
29 const int kVirtualKeyboardHeight
= 100;
31 // A login implementation of WidgetDelegate.
32 class LoginTestWidgetDelegate
: public views::WidgetDelegate
{
34 explicit LoginTestWidgetDelegate(views::Widget
* widget
) : widget_(widget
) {
36 virtual ~LoginTestWidgetDelegate() {}
38 // Overridden from WidgetDelegate:
39 virtual void DeleteDelegate() OVERRIDE
{
42 virtual views::Widget
* GetWidget() OVERRIDE
{
45 virtual const views::Widget
* GetWidget() const OVERRIDE
{
48 virtual bool CanActivate() const OVERRIDE
{
51 virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE
{
56 views::Widget
* widget_
;
58 DISALLOW_COPY_AND_ASSIGN(LoginTestWidgetDelegate
);
63 class LockLayoutManagerTest
: public AshTestBase
{
65 virtual void SetUp() OVERRIDE
{
66 // Allow a virtual keyboard (and initialize it per default).
67 CommandLine::ForCurrentProcess()->AppendSwitch(
68 keyboard::switches::kEnableVirtualKeyboard
);
70 Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
71 keyboard::KeyboardController::GetInstance());
74 virtual void TearDown() OVERRIDE
{
75 Shell::GetPrimaryRootWindowController()->DeactivateKeyboard(
76 keyboard::KeyboardController::GetInstance());
77 AshTestBase::TearDown();
80 aura::Window
* CreateTestLoginWindow(views::Widget::InitParams params
,
82 aura::Window
* parent
= Shell::GetPrimaryRootWindowController()->
83 GetContainer(ash::kShellWindowId_LockScreenContainer
);
84 params
.parent
= parent
;
85 views::Widget
* widget
= new views::Widget
;
87 params
.delegate
= new LoginTestWidgetDelegate(widget
);
90 aura::Window
* window
= widget
->GetNativeView();
94 // Show or hide the keyboard.
95 void ShowKeyboard(bool show
) {
96 keyboard::KeyboardController
* keyboard
=
97 keyboard::KeyboardController::GetInstance();
98 ASSERT_TRUE(keyboard
);
99 if (show
== keyboard
->keyboard_visible())
103 keyboard
->ShowKeyboard(true);
104 if (keyboard
->proxy()->GetKeyboardWindow()->bounds().height() == 0) {
105 keyboard
->proxy()->GetKeyboardWindow()->SetBounds(
106 keyboard::KeyboardBoundsFromWindowBounds(
107 keyboard
->GetContainerWindow()->bounds(),
108 kVirtualKeyboardHeight
));
111 keyboard
->HideKeyboard(keyboard::KeyboardController::HIDE_REASON_MANUAL
);
114 DCHECK_EQ(show
, keyboard
->keyboard_visible());
118 TEST_F(LockLayoutManagerTest
, NorwmalWindowBoundsArePreserved
) {
119 gfx::Rect screen_bounds
= Shell::GetScreen()->GetPrimaryDisplay().bounds();
121 views::Widget::InitParams
widget_params(
122 views::Widget::InitParams::TYPE_WINDOW
);
123 const gfx::Rect bounds
= gfx::Rect(10, 10, 300, 300);
124 widget_params
.bounds
= bounds
;
125 scoped_ptr
<aura::Window
> window(
126 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
127 EXPECT_EQ(bounds
.ToString(), window
->GetBoundsInScreen().ToString());
129 gfx::Rect work_area
=
130 ScreenUtil::GetDisplayWorkAreaBoundsInParent(window
.get());
131 window
->SetBounds(work_area
);
133 EXPECT_EQ(work_area
.ToString(), window
->GetBoundsInScreen().ToString());
134 EXPECT_NE(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
136 const gfx::Rect bounds2
= gfx::Rect(100, 100, 200, 200);
137 window
->SetBounds(bounds2
);
138 EXPECT_EQ(bounds2
.ToString(), window
->GetBoundsInScreen().ToString());
141 TEST_F(LockLayoutManagerTest
, MaximizedFullscreenWindowBoundsAreEqualToScreen
) {
142 gfx::Rect screen_bounds
= Shell::GetScreen()->GetPrimaryDisplay().bounds();
144 views::Widget::InitParams
widget_params(
145 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
146 widget_params
.show_state
= ui::SHOW_STATE_MAXIMIZED
;
147 const gfx::Rect bounds
= gfx::Rect(10, 10, 300, 300);
148 widget_params
.bounds
= bounds
;
149 // Maximized TYPE_WINDOW_FRAMELESS windows needs a delegate defined otherwise
150 // it won't get initial SetBounds event.
151 scoped_ptr
<aura::Window
> maximized_window(
152 CreateTestLoginWindow(widget_params
, true /* use_delegate */));
154 widget_params
.show_state
= ui::SHOW_STATE_FULLSCREEN
;
155 widget_params
.delegate
= NULL
;
156 scoped_ptr
<aura::Window
> fullscreen_window(
157 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
159 EXPECT_EQ(screen_bounds
.ToString(),
160 maximized_window
->GetBoundsInScreen().ToString());
161 EXPECT_EQ(screen_bounds
.ToString(),
162 fullscreen_window
->GetBoundsInScreen().ToString());
164 gfx::Rect work_area
=
165 ScreenUtil::GetDisplayWorkAreaBoundsInParent(maximized_window
.get());
166 maximized_window
->SetBounds(work_area
);
168 EXPECT_NE(work_area
.ToString(),
169 maximized_window
->GetBoundsInScreen().ToString());
170 EXPECT_EQ(screen_bounds
.ToString(),
171 maximized_window
->GetBoundsInScreen().ToString());
174 ScreenUtil::GetDisplayWorkAreaBoundsInParent(fullscreen_window
.get());
175 fullscreen_window
->SetBounds(work_area
);
176 EXPECT_NE(work_area
.ToString(),
177 fullscreen_window
->GetBoundsInScreen().ToString());
178 EXPECT_EQ(screen_bounds
.ToString(),
179 fullscreen_window
->GetBoundsInScreen().ToString());
181 const gfx::Rect bounds2
= gfx::Rect(100, 100, 200, 200);
182 maximized_window
->SetBounds(bounds2
);
183 fullscreen_window
->SetBounds(bounds2
);
184 EXPECT_EQ(screen_bounds
.ToString(),
185 maximized_window
->GetBoundsInScreen().ToString());
186 EXPECT_EQ(screen_bounds
.ToString(),
187 fullscreen_window
->GetBoundsInScreen().ToString());
190 TEST_F(LockLayoutManagerTest
, KeyboardBounds
) {
191 gfx::Display primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
192 gfx::Rect screen_bounds
= primary_display
.bounds();
194 views::Widget::InitParams
widget_params(
195 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
196 widget_params
.show_state
= ui::SHOW_STATE_FULLSCREEN
;
197 scoped_ptr
<aura::Window
> window(
198 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
200 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
202 // When virtual keyboard overscroll is enabled keyboard bounds should not
203 // affect window bounds.
204 keyboard::SetKeyboardOverscrollOverride(
205 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_ENABLED
);
207 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
208 gfx::Rect keyboard_bounds
=
209 keyboard::KeyboardController::GetInstance()->current_keyboard_bounds();
210 EXPECT_NE(keyboard_bounds
, gfx::Rect());
213 // When keyboard is hidden make sure that rotating the screen gives 100% of
214 // screen size to window.
215 // Repro steps for http://crbug.com/401667:
216 // 1. Set up login screen defaults: VK override disabled
217 // 2. Show/hide keyboard, make sure that no stale keyboard bounds are cached.
218 keyboard::SetKeyboardOverscrollOverride(
219 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED
);
222 ash::DisplayManager
* display_manager
=
223 Shell::GetInstance()->display_manager();
224 display_manager
->SetDisplayRotation(primary_display
.id(),
225 gfx::Display::ROTATE_90
);
226 primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
227 screen_bounds
= primary_display
.bounds();
228 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
229 display_manager
->SetDisplayRotation(primary_display
.id(),
230 gfx::Display::ROTATE_0
);
232 // When virtual keyboard overscroll is disabled keyboard bounds do
233 // affect window bounds.
234 keyboard::SetKeyboardOverscrollOverride(
235 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED
);
237 keyboard::KeyboardController
* keyboard
=
238 keyboard::KeyboardController::GetInstance();
239 primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
240 screen_bounds
= primary_display
.bounds();
241 gfx::Rect
target_bounds(screen_bounds
);
242 target_bounds
.set_height(target_bounds
.height() -
243 keyboard
->proxy()->GetKeyboardWindow()->bounds().height());
244 EXPECT_EQ(target_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
247 keyboard::SetKeyboardOverscrollOverride(
248 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_NONE
);
251 TEST_F(LockLayoutManagerTest
, MultipleMonitors
) {
252 if (!SupportsMultipleDisplays())
255 UpdateDisplay("300x400,400x500");
256 gfx::Rect screen_bounds
= Shell::GetScreen()->GetPrimaryDisplay().bounds();
257 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
259 views::Widget::InitParams
widget_params(
260 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
261 widget_params
.show_state
= ui::SHOW_STATE_FULLSCREEN
;
262 scoped_ptr
<aura::Window
> window(
263 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
264 window
->SetProperty(aura::client::kCanMaximizeKey
, true);
266 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
268 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
270 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
271 window_state
->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40));
273 // Maximize the window with as the restore bounds is inside 2nd display but
274 // lock container windows are always on primary display.
275 window
->SetProperty(aura::client::kShowStateKey
, ui::SHOW_STATE_FULLSCREEN
);
276 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
277 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
279 window_state
->Restore();
280 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
281 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
283 window_state
->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40));
284 window
->SetProperty(aura::client::kShowStateKey
, ui::SHOW_STATE_FULLSCREEN
);
285 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
286 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
288 window_state
->Restore();
289 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
290 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
292 gfx::Rect work_area
=
293 ScreenUtil::GetDisplayWorkAreaBoundsInParent(window
.get());
294 window
->SetBounds(work_area
);
295 // Usually work_area takes Shelf into account but that doesn't affect
296 // LockScreen container windows.
297 EXPECT_NE(work_area
.ToString(), window
->GetBoundsInScreen().ToString());
298 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());