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 ~LoginTestWidgetDelegate() override
{}
38 // Overridden from WidgetDelegate:
39 void DeleteDelegate() override
{ delete this; }
40 views::Widget
* GetWidget() override
{ return widget_
; }
41 const views::Widget
* GetWidget() const override
{ return widget_
; }
42 bool CanActivate() const override
{ return true; }
43 bool ShouldAdvanceFocusToTopLevelWidget() const override
{ return true; }
46 views::Widget
* widget_
;
48 DISALLOW_COPY_AND_ASSIGN(LoginTestWidgetDelegate
);
53 class LockLayoutManagerTest
: public AshTestBase
{
55 void SetUp() override
{
56 // Allow a virtual keyboard (and initialize it per default).
57 base::CommandLine::ForCurrentProcess()->AppendSwitch(
58 keyboard::switches::kEnableVirtualKeyboard
);
60 Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
61 keyboard::KeyboardController::GetInstance());
64 void TearDown() override
{
65 Shell::GetPrimaryRootWindowController()->DeactivateKeyboard(
66 keyboard::KeyboardController::GetInstance());
67 AshTestBase::TearDown();
70 aura::Window
* CreateTestLoginWindow(views::Widget::InitParams params
,
72 aura::Window
* parent
= Shell::GetPrimaryRootWindowController()->
73 GetContainer(ash::kShellWindowId_LockScreenContainer
);
74 params
.parent
= parent
;
75 views::Widget
* widget
= new views::Widget
;
77 params
.delegate
= new LoginTestWidgetDelegate(widget
);
80 aura::Window
* window
= widget
->GetNativeView();
84 // Show or hide the keyboard.
85 void ShowKeyboard(bool show
) {
86 keyboard::KeyboardController
* keyboard
=
87 keyboard::KeyboardController::GetInstance();
88 ASSERT_TRUE(keyboard
);
89 if (show
== keyboard
->keyboard_visible())
93 keyboard
->ShowKeyboard(true);
94 if (keyboard
->proxy()->GetKeyboardWindow()->bounds().height() == 0) {
95 keyboard
->proxy()->GetKeyboardWindow()->SetBounds(
96 keyboard::FullWidthKeyboardBoundsFromRootBounds(
97 Shell::GetPrimaryRootWindow()->bounds(),
98 kVirtualKeyboardHeight
));
101 keyboard
->HideKeyboard(keyboard::KeyboardController::HIDE_REASON_MANUAL
);
104 DCHECK_EQ(show
, keyboard
->keyboard_visible());
108 TEST_F(LockLayoutManagerTest
, NorwmalWindowBoundsArePreserved
) {
109 gfx::Rect screen_bounds
= Shell::GetScreen()->GetPrimaryDisplay().bounds();
111 views::Widget::InitParams
widget_params(
112 views::Widget::InitParams::TYPE_WINDOW
);
113 const gfx::Rect bounds
= gfx::Rect(10, 10, 300, 300);
114 widget_params
.bounds
= bounds
;
115 scoped_ptr
<aura::Window
> window(
116 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
117 EXPECT_EQ(bounds
.ToString(), window
->GetBoundsInScreen().ToString());
119 gfx::Rect work_area
=
120 ScreenUtil::GetDisplayWorkAreaBoundsInParent(window
.get());
121 window
->SetBounds(work_area
);
123 EXPECT_EQ(work_area
.ToString(), window
->GetBoundsInScreen().ToString());
124 EXPECT_NE(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
126 const gfx::Rect bounds2
= gfx::Rect(100, 100, 200, 200);
127 window
->SetBounds(bounds2
);
128 EXPECT_EQ(bounds2
.ToString(), window
->GetBoundsInScreen().ToString());
131 TEST_F(LockLayoutManagerTest
, MaximizedFullscreenWindowBoundsAreEqualToScreen
) {
132 gfx::Rect screen_bounds
= Shell::GetScreen()->GetPrimaryDisplay().bounds();
134 views::Widget::InitParams
widget_params(
135 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
136 widget_params
.show_state
= ui::SHOW_STATE_MAXIMIZED
;
137 const gfx::Rect bounds
= gfx::Rect(10, 10, 300, 300);
138 widget_params
.bounds
= bounds
;
139 // Maximized TYPE_WINDOW_FRAMELESS windows needs a delegate defined otherwise
140 // it won't get initial SetBounds event.
141 scoped_ptr
<aura::Window
> maximized_window(
142 CreateTestLoginWindow(widget_params
, true /* use_delegate */));
144 widget_params
.show_state
= ui::SHOW_STATE_FULLSCREEN
;
145 widget_params
.delegate
= NULL
;
146 scoped_ptr
<aura::Window
> fullscreen_window(
147 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
149 EXPECT_EQ(screen_bounds
.ToString(),
150 maximized_window
->GetBoundsInScreen().ToString());
151 EXPECT_EQ(screen_bounds
.ToString(),
152 fullscreen_window
->GetBoundsInScreen().ToString());
154 gfx::Rect work_area
=
155 ScreenUtil::GetDisplayWorkAreaBoundsInParent(maximized_window
.get());
156 maximized_window
->SetBounds(work_area
);
158 EXPECT_NE(work_area
.ToString(),
159 maximized_window
->GetBoundsInScreen().ToString());
160 EXPECT_EQ(screen_bounds
.ToString(),
161 maximized_window
->GetBoundsInScreen().ToString());
164 ScreenUtil::GetDisplayWorkAreaBoundsInParent(fullscreen_window
.get());
165 fullscreen_window
->SetBounds(work_area
);
166 EXPECT_NE(work_area
.ToString(),
167 fullscreen_window
->GetBoundsInScreen().ToString());
168 EXPECT_EQ(screen_bounds
.ToString(),
169 fullscreen_window
->GetBoundsInScreen().ToString());
171 const gfx::Rect bounds2
= gfx::Rect(100, 100, 200, 200);
172 maximized_window
->SetBounds(bounds2
);
173 fullscreen_window
->SetBounds(bounds2
);
174 EXPECT_EQ(screen_bounds
.ToString(),
175 maximized_window
->GetBoundsInScreen().ToString());
176 EXPECT_EQ(screen_bounds
.ToString(),
177 fullscreen_window
->GetBoundsInScreen().ToString());
180 TEST_F(LockLayoutManagerTest
, KeyboardBounds
) {
181 gfx::Display primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
182 gfx::Rect screen_bounds
= primary_display
.bounds();
184 views::Widget::InitParams
widget_params(
185 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
186 widget_params
.show_state
= ui::SHOW_STATE_FULLSCREEN
;
187 scoped_ptr
<aura::Window
> window(
188 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
190 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
192 // When virtual keyboard overscroll is enabled keyboard bounds should not
193 // affect window bounds.
194 keyboard::SetKeyboardOverscrollOverride(
195 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_ENABLED
);
197 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
198 gfx::Rect keyboard_bounds
=
199 keyboard::KeyboardController::GetInstance()->current_keyboard_bounds();
200 EXPECT_NE(keyboard_bounds
, gfx::Rect());
203 // When keyboard is hidden make sure that rotating the screen gives 100% of
204 // screen size to window.
205 // Repro steps for http://crbug.com/401667:
206 // 1. Set up login screen defaults: VK override disabled
207 // 2. Show/hide keyboard, make sure that no stale keyboard bounds are cached.
208 keyboard::SetKeyboardOverscrollOverride(
209 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED
);
212 ash::DisplayManager
* display_manager
=
213 Shell::GetInstance()->display_manager();
214 display_manager
->SetDisplayRotation(primary_display
.id(),
215 gfx::Display::ROTATE_90
,
216 gfx::Display::ROTATION_SOURCE_ACTIVE
);
217 primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
218 screen_bounds
= primary_display
.bounds();
219 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
220 display_manager
->SetDisplayRotation(primary_display
.id(),
221 gfx::Display::ROTATE_0
,
222 gfx::Display::ROTATION_SOURCE_ACTIVE
);
224 // When virtual keyboard overscroll is disabled keyboard bounds do
225 // affect window bounds.
226 keyboard::SetKeyboardOverscrollOverride(
227 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED
);
229 keyboard::KeyboardController
* keyboard
=
230 keyboard::KeyboardController::GetInstance();
231 primary_display
= Shell::GetScreen()->GetPrimaryDisplay();
232 screen_bounds
= primary_display
.bounds();
233 gfx::Rect
target_bounds(screen_bounds
);
234 target_bounds
.set_height(target_bounds
.height() -
235 keyboard
->proxy()->GetKeyboardWindow()->bounds().height());
236 EXPECT_EQ(target_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
239 keyboard::SetKeyboardOverscrollOverride(
240 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_NONE
);
243 TEST_F(LockLayoutManagerTest
, MultipleMonitors
) {
244 if (!SupportsMultipleDisplays())
247 UpdateDisplay("300x400,400x500");
248 gfx::Rect screen_bounds
= Shell::GetScreen()->GetPrimaryDisplay().bounds();
249 aura::Window::Windows root_windows
= Shell::GetAllRootWindows();
251 views::Widget::InitParams
widget_params(
252 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS
);
253 widget_params
.show_state
= ui::SHOW_STATE_FULLSCREEN
;
254 scoped_ptr
<aura::Window
> window(
255 CreateTestLoginWindow(widget_params
, false /* use_delegate */));
256 window
->SetProperty(aura::client::kCanMaximizeKey
, true);
258 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());
260 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
262 wm::WindowState
* window_state
= wm::GetWindowState(window
.get());
263 window_state
->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40));
265 // Maximize the window with as the restore bounds is inside 2nd display but
266 // lock container windows are always on primary display.
267 window
->SetProperty(aura::client::kShowStateKey
, ui::SHOW_STATE_FULLSCREEN
);
268 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
269 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
271 window_state
->Restore();
272 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
273 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
275 window_state
->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40));
276 window
->SetProperty(aura::client::kShowStateKey
, ui::SHOW_STATE_FULLSCREEN
);
277 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
278 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
280 window_state
->Restore();
281 EXPECT_EQ(root_windows
[0], window
->GetRootWindow());
282 EXPECT_EQ("0,0 300x400", window
->GetBoundsInScreen().ToString());
284 gfx::Rect work_area
=
285 ScreenUtil::GetDisplayWorkAreaBoundsInParent(window
.get());
286 window
->SetBounds(work_area
);
287 // Usually work_area takes Shelf into account but that doesn't affect
288 // LockScreen container windows.
289 EXPECT_NE(work_area
.ToString(), window
->GetBoundsInScreen().ToString());
290 EXPECT_EQ(screen_bounds
.ToString(), window
->GetBoundsInScreen().ToString());