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/ash_switches.h"
6 #include "ash/launcher/launcher.h"
8 #include "ash/shell_window_ids.h"
9 #include "ash/test/aura_shell_test_base.h"
10 #include "ash/wm/root_window_layout_manager.h"
11 #include "ash/wm/shelf_layout_manager.h"
12 #include "base/command_line.h"
13 #include "base/utf_string_conversions.h"
14 #include "ui/aura/client/aura_constants.h"
15 #include "ui/aura/test/aura_test_base.h"
16 #include "ui/aura/root_window.h"
17 #include "ui/aura/window.h"
18 #include "ui/gfx/size.h"
19 #include "ui/views/widget/widget.h"
20 #include "ui/views/widget/widget_delegate.h"
22 using aura::RootWindow
;
28 views::Widget
* CreateTestWindow(const views::Widget::InitParams
& params
) {
29 views::Widget
* widget
= new views::Widget
;
34 aura::Window
* GetDefaultContainer() {
35 return Shell::GetInstance()->GetContainer(
36 ash::internal::kShellWindowId_DefaultContainer
);
39 aura::Window
* GetAlwaysOnTopContainer() {
40 return Shell::GetInstance()->GetContainer(
41 ash::internal::kShellWindowId_AlwaysOnTopContainer
);
44 // Expect ALL the containers!
45 void ExpectAllContainers() {
46 Shell
* shell
= Shell::GetInstance();
48 shell
->GetContainer(internal::kShellWindowId_DesktopBackgroundContainer
));
50 shell
->GetContainer(internal::kShellWindowId_DefaultContainer
));
52 shell
->GetContainer(internal::kShellWindowId_AlwaysOnTopContainer
));
54 shell
->GetContainer(internal::kShellWindowId_PanelContainer
));
56 shell
->GetContainer(internal::kShellWindowId_LauncherContainer
));
58 shell
->GetContainer(internal::kShellWindowId_SystemModalContainer
));
60 shell
->GetContainer(internal::kShellWindowId_LockScreenContainer
));
62 shell
->GetContainer(internal::kShellWindowId_LockSystemModalContainer
));
64 shell
->GetContainer(internal::kShellWindowId_StatusContainer
));
66 shell
->GetContainer(internal::kShellWindowId_MenuContainer
));
67 EXPECT_TRUE(shell
->GetContainer(
68 internal::kShellWindowId_DragImageAndTooltipContainer
));
70 shell
->GetContainer(internal::kShellWindowId_SettingBubbleContainer
));
73 void TestCreateWindow(views::Widget::InitParams::Type type
,
75 aura::Window
* expected_container
) {
76 views::Widget::InitParams
widget_params(type
);
77 widget_params
.keep_on_top
= always_on_top
;
79 views::Widget
* widget
= CreateTestWindow(widget_params
);
82 EXPECT_EQ(expected_container
, widget
->GetNativeWindow()->parent()) <<
83 "TestCreateWindow: type=" << type
<< ", always_on_top=" << always_on_top
;
88 class ModalWindow
: public views::WidgetDelegateView
{
91 virtual ~ModalWindow() {}
93 // Overridden from views::WidgetDelegate:
94 virtual views::View
* GetContentsView() OVERRIDE
{
97 virtual bool CanResize() const OVERRIDE
{
100 virtual string16
GetWindowTitle() const OVERRIDE
{
101 return ASCIIToUTF16("Modal Window");
103 virtual ui::ModalType
GetModalType() const OVERRIDE
{
104 return ui::MODAL_TYPE_SYSTEM
;
108 DISALLOW_COPY_AND_ASSIGN(ModalWindow
);
113 class ShellTest
: public test::AuraShellTestBase
{
116 virtual ~ShellTest() {}
119 DISALLOW_COPY_AND_ASSIGN(ShellTest
);
122 TEST_F(ShellTest
, CreateWindow
) {
123 // Normal window should be created in default container.
124 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW
,
125 false, // always_on_top
126 GetDefaultContainer());
127 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP
,
128 false, // always_on_top
129 GetDefaultContainer());
131 // Always-on-top window and popup are created in always-on-top container.
132 TestCreateWindow(views::Widget::InitParams::TYPE_WINDOW
,
133 true, // always_on_top
134 GetAlwaysOnTopContainer());
135 TestCreateWindow(views::Widget::InitParams::TYPE_POPUP
,
136 true, // always_on_top
137 GetAlwaysOnTopContainer());
140 TEST_F(ShellTest
, ChangeAlwaysOnTop
) {
141 views::Widget::InitParams
widget_params(
142 views::Widget::InitParams::TYPE_WINDOW
);
144 // Creates a normal window
145 views::Widget
* widget
= CreateTestWindow(widget_params
);
148 // It should be in default container.
149 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
151 // Flip always-on-top flag.
152 widget
->SetAlwaysOnTop(true);
153 // And it should in always on top container now.
154 EXPECT_EQ(GetAlwaysOnTopContainer(), widget
->GetNativeWindow()->parent());
156 // Flip always-on-top flag.
157 widget
->SetAlwaysOnTop(false);
158 // It should go back to default container.
159 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
161 // Set the same always-on-top flag again.
162 widget
->SetAlwaysOnTop(false);
163 // Should have no effect and we are still in the default container.
164 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
169 TEST_F(ShellTest
, CreateModalWindow
) {
170 views::Widget::InitParams
widget_params(
171 views::Widget::InitParams::TYPE_WINDOW
);
173 // Create a normal window.
174 views::Widget
* widget
= CreateTestWindow(widget_params
);
177 // It should be in default container.
178 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
180 // Create a modal window.
181 views::Widget
* modal_widget
= views::Widget::CreateWindowWithParent(
182 new ModalWindow(), widget
->GetNativeView());
183 modal_widget
->Show();
185 // It should be in modal container.
186 aura::Window
* modal_container
= Shell::GetInstance()->GetContainer(
187 ash::internal::kShellWindowId_SystemModalContainer
);
188 EXPECT_EQ(modal_container
, modal_widget
->GetNativeWindow()->parent());
190 modal_widget
->Close();
194 TEST_F(ShellTest
, CreateLockScreenModalWindow
) {
195 views::Widget::InitParams
widget_params(
196 views::Widget::InitParams::TYPE_WINDOW
);
198 // Create a normal window.
199 views::Widget
* widget
= CreateTestWindow(widget_params
);
202 // It should be in default container.
203 EXPECT_EQ(GetDefaultContainer(), widget
->GetNativeWindow()->parent());
205 // Create a LockScreen window.
206 views::Widget
* lock_widget
= CreateTestWindow(widget_params
);
207 ash::Shell::GetInstance()->GetContainer(
208 ash::internal::kShellWindowId_LockScreenContainer
)->
209 AddChild(lock_widget
->GetNativeView());
212 // It should be in LockScreen container.
213 aura::Window
* lock_screen
= Shell::GetInstance()->GetContainer(
214 ash::internal::kShellWindowId_LockScreenContainer
);
215 EXPECT_EQ(lock_screen
, lock_widget
->GetNativeWindow()->parent());
217 // Create a modal window with a lock window as parent.
218 views::Widget
* lock_modal_widget
= views::Widget::CreateWindowWithParent(
219 new ModalWindow(), lock_widget
->GetNativeView());
220 lock_modal_widget
->Show();
222 // It should be in LockScreen modal container.
223 aura::Window
* lock_modal_container
= Shell::GetInstance()->GetContainer(
224 ash::internal::kShellWindowId_LockSystemModalContainer
);
225 EXPECT_EQ(lock_modal_container
,
226 lock_modal_widget
->GetNativeWindow()->parent());
228 // Create a modal window with a normal window as parent.
229 views::Widget
* modal_widget
= views::Widget::CreateWindowWithParent(
230 new ModalWindow(), widget
->GetNativeView());
231 modal_widget
->Show();
233 // It should be in non-LockScreen modal container.
234 aura::Window
* modal_container
= Shell::GetInstance()->GetContainer(
235 ash::internal::kShellWindowId_SystemModalContainer
);
236 EXPECT_EQ(modal_container
, modal_widget
->GetNativeWindow()->parent());
238 modal_widget
->Close();
239 lock_modal_widget
->Close();
240 lock_widget
->Close();
244 TEST_F(ShellTest
, IsScreenLocked
) {
245 views::Widget::InitParams
widget_params(
246 views::Widget::InitParams::TYPE_WINDOW
);
248 // A normal window does not lock the screen.
249 views::Widget
* widget
= CreateTestWindow(widget_params
);
251 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
253 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
255 // A modal window with a normal window as parent does not locks the screen.
256 views::Widget
* modal_widget
= views::Widget::CreateWindowWithParent(
257 new ModalWindow(), widget
->GetNativeView());
258 modal_widget
->Show();
259 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
260 modal_widget
->Close();
261 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
264 // A lock screen window locks the screen.
265 views::Widget
* lock_widget
= CreateTestWindow(widget_params
);
266 ash::Shell::GetInstance()->GetContainer(
267 ash::internal::kShellWindowId_LockScreenContainer
)->
268 AddChild(lock_widget
->GetNativeView());
270 EXPECT_TRUE(Shell::GetInstance()->IsScreenLocked());
272 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
274 // A modal window with a lock window as parent does not lock the screen. The
275 // screen is locked only when a lock window is visible.
276 views::Widget
* lock_modal_widget
= views::Widget::CreateWindowWithParent(
277 new ModalWindow(), lock_widget
->GetNativeView());
278 lock_modal_widget
->Show();
279 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
281 EXPECT_TRUE(Shell::GetInstance()->IsScreenLocked());
282 lock_modal_widget
->Close();
283 EXPECT_TRUE(Shell::GetInstance()->IsScreenLocked());
284 lock_widget
->Close();
285 EXPECT_FALSE(Shell::GetInstance()->IsScreenLocked());
288 TEST_F(ShellTest
, ComputeWindowMode
) {
289 // By default, we use overlapping mode for large screens.
290 Shell
* shell
= Shell::GetInstance();
291 gfx::Size
monitor_size(1440, 900);
292 CommandLine
command_line_blank(CommandLine::NO_PROGRAM
);
293 EXPECT_EQ(Shell::MODE_OVERLAPPING
,
294 shell
->ComputeWindowMode(monitor_size
, &command_line_blank
));
296 // By default, we use overlapping mode for small screens too.
297 monitor_size
.SetSize(800, 600);
298 EXPECT_EQ(Shell::MODE_OVERLAPPING
,
299 shell
->ComputeWindowMode(monitor_size
, &command_line_blank
));
301 // Even for a large screen, the user can force compact mode.
302 monitor_size
.SetSize(1920, 1080);
303 CommandLine
command_line_compact(CommandLine::NO_PROGRAM
);
304 command_line_compact
.AppendSwitchASCII(switches::kAuraWindowMode
,
305 switches::kAuraWindowModeCompact
);
306 EXPECT_EQ(Shell::MODE_COMPACT
,
307 shell
->ComputeWindowMode(monitor_size
, &command_line_compact
));
309 // Now test dynamic window mode computation.
310 Shell::GetInstance()->set_dynamic_window_mode(true);
312 // Alex-sized screens need compact mode when choosing dynamically.
313 monitor_size
.SetSize(1280, 800);
314 EXPECT_EQ(Shell::MODE_COMPACT
,
315 shell
->ComputeWindowMode(monitor_size
, &command_line_blank
));
317 // ZGB-sized screens need compact mode when choosing dynamically.
318 monitor_size
.SetSize(1366, 768);
319 EXPECT_EQ(Shell::MODE_COMPACT
,
320 shell
->ComputeWindowMode(monitor_size
, &command_line_blank
));
322 // Even for a small screen, the user can force overlapping mode.
323 monitor_size
.SetSize(800, 600);
324 CommandLine
command_line_force(CommandLine::NO_PROGRAM
);
325 command_line_force
.AppendSwitchASCII(switches::kAuraWindowMode
,
326 switches::kAuraWindowModeOverlapping
);
327 EXPECT_EQ(Shell::MODE_OVERLAPPING
,
328 shell
->ComputeWindowMode(monitor_size
, &command_line_force
));
331 // Fails on Mac only. Need to be corrected. http://crbug.com/111279.
332 #if defined(OS_MACOSX)
333 #define MAYBE_ChangeWindowMode FAILS_ChangeWindowMode
335 #define MAYBE_ChangeWindowMode ChangeWindowMode
337 TEST_F(ShellTest
, MAYBE_ChangeWindowMode
) {
338 // We start with the usual window containers.
339 ExpectAllContainers();
340 // We're not in compact window mode by default.
341 Shell
* shell
= Shell::GetInstance();
342 EXPECT_FALSE(shell
->IsWindowModeCompact());
343 // We have a default container event filter (for window drags).
344 EXPECT_TRUE(GetDefaultContainer()->event_filter());
345 // Launcher is visible.
346 views::Widget
* launcher_widget
= shell
->launcher()->widget();
347 EXPECT_TRUE(launcher_widget
->IsVisible());
348 // Launcher is at bottom-left of screen.
349 EXPECT_EQ(0, launcher_widget
->GetWindowScreenBounds().x());
350 EXPECT_EQ(RootWindow::GetInstance()->GetHostSize().height(),
351 launcher_widget
->GetWindowScreenBounds().bottom());
352 // We have a desktop background but not a bare layer.
353 EXPECT_TRUE(shell
->root_window_layout_
->background_widget());
354 EXPECT_FALSE(shell
->root_window_layout_
->background_layer());
356 // Create a normal window. It is not maximized.
357 views::Widget::InitParams
widget_params(
358 views::Widget::InitParams::TYPE_WINDOW
);
359 widget_params
.bounds
.SetRect(11, 22, 300, 400);
360 views::Widget
* widget
= CreateTestWindow(widget_params
);
362 EXPECT_FALSE(widget
->IsMaximized());
365 shell
->ChangeWindowMode(Shell::MODE_COMPACT
);
366 EXPECT_TRUE(shell
->IsWindowModeCompact());
367 // Compact mode does not use a default container event filter.
368 EXPECT_FALSE(GetDefaultContainer()->event_filter());
369 // We still have all the usual containers.
370 ExpectAllContainers();
372 // In compact window mode, all windows are maximized.
373 EXPECT_TRUE(widget
->IsMaximized());
374 // Window bounds got updated to fill the work area.
375 EXPECT_EQ(widget
->GetWorkAreaBoundsInScreen(),
376 widget
->GetWindowScreenBounds());
377 // Launcher is hidden.
378 EXPECT_FALSE(launcher_widget
->IsVisible());
379 // Desktop background widget is gone but we have a layer.
380 EXPECT_FALSE(shell
->root_window_layout_
->background_widget());
381 EXPECT_TRUE(shell
->root_window_layout_
->background_layer());
383 // Switch back to overlapping mode.
384 shell
->ChangeWindowMode(Shell::MODE_OVERLAPPING
);
385 EXPECT_FALSE(shell
->IsWindowModeCompact());
386 // Event filter came back.
387 EXPECT_TRUE(GetDefaultContainer()->event_filter());
388 // Launcher is visible again.
389 EXPECT_TRUE(launcher_widget
->IsVisible());
390 // Launcher is at bottom-left of screen.
391 EXPECT_EQ(0, launcher_widget
->GetWindowScreenBounds().x());
392 EXPECT_EQ(RootWindow::GetInstance()->GetHostSize().height(),
393 launcher_widget
->GetWindowScreenBounds().bottom());
394 // Desktop background is back.
395 EXPECT_TRUE(shell
->root_window_layout_
->background_widget());
396 EXPECT_FALSE(shell
->root_window_layout_
->background_layer());
402 // Windows bots won't let us create large root windows, and this behavior is
403 // only relevant on Chrome OS devices.
404 #if defined(OS_CHROMEOS)
405 TEST_F(ShellTest
, ResizeRootWindow
) {
406 // Allow dynamic window mode switching.
407 Shell::GetInstance()->set_dynamic_window_mode(true);
409 // Switching to a small screen enables compact window mode.
410 RootWindow::GetInstance()->SetHostSize(gfx::Size(1024, 768));
411 EXPECT_TRUE(Shell::GetInstance()->IsWindowModeCompact());
413 // Launcher is hidden.
414 views::Widget
* launcher_widget
= Shell::GetInstance()->launcher()->widget();
415 EXPECT_FALSE(launcher_widget
->IsVisible());
417 // Switching to a large screen disables compact window mode.
418 RootWindow::GetInstance()->SetHostSize(gfx::Size(1920, 1080));
419 EXPECT_FALSE(Shell::GetInstance()->IsWindowModeCompact());
421 // Launcher is in the bottom-left corner of window.
422 EXPECT_EQ(0, launcher_widget
->GetWindowScreenBounds().x());
423 EXPECT_EQ(1080, launcher_widget
->GetWindowScreenBounds().bottom());
425 #endif // defined(OS_CHROMEOS)
427 TEST_F(ShellTest
, FullscreenWindowHidesShelf
) {
428 ExpectAllContainers();
429 Shell
* shell
= Shell::GetInstance();
431 // Create a normal window. It is not maximized.
432 views::Widget::InitParams
widget_params(
433 views::Widget::InitParams::TYPE_WINDOW
);
434 widget_params
.bounds
.SetRect(11, 22, 300, 400);
435 views::Widget
* widget
= CreateTestWindow(widget_params
);
437 EXPECT_FALSE(widget
->IsMaximized());
439 // Test in the compact mode. There should be no shelf.
440 shell
->ChangeWindowMode(Shell::MODE_COMPACT
);
441 EXPECT_FALSE(Shell::GetInstance()->shelf());
443 // Test in the managed mode.
444 shell
->ChangeWindowMode(Shell::MODE_MANAGED
);
445 EXPECT_TRUE(Shell::GetInstance()->shelf()->visible());
447 widget
->SetFullscreen(true);
448 EXPECT_FALSE(Shell::GetInstance()->shelf()->visible());
451 EXPECT_TRUE(Shell::GetInstance()->shelf()->visible());
453 // Test in the overlap mode.
454 shell
->ChangeWindowMode(Shell::MODE_OVERLAPPING
);
455 EXPECT_TRUE(Shell::GetInstance()->shelf()->visible());
457 widget
->SetFullscreen(true);
458 EXPECT_FALSE(Shell::GetInstance()->shelf()->visible());
461 EXPECT_TRUE(Shell::GetInstance()->shelf()->visible());