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. 4 5 #include "ash/wm/base_layout_manager.h" 6 7 #include "ash/screen_ash.h" 8 #include "ash/session_state_delegate.h" 9 #include "ash/shelf/shelf_layout_manager.h" 10 #include "ash/shell.h" 11 #include "ash/shell_window_ids.h" 12 #include "ash/test/ash_test_base.h" 13 #include "ash/wm/property_util.h" 14 #include "ash/wm/window_util.h" 15 #include "ash/wm/workspace/workspace_window_resizer.h" 16 #include "base/basictypes.h" 17 #include "base/compiler_specific.h" 18 #include "ui/aura/client/aura_constants.h" 19 #include "ui/aura/root_window.h" 20 #include "ui/aura/test/test_windows.h" 21 #include "ui/aura/window.h" 22 #include "ui/base/ui_base_types.h" 23 #include "ui/gfx/insets.h" 24 #include "ui/gfx/screen.h" 25 26 namespace ash { 27 28 namespace { 29 30 class BaseLayoutManagerTest : public test::AshTestBase { 31 public: 32 BaseLayoutManagerTest() {} 33 virtual ~BaseLayoutManagerTest() {} 34 35 virtual void SetUp() OVERRIDE { 36 test::AshTestBase::SetUp(); 37 UpdateDisplay("800x600"); 38 aura::Window* default_container = Shell::GetContainer( 39 Shell::GetPrimaryRootWindow(), 40 internal::kShellWindowId_DefaultContainer); 41 default_container->SetLayoutManager(new internal::BaseLayoutManager( 42 Shell::GetPrimaryRootWindow())); 43 } 44 45 aura::Window* CreateTestWindow(const gfx::Rect& bounds) { 46 return CreateTestWindowInShellWithBounds(bounds); 47 } 48 49 private: 50 DISALLOW_COPY_AND_ASSIGN(BaseLayoutManagerTest); 51 }; 52 53 // Tests normal->maximize->normal. 54 TEST_F(BaseLayoutManagerTest, Maximize) { 55 gfx::Rect bounds(100, 100, 200, 200); 56 scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); 57 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); 58 // Maximized window fills the work area, not the whole display. 59 EXPECT_EQ( 60 ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), 61 window->bounds().ToString()); 62 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 63 EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); 64 } 65 66 // Tests normal->minimize->normal. 67 TEST_F(BaseLayoutManagerTest, Minimize) { 68 gfx::Rect bounds(100, 100, 200, 200); 69 scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); 70 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); 71 // Note: Currently minimize doesn't do anything except set the state. 72 // See crbug.com/104571. 73 EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); 74 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 75 EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); 76 } 77 78 // A WindowDelegate which sets the focus when the window 79 // becomes visible. 80 class FocusDelegate : public aura::test::TestWindowDelegate { 81 public: 82 FocusDelegate() 83 : window_(NULL), 84 show_state_(ui::SHOW_STATE_END) { 85 } 86 virtual ~FocusDelegate() {} 87 88 void set_window(aura::Window* window) { window_ = window; } 89 90 // aura::test::TestWindowDelegate overrides: 91 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { 92 if (window_) { 93 if (visible) 94 window_->Focus(); 95 show_state_ = window_->GetProperty(aura::client::kShowStateKey); 96 } 97 } 98 99 ui::WindowShowState GetShowStateAndReset() { 100 ui::WindowShowState ret = show_state_; 101 show_state_ = ui::SHOW_STATE_END; 102 return ret; 103 } 104 105 private: 106 aura::Window* window_; 107 ui::WindowShowState show_state_; 108 109 DISALLOW_COPY_AND_ASSIGN(FocusDelegate); 110 }; 111 112 // Make sure that the window's show state is correct in 113 // |WindowDelegate::OnWindowTargetVisibilityChanged|, and setting 114 // focus in this callback doesn't cause DCHECK error. See 115 // crbug.com/168383. 116 TEST_F(BaseLayoutManagerTest, FocusDuringUnminimize) { 117 FocusDelegate delegate; 118 scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate( 119 &delegate, 0, gfx::Rect(100, 100, 100, 100))); 120 delegate.set_window(window.get()); 121 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); 122 EXPECT_FALSE(window->IsVisible()); 123 EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, delegate.GetShowStateAndReset()); 124 window->Show(); 125 EXPECT_TRUE(window->IsVisible()); 126 EXPECT_EQ(ui::SHOW_STATE_DEFAULT, delegate.GetShowStateAndReset()); 127 } 128 129 // Tests maximized window size during root window resize. 130 TEST_F(BaseLayoutManagerTest, MaximizeRootWindowResize) { 131 gfx::Rect bounds(100, 100, 200, 200); 132 scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); 133 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); 134 gfx::Rect initial_work_area_bounds = 135 ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()); 136 EXPECT_EQ(initial_work_area_bounds.ToString(), window->bounds().ToString()); 137 // Enlarge the root window. We should still match the work area size. 138 UpdateDisplay("900x700"); 139 EXPECT_EQ( 140 ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), 141 window->bounds().ToString()); 142 EXPECT_NE( 143 initial_work_area_bounds.ToString(), 144 ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString()); 145 } 146 147 // Tests normal->fullscreen->normal. 148 TEST_F(BaseLayoutManagerTest, Fullscreen) { 149 gfx::Rect bounds(100, 100, 200, 200); 150 scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); 151 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); 152 // Fullscreen window fills the whole display. 153 EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( 154 window.get()).bounds().ToString(), 155 window->bounds().ToString()); 156 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 157 EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); 158 } 159 160 // Tests fullscreen window size during root window resize. 161 TEST_F(BaseLayoutManagerTest, FullscreenRootWindowResize) { 162 gfx::Rect bounds(100, 100, 200, 200); 163 scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); 164 // Fullscreen window fills the whole display. 165 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN); 166 EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( 167 window.get()).bounds().ToString(), 168 window->bounds().ToString()); 169 // Enlarge the root window. We should still match the display size. 170 UpdateDisplay("800x600"); 171 EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow( 172 window.get()).bounds().ToString(), 173 window->bounds().ToString()); 174 } 175 176 // Fails on Mac only. Need to be implemented. http://crbug.com/111279. 177 #if defined(OS_MACOSX) 178 #define MAYBE_RootWindowResizeShrinksWindows \ 179 DISABLED_RootWindowResizeShrinksWindows 180 #else 181 #define MAYBE_RootWindowResizeShrinksWindows RootWindowResizeShrinksWindows 182 #endif 183 // Tests that when the screen gets smaller the windows aren't bigger than 184 // the screen. 185 TEST_F(BaseLayoutManagerTest, MAYBE_RootWindowResizeShrinksWindows) { 186 scoped_ptr<aura::Window> window( 187 CreateTestWindow(gfx::Rect(10, 20, 500, 400))); 188 gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow( 189 window.get()).work_area(); 190 // Invariant: Window is smaller than work area. 191 EXPECT_LE(window->bounds().width(), work_area.width()); 192 EXPECT_LE(window->bounds().height(), work_area.height()); 193 194 // Make the root window narrower than our window. 195 UpdateDisplay("300x400"); 196 work_area = Shell::GetScreen()->GetDisplayNearestWindow( 197 window.get()).work_area(); 198 EXPECT_LE(window->bounds().width(), work_area.width()); 199 EXPECT_LE(window->bounds().height(), work_area.height()); 200 201 // Make the root window shorter than our window. 202 UpdateDisplay("300x200"); 203 work_area = Shell::GetScreen()->GetDisplayNearestWindow( 204 window.get()).work_area(); 205 EXPECT_LE(window->bounds().width(), work_area.width()); 206 EXPECT_LE(window->bounds().height(), work_area.height()); 207 208 // Enlarging the root window does not change the window bounds. 209 gfx::Rect old_bounds = window->bounds(); 210 UpdateDisplay("800x600"); 211 EXPECT_EQ(old_bounds.width(), window->bounds().width()); 212 EXPECT_EQ(old_bounds.height(), window->bounds().height()); 213 } 214 215 // Tests that a maximized window with too-large restore bounds will be restored 216 // to smaller than the full work area. 217 TEST_F(BaseLayoutManagerTest, BoundsWithScreenEdgeVisible) { 218 // Create a window with bounds that fill the screen. 219 gfx::Rect bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds(); 220 scoped_ptr<aura::Window> window(CreateTestWindow(bounds)); 221 // Maximize it, which writes the old bounds to restore bounds. 222 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); 223 // Restore it. 224 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 225 // It should have the default maximized window bounds, inset by the grid size. 226 int grid_size = internal::WorkspaceWindowResizer::kScreenEdgeInset; 227 gfx::Rect max_bounds = 228 ash::ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()); 229 max_bounds.Inset(grid_size, grid_size); 230 EXPECT_EQ(max_bounds.ToString(), window->bounds().ToString()); 231 } 232 233 // Verifies maximizing sets the restore bounds, and restoring 234 // restores the bounds. 235 TEST_F(BaseLayoutManagerTest, MaximizeSetsRestoreBounds) { 236 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); 237 238 // Maximize it, which will keep the previous restore bounds. 239 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); 240 EXPECT_EQ("1,2 3x4", GetRestoreBoundsInParent(window.get()).ToString()); 241 242 // Restore it, which should restore bounds and reset restore bounds. 243 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 244 EXPECT_EQ("1,2 3x4", window->bounds().ToString()); 245 EXPECT_TRUE(GetRestoreBoundsInScreen(window.get()) == NULL); 246 } 247 248 // Verifies maximizing keeps the restore bounds if set. 249 TEST_F(BaseLayoutManagerTest, MaximizeResetsRestoreBounds) { 250 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); 251 SetRestoreBoundsInParent(window.get(), gfx::Rect(10, 11, 12, 13)); 252 253 // Maximize it, which will keep the previous restore bounds. 254 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); 255 EXPECT_EQ("10,11 12x13", GetRestoreBoundsInParent(window.get()).ToString()); 256 } 257 258 // Verifies that the restore bounds do not get reset when restoring to a 259 // maximzied state from a minimized state. 260 TEST_F(BaseLayoutManagerTest, BoundsAfterRestoringToMaximizeFromMinimize) { 261 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); 262 gfx::Rect bounds(10, 15, 25, 35); 263 window->SetBounds(bounds); 264 265 // Maximize it, which should reset restore bounds. 266 wm::MaximizeWindow(window.get()); 267 EXPECT_EQ(bounds.ToString(), 268 GetRestoreBoundsInParent(window.get()).ToString()); 269 270 // Minimize the window. The restore bounds should not change. 271 wm::MinimizeWindow(window.get()); 272 EXPECT_EQ(bounds.ToString(), 273 GetRestoreBoundsInParent(window.get()).ToString()); 274 275 // Show the window again. The window should be maximized, and the restore 276 // bounds should not change. 277 window->Show(); 278 EXPECT_EQ(bounds.ToString(), 279 GetRestoreBoundsInParent(window.get()).ToString()); 280 EXPECT_TRUE(wm::IsWindowMaximized(window.get())); 281 282 wm::RestoreWindow(window.get()); 283 EXPECT_EQ(bounds.ToString(), window->bounds().ToString()); 284 } 285 286 // Verify if the window is not resized during screen lock. See: crbug.com/173127 287 TEST_F(BaseLayoutManagerTest, NotResizeWhenScreenIsLocked) { 288 SetCanLockScreen(true); 289 scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4))); 290 // window with AlwaysOnTop will be managed by BaseLayoutManager. 291 window->SetProperty(aura::client::kAlwaysOnTopKey, true); 292 window->Show(); 293 294 internal::ShelfLayoutManager* shelf = 295 internal::ShelfLayoutManager::ForLauncher(window.get()); 296 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); 297 298 window->SetBounds(ScreenAsh::GetMaximizedWindowBoundsInParent(window.get())); 299 gfx::Rect window_bounds = window->bounds(); 300 EXPECT_EQ( 301 ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), 302 window_bounds.ToString()); 303 304 Shell::GetInstance()->session_state_delegate()->LockScreen(); 305 shelf->UpdateVisibilityState(); 306 EXPECT_NE( 307 ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(), 308 window_bounds.ToString()); 309 310 Shell::GetInstance()->session_state_delegate()->UnlockScreen(); 311 shelf->UpdateVisibilityState(); 312 EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString()); 313 } 314 315 } // namespace 316 } // namespace ash 317