// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ash/wm/base_layout_manager.h" #include "ash/screen_ash.h" #include "ash/session_state_delegate.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/wm/window_state.h" #include "ash/wm/window_util.h" #include "ash/wm/workspace/workspace_window_resizer.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/root_window.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/insets.h" #include "ui/gfx/screen.h" namespace ash { namespace { class BaseLayoutManagerTest : public test::AshTestBase { public: BaseLayoutManagerTest() {} virtual ~BaseLayoutManagerTest() {} virtual void SetUp() OVERRIDE { test::AshTestBase::SetUp(); UpdateDisplay("800x600"); aura::Window* default_container = Shell::GetContainer( Shell::GetPrimaryRootWindow(), internal::kShellWindowId_DefaultContainer); default_container->SetLayoutManager(new internal::BaseLayoutManager( Shell::GetPrimaryRootWindow())); } aura::Window* CreateTestWindow(const gfx::Rect& bounds) { return CreateTestWindowInShellWithBounds(bounds); } private: DISALLOW_COPY_AND_ASSIGN(BaseLayoutManagerTest); }; // Tests normal->maximize->normal. TEST_F(BaseLayoutManagerTest, Maximize) { gfx::Rect bounds(100, 100, 200, 200); scoped_ptr window(CreateTestWindow(bounds)); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); // Maximized window fills the work area, not the whole display. EXPECT_EQ( ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), window->bounds().ToString()); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); } // Tests normal->minimize->normal. TEST_F(BaseLayoutManagerTest, Minimize) { gfx::Rect bounds(100, 100, 200, 200); scoped_ptr window(CreateTestWindow(bounds)); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); // Note: Currently minimize doesn't do anything except set the state. // See crbug.com/104571. EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); } // A WindowDelegate which sets the focus when the window // becomes visible. class FocusDelegate : public aura::test::TestWindowDelegate { public: FocusDelegate() : window_(NULL), show_state_(ui::SHOW_STATE_END) { } virtual ~FocusDelegate() {} void set_window(aura::Window* window) { window_ = window; } // aura::test::TestWindowDelegate overrides: virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { if (window_) { if (visible) window_->Focus(); show_state_ = window_->GetProperty(aura::client::kShowStateKey); } } ui::WindowShowState GetShowStateAndReset() { ui::WindowShowState ret = show_state_; show_state_ = ui::SHOW_STATE_END; return ret; } private: aura::Window* window_; ui::WindowShowState show_state_; DISALLOW_COPY_AND_ASSIGN(FocusDelegate); }; // Make sure that the window's show state is correct in // |WindowDelegate::OnWindowTargetVisibilityChanged|, and setting // focus in this callback doesn't cause DCHECK error. See // crbug.com/168383. TEST_F(BaseLayoutManagerTest, FocusDuringUnminimize) { FocusDelegate delegate; scoped_ptr window(CreateTestWindowInShellWithDelegate( &delegate, 0, gfx::Rect(100, 100, 100, 100))); delegate.set_window(window.get()); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); EXPECT_FALSE(window->IsVisible()); EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, delegate.GetShowStateAndReset()); window->Show(); EXPECT_TRUE(window->IsVisible()); EXPECT_EQ(ui::SHOW_STATE_DEFAULT, delegate.GetShowStateAndReset()); } // Tests maximized window size during root window resize. TEST_F(BaseLayoutManagerTest, MaximizeRootWindowResize) { gfx::Rect bounds(100, 100, 200, 200); scoped_ptr window(CreateTestWindow(bounds)); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); gfx::Rect initial_work_area_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()); EXPECT_EQ(initial_work_area_bounds.ToString(), window->bounds().ToString()); // Enlarge the root window. We should still match the work area size. UpdateDisplay("900x700"); EXPECT_EQ( ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), window->bounds().ToString()); EXPECT_NE( initial_work_area_bounds.ToString(), ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString()); } // Tests normal->fullscreen->normal. TEST_F(BaseLayoutManagerTest, Fullscreen) { gfx::Rect bounds(100, 100, 200, 200); scoped_ptr window(CreateTestWindow(bounds)); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); // Fullscreen window fills the whole display. EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( window.get()).bounds().ToString(), window->bounds().ToString()); window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); } // Tests fullscreen window size during root window resize. TEST_F(BaseLayoutManagerTest, FullscreenRootWindowResize) { gfx::Rect bounds(100, 100, 200, 200); scoped_ptr window(CreateTestWindow(bounds)); // Fullscreen window fills the whole display. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( window.get()).bounds().ToString(), window->bounds().ToString()); // Enlarge the root window. We should still match the display size. UpdateDisplay("800x600"); EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( window.get()).bounds().ToString(), window->bounds().ToString()); } // Tests that when the screen gets smaller the windows aren't bigger than // the screen. TEST_F(BaseLayoutManagerTest, RootWindowResizeShrinksWindows) { scoped_ptr window( CreateTestWindow(gfx::Rect(10, 20, 500, 400))); gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( window.get()).work_area(); // Invariant: Window is smaller than work area. EXPECT_LE(window->bounds().width(), work_area.width()); EXPECT_LE(window->bounds().height(), work_area.height()); // Make the root window narrower than our window. UpdateDisplay("300x400"); work_area = Shell::GetScreen()->GetDisplayNearestWindow( window.get()).work_area(); EXPECT_LE(window->bounds().width(), work_area.width()); EXPECT_LE(window->bounds().height(), work_area.height()); // Make the root window shorter than our window. UpdateDisplay("300x200"); work_area = Shell::GetScreen()->GetDisplayNearestWindow( window.get()).work_area(); EXPECT_LE(window->bounds().width(), work_area.width()); EXPECT_LE(window->bounds().height(), work_area.height()); // Enlarging the root window does not change the window bounds. gfx::Rect old_bounds = window->bounds(); UpdateDisplay("800x600"); EXPECT_EQ(old_bounds.width(), window->bounds().width()); EXPECT_EQ(old_bounds.height(), window->bounds().height()); } // Tests that a maximized window with too-large restore bounds will be restored // to smaller than the full work area. TEST_F(BaseLayoutManagerTest, BoundsWithScreenEdgeVisible) { // Create a window with bounds that fill the screen. gfx::Rect bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds(); scoped_ptr window(CreateTestWindow(bounds)); // Maximize it, which writes the old bounds to restore bounds. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); // Restore it. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); // It should have the default maximized window bounds, inset by the grid size. int grid_size = internal::WorkspaceWindowResizer::kScreenEdgeInset; gfx::Rect max_bounds = ash::ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()); max_bounds.Inset(grid_size, grid_size); EXPECT_EQ(max_bounds.ToString(), window->bounds().ToString()); } // Verifies maximizing sets the restore bounds, and restoring // restores the bounds. TEST_F(BaseLayoutManagerTest, MaximizeSetsRestoreBounds) { scoped_ptr window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); wm::WindowState* window_state = wm::GetWindowState(window.get()); // Maximize it, which will keep the previous restore bounds. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); EXPECT_EQ("1,2 3x4", window_state->GetRestoreBoundsInParent().ToString()); // Restore it, which should restore bounds and reset restore bounds. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); EXPECT_EQ("1,2 3x4", window->bounds().ToString()); EXPECT_FALSE(window_state->HasRestoreBounds()); } // Verifies maximizing keeps the restore bounds if set. TEST_F(BaseLayoutManagerTest, MaximizeResetsRestoreBounds) { scoped_ptr window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); wm::WindowState* window_state = wm::GetWindowState(window.get()); window_state->SetRestoreBoundsInParent(gfx::Rect(10, 11, 12, 13)); // Maximize it, which will keep the previous restore bounds. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); EXPECT_EQ("10,11 12x13", window_state->GetRestoreBoundsInParent().ToString()); } // Verifies that the restore bounds do not get reset when restoring to a // maximzied state from a minimized state. TEST_F(BaseLayoutManagerTest, BoundsAfterRestoringToMaximizeFromMinimize) { scoped_ptr window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); gfx::Rect bounds(10, 15, 25, 35); window->SetBounds(bounds); wm::WindowState* window_state = wm::GetWindowState(window.get()); // Maximize it, which should reset restore bounds. window_state->Maximize(); EXPECT_EQ(bounds.ToString(), window_state->GetRestoreBoundsInParent().ToString()); // Minimize the window. The restore bounds should not change. window_state->Minimize(); EXPECT_EQ(bounds.ToString(), window_state->GetRestoreBoundsInParent().ToString()); // Show the window again. The window should be maximized, and the restore // bounds should not change. window->Show(); EXPECT_EQ(bounds.ToString(), window_state->GetRestoreBoundsInParent().ToString()); EXPECT_TRUE(window_state->IsMaximized()); window_state->Restore(); EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); } // Verify if the window is not resized during screen lock. See: crbug.com/173127 TEST_F(BaseLayoutManagerTest, NotResizeWhenScreenIsLocked) { SetCanLockScreen(true); scoped_ptr window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); // window with AlwaysOnTop will be managed by BaseLayoutManager. window->SetProperty(aura::client::kAlwaysOnTopKey, true); window->Show(); internal::ShelfLayoutManager* shelf = internal::ShelfLayoutManager::ForLauncher(window.get()); shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); window->SetBounds(ScreenAsh::GetMaximizedWindowBoundsInParent(window.get())); gfx::Rect window_bounds = window->bounds(); EXPECT_EQ( ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), window_bounds.ToString()); Shell::GetInstance()->session_state_delegate()->LockScreen(); shelf->UpdateVisibilityState(); EXPECT_NE( ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), window_bounds.ToString()); Shell::GetInstance()->session_state_delegate()->UnlockScreen(); shelf->UpdateVisibilityState(); EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString()); } } // namespace } // namespace ash